diff options
author | Lluis Sanchez <lluis@xamarin.com> | 2014-01-20 19:32:53 +0400 |
---|---|---|
committer | Lluis Sanchez Gual <lluis@xamarin.com> | 2014-10-21 18:39:14 +0400 |
commit | f73b2a9990495587d514aa1856919c21170a3940 (patch) | |
tree | 9842411ee8644ead5915a715ee7e53984a601df4 /main/src | |
parent | a2046b6331a271e8203df7d3d0f14500d33d60fa (diff) |
Initial drop of the new project model
Diffstat (limited to 'main/src')
775 files changed, 22641 insertions, 17866 deletions
diff --git a/main/src/addins/AspNet/Commands/AddControllerDialog.cs b/main/src/addins/AspNet/Commands/AddControllerDialog.cs index 603e60dbf0..c3af4ed5db 100644 --- a/main/src/addins/AspNet/Commands/AddControllerDialog.cs +++ b/main/src/addins/AspNet/Commands/AddControllerDialog.cs @@ -29,6 +29,7 @@ using System.Collections.Generic; using Gtk;
using MonoDevelop.Core;
using MonoDevelop.AspNet.Projects;
+using MonoDevelop.Projects;
namespace MonoDevelop.AspNet.Commands
{
@@ -57,13 +58,14 @@ namespace MonoDevelop.AspNet.Commands }
}
- public AddControllerDialog (AspNetAppProject project)
+ public AddControllerDialog (DotNetProject project)
{
Build ();
+ var ext = project.GetService<AspNetFlavor> ();
provider = project.LanguageBinding.GetCodeDomProvider ();
- loadedTemplateList = project.GetCodeTemplates ("AddController");
+ loadedTemplateList = ext.GetCodeTemplates ("AddController");
bool foundEmptyTemplate = false;
int templateIndex = 0;
foreach (string file in loadedTemplateList) {
diff --git a/main/src/addins/AspNet/Commands/AddViewDialog.cs b/main/src/addins/AspNet/Commands/AddViewDialog.cs index c9d4c56a21..ef54af54bb 100644 --- a/main/src/addins/AspNet/Commands/AddViewDialog.cs +++ b/main/src/addins/AspNet/Commands/AddViewDialog.cs @@ -37,12 +37,14 @@ using MonoDevelop.AspNet.Projects; using MonoDevelop.AspNet.WebForms.Dom; using MonoDevelop.AspNet.WebForms; using Gtk; +using MonoDevelop.Projects; namespace MonoDevelop.AspNet.Commands { class AddViewDialog : Dialog { - readonly AspNetAppProject project;
+ readonly DotNetProject project; + readonly AspNetFlavor aspFlavor;
IDictionary<string, IList<string>> loadedTemplateList;
IDictionary<string, ListStore> templateStore;
ListStore dataClassStore;
@@ -61,9 +63,10 @@ namespace MonoDevelop.AspNet.Commands CheckButton partialCheck, stronglyTypedCheck, masterCheck; Alignment typePanel, masterPanel; - public AddViewDialog (AspNetAppProject project) + public AddViewDialog (DotNetProject project) { this.project = project; + aspFlavor = project.GetService<AspNetFlavor> (); Build (); @@ -73,14 +76,14 @@ namespace MonoDevelop.AspNet.Commands loadedTemplateList = new Dictionary<string, IList<string>> ();
foreach (var engine in viewEngines) {
viewEngineCombo.AppendText (engine);
- loadedTemplateList[engine] = project.GetCodeTemplates ("AddView", engine);
+ loadedTemplateList[engine] = aspFlavor.GetCodeTemplates ("AddView", engine);
}
viewEngineCombo.Active = 0;
InitializeTemplateStore (loadedTemplateList); ContentPlaceHolders = new List<string> (); - string siteMaster = project.VirtualToLocalPath ("~/Views/Shared/Site.master", null); + string siteMaster = aspFlavor.VirtualToLocalPath ("~/Views/Shared/Site.master", null); if (project.Files.GetFile (siteMaster) != null) masterEntry.Text = "~/Views/Shared/Site.master"; @@ -221,7 +224,7 @@ namespace MonoDevelop.AspNet.Commands IEnumerable<string> GetProperViewEngines ()
{
yield return "Aspx";
- if (project.SupportsRazorViewEngine)
+ if (aspFlavor.SupportsRazorViewEngine)
yield return "Razor";
}
@@ -307,7 +310,7 @@ namespace MonoDevelop.AspNet.Commands return false;
if (!IsPartialView && HasMaster && ActiveViewEngine != "Razor") {
- if (String.IsNullOrEmpty (MasterFile) || !File.Exists (project.VirtualToLocalPath (oldMaster, null)))
+ if (String.IsNullOrEmpty (MasterFile) || !File.Exists (aspFlavor.VirtualToLocalPath (oldMaster, null)))
return false;
//PrimaryPlaceHolder can be empty
//Layout Page can be empty in Razor Views - it's usually set in _ViewStart.cshtml file
@@ -341,7 +344,7 @@ namespace MonoDevelop.AspNet.Commands }; try { if (MessageService.RunCustomDialog (dialog) == (int) ResponseType.Ok) - masterEntry.Text = project.LocalToVirtualPath (dialog.SelectedFile.FilePath); + masterEntry.Text = aspFlavor.LocalToVirtualPath (dialog.SelectedFile.FilePath); } finally { dialog.Destroy (); } @@ -359,7 +362,7 @@ namespace MonoDevelop.AspNet.Commands primaryPlaceholderStore.Clear (); ContentPlaceHolders.Clear (); - string realPath = project.VirtualToLocalPath (oldMaster, null); + string realPath = aspFlavor.VirtualToLocalPath (oldMaster, null); if (!File.Exists (realPath)) return; diff --git a/main/src/addins/AspNet/Commands/AddViewFromControllerCommandHandler.cs b/main/src/addins/AspNet/Commands/AddViewFromControllerCommandHandler.cs index 0bf46856ec..0d732c6f54 100644 --- a/main/src/addins/AspNet/Commands/AddViewFromControllerCommandHandler.cs +++ b/main/src/addins/AspNet/Commands/AddViewFromControllerCommandHandler.cs @@ -28,6 +28,7 @@ using System; using MonoDevelop.Components.Commands;
using MonoDevelop.Ide;
using MonoDevelop.AspNet.Projects;
+using MonoDevelop.Projects;
namespace MonoDevelop.AspNet.Commands
{
@@ -41,7 +42,7 @@ namespace MonoDevelop.AspNet.Commands protected override void Run ()
{
var doc = IdeApp.Workbench.ActiveDocument;
- var project = (AspNetAppProject)doc.Project;
+ var project = (DotNetProject)doc.Project;
var currentLocation = doc.Editor.Caret.Location;
string controllerName = doc.ParsedDocument.GetTopLevelTypeDefinition (currentLocation).Name;
@@ -54,7 +55,7 @@ namespace MonoDevelop.AspNet.Commands AddView (project, path, actionName);
}
- public static void AddView (AspNetAppProject project, string path, string name)
+ public static void AddView (DotNetProject project, string path, string name)
{
var provider = project.LanguageBinding.GetCodeDomProvider ();
if (provider == null)
@@ -125,7 +126,7 @@ namespace MonoDevelop.AspNet.Commands if (System.IO.File.Exists (outputFile)) {
project.AddFile (outputFile);
- IdeApp.ProjectOperations.Save (project);
+ IdeApp.ProjectOperations.SaveAsync (project);
}
}
}
diff --git a/main/src/addins/AspNet/Commands/GoToControllerCommandHandler.cs b/main/src/addins/AspNet/Commands/GoToControllerCommandHandler.cs index ed2251cb31..3e62a685bb 100644 --- a/main/src/addins/AspNet/Commands/GoToControllerCommandHandler.cs +++ b/main/src/addins/AspNet/Commands/GoToControllerCommandHandler.cs @@ -40,8 +40,12 @@ namespace MonoDevelop.AspNet.Commands protected override void Update (CommandInfo info)
{
var doc = IdeApp.Workbench.ActiveDocument;
- AspNetAppProject project;
- if (doc == null || (project = doc.Project as AspNetAppProject) == null || !project.IsAspMvcProject) {
+ if (doc == null || doc.Project == null) {
+ info.Enabled = info.Visible = false;
+ return;
+ }
+ var aspFlavor = doc.Project.GetService<AspNetFlavor> ();
+ if (aspFlavor == null || !aspFlavor.IsAspMvcProject) {
info.Enabled = info.Visible = false;
return;
}
diff --git a/main/src/addins/AspNet/Commands/MvcCommandsCommonHandler.cs b/main/src/addins/AspNet/Commands/MvcCommandsCommonHandler.cs index 03fa16fb63..fcc9aa7acd 100644 --- a/main/src/addins/AspNet/Commands/MvcCommandsCommonHandler.cs +++ b/main/src/addins/AspNet/Commands/MvcCommandsCommonHandler.cs @@ -38,8 +38,12 @@ namespace MonoDevelop.AspNet.Commands public static void Update (CommandInfo info)
{
var doc = IdeApp.Workbench.ActiveDocument;
- AspNetAppProject project;
- if (doc == null || (project = doc.Project as AspNetAppProject) == null || !project.IsAspMvcProject || doc.ParsedDocument == null) {
+ if (doc == null || doc.Project == null || doc.ParsedDocument == null) {
+ info.Enabled = info.Visible = false;
+ return;
+ }
+ var aspFlavor = doc.Project.GetService<AspNetFlavor> ();
+ if (aspFlavor == null || !aspFlavor.IsAspMvcProject) {
info.Enabled = info.Visible = false;
return;
}
diff --git a/main/src/addins/AspNet/Execution/AspNetExecutionHandler.cs b/main/src/addins/AspNet/Execution/AspNetExecutionHandler.cs index 2e0dcca894..19566f4656 100644 --- a/main/src/addins/AspNet/Execution/AspNetExecutionHandler.cs +++ b/main/src/addins/AspNet/Execution/AspNetExecutionHandler.cs @@ -89,7 +89,7 @@ namespace MonoDevelop.AspNet.Execution return cmd != null && !string.IsNullOrEmpty (GetXspName (cmd)); } - public IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) + public ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) { var cmd = (AspNetExecutionCommand) command; var xspPath = GetXspPath (cmd); diff --git a/main/src/addins/AspNet/Execution/BrowserLauncher.cs b/main/src/addins/AspNet/Execution/BrowserLauncher.cs index 6a03216721..628b4cdd00 100644 --- a/main/src/addins/AspNet/Execution/BrowserLauncher.cs +++ b/main/src/addins/AspNet/Execution/BrowserLauncher.cs @@ -35,7 +35,7 @@ namespace MonoDevelop.AspNet.Execution { static class BrowserLauncher { - public static IProcessAsyncOperation LaunchDefaultBrowser (string url) + public static ProcessAsyncOperation LaunchDefaultBrowser (string url) { try { DesktopService.ShowUrl (url); diff --git a/main/src/addins/AspNet/Execution/XspOptionsPanel.cs b/main/src/addins/AspNet/Execution/XspOptionsPanel.cs index 6bd97b965d..1565afca86 100644 --- a/main/src/addins/AspNet/Execution/XspOptionsPanel.cs +++ b/main/src/addins/AspNet/Execution/XspOptionsPanel.cs @@ -41,12 +41,12 @@ namespace MonoDevelop.AspNet.Execution public override Widget CreatePanelWidget () { - return panel = new XspOptionsPanelWidget ((AspNetAppProject) ConfiguredProject); + return panel = new XspOptionsPanelWidget (ConfiguredProject.GetService<AspNetFlavor> ()); } public override void ApplyChanges () { - panel.Store ((AspNetAppProject) ConfiguredProject); + panel.Store (ConfiguredProject.GetService<AspNetFlavor> ()); } } } diff --git a/main/src/addins/AspNet/Execution/XspOptionsPanelWidget.cs b/main/src/addins/AspNet/Execution/XspOptionsPanelWidget.cs index 18126f4836..da3a559f14 100644 --- a/main/src/addins/AspNet/Execution/XspOptionsPanelWidget.cs +++ b/main/src/addins/AspNet/Execution/XspOptionsPanelWidget.cs @@ -46,7 +46,7 @@ namespace MonoDevelop.AspNet.Execution readonly FileEntry certLocation = new FileEntry (); readonly Entry passwordEntry = new Entry { InvisibleChar = '●' }; - public XspOptionsPanelWidget (AspNetAppProject project) + public XspOptionsPanelWidget (AspNetFlavor project) { Build (); @@ -165,7 +165,7 @@ namespace MonoDevelop.AspNet.Execution ShowAll (); } - public void Store (AspNetAppProject project) + public void Store (AspNetFlavor project) { XspParameters xPar = project.XspParameters; diff --git a/main/src/addins/AspNet/Makefile.am b/main/src/addins/AspNet/Makefile.am index b8a06787c8..2dc30cad76 100644 --- a/main/src/addins/AspNet/Makefile.am +++ b/main/src/addins/AspNet/Makefile.am @@ -1,4 +1,4 @@ include $(top_srcdir)/xbuild.include EXTRA_DIST += \ $(wildcard lib/*) \ - $(wildcard Templates/Common/*.cshtml) + $(wildcard Templates/MvcCommon/*.cshtml) diff --git a/main/src/addins/AspNet/MonoDevelop.AspNet.csproj b/main/src/addins/AspNet/MonoDevelop.AspNet.csproj index 26e3e80662..f0b66a4ae4 100644 --- a/main/src/addins/AspNet/MonoDevelop.AspNet.csproj +++ b/main/src/addins/AspNet/MonoDevelop.AspNet.csproj @@ -9,6 +9,7 @@ <OutputType>Library</OutputType> <AssemblyName>MonoDevelop.AspNet</AssemblyName> <RootNamespace>MonoDevelop.AspNet</RootNamespace> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>True</DebugSymbols> @@ -125,6 +126,7 @@ <Reference Include="System.Web.WebPages.Razor"> <HintPath>..\..\..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.Razor.dll</HintPath> </Reference> + <Reference Condition="!Exists('$(SolutionDir)\..\.git')" Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> <Reference Include="System.Web.Mvc"> <HintPath>..\..\..\packages\Microsoft.AspNet.Mvc.4.0.30506.0\lib\net40\System.Web.Mvc.dll</HintPath> </Reference> @@ -187,8 +189,6 @@ <Compile Include="Razor\EditorParserFixed\RazorResources.Designer.cs" /> <Compile Include="Projects\AspMvcProject.cs" /> <Compile Include="Projects\AspMvcProjectConfiguration.cs" /> - <Compile Include="Projects\AspNetAppProject.cs" /> - <Compile Include="Projects\AspNetAppProjectBinding.cs" /> <Compile Include="Projects\AspNetAppProjectConfiguration.cs" /> <Compile Include="Projects\AspNetMSBuildImportProvider.cs" /> <Compile Include="WebForms\MasterContentFileDescriptionTemplate.cs" /> @@ -290,6 +290,7 @@ <Compile Include="Razor\RazorCSharpParsedDocument.cs" /> <Compile Include="Razor\RazorPageInfo.cs" /> <Compile Include="WebForms\WebFormsTypeContext.cs" /> + <Compile Include="Projects\AspNetFlavor.cs" /> </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> @@ -490,10 +491,9 @@ </ItemGroup> <Target Name="BeforeBuild"> <PropertyGroup> - <NuGet>..\..\..\external\nuget-binary\NuGet.exe</NuGet> + <NuGet>$(SolutionDir)\external\nuget-binary\NuGet.exe</NuGet> <NuGet Condition="$(OS)=='Unix'">mono $(NuGet)</NuGet> - <SlnDir>..\..\..</SlnDir> </PropertyGroup> - <Exec Command="$(NuGet) restore -SolutionDirectory $(SlnDir)" /> + <Exec Condition="Exists('$(SolutionDir)\..\.git')" Command="$(NuGet) restore -SolutionDirectory $(SolutionDir)" /> </Target> </Project> diff --git a/main/src/addins/AspNet/ProjectPad/AspNetFolderNodeCommandHandler.cs b/main/src/addins/AspNet/ProjectPad/AspNetFolderNodeCommandHandler.cs index 30e870fccc..b6f5169fc6 100644 --- a/main/src/addins/AspNet/ProjectPad/AspNetFolderNodeCommandHandler.cs +++ b/main/src/addins/AspNet/ProjectPad/AspNetFolderNodeCommandHandler.cs @@ -31,7 +31,8 @@ using MonoDevelop.Ide.Gui.Components; using MonoDevelop.Ide.Gui.Pads.ProjectPad; using MonoDevelop.Ide; using MonoDevelop.AspNet.Projects;
-using MonoDevelop.AspNet.Commands; +using MonoDevelop.AspNet.Commands;
+using MonoDevelop.Projects; namespace MonoDevelop.AspNet.ProjectPad { @@ -40,8 +41,9 @@ namespace MonoDevelop.AspNet.ProjectPad [CommandUpdateHandler (AspNetCommands.AddController)] public void AddControllerUpdate (CommandInfo info) { - var project = CurrentNode.GetParentDataItem (typeof (AspNetAppProject), true) as AspNetAppProject; - if (project == null || !project.IsAspMvcProject) { + var project = CurrentNode.GetParentDataItem (typeof (DotNetProject), true) as DotNetProject;
+ var aspFlavor = project != null ? project.GetService<AspNetFlavor> () : null; + if (aspFlavor == null || !aspFlavor.IsAspMvcProject) { info.Enabled = info.Visible = false; return; } @@ -54,7 +56,7 @@ namespace MonoDevelop.AspNet.ProjectPad [CommandHandler (AspNetCommands.AddController)] public void AddController () { - var project = (AspNetAppProject) CurrentNode.GetParentDataItem (typeof (AspNetAppProject), true); + var project = (DotNetProject) CurrentNode.GetParentDataItem (typeof (DotNetProject), true); object currentItem = CurrentNode.DataItem;
@@ -68,7 +70,7 @@ namespace MonoDevelop.AspNet.ProjectPad nav.Expanded = true; } - public static void AddController (AspNetAppProject project, string path, string name) + public static void AddController (DotNetProject project, string path, string name) {
var provider = project.LanguageBinding.GetCodeDomProvider ();
if (provider == null)
@@ -119,15 +121,15 @@ namespace MonoDevelop.AspNet.ProjectPad if (System.IO.File.Exists (outputFile)) {
project.AddFile (outputFile);
- IdeApp.ProjectOperations.Save (project);
+ IdeApp.ProjectOperations.SaveAsync (project);
} } [CommandUpdateHandler (AspNetCommands.AddView)] public void AddViewUpdate (CommandInfo info) { - var project = CurrentNode.GetParentDataItem (typeof (AspNetAppProject), true) as AspNetAppProject; - if (project == null || !project.IsAspMvcProject) { + var project = CurrentNode.GetParentDataItem<DotNetProject> (true); + if (project == null || !project.HasFlavor<AspNetFlavor>() || !project.GetFlavor<AspNetFlavor>().IsAspMvcProject) { info.Enabled = info.Visible = false; return; } @@ -140,7 +142,7 @@ namespace MonoDevelop.AspNet.ProjectPad [CommandHandler (AspNetCommands.AddView)] public void AddView () { - var project = (AspNetAppProject) CurrentNode.GetParentDataItem (typeof (AspNetAppProject), true); + var project = CurrentNode.GetParentDataItem<DotNetProject> (true); object currentItem = CurrentNode.DataItem; diff --git a/main/src/addins/AspNet/ProjectPad/AspNetProjectNodeBuilderExtension.cs b/main/src/addins/AspNet/ProjectPad/AspNetProjectNodeBuilderExtension.cs index da125b8376..572f5e864b 100644 --- a/main/src/addins/AspNet/ProjectPad/AspNetProjectNodeBuilderExtension.cs +++ b/main/src/addins/AspNet/ProjectPad/AspNetProjectNodeBuilderExtension.cs @@ -29,6 +29,7 @@ using System; using MonoDevelop.Ide.Gui.Components; using MonoDevelop.AspNet.Projects; +using MonoDevelop.Projects; namespace MonoDevelop.AspNet.ProjectPad { @@ -36,7 +37,7 @@ namespace MonoDevelop.AspNet.ProjectPad { public override bool CanBuildNode (Type dataType) { - return typeof(AspNetAppProject).IsAssignableFrom (dataType); + return typeof(DotNetProject).IsAssignableFrom (dataType); } public override Type CommandHandlerType { diff --git a/main/src/addins/AspNet/ProjectPad/AspNetProjectNodeCommandHandler.cs b/main/src/addins/AspNet/ProjectPad/AspNetProjectNodeCommandHandler.cs index 3bf027f7c8..3373c62b1b 100644 --- a/main/src/addins/AspNet/ProjectPad/AspNetProjectNodeCommandHandler.cs +++ b/main/src/addins/AspNet/ProjectPad/AspNetProjectNodeCommandHandler.cs @@ -42,21 +42,25 @@ namespace MonoDevelop.AspNet.ProjectPad [CommandHandler (AspNetCommands.AddAspNetDirectory)] public void OnAddSpecialDirectory (object ob) { - AspNetAppProject proj = CurrentNode.DataItem as AspNetAppProject; + var proj = CurrentNode.DataItem as DotNetProject; if (proj == null) return; proj.AddDirectory ((string) ob); - IdeApp.ProjectOperations.Save (proj); + IdeApp.ProjectOperations.SaveAsync (proj); } [CommandUpdateHandler (AspNetCommands.AddAspNetDirectory)] public void OnAddSpecialDirectoryUpdate (CommandArrayInfo info) { - AspNetAppProject proj = CurrentNode.DataItem as AspNetAppProject; - if (proj == null) - return; - - List<string> dirs = new List<string> (proj.GetSpecialDirectories ()); + var proj = CurrentNode.DataItem as DotNetProject; + if (proj == null)
+ return;
+
+ var asp = proj.GetFlavor<AspNetFlavor> ();
+ if (asp == null)
+ return;
+ + List<string> dirs = new List<string> (asp.GetSpecialDirectories ()); dirs.Sort ();
List<FilePath> fullPaths = new List<FilePath> (dirs.Count); foreach (string s in dirs) diff --git a/main/src/addins/AspNet/Projects/AspMvcProject.cs b/main/src/addins/AspNet/Projects/AspMvcProject.cs index 8161c25ee2..9faf060a04 100644 --- a/main/src/addins/AspNet/Projects/AspMvcProject.cs +++ b/main/src/addins/AspNet/Projects/AspMvcProject.cs @@ -31,37 +31,21 @@ using MonoDevelop.Projects; namespace MonoDevelop.AspNet.Projects { - abstract class AspMvcProject : AspNetAppProject + abstract class AspMvcProject : AspNetFlavor { - protected AspMvcProject () - { - } - - protected AspMvcProject (string languageName) - : base (languageName) - { - } - - protected AspMvcProject (string languageName, ProjectCreateInformation info, XmlElement projectOptions) - : base (languageName, info, projectOptions) - { - } - - public override SolutionItemConfiguration CreateConfiguration (string name) + protected override SolutionItemConfiguration OnCreateConfiguration (string name) { var conf = new AspMvcProjectConfiguration (name); - conf.CopyFrom (base.CreateConfiguration (name)); + conf.CopyFrom (base.OnCreateConfiguration (name)); return conf; } - public override IEnumerable<string> GetProjectTypes () + protected override void OnGetProjectTypes (HashSet<string> types) { - yield return "AspNetMvc"; - foreach (var t in base.GetProjectTypes ()) - yield return t; + types.Add ("AspNetMvc"); } - public override bool SupportsFramework (MonoDevelop.Core.Assemblies.TargetFramework framework) + protected override bool OnGetSupportsFramework (MonoDevelop.Core.Assemblies.TargetFramework framework) { return framework.CanReferenceAssembliesTargetingFramework (MonoDevelop.Core.Assemblies.TargetFrameworkMoniker.NET_3_5); } @@ -75,20 +59,6 @@ namespace MonoDevelop.AspNet.Projects class AspMvc1Project : AspMvcProject
{
- public AspMvc1Project ()
- {
- }
-
- public AspMvc1Project (string languageName)
- : base (languageName)
- {
- }
-
- public AspMvc1Project (string languageName, ProjectCreateInformation info, XmlElement projectOptions)
- : base (languageName, info, projectOptions)
- {
- } - protected override string GetDefaultAspNetMvcVersion () { return "1.0.0.0"; @@ -97,20 +67,6 @@ namespace MonoDevelop.AspNet.Projects class AspMvc2Project : AspMvcProject
{
- public AspMvc2Project ()
- {
- }
-
- public AspMvc2Project (string languageName)
- : base (languageName)
- {
- }
-
- public AspMvc2Project (string languageName, ProjectCreateInformation info, XmlElement projectOptions)
- : base (languageName, info, projectOptions)
- {
- } - protected override string GetDefaultAspNetMvcVersion () { return "2.0.0.0"; @@ -119,21 +75,7 @@ namespace MonoDevelop.AspNet.Projects class AspMvc3Project : AspMvcProject
{
- public AspMvc3Project ()
- {
- }
-
- public AspMvc3Project (string languageName)
- : base (languageName)
- {
- }
-
- public AspMvc3Project (string languageName, ProjectCreateInformation info, XmlElement projectOptions)
- : base (languageName, info, projectOptions)
- {
- }
-
- public override bool SupportsFramework (MonoDevelop.Core.Assemblies.TargetFramework framework)
+ protected override bool OnGetSupportsFramework (MonoDevelop.Core.Assemblies.TargetFramework framework)
{
return framework.CanReferenceAssembliesTargetingFramework (MonoDevelop.Core.Assemblies.TargetFrameworkMoniker.NET_4_0);
} @@ -146,21 +88,7 @@ namespace MonoDevelop.AspNet.Projects class AspMvc4Project : AspMvcProject { - public AspMvc4Project () - { - } - - public AspMvc4Project (string languageName) - : base (languageName) - { - } - - public AspMvc4Project (string languageName, ProjectCreateInformation info, XmlElement projectOptions) - : base (languageName, info, projectOptions) - { - } - - public override bool SupportsFramework (MonoDevelop.Core.Assemblies.TargetFramework framework) + protected override bool OnGetSupportsFramework (MonoDevelop.Core.Assemblies.TargetFramework framework) { return framework.CanReferenceAssembliesTargetingFramework (MonoDevelop.Core.Assemblies.TargetFrameworkMoniker.NET_4_0); } diff --git a/main/src/addins/AspNet/Projects/AspNetAppProjectBinding.cs b/main/src/addins/AspNet/Projects/AspNetAppProjectBinding.cs deleted file mode 100644 index 3a89feac81..0000000000 --- a/main/src/addins/AspNet/Projects/AspNetAppProjectBinding.cs +++ /dev/null @@ -1,84 +0,0 @@ -// -// AspNetAppProjectBinding.cs: Project binding for AspNetAppProject -// -// Authors: -// Michael Hutchinson <m.j.hutchinson@gmail.com> -// -// Copyright (C) 2006 Michael Hutchinson -// -// -// This source code is licenced under The MIT License: -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.IO; -using MonoDevelop.Core; -using MonoDevelop.Projects; -using MonoDevelop.Core.Serialization; -using System.Xml; - -namespace MonoDevelop.AspNet.Projects -{ - //based heavily on DotNetProjectBinding - public class AspNetAppProjectBinding : IProjectBinding - { - - public string Name { - get { return "AspNetApp"; } - } - - public Project CreateProject (ProjectCreateInformation info, XmlElement projectOptions) - { - string lang = projectOptions.GetAttribute ("language"); - return CreateProject (lang, info, projectOptions); - } - - public Project CreateProject (string language, ProjectCreateInformation info, XmlElement projectOptions) - { - return new AspNetAppProject (language, info, projectOptions); - } - - public Project CreateSingleFileProject (string file) - { - //TODO: get page language - string language = "C#"; - - var info = new ProjectCreateInformation () { - ProjectName = Path.GetFileNameWithoutExtension (file), - SolutionPath = Path.GetDirectoryName (file), - ProjectBasePath = Path.GetDirectoryName (file), - }; - var project = CreateProject (language, info, null); - project.Files.Add (new ProjectFile (file)); - return project; - } - - public bool CanCreateSingleFileProject (string sourceFile) - { - WebSubtype type = AspNetAppProject.DetermineWebSubtype (sourceFile); - - return ((type == WebSubtype.WebForm) - || (type == WebSubtype.WebHandler) - || (type == WebSubtype.WebService)); - } - } -} diff --git a/main/src/addins/AspNet/Projects/AspNetAppProject.cs b/main/src/addins/AspNet/Projects/AspNetFlavor.cs index ef44893202..96902a8fdb 100644 --- a/main/src/addins/AspNet/Projects/AspNetAppProject.cs +++ b/main/src/addins/AspNet/Projects/AspNetFlavor.cs @@ -16,10 +16,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -49,148 +49,130 @@ using MonoDevelop.Ide.TypeSystem; using MonoDevelop.Projects; using MonoDevelop.AspNet.Execution; using MonoDevelop.AspNet.WebForms; +using System.Threading.Tasks; namespace MonoDevelop.AspNet.Projects { [DataInclude (typeof(AspNetAppProjectConfiguration))] - public class AspNetAppProject : DotNetAssemblyProject + public class AspNetFlavor : DotNetProjectExtension { [ItemProperty("XspParameters", IsExternal=true)] XspParameters xspParameters = new XspParameters (); WebFormsRegistrationCache registrationCache; WebFormsCodeBehindTypeNameCache codebehindTypeNameCache; - + #region properties - public override IEnumerable<string> GetProjectTypes () + protected override void OnGetProjectTypes (HashSet<string> types) { - yield return "AspNetApp"; - foreach (var t in base.GetProjectTypes ()) - yield return t; + types.Add ("AspNetApp"); } - public override bool IsLibraryBasedProjectType { + protected override bool IsLibraryBasedProjectType { get { return true; } } - + public XspParameters XspParameters { get { return xspParameters; } } - + internal WebFormsRegistrationCache RegistrationCache { get { if (registrationCache == null) - registrationCache = new WebFormsRegistrationCache (this); + registrationCache = new WebFormsRegistrationCache (Project); return registrationCache; } } - + #endregion - + #region constructors - - public AspNetAppProject () - { - Init (); - } - - public AspNetAppProject (string languageName) - : base (languageName) - { - Init (); - } - - public AspNetAppProject (string languageName, ProjectCreateInformation info, XmlElement projectOptions) - : base (languageName, info, projectOptions) + + protected override void OnInitializeNew (string languageName, ProjectCreateInformation info, XmlElement projectOptions) { - Init (); - + base.OnInitializeNew (languageName, info, projectOptions); + codebehindTypeNameCache = new WebFormsCodeBehindTypeNameCache (Project); + var binPath = info == null? (FilePath)"bin" : info.BinPath; - foreach (var cfg in Configurations.Cast<AspNetAppProjectConfiguration> ()) + foreach (var cfg in Project.Configurations.Cast<DotNetProjectConfiguration> ()) cfg.OutputDirectory = binPath; - } - - public override SolutionItemConfiguration CreateConfiguration (string name) + } + + protected override SolutionItemConfiguration OnCreateConfiguration (string name) { var conf = new AspNetAppProjectConfiguration (name); - conf.CopyFrom (base.CreateConfiguration (name)); - conf.OutputDirectory = BaseDirectory.IsNullOrEmpty? "bin" : (string)BaseDirectory.Combine ("bin"); + conf.CopyFrom (base.OnCreateConfiguration (name)); + conf.OutputDirectory = Project.BaseDirectory.IsNullOrEmpty? "bin" : (string)Project.BaseDirectory.Combine ("bin"); return conf; } - - void Init () - { - codebehindTypeNameCache = new WebFormsCodeBehindTypeNameCache (this); - } - public new AspNetAppProjectConfiguration GetConfiguration (ConfigurationSelector configuration) + public AspNetAppProjectConfiguration GetConfiguration (ConfigurationSelector configuration) { - return (AspNetAppProjectConfiguration) base.GetConfiguration (configuration); + return (AspNetAppProjectConfiguration) Project.GetConfiguration (configuration); } - + #endregion - + public override void Dispose () { codebehindTypeNameCache.Dispose (); RegistrationCache.Dispose (); base.Dispose (); } - + #region build/prebuild/execute - - - protected override BuildResult DoBuild (IProgressMonitor monitor, ConfigurationSelector configuration) + + + protected override Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { //if no files are set to compile, then some compilers will error out //though this is valid with ASP.NET apps, so we just avoid calling the compiler in this case bool needsCompile = false; - foreach (ProjectFile pf in Files) { + foreach (ProjectFile pf in Project.Files) { if (pf.BuildAction == BuildAction.Compile) { needsCompile = true; break; } } - + if (needsCompile) - return base.DoBuild (monitor, configuration); - return new BuildResult (); + return base.OnBuild (monitor, configuration); + return Task.FromResult (BuildResult.Success); } - + ExecutionCommand CreateExecutionCommand (ConfigurationSelector config, AspNetAppProjectConfiguration configuration) { return new AspNetExecutionCommand { ClrVersion = configuration.ClrVersion, DebugMode = configuration.DebugMode, XspParameters = XspParameters, - BaseDirectory = BaseDirectory, - TargetRuntime = TargetRuntime, - TargetFramework = TargetFramework, - UserAssemblyPaths = GetUserAssemblyPaths (config), + BaseDirectory = Project.BaseDirectory, + TargetRuntime = Project.TargetRuntime, + TargetFramework = Project.TargetFramework, + UserAssemblyPaths = Project.GetUserAssemblyPaths (config), EnvironmentVariables = configuration.EnvironmentVariables, }; } - + protected override bool OnGetCanExecute (ExecutionContext context, ConfigurationSelector configuration) { var cmd = CreateExecutionCommand (configuration, GetConfiguration (configuration)); return context.ExecutionHandler.CanExecute (cmd); } - - protected override void DoExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + + protected async override Task OnExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { //check XSP is available - + var cfg = GetConfiguration (configuration); var cmd = CreateExecutionCommand (configuration, cfg); var browserExcTarget = (BrowserExecutionTarget) context.ExecutionTarget; IConsole console = null; - var operationMonitor = new AggregatedOperationMonitor (monitor); bool isXsp = true; //FIXME: fix this when it might not be true - should delegate to the ExecutionHandler - + try { //HACK: check XSP exists first, because error UX is cleaner w/o displaying a blank console pad. if (isXsp) { @@ -211,8 +193,8 @@ namespace MonoDevelop.AspNet.Projects // The running Port value is now captured in the XspBrowserLauncherConsole object string url = String.Format ("http://{0}", XspParameters.Address); - - + + if (isXsp) { console = new XspBrowserLauncherConsole (console, delegate (string port) { if (browserExcTarget != null) @@ -221,53 +203,52 @@ namespace MonoDevelop.AspNet.Projects BrowserLauncher.LaunchDefaultBrowser (String.Format("{0}:{1}", url, port)); }); } - + monitor.Log.WriteLine ("Running web server..."); - + var op = context.ExecutionHandler.Execute (cmd, console); - operationMonitor.AddOperation (op); //handles cancellation - + if (!isXsp) { if (browserExcTarget != null) browserExcTarget.DesktopApp.Launch (url); else BrowserLauncher.LaunchDefaultBrowser (url); } - - op.WaitForCompleted (); - + + using (monitor.CancellationToken.Register (op.Cancel)) + await op.Task; + monitor.Log.WriteLine ("The web server exited with code: {0}", op.ExitCode); - + } catch (Exception ex) { if (!(ex is UserException)) { LoggingService.LogError ("Could not launch ASP.NET web server.", ex); } monitor.ReportError ("Could not launch web server.", ex); } finally { - operationMonitor.Dispose (); if (console != null) console.Dispose (); } } - + #endregion - + #region File utility methods - + public WebSubtype DetermineWebSubtype (ProjectFile file) { - if (LanguageBinding != null && LanguageBinding.IsSourceCodeFile (file.FilePath)) + if (Project.LanguageBinding != null && Project.LanguageBinding.IsSourceCodeFile (file.FilePath)) return WebSubtype.Code; return DetermineWebSubtype (file.Name); } - + public static WebSubtype DetermineWebSubtype (string fileName) { string extension = Path.GetExtension (fileName); if (extension == null) return WebSubtype.None; extension = extension.ToUpperInvariant ().TrimStart ('.'); - + //NOTE: No way to identify WebSubtype.Code from here //use the instance method for that switch (extension) { @@ -325,21 +306,21 @@ namespace MonoDevelop.AspNet.Projects return WebSubtype.None; } } - + #endregion - + #region special files - + #endregion - + public ProjectFile ResolveVirtualPath (string virtualPath, string relativeToFile) { string name = VirtualToLocalPath (virtualPath, relativeToFile); if (name == null) return null; - return Files.GetFile (name); + return Project.Files.GetFile (name); } - + public string VirtualToLocalPath (string virtualPath, string relativeToFile) { if (string.IsNullOrEmpty (virtualPath) || virtualPath [0] == '/' || virtualPath.IndexOf (':') > -1) @@ -351,60 +332,60 @@ namespace MonoDevelop.AspNet.Projects virtualPath = virtualPath.Substring (2); else virtualPath = virtualPath.Substring (1); - relativeToDir = BaseDirectory; + relativeToDir = Project.BaseDirectory; } else { relativeToDir = String.IsNullOrEmpty (relativeToFile) - ? BaseDirectory + ? Project.BaseDirectory : (FilePath) Path.GetDirectoryName (relativeToFile); } - + virtualPath = virtualPath.Replace ('/', Path.DirectorySeparatorChar); return relativeToDir.Combine (virtualPath).FullPath; } - + public string LocalToVirtualPath (string filename) { - string rel = FileService.AbsoluteToRelativePath (BaseDirectory, filename); + string rel = FileService.AbsoluteToRelativePath (Project.BaseDirectory, filename); return "~/" + rel.Replace (Path.DirectorySeparatorChar, '/'); } - + public string LocalToVirtualPath (ProjectFile file) { return LocalToVirtualPath (file.FilePath); } - + #region Reference handling - + protected override void OnReferenceAddedToProject (ProjectReferenceEventArgs e) { //short-circuit if the project is being deserialised - if (Loading) { + if (Project.Loading) { base.OnReferenceAddedToProject (e); return; } - + UpdateWebConfigRefs (); - + base.OnReferenceAddedToProject (e); } - + protected override void OnReferenceRemovedFromProject (ProjectReferenceEventArgs e) { //short-circuit if the project is being deserialised - if (Loading) { + if (Project.Loading) { base.OnReferenceAddedToProject (e); return; } - + UpdateWebConfigRefs (); - + base.OnReferenceRemovedFromProject (e); } - + void UpdateWebConfigRefs () { var refs = new List<string> (); - foreach (var reference in References) { + foreach (var reference in Project.References) { //local copied assemblies are copied to the bin directory so ASP.NET references them automatically if (reference.LocalCopy && (reference.ReferenceType == ReferenceType.Project || reference.ReferenceType == ReferenceType.Assembly)) continue; @@ -419,39 +400,39 @@ namespace MonoDevelop.AspNet.Projects continue; refs.Add (reference.Reference); } - + var webConfig = GetWebConfig (); if (webConfig == null || !File.Exists (webConfig.FilePath)) return; - + var textFile = TextFileProvider.Instance.GetEditableTextFile (webConfig.FilePath); //use textfile API because it's write safe (writes out to another file then moves) if (textFile == null) textFile = MonoDevelop.Projects.Text.TextFile.ReadFile (webConfig.FilePath); - + //can't use System.Web.Configuration.WebConfigurationManager, as it can only access virtual paths within an app //so need full manual handling try { var doc = new XmlDocument (); - + //FIXME: PreserveWhitespace doesn't handle whitespace in attribute lists //doc.PreserveWhitespace = true; doc.LoadXml (textFile.Text); - + //hunt our way to the assemblies element, creating elements if necessary XmlElement configElement = doc.DocumentElement; if (configElement == null || string.Compare (configElement.Name, "configuration", StringComparison.OrdinalIgnoreCase) != 0) { configElement = (XmlElement) doc.AppendChild (doc.CreateNode (XmlNodeType.Document, "configuration", null)); } - XmlElement webElement = GetNamedXmlElement (doc, configElement, "system.web"); + XmlElement webElement = GetNamedXmlElement (doc, configElement, "system.web"); XmlElement compilationNode = GetNamedXmlElement (doc, webElement, "compilation"); XmlElement assembliesNode = GetNamedXmlElement (doc, compilationNode, "assemblies"); - + List<XmlNode> existingAdds = new List<XmlNode> (); foreach (XmlNode node in assembliesNode) if (string.Compare (node.Name, "add", StringComparison.OrdinalIgnoreCase) == 0) existingAdds.Add (node); - + //add refs to the doc if they're not in it foreach (string reference in refs) { int index = 0; @@ -477,27 +458,27 @@ namespace MonoDevelop.AspNet.Projects assembliesNode.AppendChild (newAdd); } } - + //any nodes that weren't removed from the existingAdds list are old/redundant, so remove from doc foreach (XmlNode node in existingAdds) assembliesNode.RemoveChild (node); - + StringWriter sw = new StringWriter (); XmlTextWriter tw = new XmlTextWriter (sw); tw.Formatting = Formatting.Indented; doc.WriteTo (tw); tw.Flush (); textFile.Text = sw.ToString (); - + MonoDevelop.Projects.Text.TextFile tf = textFile as MonoDevelop.Projects.Text.TextFile; if (tf != null) tf.Save (); } catch (Exception e) { - LoggingService.LogWarning ("Could not modify application web.config in project " + Name, e); + LoggingService.LogWarning ("Could not modify application web.config in project " + Project.Name, e); } } - - + + XmlElement GetNamedXmlElement (XmlDocument doc, XmlElement parent, string name) { XmlElement result = null; @@ -513,78 +494,78 @@ namespace MonoDevelop.AspNet.Projects } return result; } - + ProjectFile GetWebConfig () { - var webConf = BaseDirectory.Combine ("web.config"); - foreach (var file in Files) + var webConf = Project.BaseDirectory.Combine ("web.config"); + foreach (var file in Project.Files) if (string.Compare (file.FilePath.ToString (), webConf, StringComparison.OrdinalIgnoreCase) == 0) return file; return null; } - + bool IsWebConfig (FilePath file) { - var webConf = BaseDirectory.Combine ("web.config"); + var webConf = Project.BaseDirectory.Combine ("web.config"); return (string.Compare (file, webConf, StringComparison.OrdinalIgnoreCase) == 0); } - + #endregion - + #region File event handlers - + protected override void OnFileAddedToProject (ProjectFileEventArgs e) { //short-circuit if the project is being deserialised - if (Loading) { + if (Project.Loading) { base.OnFileAddedToProject (e); return; } bool webConfigChange = false; List<string> filesToAdd = new List<string> (); - + foreach (ProjectFileEventInfo fargs in e) { IEnumerable<string> files = MonoDevelop.DesignerSupport.CodeBehind.GuessDependencies - (this, fargs.ProjectFile, groupedExtensions); + (Project, fargs.ProjectFile, groupedExtensions); if (files != null) filesToAdd.AddRange (files); if (IsWebConfig (fargs.ProjectFile.FilePath)) webConfigChange = true; } - + if (webConfigChange) UpdateWebConfigRefs (); - + //let the base fire the event before we add files //don't want to fire events out of order of files being added base.OnFileAddedToProject (e); - + //make sure that the parent and child files are in the project foreach (string file in filesToAdd) { //NOTE: this only adds files if they are not already in the project - AddFile (file); + Project.AddFile (file); } } - - public override string GetDefaultBuildAction (string fileName) + + protected override string OnGetDefaultBuildAction (string fileName) { - + WebSubtype type = DetermineWebSubtype (fileName); switch (type) { case WebSubtype.Code: return BuildAction.Compile; case WebSubtype.None: - return base.GetDefaultBuildAction (fileName); + return base.OnGetDefaultBuildAction (fileName); default: return BuildAction.Content; } } - + static string[] groupedExtensions = { ".aspx", ".master", ".ashx", ".ascx", ".asmx", ".asax" }; - + #endregion - + public virtual IEnumerable<string> GetSpecialDirectories () { yield return "App_Browsers"; @@ -598,12 +579,12 @@ namespace MonoDevelop.AspNet.Projects yield return "Models"; yield return "Controllers"; } - + // For "web site" projects // "App_WebReferences", "App_Resources","App_Themes", "App_Code", } - - protected override IList<string> GetCommonBuildActions () + + protected override IList<string> OnGetCommonBuildActions () { return new [] { BuildAction.None, @@ -612,7 +593,7 @@ namespace MonoDevelop.AspNet.Projects BuildAction.EmbeddedResource, }; } - + public string GetCodebehindTypeName (string fileName) { lock (codebehindTypeNameCache) @@ -624,8 +605,8 @@ namespace MonoDevelop.AspNet.Projects var files = new List<string> (); var names = new HashSet<string> (); - string asmDir = Path.GetDirectoryName (typeof (AspNetAppProject).Assembly.Location); - string lang = LanguageName; + string asmDir = Path.GetDirectoryName (GetType().Assembly.Location); + string lang = Project.LanguageName; if (lang == "C#") { lang = "CSharp"; } @@ -635,8 +616,8 @@ namespace MonoDevelop.AspNet.Projects } var dirs = new [] { - Path.Combine (BaseDirectory, "CodeTemplates", type), - Path.Combine (BaseDirectory, "CodeTemplates", lang, type), + Path.Combine (Project.BaseDirectory, "CodeTemplates", type), + Path.Combine (Project.BaseDirectory, "CodeTemplates", lang, type), Path.Combine (asmDir, "CodeTemplates", type), Path.Combine (asmDir, "CodeTemplates", lang, type), }; @@ -650,12 +631,12 @@ namespace MonoDevelop.AspNet.Projects return files; } - protected override void PopulateSupportFileList (FileCopySet list, ConfigurationSelector configuration) + protected override void OnPopulateSupportFileList (FileCopySet list, ConfigurationSelector configuration) { - base.PopulateSupportFileList (list, configuration); + base.OnPopulateSupportFileList (list, configuration); //HACK: workaround for MD not local-copying package references - foreach (MonoDevelop.Projects.ProjectReference projectReference in References) { + foreach (MonoDevelop.Projects.ProjectReference projectReference in Project.References) { if (projectReference.Package != null && projectReference.Package.Name == "system.web.mvc") { if (projectReference.ReferenceType == ReferenceType.Package) foreach (SystemAssembly assem in projectReference.Package.Assemblies) @@ -667,7 +648,7 @@ namespace MonoDevelop.AspNet.Projects public string GetAspNetMvcVersion () { - foreach (var pref in References) { + foreach (var pref in Project.References) { if (pref.Reference.IndexOf ("System.Web.Mvc", StringComparison.OrdinalIgnoreCase) < 0) continue; switch (pref.ReferenceType) { @@ -692,7 +673,7 @@ namespace MonoDevelop.AspNet.Projects public bool SupportsRazorViewEngine { get { - return References.Any (r => r.Reference.StartsWith ("System.Web.WebPages.Razor", StringComparison.Ordinal)); + return Project.References.Any (r => r.Reference.StartsWith ("System.Web.WebPages.Razor", StringComparison.Ordinal)); } } @@ -703,7 +684,7 @@ namespace MonoDevelop.AspNet.Projects public virtual bool IsAspMvcProject { get { - return References.Any (r => r.Reference.StartsWith ("System.Web.Mvc", StringComparison.Ordinal)); + return Project.References.Any (r => r.Reference.StartsWith ("System.Web.Mvc", StringComparison.Ordinal)); } } diff --git a/main/src/addins/AspNet/Projects/AspNetMvcFileTemplateCondition.cs b/main/src/addins/AspNet/Projects/AspNetMvcFileTemplateCondition.cs index 0a4f581ad1..58a71c5371 100644 --- a/main/src/addins/AspNet/Projects/AspNetMvcFileTemplateCondition.cs +++ b/main/src/addins/AspNet/Projects/AspNetMvcFileTemplateCondition.cs @@ -50,7 +50,7 @@ namespace MonoDevelop.AspNet.Projects if (proj == null)
return true;
- var aspProj = proj as AspNetAppProject;
+ var aspProj = proj.GetFlavor<AspNetFlavor> ();
if (aspProj == null)
return false;
diff --git a/main/src/addins/AspNet/Properties/MonoDevelop.AspNet.addin.xml b/main/src/addins/AspNet/Properties/MonoDevelop.AspNet.addin.xml index 17406e444f..a6f13d0f3d 100644 --- a/main/src/addins/AspNet/Properties/MonoDevelop.AspNet.addin.xml +++ b/main/src/addins/AspNet/Properties/MonoDevelop.AspNet.addin.xml @@ -178,32 +178,23 @@ extensions = "*.htm,*.html"/>
</Extension>
- <Extension path = "/MonoDevelop/ProjectModel/ProjectBindings">
- <ProjectBinding id = "AspNetApp" class = "MonoDevelop.AspNet.Projects.AspNetAppProjectBinding" />
- </Extension>
-
- <Extension path = "/MonoDevelop/ProjectModel/MSBuildItemTypes">
- <DotNetProjectSubtype
+ <Extension path = "/MonoDevelop/ProjectModel/ProjectModelExtensions">
+ <ProjectExtension
guid="{603C0E0B-DB56-11DC-BE95-000D561079B0}"
- type="MonoDevelop.AspNet.Projects.AspMvc1Project"
- useXBuild="true" />
- <DotNetProjectSubtype
+ type="MonoDevelop.AspNet.Projects.AspMvc1ProjectExtension" />
+ <ProjectExtension
guid="{F85E285D-A4E0-4152-9332-AB1D724D3325}"
- type="MonoDevelop.AspNet.Projects.AspMvc2Project"
- useXBuild="true" />
- <DotNetProjectSubtype
+ type="MonoDevelop.AspNet.Projects.AspMvc2ProjectExtension" />
+ <ProjectExtension
guid="{E53F8FEA-EAE0-44A6-8774-FFD645390401}"
- type="MonoDevelop.AspNet.Projects.AspMvc3Project"
- useXBuild="true" />
- <DotNetProjectSubtype
+ type="MonoDevelop.AspNet.Projects.AspMvc3ProjectExtension" />
+ <ProjectExtension
guid="{E3E379DF-F4C6-4180-9B81-6769533ABE47}"
- type="MonoDevelop.AspNet.Projects.AspMvc4Project"
- useXBuild="true" />
- <DotNetProjectSubtype
- id="MonoDevelop.AspNet.Projects.AspNetAppProject"
+ type="MonoDevelop.AspNet.Projects.AspMvc4ProjectExtension" />
+ <ProjectExtension
+ id="MonoDevelop.AspNet.Projects.AspNetAppProjectExtension"
guid="{349C5851-65DF-11DA-9384-00065B846F21}"
- type="MonoDevelop.AspNet.Projects.AspNetAppProject"
- useXBuild="true" />
+ type="MonoDevelop.AspNet.Projects.AspNetAppProjectExtension" />
</Extension>
<Extension path = "/MonoDevelop/TypeSystem/Parser">
@@ -217,7 +208,7 @@ </Extension>
<Extension path = "/MonoDevelop/ProjectModel/Gui/ItemOptionPanels/Run">
- <Condition id="ItemType" value="MonoDevelop.AspNet.Projects.AspNetAppProject">
+ <Condition id="FlavorType" value="MonoDevelop.AspNet.Projects.AspNetFlavor">
<Section id = "XspOptions"
_label = "XSP Web Server"
class = "MonoDevelop.AspNet.Execution.XspOptionsPanel"/>
@@ -262,11 +253,9 @@ </Extension>
<Extension path = "/MonoDevelop/Ide/ContextMenu/ProjectPad/Add">
- <Condition id="ItemType" value="MonoDevelop.AspNet.Projects.AspNetAppProject">
- <ItemSet id = "AspNetDirectories" _label = "ASP.NET Directory" insertafter = "MonoDevelop.Ide.Commands.ProjectCommands.NewFolder" autohide = "true">
- <CommandItem id = "MonoDevelop.AspNet.Commands.AspNetCommands.AddAspNetDirectory" />
- </ItemSet>
- </Condition>
+ <ItemSet id = "AspNetDirectories" _label = "ASP.NET Directory" insertafter = "MonoDevelop.Ide.Commands.ProjectCommands.NewFolder" autohide = "true">
+ <CommandItem id = "MonoDevelop.AspNet.Commands.AspNetCommands.AddAspNetDirectory" />
+ </ItemSet>
</Extension>
<Extension path = "/MonoDevelop/Ide/ContextMenu/ProjectPad/Add">
diff --git a/main/src/addins/AspNet/Razor/Generator/RazorTemplatePreprocessor.cs b/main/src/addins/AspNet/Razor/Generator/RazorTemplatePreprocessor.cs index 32a8a31ff2..41d105e862 100644 --- a/main/src/addins/AspNet/Razor/Generator/RazorTemplatePreprocessor.cs +++ b/main/src/addins/AspNet/Razor/Generator/RazorTemplatePreprocessor.cs @@ -30,6 +30,7 @@ using System.CodeDom.Compiler; using MonoDevelop.Projects; using MonoDevelop.Core; using MonoDevelop.TextTemplating; +using System.Threading.Tasks; namespace MonoDevelop.AspNet.Razor.Generator { @@ -46,18 +47,18 @@ namespace MonoDevelop.AspNet.Razor.Generator return ns; } - public IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) + public Task Generate (ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { - return new ThreadAsyncOperation (delegate { + return Task.Factory.StartNew (delegate { try { GenerateInternal (monitor, file, result); } catch (Exception ex) { result.UnhandledException = ex; } - }, result); + }); } - void GenerateInternal (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) + void GenerateInternal (ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { var dnp = file.Project as DotNetProject; if (dnp == null || dnp.LanguageName != "C#") { diff --git a/main/src/addins/AspNet/Razor/RazorCSharpParser.cs b/main/src/addins/AspNet/Razor/RazorCSharpParser.cs index ac77e93f69..390e00e819 100644 --- a/main/src/addins/AspNet/Razor/RazorCSharpParser.cs +++ b/main/src/addins/AspNet/Razor/RazorCSharpParser.cs @@ -64,7 +64,7 @@ namespace MonoDevelop.AspNet.Razor ChangeInfo lastChange; string lastParsedFile; TextDocument currentDocument; - AspNetAppProject aspProject; + AspNetFlavor aspProject; DotNetProject project; IList<TextDocument> openDocuments; @@ -90,7 +90,7 @@ namespace MonoDevelop.AspNet.Razor if (currentDocument == null && !TryAddDocument (fileName)) return new RazorCSharpParsedDocument (fileName, new RazorCSharpPageInfo ()); - this.aspProject = project as AspNetAppProject; + this.aspProject = project.GetService<AspNetFlavor> (); EnsureParserInitializedFor (fileName); @@ -211,7 +211,7 @@ namespace MonoDevelop.AspNet.Razor // Try to create host using web.config file var webConfigMap = new WebConfigurationFileMap (); if (aspProject != null) { - var vdm = new VirtualDirectoryMapping (aspProject.BaseDirectory.Combine ("Views"), true, "web.config"); + var vdm = new VirtualDirectoryMapping (project.BaseDirectory.Combine ("Views"), true, "web.config"); webConfigMap.VirtualDirectories.Add ("/", vdm); } Configuration configuration; diff --git a/main/src/addins/AspNet/Tests/Razor/RazorCompletionTesting.cs b/main/src/addins/AspNet/Tests/Razor/RazorCompletionTesting.cs index 7da98546eb..d35f5f9ca5 100644 --- a/main/src/addins/AspNet/Tests/Razor/RazorCompletionTesting.cs +++ b/main/src/addins/AspNet/Tests/Razor/RazorCompletionTesting.cs @@ -92,7 +92,7 @@ namespace MonoDevelop.AspNet.Tests.Razor cursorPosition = endPos - 1;
}
- var project = new AspNetAppProject ("C#");
+ var project = Services.ProjectService.CreateDotNetProject ("C#");
project.FileName = UnitTests.TestBase.GetTempFile (".csproj");
string file = UnitTests.TestBase.GetTempFile (extension);
diff --git a/main/src/addins/AspNet/Tests/WebForms/WebFormsTesting.cs b/main/src/addins/AspNet/Tests/WebForms/WebFormsTesting.cs index 4f8e2444d9..74f486803c 100644 --- a/main/src/addins/AspNet/Tests/WebForms/WebFormsTesting.cs +++ b/main/src/addins/AspNet/Tests/WebForms/WebFormsTesting.cs @@ -69,7 +69,7 @@ namespace MonoDevelop.AspNet.Tests.WebForms cursorPosition = endPos - 1; } - var project = new AspNetAppProject ("C#"); + var project = Services.ProjectService.CreateDotNetProject ("C#"); project.References.Add (new ProjectReference (ReferenceType.Package, "System")); project.References.Add (new ProjectReference (ReferenceType.Package, "System.Web")); project.FileName = UnitTests.TestBase.GetTempFile (".csproj"); diff --git a/main/src/addins/AspNet/WebForms/MasterContentFileDescriptionTemplate.cs b/main/src/addins/AspNet/WebForms/MasterContentFileDescriptionTemplate.cs index bced906b6d..8ca2ded55d 100644 --- a/main/src/addins/AspNet/WebForms/MasterContentFileDescriptionTemplate.cs +++ b/main/src/addins/AspNet/WebForms/MasterContentFileDescriptionTemplate.cs @@ -38,7 +38,7 @@ namespace MonoDevelop.AspNet.WebForms { public class MasterContentFileDescriptionTemplate : SingleFileDescriptionTemplate { - public override void ModifyTags (SolutionItem policyParent, Project project, string language, string identifier, string fileName, ref Dictionary<string,string> tags) + public override void ModifyTags (SolutionFolderItem policyParent, Project project, string language, string identifier, string fileName, ref Dictionary<string,string> tags) { base.ModifyTags (policyParent, project, language, identifier, fileName, ref tags); if (fileName == null) @@ -47,13 +47,13 @@ namespace MonoDevelop.AspNet.WebForms tags ["AspNetMaster"] = ""; tags ["AspNetMasterContent"] = ""; - AspNetAppProject aspProj = project as AspNetAppProject; + var aspProj = project.GetService<AspNetFlavor> (); if (aspProj == null) throw new InvalidOperationException ("MasterContentFileDescriptionTemplate is only valid for ASP.NET projects"); ProjectFile masterPage = null; - var dialog = new MonoDevelop.Ide.Projects.ProjectFileSelectorDialog (aspProj, null, "*.master"); + var dialog = new MonoDevelop.Ide.Projects.ProjectFileSelectorDialog (project, null, "*.master"); try { dialog.Title = GettextCatalog.GetString ("Select a Master Page..."); int response = MonoDevelop.Ide.MessageService.RunCustomDialog (dialog); diff --git a/main/src/addins/AspNet/WebForms/WebFormsCodeBehind.cs b/main/src/addins/AspNet/WebForms/WebFormsCodeBehind.cs index bfdce9399f..ed1977dc84 100644 --- a/main/src/addins/AspNet/WebForms/WebFormsCodeBehind.cs +++ b/main/src/addins/AspNet/WebForms/WebFormsCodeBehind.cs @@ -47,7 +47,7 @@ namespace MonoDevelop.AspNet.WebForms { public static string GetCodeBehindClassName (ProjectFile file) { - AspNetAppProject proj = file.Project as AspNetAppProject; + var proj = file.Project.GetService<AspNetFlavor> (); if (proj == null) return null; return proj.GetCodebehindTypeName (file.Name); @@ -55,19 +55,19 @@ namespace MonoDevelop.AspNet.WebForms public static ProjectFile GetDesignerFile (ProjectFile file) { - var project = file.Project as AspNetAppProject; + var ext = file.Project.GetService<AspNetFlavor> (); - var type = AspNetAppProject.DetermineWebSubtype (file.FilePath); + var type = AspNetFlavor.DetermineWebSubtype (file.FilePath); if (type != WebSubtype.WebForm && type != WebSubtype.WebControl && type != WebSubtype.MasterPage) return null; - var dfName = project.LanguageBinding.GetFileName (file.FilePath + ".designer"); - return project.Files.GetFile (dfName); + var dfName = ext.Project.LanguageBinding.GetFileName (file.FilePath + ".designer"); + return ext.Project.Files.GetFile (dfName); } public static BuildResult UpdateDesignerFile ( CodeBehindWriter writer, - AspNetAppProject project, + DotNetProject project, ProjectFile file, ProjectFile designerFile ) { @@ -102,7 +102,7 @@ namespace MonoDevelop.AspNet.WebForms } public static BuildResult GenerateCodeBehind ( - AspNetAppProject project, + DotNetProject project, string filename, WebFormsParsedDocument document, out CodeCompileUnit ccu) @@ -149,7 +149,8 @@ namespace MonoDevelop.AspNet.WebForms masterTypeName = document.Info.MasterPageTypeName; } else if (!String.IsNullOrEmpty (document.Info.MasterPageTypeVPath)) { try { - ProjectFile resolvedMaster = project.ResolveVirtualPath (document.Info.MasterPageTypeVPath, document.FileName); + var ext = project.GetService<AspNetFlavor> (); + ProjectFile resolvedMaster = ext.ResolveVirtualPath (document.Info.MasterPageTypeVPath, document.FileName); WebFormsParsedDocument masterParsedDocument = null; if (resolvedMaster != null) masterParsedDocument = TypeSystemService.ParseFile (project, resolvedMaster.FilePath) as WebFormsParsedDocument; diff --git a/main/src/addins/AspNet/WebForms/WebFormsCodeBehindTypeNameCache.cs b/main/src/addins/AspNet/WebForms/WebFormsCodeBehindTypeNameCache.cs index 526911a74f..c5088a67b6 100644 --- a/main/src/addins/AspNet/WebForms/WebFormsCodeBehindTypeNameCache.cs +++ b/main/src/addins/AspNet/WebForms/WebFormsCodeBehindTypeNameCache.cs @@ -31,13 +31,14 @@ using MonoDevelop.Core; using MonoDevelop.Ide.TypeSystem; using MonoDevelop.Ide; using MonoDevelop.AspNet.WebForms;
-using MonoDevelop.AspNet.Projects; +using MonoDevelop.AspNet.Projects;
+using MonoDevelop.Projects; namespace MonoDevelop.AspNet.WebForms { - class WebFormsCodeBehindTypeNameCache : ProjectFileCache<AspNetAppProject,string> + class WebFormsCodeBehindTypeNameCache : ProjectFileCache<Project,string> { - public WebFormsCodeBehindTypeNameCache (AspNetAppProject proj) : base (proj) + public WebFormsCodeBehindTypeNameCache (Project proj) : base (proj) { } diff --git a/main/src/addins/AspNet/WebForms/WebFormsDirectiveCompletion.cs b/main/src/addins/AspNet/WebForms/WebFormsDirectiveCompletion.cs index 54839d53ae..a7ded63cf7 100644 --- a/main/src/addins/AspNet/WebForms/WebFormsDirectiveCompletion.cs +++ b/main/src/addins/AspNet/WebForms/WebFormsDirectiveCompletion.cs @@ -36,6 +36,7 @@ using System.Web.UI; using MonoDevelop.Core; using MonoDevelop.Ide.CodeCompletion; using MonoDevelop.AspNet.Projects; +using MonoDevelop.Projects; namespace MonoDevelop.AspNet.WebForms { @@ -94,7 +95,7 @@ namespace MonoDevelop.AspNet.WebForms } - public static CompletionDataList GetAttributeValues (AspNetAppProject project, FilePath fromFile, string directiveName, string attribute) + public static CompletionDataList GetAttributeValues (DotNetProject project, FilePath fromFile, string directiveName, string attribute) { switch (directiveName.ToLowerInvariant ()) { case "page": @@ -105,7 +106,7 @@ namespace MonoDevelop.AspNet.WebForms return null; } - public static CompletionDataList GetAttributes (AspNetAppProject project, string directiveName, + public static CompletionDataList GetAttributes (DotNetProject project, string directiveName, Dictionary<string, string> existingAtts) { var list = new CompletionDataList (); @@ -199,7 +200,7 @@ namespace MonoDevelop.AspNet.WebForms list.Add (s); } - static CompletionDataList GetPageAttributeValues (AspNetAppProject project, FilePath fromFile, string attribute) + static CompletionDataList GetPageAttributeValues (Project project, FilePath fromFile, string attribute) { var list = new CompletionDataList (); switch (attribute.ToLowerInvariant ()) { @@ -346,7 +347,7 @@ namespace MonoDevelop.AspNet.WebForms return list.Count > 0? list : null; } - static CompletionDataList GetRegisterAttributeValues (AspNetAppProject project, FilePath fromFile, string attribute) + static CompletionDataList GetRegisterAttributeValues (Project project, FilePath fromFile, string attribute) { switch (attribute.ToLowerInvariant ()) { case "src": diff --git a/main/src/addins/AspNet/WebForms/WebFormsEditorExtension.cs b/main/src/addins/AspNet/WebForms/WebFormsEditorExtension.cs index 96a0239b78..bc2cc3ef64 100644 --- a/main/src/addins/AspNet/WebForms/WebFormsEditorExtension.cs +++ b/main/src/addins/AspNet/WebForms/WebFormsEditorExtension.cs @@ -48,6 +48,7 @@ using S = MonoDevelop.Xml.Parser; using MonoDevelop.AspNet.WebForms.Dom; using MonoDevelop.Xml.Parser; using MonoDevelop.Xml.Dom; +using MonoDevelop.Projects; namespace MonoDevelop.AspNet.WebForms { @@ -56,7 +57,7 @@ namespace MonoDevelop.AspNet.WebForms static readonly Regex DocTypeRegex = new Regex (@"(?:PUBLIC|public)\s+""(?<fpi>[^""]*)""\s+""(?<uri>[^""]*)"""); WebFormsParsedDocument aspDoc; - AspNetAppProject project; + DotNetProject project; WebFormsTypeContext refman = new WebFormsTypeContext (); ILanguageCompletionBuilder documentBuilder; @@ -90,7 +91,7 @@ namespace MonoDevelop.AspNet.WebForms if (HasDoc) refman.Doc = aspDoc; - var newProj = Document.Project as AspNetAppProject; + var newProj = Document.Project as DotNetProject; if (newProj != null) { project = newProj; refman.Project = newProj; diff --git a/main/src/addins/AspNet/WebForms/WebFormsParser.cs b/main/src/addins/AspNet/WebForms/WebFormsParser.cs index 03f19b91be..f29967ff7d 100644 --- a/main/src/addins/AspNet/WebForms/WebFormsParser.cs +++ b/main/src/addins/AspNet/WebForms/WebFormsParser.cs @@ -67,7 +67,7 @@ namespace MonoDevelop.AspNet.WebForms XDocument xDoc = parser.Nodes.GetRoot (); info.Populate (xDoc, errors); - var type = AspNetAppProject.DetermineWebSubtype (fileName); + var type = AspNetFlavor.DetermineWebSubtype (fileName); if (type != info.Subtype) { if (info.Subtype == WebSubtype.None) { errors.Add (new Error (ErrorType.Error, "File directive is missing", 1, 1)); diff --git a/main/src/addins/AspNet/WebForms/WebFormsRegistrationCache.cs b/main/src/addins/AspNet/WebForms/WebFormsRegistrationCache.cs index ac1a6ccb6c..494eae7723 100644 --- a/main/src/addins/AspNet/WebForms/WebFormsRegistrationCache.cs +++ b/main/src/addins/AspNet/WebForms/WebFormsRegistrationCache.cs @@ -38,9 +38,9 @@ using MonoDevelop.AspNet.Projects; namespace MonoDevelop.AspNet.WebForms { - class WebFormsRegistrationCache : ProjectFileCache<AspNetAppProject,RegistrationInfo> + class WebFormsRegistrationCache : ProjectFileCache<DotNetProject,RegistrationInfo> { - public WebFormsRegistrationCache (AspNetAppProject project) : base (project) + public WebFormsRegistrationCache (DotNetProject project) : base (project) { } @@ -135,6 +135,16 @@ namespace MonoDevelop.AspNet.WebForms info.Namespaces.AddRange (defaultNamespaces.Select (ns => new NamespaceRegistration (true, ns))); info.Assemblies.AddRange (defaultAssemblies.Select (asm => new AssemblyRegistration (true, asm))); + + // from Mono's 4.5 machine web.config + info.Controls.AddRange (new [] { + MachineControlReg ("asp", "System.Web.UI.WebControls.WebParts", "System.Web"), + MachineControlReg ("asp", "System.Web.UI", "System.Web.Extensions"), + MachineControlReg ("asp", "System.Web.UI.WebControls", "System.Web.Extensions"), + MachineControlReg ("asp", "System.Web.UI.WebControls.Expressions", "System.Web.Extensions"), + MachineControlReg ("asp", "System.Web.DynamicData", "System.Web.DynamicData"), + MachineControlReg ("asp", "System.Web.UI.WebControls", "System.Web.Entity"), + }); return info; } @@ -171,6 +181,11 @@ namespace MonoDevelop.AspNet.WebForms "System.Web.UI.WebControls.WebParts", }; + static ControlRegistration MachineControlReg(string prefix, string ns, string asm) + { + return new ControlRegistration (null, true, prefix, ns, asm, null, null); + } + public static bool IsDefaultReference (string reference) { return defaultAssemblies.Any (r => diff --git a/main/src/addins/AspNet/WebForms/WebFormsToolboxNode.cs b/main/src/addins/AspNet/WebForms/WebFormsToolboxNode.cs index 6ccccbddc5..f0804abf65 100644 --- a/main/src/addins/AspNet/WebForms/WebFormsToolboxNode.cs +++ b/main/src/addins/AspNet/WebForms/WebFormsToolboxNode.cs @@ -157,7 +157,7 @@ namespace MonoDevelop.AspNet.WebForms public bool IsCompatibleWith (MonoDevelop.Ide.Gui.Document document)
{ - switch (AspNetAppProject.DetermineWebSubtype (document.FileName)) { + switch (AspNetFlavor.DetermineWebSubtype (document.FileName)) { case WebSubtype.WebForm: case WebSubtype.MasterPage: case WebSubtype.WebControl: @@ -167,7 +167,7 @@ namespace MonoDevelop.AspNet.WebForms } var clrVersion = ClrVersion.Net_2_0; - var aspProj = document.Project as AspNetAppProject; + var aspProj = document.Project as DotNetProject; if (aspProj != null && aspProj.TargetFramework.ClrVersion != ClrVersion.Default) clrVersion = aspProj.TargetFramework.ClrVersion; diff --git a/main/src/addins/AspNet/WebForms/WebFormsTypeContext.cs b/main/src/addins/AspNet/WebForms/WebFormsTypeContext.cs index 7778cf5844..5af1c706a6 100644 --- a/main/src/addins/AspNet/WebForms/WebFormsTypeContext.cs +++ b/main/src/addins/AspNet/WebForms/WebFormsTypeContext.cs @@ -51,8 +51,9 @@ namespace MonoDevelop.AspNet.WebForms public class WebFormsTypeContext { ICompilation compilation; - AspNetAppProject project; + DotNetProject project; WebFormsParsedDocument doc; + AspNetFlavor aspFlavor; public WebFormsParsedDocument Doc { get { @@ -66,7 +67,7 @@ namespace MonoDevelop.AspNet.WebForms } } - public AspNetAppProject Project { + public DotNetProject Project { get { return project; } @@ -75,6 +76,7 @@ namespace MonoDevelop.AspNet.WebForms return; project = value; compilation = null; + aspFlavor = project.GetFlavor<AspNetFlavor> (); } } @@ -336,7 +338,7 @@ namespace MonoDevelop.AspNet.WebForms IList<RegistrationInfo> GetRegistrationInfos () { if (project != null && doc != null) - return project.RegistrationCache.GetInfosForPath (Path.GetDirectoryName (doc.FileName)); + return aspFlavor.RegistrationCache.GetInfosForPath (Path.GetDirectoryName (doc.FileName)); return new[] { WebFormsRegistrationCache.MachineRegistrationInfo }; } @@ -570,7 +572,10 @@ namespace MonoDevelop.AspNet.WebForms IType AssemblyTypeLookup (string namespac, string tagName) { var fullName = namespac + "." + tagName; - return ReflectionHelper.ParseReflectionName (fullName).Resolve (Compilation); + var type = ReflectionHelper.ParseReflectionName (fullName).Resolve (Compilation); + if (type.Kind == TypeKind.Unknown) + return null; + return type; } public string GetControlPrefix (IType control) @@ -595,8 +600,8 @@ namespace MonoDevelop.AspNet.WebForms { string typeName = null; if (project != null && doc != null) { - string absolute = project.VirtualToLocalPath (virtualPath, doc.FileName); - typeName = project.GetCodebehindTypeName (absolute); + string absolute = aspFlavor.VirtualToLocalPath (virtualPath, doc.FileName); + typeName = aspFlavor.GetCodebehindTypeName (absolute); } return typeName ?? "System.Web.UI.UserControl"; } @@ -604,7 +609,10 @@ namespace MonoDevelop.AspNet.WebForms IType GetUserControlType (string virtualPath) { var name = GetUserControlTypeName (virtualPath); - return ReflectionHelper.ParseReflectionName (name).Resolve (Compilation); + var type = ReflectionHelper.ParseReflectionName (name).Resolve (Compilation); + if (type.Kind == TypeKind.Unknown) + return null; + return type; } } diff --git a/main/src/addins/CBinding/CBinding.addin.xml b/main/src/addins/CBinding/CBinding.addin.xml index 35cb77e26d..1fef8d00e9 100644 --- a/main/src/addins/CBinding/CBinding.addin.xml +++ b/main/src/addins/CBinding/CBinding.addin.xml @@ -190,12 +190,6 @@ <CommandItem id = "MonoDevelop.Ide.Commands.EditCommands.Delete"/> </Extension> - <Extension path = "/MonoDevelop/ProjectModel/ProjectServiceExtensions"> - <Condition id="ItemType" value="CBinding.CProject"> - <Class id = "ExtraSteps" class = "CBinding.CProjectServiceExtension"/> - </Condition> - </Extension> - <Extension path = "/MonoDevelop/Ide/TextEditorExtensions"> <Class fileExtensions=".c,.cpp,.cxx,.cc,.h,.hpp,.hh,.hxx,.m,.mm,.M" class = "CBinding.CTextEditorExtension" /> </Extension> @@ -207,11 +201,7 @@ <DataType class = "CBinding.GppCompiler"/> <DataType class = "CBinding.Package"/> </Extension> - - <Extension path = "/MonoDevelop/ProjectModel/MSBuildItemTypes"> - <SolutionItem type="CBinding.CProject" extension="cproj" guid="{2857B73E-F847-4B02-9238-064979017E93}"/> - </Extension> - + <!-- Current Autotools AddIn is very .NET specific <Module> <Runtime> diff --git a/main/src/addins/CBinding/CBinding.csproj b/main/src/addins/CBinding/CBinding.csproj index 94f0eb7bb6..7962736351 100644 --- a/main/src/addins/CBinding/CBinding.csproj +++ b/main/src/addins/CBinding/CBinding.csproj @@ -200,7 +200,6 @@ </ItemGroup> <ItemGroup> <Compile Include="Project\CProject.cs" /> - <Compile Include="Project\CProjectBinding.cs" /> <Compile Include="Project\CProjectConfiguration.cs" /> <Compile Include="gtk-gui\generated.cs" /> <Compile Include="Gui\CodeGenerationPanel.cs" /> @@ -220,7 +219,6 @@ <Compile Include="Project\ProjectPackageEventArgs.cs" /> <Compile Include="Gui\OutputOptionsPanel.cs" /> <Compile Include="gtk-gui\CBinding.OutputOptionsPanel.cs" /> - <Compile Include="Project\CProjectServiceExtension.cs" /> <Compile Include="Navigation\ProjectNodeBuilderExtension.cs" /> <Compile Include="Navigation\NamespaceNodeBuilder.cs" /> <Compile Include="ProjectPad\ProjectReferencesExtension.cs" /> diff --git a/main/src/addins/CBinding/Compiler/CCompiler.cs b/main/src/addins/CBinding/Compiler/CCompiler.cs index b094faf03f..4a92d92bc2 100644 --- a/main/src/addins/CBinding/Compiler/CCompiler.cs +++ b/main/src/addins/CBinding/Compiler/CCompiler.cs @@ -75,9 +75,9 @@ namespace CBinding ProjectFileCollection projectFiles, ProjectPackageCollection packages, CProjectConfiguration configuration, - IProgressMonitor monitor); + ProgressMonitor monitor); - public abstract void Clean (ProjectFileCollection projectFiles, CProjectConfiguration configuration, IProgressMonitor monitor); + public abstract void Clean (ProjectFileCollection projectFiles, CProjectConfiguration configuration, ProgressMonitor monitor); protected abstract void ParseCompilerOutput (string errorString, CompilerResults cr); diff --git a/main/src/addins/CBinding/Compiler/GNUCompiler.cs b/main/src/addins/CBinding/Compiler/GNUCompiler.cs index b75471a9ff..be4a0bc5f8 100644 --- a/main/src/addins/CBinding/Compiler/GNUCompiler.cs +++ b/main/src/addins/CBinding/Compiler/GNUCompiler.cs @@ -56,7 +56,7 @@ namespace CBinding ProjectFileCollection projectFiles, ProjectPackageCollection packages, CProjectConfiguration configuration, - IProgressMonitor monitor) + ProgressMonitor monitor) { if (!appsChecked) { appsChecked = true; @@ -271,7 +271,7 @@ namespace CBinding private bool PrecompileHeaders (ProjectFileCollection projectFiles, CProjectConfiguration configuration, string args, - IProgressMonitor monitor, + ProgressMonitor monitor, CompilerResults cr) { monitor.BeginTask (GettextCatalog.GetString ("Precompiling headers"), 1); @@ -303,7 +303,7 @@ namespace CBinding return success; } - private bool DoPrecompileHeader (ProjectFile file, string output, string args, IProgressMonitor monitor, CompilerResults cr) + private bool DoPrecompileHeader (ProjectFile file, string output, string args, ProgressMonitor monitor, CompilerResults cr) { string completeArgs = String.Format ("\"{0}\" {1} -o {2}", file.Name, args, output); string errorOutput; @@ -353,7 +353,7 @@ namespace CBinding CProjectConfiguration configuration, ProjectPackageCollection packages, CompilerResults cr, - IProgressMonitor monitor, string outputName) + ProgressMonitor monitor, string outputName) { if (!NeedsUpdate (projectFiles, configuration, outputName)) return; @@ -406,7 +406,7 @@ namespace CBinding CProjectConfiguration configuration, ProjectPackageCollection packages, CompilerResults cr, - IProgressMonitor monitor, string outputName) + ProgressMonitor monitor, string outputName) { if (!NeedsUpdate (projectFiles, configuration, outputName)) return; @@ -431,7 +431,7 @@ namespace CBinding CProjectConfiguration configuration, ProjectPackageCollection packages, CompilerResults cr, - IProgressMonitor monitor, string outputName) + ProgressMonitor monitor, string outputName) { if (!NeedsUpdate (projectFiles, configuration, outputName)) return; @@ -479,7 +479,7 @@ namespace CBinding CheckReturnCode (exitCode, cr); } - int ExecuteCommand (string command, string args, string baseDirectory, IProgressMonitor monitor, out string errorOutput) + int ExecuteCommand (string command, string args, string baseDirectory, ProgressMonitor monitor, out string errorOutput) { errorOutput = string.Empty; int exitCode = -1; @@ -491,23 +491,20 @@ namespace CBinding monitor.Log.WriteLine ("{0} {1}", command, args); - using (var operationMonitor = new AggregatedOperationMonitor (monitor)) { - using (ProcessWrapper p = Runtime.ProcessService.StartProcess (command, args, baseDirectory, monitor.Log, chainedError, null)) { - operationMonitor.AddOperation (p); //handles cancellation - - p.WaitForOutput (); - chainedError.UnchainWriter (monitor.Log); - chainedError.UnchainWriter (swError); + using (ProcessWrapper p = Runtime.ProcessService.StartProcess (command, args, baseDirectory, monitor.Log, chainedError, null)) + using (monitor.CancellationToken.Register (p.Cancel)) { + p.WaitForOutput (); + chainedError.UnchainWriter (monitor.Log); + chainedError.UnchainWriter (swError); - errorOutput = swError.ToString (); - exitCode = p.ExitCode; - - if (monitor.IsCancelRequested) { - monitor.Log.WriteLine (GettextCatalog.GetString ("Build cancelled")); - monitor.ReportError (GettextCatalog.GetString ("Build cancelled"), null); - if (exitCode == 0) - exitCode = -1; - } + errorOutput = swError.ToString (); + exitCode = p.ExitCode; + + if (monitor.CancellationToken.IsCancellationRequested) { + monitor.Log.WriteLine (GettextCatalog.GetString ("Build cancelled")); + monitor.ReportError (GettextCatalog.GetString ("Build cancelled"), null); + if (exitCode == 0) + exitCode = -1; } } } @@ -542,7 +539,7 @@ namespace CBinding private bool DoCompilation (ProjectFile file, CProjectConfiguration configuration, string args, - IProgressMonitor monitor, + ProgressMonitor monitor, CompilerResults cr, bool use_ccache) { @@ -605,7 +602,7 @@ namespace CBinding return objectFiles.ToArray (); } - public override void Clean (ProjectFileCollection projectFiles, CProjectConfiguration configuration, IProgressMonitor monitor) + public override void Clean (ProjectFileCollection projectFiles, CProjectConfiguration configuration, ProgressMonitor monitor) { //clean up object files foreach (string oFile in ObjectFiles(projectFiles, configuration, false)) { diff --git a/main/src/addins/CBinding/Compiler/ICompiler.cs b/main/src/addins/CBinding/Compiler/ICompiler.cs index edb2b80c96..a3b7ad7a0e 100644 --- a/main/src/addins/CBinding/Compiler/ICompiler.cs +++ b/main/src/addins/CBinding/Compiler/ICompiler.cs @@ -69,8 +69,8 @@ namespace CBinding ProjectFileCollection projectFiles, ProjectPackageCollection packages, CProjectConfiguration configuration, - IProgressMonitor monitor); + ProgressMonitor monitor); - void Clean (ProjectFileCollection projectFiles, CProjectConfiguration configuration, IProgressMonitor monitor); + void Clean (ProjectFileCollection projectFiles, CProjectConfiguration configuration, ProgressMonitor monitor); } } diff --git a/main/src/addins/CBinding/Gui/EditPackagesDialog.cs b/main/src/addins/CBinding/Gui/EditPackagesDialog.cs index d7cd1f8adb..b43001e1b3 100644 --- a/main/src/addins/CBinding/Gui/EditPackagesDialog.cs +++ b/main/src/addins/CBinding/Gui/EditPackagesDialog.cs @@ -192,7 +192,7 @@ namespace CBinding List<Package> packages = new List<Package>(); Package package; - foreach (SolutionItem c in project.ParentFolder.Items) { + foreach (SolutionFolderItem c in project.ParentFolder.Items) { if (null != c && c is CProject) { CProject cproj = (CProject)c; CProjectConfiguration conf = (CProjectConfiguration)cproj.GetConfiguration (IdeApp.Workspace.ActiveConfiguration); diff --git a/main/src/addins/CBinding/Project/CProject.cs b/main/src/addins/CBinding/Project/CProject.cs index 231830b4f0..79e1bc2535 100644 --- a/main/src/addins/CBinding/Project/CProject.cs +++ b/main/src/addins/CBinding/Project/CProject.cs @@ -46,6 +46,7 @@ using MonoDevelop.Deployment; using MonoDevelop.Deployment.Linux; using CBinding.Parser; using MonoDevelop.Ide; +using System.Threading.Tasks; namespace CBinding { @@ -62,8 +63,8 @@ namespace CBinding ShowPackageDetails, GotoDeclaration, } - - [DataInclude(typeof(CProjectConfiguration))] + + [RegisterProjectType ("{2857B73E-F847-4B02-9238-064979017E93}", Extension="cproj", Alias="C/C++")] public class CProject : Project, IDeployable { [ItemProperty ("Compiler", ValueType = typeof(CCompiler))] @@ -177,9 +178,9 @@ namespace CBinding } } - public override IEnumerable<string> GetProjectTypes () + protected override void OnGetProjectTypes (HashSet<string> types) { - yield return "Native"; + types.Add ("Native"); } public override string[] SupportedLanguages { @@ -202,7 +203,7 @@ namespace CBinding } } - public override IEnumerable<SolutionItem> GetReferencedItems (ConfigurationSelector configuration) + protected override IEnumerable<SolutionItem> OnGetReferencedItems (ConfigurationSelector configuration) { foreach (var p in base.GetReferencedItems (configuration)) yield return p; @@ -302,15 +303,33 @@ namespace CBinding return pkgfile; } - protected override BuildResult DoBuild (IProgressMonitor monitor, ConfigurationSelector configuration) + protected override Task<BuildResult> DoBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { CProjectConfiguration pc = (CProjectConfiguration) GetConfiguration (configuration); pc.SourceDirectory = BaseDirectory; - - return compiler_manager.Compile (this, - Files, packages, - pc, - monitor); + + return Task<BuildResult>.Factory.StartNew (delegate { + if (pc.CompileTarget != CompileTarget.Bin) + WriteMDPkgPackage (configuration); + + return compiler_manager.Compile (this, + Files, packages, + pc, + monitor); + }); + } + + protected async override Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration) + { + CProjectConfiguration conf = (CProjectConfiguration) GetConfiguration (configuration); + + var res = await base.OnClean (monitor, configuration); + if (res.HasErrors) + return res; + + await Task.Factory.StartNew (() => Compiler.Clean (Files, conf, monitor)); + + return res; } protected virtual ExecutionCommand CreateExecutionCommand (CProjectConfiguration conf) @@ -330,7 +349,7 @@ namespace CBinding return (target == CBinding.CompileTarget.Bin) && context.ExecutionHandler.CanExecute (cmd); } - protected override void DoExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + protected async override Task DoExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { CProjectConfiguration conf = (CProjectConfiguration) GetConfiguration (configuration); bool pause = conf.PauseConsoleOutput; @@ -348,26 +367,22 @@ namespace CBinding else console = context.ConsoleFactory.CreateConsole (!pause); - AggregatedOperationMonitor operationMonitor = new AggregatedOperationMonitor (monitor); - try { ExecutionCommand cmd = CreateExecutionCommand (conf); if (!context.ExecutionHandler.CanExecute (cmd)) { monitor.ReportError ("Cannot execute \"" + conf.Output + "\". The selected execution mode is not supported for C projects.", null); return; } - - IProcessAsyncOperation op = context.ExecutionHandler.Execute (cmd, console); - - operationMonitor.AddOperation (op); - op.WaitForCompleted (); + + ProcessAsyncOperation op = context.ExecutionHandler.Execute (cmd, console); + using (var t = monitor.CancellationToken.Register (op.Cancel)) + await op.Task; monitor.Log.WriteLine ("The operation exited with code: {0}", op.ExitCode); } catch (Exception ex) { LoggingService.LogError (string.Format ("Cannot execute \"{0}\"", conf.Output), ex); monitor.ReportError ("Cannot execute \"" + conf.Output + "\"", ex); } finally { - operationMonitor.Dispose (); console.Dispose (); } } diff --git a/main/src/addins/CBinding/Project/CProjectBinding.cs b/main/src/addins/CBinding/Project/CProjectBinding.cs deleted file mode 100644 index db379d8763..0000000000 --- a/main/src/addins/CBinding/Project/CProjectBinding.cs +++ /dev/null @@ -1,85 +0,0 @@ -// -// CProjectBinding.cs: binding with the CProject -// -// Authors: -// Marcos David Marin Amador <MarcosMarin@gmail.com> -// -// Copyright (C) 2007 Marcos David Marin Amador -// -// -// This source code is licenced under The MIT License: -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System.Xml; -using System.IO; - -using Mono.Addins; - -using MonoDevelop.Projects; - -namespace CBinding -{ - public class CProjectBinding : IProjectBinding - { - public string Name { - get { return "C/C++"; } - } - - public Project CreateProject (ProjectCreateInformation info, - XmlElement projectOptions) - { - string language = projectOptions.GetAttribute ("language"); - return new CProject (info, projectOptions, language); - } - - public Project CreateSingleFileProject (string sourceFile) - { - var info = new ProjectCreateInformation () { - ProjectName = Path.GetFileNameWithoutExtension (sourceFile), - SolutionPath = Path.GetDirectoryName (sourceFile), - ProjectBasePath = Path.GetDirectoryName (sourceFile), - }; - - Project project = new CProject (info, null, GetLanguage (sourceFile)); - project.Files.Add (new ProjectFile (sourceFile)); - return project; - } - - string GetLanguage (string filename) - { - switch (Path.GetExtension (filename.ToLower ())) { - case ".c": - return "C"; - case ".cpp": - case ".cxx": - return "CPP"; - default: - return null; - } - } - - public bool CanCreateSingleFileProject (string sourceFile) - { - return GetLanguage (sourceFile) != null; - } - } -} diff --git a/main/src/addins/CBinding/Project/CProjectServiceExtension.cs b/main/src/addins/CBinding/Project/CProjectServiceExtension.cs deleted file mode 100644 index 22775dc090..0000000000 --- a/main/src/addins/CBinding/Project/CProjectServiceExtension.cs +++ /dev/null @@ -1,70 +0,0 @@ -// -// CProjectServiceExtension.cs -// -// Authors: -// Marcos David Marin Amador <MarcosMarin@gmail.com> -// -// Copyright (C) 2007 Marcos David Marin Amador -// -// -// This source code is licenced under The MIT License: -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.IO; -using System.Text; - -using Mono.Addins; - -using MonoDevelop.Core; -using MonoDevelop.Projects; -using MonoDevelop.Core.Execution; - -namespace CBinding -{ - public class CProjectServiceExtension : ProjectServiceExtension - { - public override bool SupportsItem (IBuildTarget item) - { - return item is CProject; - } - - protected override BuildResult Build (IProgressMonitor monitor, SolutionEntityItem entry, ConfigurationSelector configuration) - { - CProject project = (CProject) entry; - CProjectConfiguration conf = (CProjectConfiguration) project.GetConfiguration (configuration); - if (conf.CompileTarget != CompileTarget.Bin) - project.WriteMDPkgPackage (configuration); - - return base.Build (monitor, entry, configuration); - } - - protected override void Clean (IProgressMonitor monitor, SolutionEntityItem entry, ConfigurationSelector configuration) - { - base.Clean (monitor, entry, configuration); - - CProject project = (CProject) entry; - CProjectConfiguration conf = (CProjectConfiguration) project.GetConfiguration (configuration); - project.Compiler.Clean (project.Files, conf, monitor); - } - } -} diff --git a/main/src/addins/CBinding/ProjectPad/ProjectPackageNodeBuilder.cs b/main/src/addins/CBinding/ProjectPad/ProjectPackageNodeBuilder.cs index 6c460d9aac..42cbc28768 100644 --- a/main/src/addins/CBinding/ProjectPad/ProjectPackageNodeBuilder.cs +++ b/main/src/addins/CBinding/ProjectPad/ProjectPackageNodeBuilder.cs @@ -81,7 +81,7 @@ namespace CBinding.ProjectPad project.Packages.Remove (package); - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); } public override DragOperation CanDragNode () diff --git a/main/src/addins/CBinding/ProjectPad/ProjectPackagesFolderNodeBuilder.cs b/main/src/addins/CBinding/ProjectPad/ProjectPackagesFolderNodeBuilder.cs index dc3dd1e117..9e86d90b68 100644 --- a/main/src/addins/CBinding/ProjectPad/ProjectPackagesFolderNodeBuilder.cs +++ b/main/src/addins/CBinding/ProjectPad/ProjectPackagesFolderNodeBuilder.cs @@ -35,6 +35,8 @@ using MonoDevelop.Components.Commands; using MonoDevelop.Ide.Gui; using MonoDevelop.Ide.Gui.Components; using MonoDevelop.Ide; +using MonoDevelop.Projects; +using System.Collections.Generic; namespace CBinding.ProjectPad { @@ -132,7 +134,7 @@ namespace CBinding.ProjectPad MessageService.ShowCustomDialog (new EditPackagesDialog (project)); - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); CurrentNode.Expanded = true; } @@ -164,6 +166,7 @@ namespace CBinding.ProjectPad public override void OnNodeDrop (object dataObject, DragOperation operation) { + List<IWorkspaceFileObject> toSave = new List<IWorkspaceFileObject> (); if (dataObject is Package) { Package package = (Package)dataObject; ITreeNavigator nav = CurrentNode; @@ -173,11 +176,11 @@ namespace CBinding.ProjectPad CProject source = nav.GetParentDataItem (typeof(CProject), true) as CProject; dest.Packages.Add (package); - IdeApp.ProjectOperations.Save (dest); - + toSave.Add (dest); + if (operation == DragOperation.Move) { source.Packages.Remove (package); - IdeApp.ProjectOperations.Save (source); + toSave.Add (source); } } else if (dataObject is CProject) { CProject draggedProject = (CProject)dataObject; @@ -189,9 +192,10 @@ namespace CBinding.ProjectPad if (!destProject.Packages.Contains (package)) { destProject.Packages.Add (package); - IdeApp.ProjectOperations.Save (destProject); + toSave.Add (destProject); } } + IdeApp.ProjectOperations.SaveAsync (toSave); } } } diff --git a/main/src/addins/CSharpBinding/AspNet/ASPNetReferenceFinder.cs b/main/src/addins/CSharpBinding/AspNet/ASPNetReferenceFinder.cs index 1484fe7b1d..ec6553f68a 100644 --- a/main/src/addins/CSharpBinding/AspNet/ASPNetReferenceFinder.cs +++ b/main/src/addins/CSharpBinding/AspNet/ASPNetReferenceFinder.cs @@ -58,7 +58,7 @@ namespace MonoDevelop.CSharp.Refactoring // yield return new DomRegion (fileName, loc.Line, loc.Column, loc.Line, loc.Column + result.Name.Lenhth); // } } - public override IEnumerable<MemberReference> FindReferences (MonoDevelop.Projects.Project project, IProjectContent content, IEnumerable<FilePath> files, IProgressMonitor monitor, IEnumerable<object> searchedMembers) + public override IEnumerable<MemberReference> FindReferences (MonoDevelop.Projects.Project project, IProjectContent content, IEnumerable<FilePath> files, ProgressMonitor monitor, IEnumerable<object> searchedMembers) { // TODO: Type system conversion. yield break; // var editor = TextFileProvider.Instance.GetTextEditorData (fileName); diff --git a/main/src/addins/CSharpBinding/Autotools/CSharpAutotoolsSetup.cs b/main/src/addins/CSharpBinding/Autotools/CSharpAutotoolsSetup.cs index 3e08162ea7..9df0ae112b 100644 --- a/main/src/addins/CSharpBinding/Autotools/CSharpAutotoolsSetup.cs +++ b/main/src/addins/CSharpBinding/Autotools/CSharpAutotoolsSetup.cs @@ -43,7 +43,7 @@ namespace CSharpBinding.Autotools if ( config == null ) return ""; CSharpCompilerParameters parameters = (CSharpCompilerParameters) config.CompilationParameters; - CSharpProjectParameters projectParameters = (CSharpProjectParameters) config.ProjectParameters; + ICSharpProject projectParameters = config.ParentItem.GetService<ICSharpProject> (); StringWriter writer = new StringWriter(); diff --git a/main/src/addins/CSharpBinding/CSharpBinding.addin.xml b/main/src/addins/CSharpBinding/CSharpBinding.addin.xml index 8ac2fe8f96..6531dabcbe 100644 --- a/main/src/addins/CSharpBinding/CSharpBinding.addin.xml +++ b/main/src/addins/CSharpBinding/CSharpBinding.addin.xml @@ -10,21 +10,18 @@ </Extension> <Extension path = "/MonoDevelop/ProjectModel/MSBuildItemTypes"> - <DotNetProject + <DotNetProjectType language="C#" extension="csproj" guid="{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}" import="$(MSBuildBinPath)\Microsoft.CSharp.targets" - resourceHandler="MonoDevelop.CSharp.Project.CSharpResourceIdBuilder" + type="MonoDevelop.CSharp.Project.CSharpProject" /> + </Extension> + + <Extension path = "/MonoDevelop/ProjectModel/ProjectModelExtensions"> <Condition id="MSBuildTargetIsAvailable" target="$(MSBuildExtensionsPath)\Microsoft\Portable\v4.0\Microsoft.Portable.CSharp.targets"> - <DotNetProjectSubtype - guid="{786C830F-07A1-408B-BD7F-6EE04809D6DB}" - type="MonoDevelop.Projects.PortableDotNetProject" - useXBuild="true"> - <AddImport language="C#" projects="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" /> - <RemoveImport language="C#" projects="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> - </DotNetProjectSubtype> + <ProjectFlavor guid="{786C830F-07A1-408B-BD7F-6EE04809D6DB}" type="MonoDevelop.CSharp.Project.PortableCSharpProjectFlavor" /> </Condition> </Extension> diff --git a/main/src/addins/CSharpBinding/CSharpBinding.csproj b/main/src/addins/CSharpBinding/CSharpBinding.csproj index 180eb11cbd..5c449f40fb 100644 --- a/main/src/addins/CSharpBinding/CSharpBinding.csproj +++ b/main/src/addins/CSharpBinding/CSharpBinding.csproj @@ -222,7 +222,6 @@ <Compile Include="MonoDevelop.CSharp.Formatting\CSharpFormattingPolicyPanel.cs" /> <Compile Include="MonoDevelop.CSharp.Formatting\CSharpFormatter.cs" /> <Compile Include="MonoDevelop.CSharp.Project\CSharpCompilerParameters.cs" /> - <Compile Include="MonoDevelop.CSharp.Project\CSharpProjectParameters.cs" /> <Compile Include="MonoDevelop.CSharp.Project\CSharpResourceIdBuilder.cs" /> <Compile Include="MonoDevelop.CSharp.Project\CodeGenerationPanel.cs" /> <Compile Include="MonoDevelop.CSharp.Project\CompilerOptionsPanelWidget.cs" /> @@ -313,6 +312,8 @@ <Compile Include="MonoDevelop.CSharp.CodeGeneration\ExportCodeGenerator.cs" /> <Compile Include="MonoDevelop.CSharp.Completion\MonoCSharpCompletionEngine.cs" /> <Compile Include="MonoDevelop.CSharp.Completion\ProtocolCompletionData.cs" /> + <Compile Include="MonoDevelop.CSharp.Project\CSharpProjectExtension.cs" /> + <Compile Include="MonoDevelop.CSharp.Project\PortableCSharpProjectFlavor.cs" /> </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpCompletionTextEditorExtension.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpCompletionTextEditorExtension.cs index cdac91156d..316fa9aab4 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpCompletionTextEditorExtension.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpCompletionTextEditorExtension.cs @@ -58,6 +58,7 @@ using MonoDevelop.CSharp.Project; using MonoDevelop.CSharp.Formatting; using MonoDevelop.CSharp.Refactoring.CodeActions; using MonoDevelop.Refactoring; +using System.Xml; namespace MonoDevelop.CSharp.Completion { @@ -147,13 +148,16 @@ namespace MonoDevelop.CSharp.Completion public CSharpCompletionTextEditorExtension () { } - + + bool addEventHandlersInInitialization = true; + /// <summary> /// Used in testing environment. /// </summary> [System.ComponentModel.Browsable(false)] - public CSharpCompletionTextEditorExtension (MonoDevelop.Ide.Gui.Document doc) : this () + public CSharpCompletionTextEditorExtension (MonoDevelop.Ide.Gui.Document doc, bool addEventHandlersInInitialization = true) : this () { + this.addEventHandlersInInitialization = addEventHandlersInInitialization; Initialize (doc); } @@ -165,10 +169,12 @@ namespace MonoDevelop.CSharp.Completion this.Unit = parsedDocument.GetAst<SyntaxTree> (); this.UnresolvedFileCompilation = Document.Compilation; this.CSharpUnresolvedFile = parsedDocument.ParsedFile as CSharpUnresolvedFile; - document.Editor.Caret.PositionChanged += HandlePositionChanged; + if (addEventHandlersInInitialization) + document.Editor.Caret.PositionChanged += HandlePositionChanged; } - - Document.DocumentParsed += HandleDocumentParsed; + + if (addEventHandlersInInitialization) + Document.DocumentParsed += HandleDocumentParsed; } CancellationTokenSource src = new CancellationTokenSource (); diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/CSharpTextEditorIndentation.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/CSharpTextEditorIndentation.cs index 87898df7e1..fce4666569 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/CSharpTextEditorIndentation.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/CSharpTextEditorIndentation.cs @@ -580,6 +580,7 @@ namespace MonoDevelop.CSharp.Formatting int lastNonWsOffset = caretOffset; char lastNonWsChar = '\0'; outOffset = caretOffset; + int max = curLine.EndOffset; int end = caretOffset; @@ -595,69 +596,22 @@ namespace MonoDevelop.CSharp.Formatting return false; } - bool isInString = false, isInChar = false, isVerbatimString = false; - bool isInLineComment = false, isInBlockComment = false; - bool firstChar = true; - for (int pos = caretOffset; pos < max; pos++) { - if (pos == caretOffset) { - if (isInString || isInChar || isVerbatimString || isInLineComment || isInBlockComment) { - outOffset = pos; - return true; - } - } - char ch = data.Document.GetCharAt (pos); - switch (ch) { - case '}': - if (firstChar && !IsSemicolonalreadyPlaced (data, caretOffset)) - return false; - break; - case '/': - if (isInBlockComment) { - isInBlockComment &= pos <= 0 || data.Document.GetCharAt (pos - 1) != '*'; - } else if (!isInString && !isInChar && pos + 1 < max) { - char nextChar = data.Document.GetCharAt (pos + 1); - if (nextChar == '/') { - outOffset = lastNonWsOffset; - return true; - } - if (!isInLineComment && nextChar == '*') { - outOffset = lastNonWsOffset; - return true; - } - } - break; - case '\\': - if (isInChar || (isInString && !isVerbatimString)) - pos++; - break; - case '@': - if (!(isInString || isInChar || isInLineComment || isInBlockComment) && pos + 1 < max && data.Document.GetCharAt (pos + 1) == '"') { - isInString = true; - isVerbatimString = true; - pos++; - } - break; - case '"': - if (!(isInChar || isInLineComment || isInBlockComment)) { - if (isInString && isVerbatimString && pos + 1 < max && data.Document.GetCharAt (pos + 1) == '"') { - pos++; - } else { - isInString = !isInString; - isVerbatimString = false; - } - } - break; - case '\'': - if (!(isInString || isInLineComment || isInBlockComment)) - isInChar = !isInChar; - break; + var offset = curLine.Offset; + string lineText = data.GetTextAt (caretOffset, max - caretOffset); + var lexer = new CSharpCompletionEngineBase.MiniLexer (lineText); + lexer.Parse ((ch, i) => { + if (lexer.IsInSingleComment || lexer.IsInMultiLineComment) + return true; + if (ch == '}' && lexer.IsFistNonWs && !IsSemicolonalreadyPlaced (data, caretOffset)) { + lastNonWsChar = ';'; + return true; } if (!char.IsWhiteSpace (ch)) { - firstChar = false; - lastNonWsOffset = pos; + lastNonWsOffset = caretOffset + i; lastNonWsChar = ch; } - } + return false; + }); // if the line ends with ';' the line end is not the correct place for a new semicolon. if (lastNonWsChar == ';') return false; diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Highlighting/CSharpSyntaxMode.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Highlighting/CSharpSyntaxMode.cs index 998368be6a..76fa3cf026 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Highlighting/CSharpSyntaxMode.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Highlighting/CSharpSyntaxMode.cs @@ -281,6 +281,54 @@ namespace MonoDevelop.CSharp.Highlighting } tree.AddStyle (startOffset, endOffset, color); } + + public override void VisitSimpleType (SimpleType simpleType) + { + var identifierToken = simpleType.IdentifierToken; + VisitChildrenUntil(simpleType, identifierToken); + var resolveResult = resolver.Resolve (simpleType, cancellationToken); + if (resolveResult.Type.Namespace == "System") { + switch (resolveResult.Type.Name) { + case "nfloat": + case "nint": + case "nuint": + Colorize(identifierToken, "Keyword(Type)"); + break; + default: + Colorize (identifierToken, resolveResult); + break; + } + } else { + Colorize (identifierToken, resolveResult); + } + VisitChildrenAfter(simpleType, identifierToken); + } + + public override void VisitIdentifierExpression (IdentifierExpression identifierExpression) + { + var identifier = identifierExpression.IdentifierToken; + VisitChildrenUntil(identifierExpression, identifier); + if (isInAccessorContainingValueParameter && identifierExpression.Identifier == "value") { + Colorize(identifier, valueKeywordColor); + } else { + var resolveResult = resolver.Resolve (identifierExpression, cancellationToken); + if (resolveResult.Type.Namespace == "System") { + switch (resolveResult.Type.Name) { + case "nfloat": + case "nint": + case "nuint": + Colorize(identifier, "Keyword(Type)"); + break; + default: + Colorize (identifier, resolveResult); + break; + } + } else { + Colorize (identifier, resolveResult); + } + } + VisitChildrenAfter(identifierExpression, identifier); + } } class QuickTaskVisitor : DepthFirstAstVisitor diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/TypeSystemProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/TypeSystemProvider.cs index 475fac0ee1..0192f4a3e7 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/TypeSystemProvider.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/TypeSystemProvider.cs @@ -84,7 +84,13 @@ namespace MonoDevelop.CSharp.Parser result.ParsedFile = pf; result.Add (GetSemanticTags (unit)); - result.CreateRefactoringContext = (doc, token) => MDRefactoringContext.Create (doc, doc.Editor.Caret.Location, token).Result; + result.CreateRefactoringContext = delegate (MonoDevelop.Ide.Gui.Document doc, System.Threading.CancellationToken token) { + var task = MDRefactoringContext.Create (doc, doc.Editor.Caret.Location, token); + task.Wait (5000, token); + if (!task.IsCompleted) + return null; + return task.Result; + }; result.CreateRefactoringContextWithEditor = (data, resolver, token) => new MDRefactoringContext ((DotNetProject)project, data, result, (CSharpAstResolver)resolver, TextLocation.Empty, token); if (storeAst) { diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CSharpCompilerParameters.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CSharpCompilerParameters.cs index 6c528ba8f4..0f0ca7f675 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CSharpCompilerParameters.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CSharpCompilerParameters.cs @@ -33,6 +33,7 @@ using MonoDevelop.Core.Serialization; using MonoDevelop.Core; using Mono.Collections.Generic; using System.Linq; +using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.CSharp.Project { @@ -48,7 +49,7 @@ namespace MonoDevelop.CSharp.Project /// <summary> /// This class handles project specific compiler parameters /// </summary> - public class CSharpCompilerParameters: DotNetConfigurationParameters + public class CSharpCompilerParameters: DotNetCompilerParameters { // Configuration parameters @@ -91,60 +92,26 @@ namespace MonoDevelop.CSharp.Project [ItemProperty("DebugType", DefaultValue="")] string debugType = ""; - #region Members required for backwards compatibility. Not used for anything else. - - [ItemProperty ("StartupObject", DefaultValue = null)] - internal string mainclass; - - [ProjectPathItemProperty ("ApplicationIcon", DefaultValue = null)] - internal string win32Icon; - - [ProjectPathItemProperty ("Win32Resource", DefaultValue = null)] - internal string win32Resource; - - [ItemProperty ("CodePage", DefaultValue = null)] - internal string codePage; + protected override void Write (IMSBuildPropertySet pset, MSBuildFileFormat format) + { + base.Write (pset, format); + pset.SetPropertyOrder ("DebugSymbols", "DebugType", "Optimize", "OutputPath", "DefineConstants", "ErrorReport", "WarningLevel", "TreatWarningsAsErrors", "DocumentationFile"); + pset.WriteObjectProperties (this, typeof(CSharpCompilerParameters)); + } - [ItemProperty ("GenerateDocumentation", DefaultValue = null)] - bool? generateXmlDocumentation = null; - - #endregion - - - protected override void OnEndLoad () + protected override void Read (IMSBuildPropertySet pset, MSBuildFileFormat format) { - base.OnEndLoad (); - - // Backwards compatibility. Move parameters to the project parameters object - if (ParentConfiguration != null && ParentConfiguration.ProjectParameters != null) { - CSharpProjectParameters cparams = (CSharpProjectParameters) ParentConfiguration.ProjectParameters; - if (win32Icon != null) { - cparams.Win32Icon = win32Icon; - win32Icon = null; - } - if (win32Resource != null) { - cparams.Win32Resource = win32Resource; - win32Resource = null; - } - if (mainclass != null) { - cparams.MainClass = mainclass; - mainclass = null; - } - if (!string.IsNullOrEmpty (codePage)) { - cparams.CodePage = int.Parse (codePage); - codePage = null; - } - } + base.Read (pset, format); + pset.ReadObjectProperties (this, typeof(CSharpCompilerParameters)); - if (generateXmlDocumentation.HasValue && ParentConfiguration != null) { - if (generateXmlDocumentation.Value) + var prop = pset.GetProperty ("GenerateDocumentation"); + if (prop != null && documentationFile != null) { + if (prop.GetValue<bool> ()) documentationFile = ParentConfiguration.CompiledOutputName.ChangeExtension (".xml"); else documentationFile = null; - generateXmlDocumentation = null; } } - public LangVersion LangVersion { get { diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CSharpProjectExtension.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CSharpProjectExtension.cs new file mode 100644 index 0000000000..5c66cf0c2d --- /dev/null +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CSharpProjectExtension.cs @@ -0,0 +1,149 @@ +// +// CSharpProjectExtension.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using MonoDevelop.Projects; +using MonoDevelop.Projects.Formats.MSBuild; +using MonoDevelop.Core; +using MonoDevelop.Core.Serialization; +using MonoDevelop.Projects.Extensions; +using System.Collections.Generic; + +namespace MonoDevelop.CSharp.Project +{ + class CSharpProject: DotNetProject, ICSharpProject + { + [ItemProperty ("StartupObject", DefaultValue = "")] + string mainclass = string.Empty; + + [ProjectPathItemProperty ("ApplicationIcon", DefaultValue = "")] + string win32Icon = String.Empty; + + [ProjectPathItemProperty ("Win32Resource", DefaultValue = "")] + string win32Resource = String.Empty; + + [ItemProperty ("CodePage", DefaultValue = 0)] + int codePage; + + static CSharpResourceIdBuilder resourceHandler = new CSharpResourceIdBuilder (); + + public CSharpProject () + { + Initialize (this); + DefaultImports.Add ("$(MSBuildBinPath)\\Microsoft.CSharp.targets"); + } + + public string MainClass { + get { + return mainclass; + } + set { + mainclass = value ?? string.Empty; + } + } + + public int CodePage { + get { + return codePage; + } + set { + codePage = value; + } + } + + public string Win32Icon { + get { + return win32Icon; + } + set { + win32Icon = value ?? string.Empty; + } + } + + public string Win32Resource { + get { + return win32Resource; + } + set { + win32Resource = value ?? string.Empty; + } + } + + protected override object OnGetService (Type t) + { + if (t == typeof(IResourceHandler)) + return resourceHandler; + return base.GetService (t); + } + + protected override void OnWriteProject (ProgressMonitor monitor, MSBuildProject msproject) + { + base.OnWriteProject (monitor, msproject); + msproject.GetGlobalPropertyGroup ().WriteObjectProperties (this, typeof(CSharpProject)); + } + + protected override void OnReadProject (ProgressMonitor monitor, MSBuildProject msproject) + { + base.OnReadProject (monitor, msproject); + msproject.GetGlobalPropertyGroup ().ReadObjectProperties (this, typeof(CSharpProject)); + } + + protected override void OnReadConfiguration (ProgressMonitor monitor, ProjectConfiguration config, IMSBuildPropertySet pset) + { + base.OnReadConfiguration (monitor, config, pset); + + // Backwards compatibility. Move parameters to the project parameters object + + var prop = pset.GetProperty ("ApplicationIcon"); + if (prop != null) + win32Icon = prop.GetPathValue (); + + prop = pset.GetProperty ("Win32Resource"); + if (prop != null) + win32Resource = prop.GetPathValue (); + + prop = pset.GetProperty ("StartupObject"); + if (prop != null) + mainclass = prop.Value; + + prop = pset.GetProperty ("CodePage"); + if (prop != null) + codePage = int.Parse (prop.Value); + } + } + + public interface ICSharpProject + { + string MainClass { get; set; } + + int CodePage { get; set; } + + string Win32Icon { get; set; } + + string Win32Resource { get; set; } + } + +} + diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CompilerOptionsPanelWidget.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CompilerOptionsPanelWidget.cs index 21300b94a3..465f0e95f2 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CompilerOptionsPanelWidget.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CompilerOptionsPanelWidget.cs @@ -53,7 +53,7 @@ namespace MonoDevelop.CSharp.Project this.project = project; DotNetProjectConfiguration configuration = (DotNetProjectConfiguration) project.GetConfiguration (IdeApp.Workspace.ActiveConfiguration); CSharpCompilerParameters compilerParameters = (CSharpCompilerParameters) configuration.CompilationParameters; - CSharpProjectParameters projectParameters = (CSharpProjectParameters) configuration.ProjectParameters; + var csproject = (CSharpProject)project; ListStore store = new ListStore (typeof (string));
store.AppendValues (GettextCatalog.GetString ("Executable"));
@@ -75,7 +75,7 @@ namespace MonoDevelop.CSharp.Project classListStore = new ListStore (typeof(string));
mainClassEntry.Model = classListStore;
mainClassEntry.TextColumn = 0;
- ((Entry)mainClassEntry.Child).Text = projectParameters.MainClass ?? string.Empty; + ((Entry)mainClassEntry.Child).Text = csproject.MainClass ?? string.Empty; UpdateTarget (); } @@ -85,16 +85,16 @@ namespace MonoDevelop.CSharp.Project foreach (TextEncoding e in TextEncoding.SupportedEncodings) { if (e.CodePage == -1) continue; - if (e.CodePage == projectParameters.CodePage) + if (e.CodePage == csproject.CodePage) foundEncoding = e.Id; codepageEntry.AppendText (e.Id); } if (foundEncoding != null) codepageEntry.Entry.Text = foundEncoding; - else if (projectParameters.CodePage != 0) - codepageEntry.Entry.Text = projectParameters.CodePage.ToString (); + else if (csproject.CodePage != 0) + codepageEntry.Entry.Text = csproject.CodePage.ToString (); - iconEntry.Path = projectParameters.Win32Icon; + iconEntry.Path = csproject.Win32Icon; iconEntry.DefaultPath = project.BaseDirectory; allowUnsafeCodeCheckButton.Active = compilerParameters.UnsafeCode; noStdLibCheckButton.Active = compilerParameters.NoStdLib; @@ -171,15 +171,15 @@ namespace MonoDevelop.CSharp.Project project.CompileTarget = compileTarget; - CSharpProjectParameters projectParameters = (CSharpProjectParameters) project.LanguageParameters; + var csproject = (CSharpProject)project; - projectParameters.CodePage = codePage; + csproject.CodePage = codePage; if (iconEntry.Sensitive) - projectParameters.Win32Icon = iconEntry.Path; + csproject.Win32Icon = iconEntry.Path; if (mainClassEntry.Sensitive) - projectParameters.MainClass = mainClassEntry.Entry.Text; + csproject.MainClass = mainClassEntry.Entry.Text; foreach (DotNetProjectConfiguration configuration in configs) { CSharpCompilerParameters compilerParameters = (CSharpCompilerParameters) configuration.CompilationParameters; diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/PortableDotNetProjectBinding.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/PortableCSharpProjectFlavor.cs index 4ec770d696..c7d50c2884 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/PortableDotNetProjectBinding.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/PortableCSharpProjectFlavor.cs @@ -1,20 +1,21 @@ -// -// PortableDotNetProjectBinding.cs -// -// Author: Jeffrey Stedfast <jeff@xamarin.com> -// -// Copyright (c) 2012 Xamarin Inc. -// +// +// PortableCSharpProjectFlavor.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,36 +23,27 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - using System; -using System.IO; -using System.Xml; -using MonoDevelop.Core.Serialization; +using MonoDevelop.Projects; using MonoDevelop.Core; +using MonoDevelop.Projects.Formats.MSBuild; -namespace MonoDevelop.Projects +namespace MonoDevelop.CSharp.Project { - public class PortableDotNetProjectBinding : IProjectBinding + public class PortableCSharpProjectFlavor: PortableDotNetProjectFlavor { - public string Name { - get { return "PortableDotNet"; } - } - - public Project CreateProject (ProjectCreateInformation info, System.Xml.XmlElement projectOptions) - { - string languageName = projectOptions.GetAttribute ("language"); - - return new PortableDotNetProject (languageName, info, projectOptions); - } - - public Project CreateSingleFileProject (string sourceFile) + protected override void Initialize () { - throw new InvalidOperationException (); + base.Initialize (); + Project.UseMSBuildEngine = true; } - - public bool CanCreateSingleFileProject (string sourceFile) + + protected override void OnWriteProject (ProgressMonitor monitor, MSBuildProject msproject) { - return false; + base.OnWriteProject (monitor, msproject); + msproject.RemoveImport ("$(MSBuildBinPath)\\Microsoft.CSharp.targets"); + msproject.AddNewImport ("$(MSBuildExtensionsPath32)\\Microsoft\\Portable\\$(TargetFrameworkVersion)\\Microsoft.Portable.CSharp.targets"); } } } + diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/Actions/MoveTypeToFile.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/Actions/MoveTypeToFile.cs index bf1523421d..d9d8be69ac 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/Actions/MoveTypeToFile.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/Actions/MoveTypeToFile.cs @@ -72,7 +72,7 @@ namespace MonoDevelop.CSharp.Refactoring.CodeActions if (IsSingleType (ctx)) { FileService.RenameFile (ctx.TextEditor.FileName, correctFileName); if (ctx.FileContainerProject != null) - ctx.FileContainerProject.Save (new NullProgressMonitor ()); + ctx.FileContainerProject.Save (new ProgressMonitor ()); return; } @@ -103,7 +103,7 @@ namespace MonoDevelop.CSharp.Refactoring.CodeActions File.WriteAllText (correctFileName, content); context.FileContainerProject.AddFile (correctFileName); - MonoDevelop.Ide.IdeApp.ProjectOperations.Save (context.FileContainerProject); + MonoDevelop.Ide.IdeApp.ProjectOperations.SaveAsync (context.FileContainerProject); } static bool IsBlankLine (TextDocument doc, int i) diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringContext.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringContext.cs index a831bc4171..8674904f33 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringContext.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringContext.cs @@ -235,7 +235,7 @@ namespace MonoDevelop.CSharp.Refactoring.CodeActions if (sharedResolver == null) return null; return new MDRefactoringContext (document, sharedResolver, loc, cancellationToken); - }, TaskContinuationOptions.ExecuteSynchronously); + }); } internal MDRefactoringContext (Document document, CSharpAstResolver resolver, TextLocation loc, CancellationToken cancellationToken = default (CancellationToken)) : base (resolver, cancellationToken) diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringScript.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringScript.cs index 80db3eb8a1..02e35f0e04 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringScript.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringScript.cs @@ -269,7 +269,11 @@ namespace MonoDevelop.CSharp.Refactoring.CodeActions if (operationsRunning-- == 0) { isDisposed = true; undoGroup.Dispose (); - base.Dispose (); + try { + base.Dispose (); + } catch (Exception e) { + LoggingService.LogError ("Error while disposing refactoring script", e); + } } foreach (var script in startedScripts) script.Dispose (); @@ -363,7 +367,7 @@ namespace MonoDevelop.CSharp.Refactoring.CodeActions if (project != null) { project.AddFile (correctFileName); - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); } IdeApp.Workbench.OpenDocument (correctFileName, project); } diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/CSharpReferenceFinder.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/CSharpReferenceFinder.cs index 950209fcbf..e8e1278ee1 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/CSharpReferenceFinder.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/CSharpReferenceFinder.cs @@ -285,7 +285,7 @@ namespace MonoDevelop.CSharp.Refactoring return result; } - public override IEnumerable<MemberReference> FindReferences (Project project, IProjectContent content, IEnumerable<FilePath> possibleFiles, IProgressMonitor monitor, IEnumerable<object> members) + public override IEnumerable<MemberReference> FindReferences (Project project, IProjectContent content, IEnumerable<FilePath> possibleFiles, ProgressMonitor monitor, IEnumerable<object> members) { if (content == null) throw new ArgumentNullException ("content", "Project content not set."); diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp/CSharpBindingCompilerManager.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp/CSharpBindingCompilerManager.cs index 363af546b5..c850fda17b 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp/CSharpBindingCompilerManager.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp/CSharpBindingCompilerManager.cs @@ -55,10 +55,10 @@ namespace MonoDevelop.CSharp sb.AppendLine (); } - public static BuildResult Compile (ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, IProgressMonitor monitor) + public static BuildResult Compile (ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, ProgressMonitor monitor) { var compilerParameters = (CSharpCompilerParameters)configuration.CompilationParameters ?? new CSharpCompilerParameters (); - var projectParameters = (CSharpProjectParameters)configuration.ProjectParameters ?? new CSharpProjectParameters (); + var projectParameters = (CSharpProject) configuration.ParentItem; FilePath outputName = configuration.CompiledOutputName; string responseFileName = Path.GetTempFileName (); @@ -418,7 +418,7 @@ namespace MonoDevelop.CSharp return result; } - static int DoCompilation (IProgressMonitor monitor, string compilerName, string compilerArgs, string working_dir, ExecutionEnvironment envVars, List<string> gacRoots, ref string output, ref string error) + static int DoCompilation (ProgressMonitor monitor, string compilerName, string compilerArgs, string working_dir, ExecutionEnvironment envVars, List<string> gacRoots, ref string output, ref string error) { output = Path.GetTempFileName (); error = Path.GetTempFileName (); @@ -448,9 +448,9 @@ namespace MonoDevelop.CSharp pinfo.RedirectStandardOutput = true; pinfo.RedirectStandardError = true; - MonoDevelop.Core.Execution.ProcessWrapper pw = Runtime.ProcessService.StartProcess (pinfo, outwr, errwr, null); - using (var mon = new AggregatedOperationMonitor (monitor, pw)) { - pw.WaitForOutput (); + ProcessWrapper pw = Runtime.ProcessService.StartProcess (pinfo, outwr, errwr, null); + using (monitor.CancellationToken.Register (pw.Cancel)) { + pw.Task.Wait (); } int exitCode = pw.ExitCode; bool cancelRequested = pw.CancelRequested;
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp/CSharpLanguageBinding.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp/CSharpLanguageBinding.cs index 968bb4af36..eab17d4f76 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp/CSharpLanguageBinding.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp/CSharpLanguageBinding.cs @@ -72,12 +72,12 @@ namespace MonoDevelop.CSharp return StringComparer.OrdinalIgnoreCase.Equals (Path.GetExtension (fileName), ".cs"); } - public BuildResult Compile (ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, IProgressMonitor monitor) + public BuildResult Compile (ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, ProgressMonitor monitor) { return CSharpBindingCompilerManager.Compile (projectItems, configuration, configSelector, monitor); } - public ConfigurationParameters CreateCompilationParameters (XmlElement projectOptions) + public DotNetCompilerParameters CreateCompilationParameters (XmlElement projectOptions) { CSharpCompilerParameters pars = new CSharpCompilerParameters (); if (projectOptions != null) { @@ -96,11 +96,6 @@ namespace MonoDevelop.CSharp return pars; } - public ProjectParameters CreateProjectParameters (XmlElement projectOptions) - { - return new CSharpProjectParameters (); - } - public string SingleLineCommentTag { get { return "//"; } } public string BlockCommentStartTag { get { return "/*"; } } public string BlockCommentEndTag { get { return "*/"; } } diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp/PathedDocumentTextEditorExtension.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp/PathedDocumentTextEditorExtension.cs index 7739ce1084..4484afcad9 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp/PathedDocumentTextEditorExtension.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp/PathedDocumentTextEditorExtension.cs @@ -46,6 +46,8 @@ namespace MonoDevelop.CSharp { IdeApp.Workspace.FileAddedToProject -= HandleProjectChanged; IdeApp.Workspace.FileRemovedFromProject -= HandleProjectChanged; + IdeApp.Workspace.WorkspaceItemUnloaded -= HandleWorkspaceItemUnloaded; + IdeApp.Workspace.WorkspaceItemLoaded -= HandleWorkspaceItemLoaded;; if (caret != null) { caret.PositionChanged -= UpdatePath; @@ -65,20 +67,46 @@ namespace MonoDevelop.CSharp Mono.TextEditor.Caret caret; CSharpCompletionTextEditorExtension ext; - List<DotNetProject> ownerProjects; + List<DotNetProject> ownerProjects = new List<DotNetProject> (); public override void Initialize () { CurrentPath = new PathEntry[] { new PathEntry (GettextCatalog.GetString ("No selection")) { Tag = null } }; isPathSet = false; - UpdateOwnerProjects (); - UpdatePath (null, null); + // Delay the execution of UpdateOwnerProjects since it may end calling Document.AttachToProject, + // which shouldn't be called while the extension chain is being initialized. + Gtk.Application.Invoke (delegate { + UpdateOwnerProjects (); + UpdatePath (null, null); + }); caret = Document.Editor.Caret; caret.PositionChanged += UpdatePath; ext = Document.GetContent<CSharpCompletionTextEditorExtension> (); ext.TypeSegmentTreeUpdated += HandleTypeSegmentTreeUpdated; IdeApp.Workspace.FileAddedToProject += HandleProjectChanged; IdeApp.Workspace.FileRemovedFromProject += HandleProjectChanged; + IdeApp.Workspace.WorkspaceItemUnloaded += HandleWorkspaceItemUnloaded; + IdeApp.Workspace.WorkspaceItemLoaded += HandleWorkspaceItemLoaded;; + } + + void HandleWorkspaceItemLoaded (object sender, WorkspaceItemEventArgs e) + { + if (ownerProjects != null) + return; + UpdateOwnerProjects (e.Item.GetAllItems<DotNetProject> ()); + } + + void HandleWorkspaceItemUnloaded (object sender, WorkspaceItemEventArgs e) + { + if (ownerProjects == null) + return; + foreach (var p in e.Item.GetAllItems<DotNetProject> ()) { + ownerProjects.Remove (p); + } + if (ownerProjects.Count == 0) { + ownerProjects = null; + Document.AttachToProject (null); + } } void HandleProjectChanged (object sender, ProjectFileEventArgs e) @@ -92,9 +120,9 @@ namespace MonoDevelop.CSharp UpdatePath (null, null); } - void UpdateOwnerProjects () + void UpdateOwnerProjects (IEnumerable<DotNetProject> allProjects) { - var projects = new HashSet<DotNetProject> (IdeApp.Workspace.GetAllSolutionItems<DotNetProject> ().Where (p => p.IsFileInProject (Document.FileName))); + var projects = new HashSet<DotNetProject> (allProjects.Where (p => p.IsFileInProject (Document.FileName))); if (ownerProjects == null || !projects.SetEquals (ownerProjects)) { ownerProjects = projects.OrderBy (p => p.Name).ToList (); var dnp = Document.Project as DotNetProject; @@ -106,6 +134,11 @@ namespace MonoDevelop.CSharp Document.AttachToProject (pp); } } + } + + void UpdateOwnerProjects () + { + UpdateOwnerProjects (IdeApp.Workspace.GetAllItems<DotNetProject> ()); if (Document.Project == null && ownerProjects.Count > 0) Document.AttachToProject (ownerProjects[0]); } @@ -481,7 +514,7 @@ namespace MonoDevelop.CSharp var curType = (EntityDeclaration)unit.GetNodeAt (loc, n => n is TypeDeclaration || n is DelegateDeclaration); - var curProject = ownerProjects.Count > 1 ? Document.Project : null; + var curProject = ownerProjects != null && ownerProjects.Count > 1 ? Document.Project : null; var segMember = compExt.GetMemberAt (caretOffset); if (segMember != null) { @@ -512,7 +545,7 @@ namespace MonoDevelop.CSharp var result = new List<PathEntry> (); - if (ownerProjects.Count > 1) { + if (ownerProjects != null && ownerProjects.Count > 1) { // Current project if there is more than one result.Add (new PathEntry (ImageService.GetIcon (Document.Project.StockIcon, Gtk.IconSize.Menu), GLib.Markup.EscapeText (Document.Project.Name)) { Tag = Document.Project }); } diff --git a/main/src/addins/CSharpBinding/gtk-gui/gui.stetic b/main/src/addins/CSharpBinding/gtk-gui/gui.stetic index ea86d2e379..ebc8427558 100644 --- a/main/src/addins/CSharpBinding/gtk-gui/gui.stetic +++ b/main/src/addins/CSharpBinding/gtk-gui/gui.stetic @@ -514,6 +514,7 @@ None</property> </widget> <widget class="Gtk.Bin" id="MonoDevelop.CSharp.Project.CompilerOptionsPanelWidget" design-size="471 438"> <property name="MemberName" /> + <property name="GeneratePublic">False</property> <child> <widget class="Gtk.VBox" id="vbox1"> <property name="MemberName" /> diff --git a/main/src/addins/CSharpBinding/templates/PortableLibrary.xpt.xml b/main/src/addins/CSharpBinding/templates/PortableLibrary.xpt.xml index 51a5345be6..a26a237dce 100644 --- a/main/src/addins/CSharpBinding/templates/PortableLibrary.xpt.xml +++ b/main/src/addins/CSharpBinding/templates/PortableLibrary.xpt.xml @@ -24,8 +24,8 @@ <StartupProject>${ProjectName}</StartupProject> </Options> - <Project name = "${ProjectName}" directory = "." type = "PortableDotNet"> - <Options Target = "Library" TargetFrameworkVersion = ".NETPortable,Version=v4.5,Profile=Profile78"/> + <Project name = "${ProjectName}" directory = "."> + <Options Target = "Library" TargetFrameworkVersion = ".NETPortable,Version=v4.5,Profile=Profile78" flavorIds="{786C830F-07A1-408B-BD7F-6EE04809D6DB}"/> <References> </References> <Files> diff --git a/main/src/addins/ChangeLogAddIn/ChangeLogService.cs b/main/src/addins/ChangeLogAddIn/ChangeLogService.cs index 587bb5db7c..25581a2cf2 100644 --- a/main/src/addins/ChangeLogAddIn/ChangeLogService.cs +++ b/main/src/addins/ChangeLogAddIn/ChangeLogService.cs @@ -38,7 +38,7 @@ namespace MonoDevelop.ChangeLogAddIn // Returns the path of the ChangeLog where changes of the provided file have to be logged. // Returns null if no ChangeLog could be found. // Returns an empty string if changes don't have to be logged. - public static string GetChangeLogForFile (string baseCommitPath, FilePath file, out SolutionItem parentEntry, out ChangeLogPolicy policy) + public static string GetChangeLogForFile (string baseCommitPath, FilePath file, out SolutionFolderItem parentEntry, out ChangeLogPolicy policy) { parentEntry = null; policy = null; @@ -50,7 +50,7 @@ namespace MonoDevelop.ChangeLogAddIn string bestPath = null; file = file.CanonicalPath; - foreach (SolutionItem e in IdeApp.Workspace.GetAllSolutionItems ()) { + foreach (SolutionFolderItem e in IdeApp.Workspace.GetAllSolutionItems ()) { if (e is Project && ((Project)e).Files.GetFile (file) != null) { parentEntry = e; break; @@ -108,18 +108,18 @@ namespace MonoDevelop.ChangeLogAddIn public static string GetChangeLogForFile (string baseCommitPath, string file) { - SolutionItem parentEntry; + SolutionFolderItem parentEntry; ChangeLogPolicy policy; return GetChangeLogForFile (baseCommitPath, file, out parentEntry, out policy); } - public static CommitMessageStyle GetMessageStyle (SolutionItem item) + public static CommitMessageStyle GetMessageStyle (SolutionFolderItem item) { ChangeLogPolicy policy = item != null ? GetPolicy (item) : new ChangeLogPolicy (); return policy.MessageStyle; } - static ChangeLogPolicy GetPolicy (SolutionItem item) + static ChangeLogPolicy GetPolicy (SolutionFolderItem item) { return item.Policies.Get<ChangeLogPolicy> (); } diff --git a/main/src/addins/ChangeLogAddIn/CommitDialogExtensionWidget.cs b/main/src/addins/ChangeLogAddIn/CommitDialogExtensionWidget.cs index e5e8b5b266..3b7d78f0b9 100644 --- a/main/src/addins/ChangeLogAddIn/CommitDialogExtensionWidget.cs +++ b/main/src/addins/ChangeLogAddIn/CommitDialogExtensionWidget.cs @@ -156,7 +156,7 @@ namespace MonoDevelop.ChangeLogAddIn } if (!cset.ContainsFile (ce.File)) { if (!cset.Repository.GetVersionInfo (ce.File).IsVersioned) - cset.Repository.Add (ce.File, false, new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor ()); + cset.Repository.Add (ce.File, false, new MonoDevelop.Core.ProgressMonitor ()); cset.AddFile (ce.File); } } @@ -226,7 +226,7 @@ namespace MonoDevelop.ChangeLogAddIn requireComment = false; foreach (ChangeSetItem item in cset.Items) { - SolutionItem parentItem; + SolutionFolderItem parentItem; ChangeLogPolicy policy; string logf = ChangeLogService.GetChangeLogForFile (cset.BaseLocalPath, item.LocalPath, out parentItem, out policy); diff --git a/main/src/addins/ChangeLogAddIn/ProjectOptionPanelWidget.cs b/main/src/addins/ChangeLogAddIn/ProjectOptionPanelWidget.cs index 1492307f2b..777de0e1e4 100644 --- a/main/src/addins/ChangeLogAddIn/ProjectOptionPanelWidget.cs +++ b/main/src/addins/ChangeLogAddIn/ProjectOptionPanelWidget.cs @@ -68,7 +68,7 @@ namespace MonoDevelop.ChangeLogAddIn format.MaxColumns = 70; format.Style = style; - SolutionItem item = null; + SolutionFolderItem item = null; if (parent.ConfiguredSolutionItem != null) item = parent.ConfiguredSolutionItem; else if (parent.ConfiguredSolution != null) diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment.Linux/MonoDevelop.Deployment.Linux/BasicOptionPanelWidget.cs b/main/src/addins/Deployment/MonoDevelop.Deployment.Linux/MonoDevelop.Deployment.Linux/BasicOptionPanelWidget.cs index dd9d2e72cc..e34322c60f 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment.Linux/MonoDevelop.Deployment.Linux/BasicOptionPanelWidget.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment.Linux/MonoDevelop.Deployment.Linux/BasicOptionPanelWidget.cs @@ -10,9 +10,9 @@ namespace MonoDevelop.Deployment.Linux [System.ComponentModel.ToolboxItem(true)] public partial class BasicOptionPanelWidget : Gtk.Bin { - SolutionItem entry; + SolutionFolderItem entry; - public BasicOptionPanelWidget (SolutionItem entry, bool creatingProject) + public BasicOptionPanelWidget (SolutionFolderItem entry, bool creatingProject) { this.Build(); diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment.Linux/MonoDevelop.Deployment.Linux/LinuxDeployData.cs b/main/src/addins/Deployment/MonoDevelop.Deployment.Linux/MonoDevelop.Deployment.Linux/LinuxDeployData.cs index 255b54257b..2de01203cb 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment.Linux/MonoDevelop.Deployment.Linux/LinuxDeployData.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment.Linux/MonoDevelop.Deployment.Linux/LinuxDeployData.cs @@ -22,10 +22,10 @@ namespace MonoDevelop.Deployment.Linux [ItemProperty (DefaultValue=true)] bool generatePcFile = true; - SolutionItem entry; + SolutionFolderItem entry; bool connected; - internal LinuxDeployData (SolutionItem entry) + internal LinuxDeployData (SolutionFolderItem entry) { this.entry = entry; } @@ -34,7 +34,7 @@ namespace MonoDevelop.Deployment.Linux { } - public static LinuxDeployData GetLinuxDeployData (SolutionItem entry) + public static LinuxDeployData GetLinuxDeployData (SolutionFolderItem entry) { LinuxDeployData data = (LinuxDeployData) entry.ExtendedProperties ["Deployment.LinuxDeployData"]; if (data != null) { @@ -55,12 +55,12 @@ namespace MonoDevelop.Deployment.Linux return data; } - internal static LinuxDeployData CreateDefault (SolutionItem entry) + internal static LinuxDeployData CreateDefault (SolutionFolderItem entry) { return new LinuxDeployData (entry); } - void Bind (SolutionItem entry) + void Bind (SolutionFolderItem entry) { this.entry = entry; } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment.Linux/MonoDevelop.Deployment.Linux/LinuxIntegrationProjectFeature.cs b/main/src/addins/Deployment/MonoDevelop.Deployment.Linux/MonoDevelop.Deployment.Linux/LinuxIntegrationProjectFeature.cs index 74c0f4df37..6d01470859 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment.Linux/MonoDevelop.Deployment.Linux/LinuxIntegrationProjectFeature.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment.Linux/MonoDevelop.Deployment.Linux/LinuxIntegrationProjectFeature.cs @@ -17,32 +17,30 @@ namespace MonoDevelop.Deployment.Linux get { return GettextCatalog.GetString ("Set options for generating files to better integrate the application or library in a Unix system."); } } - public FeatureSupportLevel GetSupportLevel (SolutionFolder parentCombine, SolutionItem entry) + public FeatureSupportLevel GetSupportLevel (SolutionFolder parentCombine, SolutionFolderItem entry) { - if (entry is DotNetAssemblyProject) - return FeatureSupportLevel.SupportedByDefault; if (entry is DotNetProject) - return FeatureSupportLevel.Supported; + return FeatureSupportLevel.SupportedByDefault; else return FeatureSupportLevel.NotSupported; } - public bool SupportsSolutionItem (SolutionFolder parentCombine, SolutionItem entry) + public bool SupportsSolutionItem (SolutionFolder parentCombine, SolutionFolderItem entry) { return entry is DotNetProject; } - public Widget CreateFeatureEditor (SolutionFolder parentCombine, SolutionItem entry) + public Widget CreateFeatureEditor (SolutionFolder parentCombine, SolutionFolderItem entry) { return new BasicOptionPanelWidget ((DotNetProject) entry, true); } - public void ApplyFeature (SolutionFolder parentCombine, SolutionItem entry, Widget editor) + public void ApplyFeature (SolutionFolder parentCombine, SolutionFolderItem entry, Widget editor) { ((BasicOptionPanelWidget)editor).Store (); } - public string Validate (SolutionFolder parentCombine, SolutionItem entry, Gtk.Widget editor) + public string Validate (SolutionFolder parentCombine, SolutionFolderItem entry, Gtk.Widget editor) { return ((BasicOptionPanelWidget)editor).Validate (); } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Commands/Commands.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Commands/Commands.cs index 9096ae8463..01cf8485c4 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Commands/Commands.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Commands/Commands.cs @@ -18,7 +18,7 @@ namespace MonoDevelop.Deployment { protected override void Run () { - SolutionItem entry = IdeApp.ProjectOperations.CurrentSelectedSolutionItem; + SolutionFolderItem entry = IdeApp.ProjectOperations.CurrentSelectedSolutionItem; DeployDialog dlg = new DeployDialog (entry, false); try { if (MessageService.RunCustomDialog (dlg) == (int) Gtk.ResponseType.Ok) { @@ -33,11 +33,11 @@ namespace MonoDevelop.Deployment project.FileName = Path.Combine (dlg.NewProjectSolution.BaseDirectory, project.Name + ".mdse"); project.Packages.Add (p); dlg.NewProjectSolution.Items.Add (project); - IdeApp.ProjectOperations.Save (dlg.NewProjectSolution.ParentSolution); + IdeApp.ProjectOperations.SaveAsync (dlg.NewProjectSolution.ParentSolution); } else { dlg.ExistingPackagingProject.Packages.Add (p); - IdeApp.ProjectOperations.Save (dlg.ExistingPackagingProject); + IdeApp.ProjectOperations.SaveAsync (dlg.ExistingPackagingProject); } } Package pkg = new Package (dlg.PackageBuilder); @@ -63,7 +63,7 @@ namespace MonoDevelop.Deployment try { if (MessageService.RunCustomDialog (dlg) == (int) Gtk.ResponseType.Ok) { project.AddPackage (dlg.NewPackageName, dlg.PackageBuilder); - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); } } finally { dlg.Destroy (); @@ -80,7 +80,7 @@ namespace MonoDevelop.Deployment { protected override void Run () { - SolutionItem entry = IdeApp.ProjectOperations.CurrentSelectedSolutionItem; + SolutionFolderItem entry = IdeApp.ProjectOperations.CurrentSelectedSolutionItem; DeployOperations.Install (entry, IdeApp.Workspace.ActiveConfiguration); } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/DeployDialog.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/DeployDialog.cs index 7fa3039562..4fbe017f7b 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/DeployDialog.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/DeployDialog.cs @@ -7,6 +7,7 @@ using MonoDevelop.Projects; using MonoDevelop.Core; using MonoDevelop.Ide; using MonoDevelop.Components; +using System.Linq; namespace MonoDevelop.Deployment.Gui { @@ -16,11 +17,11 @@ namespace MonoDevelop.Deployment.Gui List<PackageBuilder> builders = new List<PackageBuilder> (); PackageBuilder currentBuilder; Gtk.Widget currentEditor; - ReadOnlyCollection<SolutionFolder> combineList; - ReadOnlyCollection<PackagingProject> projectsList; - SolutionItem defaultEntry; + List<SolutionFolder> combineList; + List<PackagingProject> projectsList; + SolutionFolderItem defaultEntry; - public DeployDialog (SolutionItem defaultEntry, bool createBuilderOnly) + public DeployDialog (SolutionFolderItem defaultEntry, bool createBuilderOnly) { this.Build(); notebook.ShowTabs = false; @@ -104,7 +105,7 @@ namespace MonoDevelop.Deployment.Gui { // Fill the combine list int n=0, sel=-1; - combineList = IdeApp.ProjectOperations.CurrentSelectedSolution.GetAllSolutionItems<SolutionFolder> (); + combineList = IdeApp.ProjectOperations.CurrentSelectedSolution.GetAllItems<SolutionFolder> ().ToList (); foreach (SolutionFolder c in combineList) { string name = c.Name; SolutionFolder co = c; @@ -121,7 +122,7 @@ namespace MonoDevelop.Deployment.Gui comboCreateProject.Active = 0; // Fill the packaging project list - projectsList = IdeApp.ProjectOperations.CurrentSelectedSolution.GetAllSolutionItems<PackagingProject> (); + projectsList = IdeApp.ProjectOperations.CurrentSelectedSolution.GetAllItems<PackagingProject> ().ToList(); if (projectsList.Count == 0) { radioAddProject.Sensitive = false; } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/DeployOperations.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/DeployOperations.cs index 1f877eef1d..74fab9ef93 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/DeployOperations.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/DeployOperations.cs @@ -3,14 +3,15 @@ using System.Collections; using MonoDevelop.Core; using MonoDevelop.Ide; using MonoDevelop.Projects; +using System.Threading.Tasks; namespace MonoDevelop.Deployment.Gui { public static class DeployOperations { - public static void Install (SolutionItem entry, ConfigurationSelector configuration) + public static void Install (SolutionFolderItem entry, ConfigurationSelector configuration) { - using (IProgressMonitor mon = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor ()) { + using (ProgressMonitor mon = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor ()) { InstallDialog dlg = new InstallDialog (entry); try { if (MessageService.RunCustomDialog (dlg) == (int) Gtk.ResponseType.Ok) @@ -21,36 +22,29 @@ namespace MonoDevelop.Deployment.Gui } } - public static IAsyncOperation BuildPackages (PackagingProject project) + public static Task BuildPackages (PackagingProject project) { return BuildPackages (project.Packages); } - static IAsyncOperation BuildPackages (ICollection packages) + static async Task BuildPackages (ICollection packages) { - IProgressMonitor mon = IdeApp.Workbench.ProgressMonitors.GetToolOutputProgressMonitor (true); + ProgressMonitor mon = IdeApp.Workbench.ProgressMonitors.GetToolOutputProgressMonitor (true); // Run the deploy command in a background thread to avoid // deadlocks with the gui thread - System.Threading.Thread t = new System.Threading.Thread ( - delegate () { - using (mon) { - mon.BeginTask ("Creating packages", packages.Count); - foreach (Package p in packages) { - DeployService.BuildPackage (mon, p); - mon.Step (1); - } - mon.EndTask (); + using (mon) { + mon.BeginTask ("Creating packages", packages.Count); + foreach (Package p in packages) { + await DeployService.BuildPackage (mon, p); + mon.Step (1); } - }); - t.IsBackground = true; - t.Start (); - - return mon.AsyncOperation; + mon.EndTask (); + } } - public static IAsyncOperation BuildPackage (Package package) + public static Task BuildPackage (Package package) { return BuildPackages (new object[] { package }); } @@ -59,7 +53,7 @@ namespace MonoDevelop.Deployment.Gui { EditPackageDialog dlg = new EditPackageDialog (package); if (MessageService.ShowCustomDialog (dlg) == (int) Gtk.ResponseType.Ok) - IdeApp.ProjectOperations.Save (package.ParentProject); + IdeApp.ProjectOperations.SaveAsync (package.ParentProject); } } } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/EditPackageDialog.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/EditPackageDialog.cs index 7c2b81062e..58049d30d0 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/EditPackageDialog.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/EditPackageDialog.cs @@ -54,7 +54,7 @@ namespace MonoDevelop.Deployment.Gui protected virtual void OnEntrySelectorSelectionChanged(object sender, System.EventArgs e) { - SolutionItem ce = entrySelector.GetSelectedEntry (); + SolutionFolderItem ce = entrySelector.GetSelectedEntry (); if (ce != null) target.SetSolutionItem (ce, entrySelector.GetSelectedChildren ()); } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/EntrySelectionTree.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/EntrySelectionTree.cs index d5e531f3b8..662d2da34f 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/EntrySelectionTree.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/EntrySelectionTree.cs @@ -7,6 +7,7 @@ using System.Collections.ObjectModel; using MonoDevelop.Ide; using MonoDevelop.Projects; using MonoDevelop.Components; +using System.Linq; namespace MonoDevelop.Deployment.Gui { @@ -15,7 +16,7 @@ namespace MonoDevelop.Deployment.Gui internal partial class EntrySelectionTree : Gtk.Bin { TreeStore store; - Dictionary<SolutionItem,SolutionItem> selectedEntries = new Dictionary<SolutionItem,SolutionItem> (); + Dictionary<SolutionFolderItem,SolutionFolderItem> selectedEntries = new Dictionary<SolutionFolderItem,SolutionFolderItem> (); PackageBuilder builder; Solution solution; @@ -44,13 +45,13 @@ namespace MonoDevelop.Deployment.Gui tree.AppendColumn (col); } - public void Fill (PackageBuilder builder, SolutionItem selection) + public void Fill (PackageBuilder builder, SolutionFolderItem selection) { store.Clear (); this.builder = builder; if (selection is SolutionFolder) { - foreach (SolutionItem e in ((SolutionFolder)selection).GetAllItems ()) { + foreach (SolutionFolderItem e in ((SolutionFolder)selection).GetAllItems ()) { if (builder.CanBuild (e)) selectedEntries [e] = e; } @@ -64,17 +65,15 @@ namespace MonoDevelop.Deployment.Gui else { solution = IdeApp.ProjectOperations.CurrentSelectedSolution; if (solution == null) { - ReadOnlyCollection<Solution> items = IdeApp.ProjectOperations.CurrentSelectedWorkspaceItem.GetAllSolutions (); - if (items.Count > 0) - solution = items [0]; - else + solution = IdeApp.ProjectOperations.CurrentSelectedWorkspaceItem.GetAllItems<Solution> ().FirstOrDefault(); + if (solution == null) return; } } AddEntry (TreeIter.Zero, solution.RootFolder); } - void AddEntry (TreeIter iter, SolutionItem entry) + void AddEntry (TreeIter iter, SolutionFolderItem entry) { string icon; if (entry.ParentFolder == null) @@ -101,49 +100,49 @@ namespace MonoDevelop.Deployment.Gui tree.ExpandToPath (store.GetPath (iter)); if (entry is SolutionFolder) { - foreach (SolutionItem ce in ((SolutionFolder)entry).Items) { + foreach (SolutionFolderItem ce in ((SolutionFolder)entry).Items) { AddEntry (iter, ce); } } } - public void SetSelection (SolutionItem rootEntry, SolutionItem[] childEntries) + public void SetSelection (SolutionFolderItem rootEntry, SolutionFolderItem[] childEntries) { selectedEntries.Clear (); selectedEntries [rootEntry] = rootEntry; - foreach (SolutionItem e in childEntries) + foreach (SolutionFolderItem e in childEntries) selectedEntries [e] = e; UpdateSelectionChecks (TreeIter.Zero, true); } - public SolutionItem GetSelectedEntry () + public SolutionFolderItem GetSelectedEntry () { return GetCommonSolutionItem (); } - public SolutionItem[] GetSelectedChildren () + public SolutionFolderItem[] GetSelectedChildren () { // The first entry is the root entry - SolutionItem common = GetCommonSolutionItem (); + SolutionFolderItem common = GetCommonSolutionItem (); if (common == null) return null; ArrayList list = new ArrayList (); - foreach (SolutionItem e in selectedEntries.Keys) + foreach (SolutionFolderItem e in selectedEntries.Keys) if (e != common) list.Add (e); - return (SolutionItem[]) list.ToArray (typeof(SolutionItem)); + return (SolutionFolderItem[]) list.ToArray (typeof(SolutionFolderItem)); } void OnToggled (object sender, Gtk.ToggledArgs args) { TreeIter iter; store.GetIterFromString (out iter, args.Path); - SolutionItem ob = (SolutionItem) store.GetValue (iter, 2); + SolutionFolderItem ob = (SolutionFolderItem) store.GetValue (iter, 2); if (selectedEntries.ContainsKey (ob)) { selectedEntries.Remove (ob); store.SetValue (iter, 3, false); if (ob is SolutionFolder) { - foreach (SolutionItem e in ((SolutionFolder)ob).GetAllItems ()) + foreach (SolutionFolderItem e in ((SolutionFolder)ob).GetAllItems ()) selectedEntries.Remove (e); UpdateSelectionChecks (TreeIter.Zero, false); } @@ -151,13 +150,13 @@ namespace MonoDevelop.Deployment.Gui selectedEntries [ob] = ob; store.SetValue (iter, 3, true); if (ob is SolutionFolder) { - foreach (SolutionItem e in ((SolutionFolder)ob).GetAllItems ()) { + foreach (SolutionFolderItem e in ((SolutionFolder)ob).GetAllItems ()) { if (builder.CanBuild (e)) selectedEntries [e] = e; } UpdateSelectionChecks (TreeIter.Zero, false); } - SelectCommonCombine ((SolutionItem)ob); + SelectCommonCombine ((SolutionFolderItem)ob); } if (SelectionChanged != null) SelectionChanged (this, EventArgs.Empty); @@ -174,7 +173,7 @@ namespace MonoDevelop.Deployment.Gui return; } do { - bool sel = selectedEntries.ContainsKey ((SolutionItem) store.GetValue (iter, 2)); + bool sel = selectedEntries.ContainsKey ((SolutionFolderItem) store.GetValue (iter, 2)); store.SetValue (iter, 3, sel); if (sel) tree.ExpandToPath (store.GetPath (iter)); @@ -183,16 +182,16 @@ namespace MonoDevelop.Deployment.Gui while (store.IterNext (ref iter)); } - void SelectCommonCombine (SolutionItem e) + void SelectCommonCombine (SolutionFolderItem e) { - SolutionItem common = GetCommonSolutionItem (); + SolutionFolderItem common = GetCommonSolutionItem (); if (common == null) return; selectedEntries [common] = common; - SolutionItem[] entries = new SolutionItem [selectedEntries.Count]; + SolutionFolderItem[] entries = new SolutionFolderItem [selectedEntries.Count]; selectedEntries.Keys.CopyTo (entries, 0); - foreach (SolutionItem se in entries) { - SolutionItem ce = se; + foreach (SolutionFolderItem se in entries) { + SolutionFolderItem ce = se; while (ce != null && ce != common) { selectedEntries [ce] = ce; ce = ce.ParentFolder; @@ -201,7 +200,7 @@ namespace MonoDevelop.Deployment.Gui UpdateSelectionChecks (TreeIter.Zero, false); } - SolutionItem GetCommonSolutionItem () + SolutionFolderItem GetCommonSolutionItem () { return PackageBuilder.GetCommonSolutionItem (selectedEntries.Keys); } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/InstallDialog.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/InstallDialog.cs index 921eab2bb2..e82e53a0d9 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/InstallDialog.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/InstallDialog.cs @@ -6,7 +6,7 @@ namespace MonoDevelop.Deployment.Gui { internal partial class InstallDialog : Gtk.Dialog { - public InstallDialog (SolutionItem entry) + public InstallDialog (SolutionFolderItem entry) { this.Build(); nameEntry.Text = entry.Name; diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/PackagingFeature.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/PackagingFeature.cs index d7ae6b1da2..823c8bf602 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/PackagingFeature.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/PackagingFeature.cs @@ -17,7 +17,7 @@ namespace MonoDevelop.Deployment.Gui get { return GettextCatalog.GetString ("Add a Packaging Project to the solution for generating different kinds of packages for the new project."); } } - public FeatureSupportLevel GetSupportLevel (SolutionFolder parentCombine, SolutionItem entry) + public FeatureSupportLevel GetSupportLevel (SolutionFolder parentCombine, SolutionFolderItem entry) { if (parentCombine == null) return FeatureSupportLevel.NotSupported; @@ -30,17 +30,17 @@ namespace MonoDevelop.Deployment.Gui return FeatureSupportLevel.NotSupported; } - public Widget CreateFeatureEditor (SolutionFolder parentCombine, SolutionItem entry) + public Widget CreateFeatureEditor (SolutionFolder parentCombine, SolutionFolderItem entry) { return new PackagingFeatureWidget (parentCombine, entry); } - public void ApplyFeature (SolutionFolder parentCombine, SolutionItem entry, Widget editor) + public void ApplyFeature (SolutionFolder parentCombine, SolutionFolderItem entry, Widget editor) { ((PackagingFeatureWidget)editor).ApplyFeature (); } - public string Validate (SolutionFolder parentCombine, SolutionItem entry, Gtk.Widget editor) + public string Validate (SolutionFolder parentCombine, SolutionFolderItem entry, Gtk.Widget editor) { return null; } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/PackagingFeatureWidget.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/PackagingFeatureWidget.cs index 75a45746c2..9f3b43045b 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/PackagingFeatureWidget.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Gui/PackagingFeatureWidget.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Collections.ObjectModel; using MonoDevelop.Core; using MonoDevelop.Projects; +using System.Linq; namespace MonoDevelop.Deployment.Gui { @@ -11,22 +12,22 @@ namespace MonoDevelop.Deployment.Gui [System.ComponentModel.ToolboxItem(true)] internal partial class PackagingFeatureWidget : Gtk.Bin { - SolutionItem entry; + SolutionFolderItem entry; SolutionFolder parentFolder; ArrayList packages = new ArrayList (); PackagingProject newPackProject; bool creatingPackProject; - public PackagingFeatureWidget (SolutionFolder parentFolder, SolutionItem entry) + public PackagingFeatureWidget (SolutionFolder parentFolder, SolutionFolderItem entry) { this.Build(); this.entry = entry; this.parentFolder = parentFolder; - + creatingPackProject = entry is PackagingProject; if (!creatingPackProject) { - ReadOnlyCollection<PackagingProject> packProjects = parentFolder.ParentSolution.GetAllSolutionItems<PackagingProject> (); + var packProjects = parentFolder.ParentSolution.GetAllItems<PackagingProject> ().ToList (); newPackProject = new PackagingProject (); string label = GettextCatalog.GetString ("Create packages for this project in a new Packaging Project"); @@ -146,12 +147,12 @@ namespace MonoDevelop.Deployment.Gui if (creatingPackProject) { pb.SetSolutionItem (parentFolder.ParentSolution.RootFolder); // Add all compatible projects - foreach (SolutionItem e in parentFolder.ParentSolution.GetAllSolutionItems ()) { + foreach (SolutionFolderItem e in parentFolder.ParentSolution.GetAllSolutionItems ()) { if (pb.CanBuild (e)) pb.AddEntry (e); } } else { - pb.SetSolutionItem (parentFolder, new SolutionItem [] { entry }); + pb.SetSolutionItem (parentFolder, new SolutionFolderItem [] { entry }); } PackageBuilder[] defp = pb.CreateDefaultBuilders (); diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.NodeBuilders/PackageNodeBuilder.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.NodeBuilders/PackageNodeBuilder.cs index 9ac26fb2c2..f721dfc27e 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.NodeBuilders/PackageNodeBuilder.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.NodeBuilders/PackageNodeBuilder.cs @@ -123,7 +123,7 @@ namespace MonoDevelop.Deployment.NodeBuilders Package package = CurrentNode.DataItem as Package; if (MessageService.AskQuestion (GettextCatalog.GetString ("Are you sure you want to delete the package '{0}'?", package.Name), AlertButton.Cancel, AlertButton.Delete) == AlertButton.Delete) { package.ParentProject.Packages.Remove (package); - IdeApp.ProjectOperations.Save (package.ParentProject); + IdeApp.ProjectOperations.SaveAsync (package.ParentProject); } } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/BaseFuseFileCopyHandler.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/BaseFuseFileCopyHandler.cs index b93a173858..dfaca87060 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/BaseFuseFileCopyHandler.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/BaseFuseFileCopyHandler.cs @@ -44,7 +44,7 @@ namespace MonoDevelop.Deployment.Targets get { throw new NotImplementedException ("Inheriting classes must override this."); } } - public override void CopyFiles (IProgressMonitor monitor, IFileReplacePolicy replacePolicy, FileCopyConfiguration copyConfig, DeployFileCollection deployFiles, DeployContext context) + public override void CopyFiles (ProgressMonitor monitor, IFileReplacePolicy replacePolicy, FileCopyConfiguration copyConfig, DeployFileCollection deployFiles, DeployContext context) { DirectoryInfo tempDir = null; try { @@ -93,9 +93,9 @@ namespace MonoDevelop.Deployment.Targets tempDir.Delete (); } - public abstract void MountTempDirectory (IProgressMonitor monitor, FileCopyConfiguration copyConfig, string tempPath); + public abstract void MountTempDirectory (ProgressMonitor monitor, FileCopyConfiguration copyConfig, string tempPath); - protected void RunFuseCommand (IProgressMonitor monitor, string command, string args) + protected void RunFuseCommand (ProgressMonitor monitor, string command, string args) { LoggingService.LogInfo ("Running FUSE command: {0} {1}", command, args); var log = new StringWriter (); @@ -104,13 +104,12 @@ namespace MonoDevelop.Deployment.Targets RedirectStandardOutput = true, UseShellExecute = false, }; - using (var opMon = new AggregatedOperationMonitor (monitor)) { - using (var pWrapper = MonoDevelop.Core.Runtime.ProcessService.StartProcess (psi, log, log, null)) { - opMon.AddOperation (pWrapper); - pWrapper.WaitForOutput (); - if (pWrapper.ExitCode != 0) - throw new Exception (log.ToString ()); - } + + using (var pWrapper = Runtime.ProcessService.StartProcess (psi, log, log, null)) + using (monitor.CancellationToken.Register (pWrapper.Cancel)) { + pWrapper.WaitForOutput (); + if (pWrapper.ExitCode != 0) + throw new Exception (log.ToString ()); } } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/BinariesZipPackageBuilder.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/BinariesZipPackageBuilder.cs index b663c990b9..2149ea019b 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/BinariesZipPackageBuilder.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/BinariesZipPackageBuilder.cs @@ -39,7 +39,7 @@ namespace MonoDevelop.Deployment.Targets get { return "Archive of Binaries"; } } - public override void InitializeSettings (SolutionItem entry) + public override void InitializeSettings (SolutionFolderItem entry) { targetFile = Path.Combine (entry.BaseDirectory, entry.Name) + ".tar.gz"; if (entry.ParentSolution != null) @@ -51,7 +51,7 @@ namespace MonoDevelop.Deployment.Targets return configuration != null ? new string [] { configuration } : new string [0]; } - public override bool CanBuild (SolutionItem entry) + public override bool CanBuild (SolutionFolderItem entry) { // Can build anything but PackagingProject return !(entry is PackagingProject); @@ -62,18 +62,21 @@ namespace MonoDevelop.Deployment.Targets return new DeployContext (this, platform, null); } - protected override bool OnBuild (IProgressMonitor monitor, DeployContext ctx) + protected override bool OnBuild (ProgressMonitor monitor, DeployContext ctx) { string tmpFolder = null; - + try { SolutionConfigurationSelector conf = (SolutionConfigurationSelector) configuration; - BuildResult res = RootSolutionItem.Build (monitor, conf); - if (res.ErrorCount > 0) { - foreach (BuildError e in res.Errors) - monitor.ReportError (e.ToString (), null); - monitor.ReportError (GettextCatalog.GetString ("The source project failed to build."), null); - return false; + var bt = RootSolutionItem as IBuildTarget; + if (bt != null) { + BuildResult res = bt.Build (monitor, conf).Result; + if (res.ErrorCount > 0) { + foreach (BuildError e in res.Errors) + monitor.ReportError (e.ToString (), null); + monitor.ReportError (GettextCatalog.GetString ("The source project failed to build."), null); + return false; + } } tmpFolder = FileService.CreateTempDirectory (); @@ -107,8 +110,7 @@ namespace MonoDevelop.Deployment.Targets if (tmpFolder != null) Directory.Delete (tmpFolder, true); } - if (monitor.AsyncOperation.Success) - monitor.Log.WriteLine (GettextCatalog.GetString ("Created file: {0}", targetFile)); + monitor.Log.WriteLine (GettextCatalog.GetString ("Created file: {0}", targetFile)); return true; } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/CommandPackageBuilder.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/CommandPackageBuilder.cs index 353331931a..a3d2a975c0 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/CommandPackageBuilder.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/CommandPackageBuilder.cs @@ -33,6 +33,7 @@ using MonoDevelop.Projects; using MonoDevelop.Core.Serialization; using MonoDevelop.Core; using MonoDevelop.Core.Execution; +using System.Threading; namespace MonoDevelop.Deployment.Targets { @@ -88,7 +89,7 @@ namespace MonoDevelop.Deployment.Targets } } - protected override bool OnBuild (IProgressMonitor monitor, DeployContext ctx) + protected override bool OnBuild (ProgressMonitor monitor, DeployContext ctx) { string consMsg; IConsole cons; @@ -101,7 +102,7 @@ namespace MonoDevelop.Deployment.Targets } monitor.Log.WriteLine (GettextCatalog.GetString ("Executing: {0} {1} {2}", Command, Arguments, consMsg)); - IProcessAsyncOperation process = Runtime.ProcessService.StartConsoleProcess (Command, Arguments, workingDirectory, cons, null); + ProcessAsyncOperation process = Runtime.ProcessService.StartConsoleProcess (Command, Arguments, workingDirectory, cons, null); process.WaitForCompleted (); @@ -115,20 +116,21 @@ namespace MonoDevelop.Deployment.Targets class MonitorConsole: IConsole { StringReader nullReader; - IProgressMonitor monitor; + ProgressMonitor monitor; + CancellationTokenRegistration tr; - public MonitorConsole (IProgressMonitor monitor) + public MonitorConsole (ProgressMonitor monitor) { this.monitor = monitor; - monitor.CancelRequested += OnCancel; + tr = monitor.CancellationToken.Register (OnCancel); } public void Dispose () { - monitor.CancelRequested -= OnCancel; + tr.Dispose (); } - void OnCancel (IProgressMonitor monitor) + void OnCancel () { if (CancelRequested != null) CancelRequested (this, EventArgs.Empty); diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/LocalFileCopyHandler.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/LocalFileCopyHandler.cs index f961d05edf..e143d62d39 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/LocalFileCopyHandler.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/LocalFileCopyHandler.cs @@ -51,12 +51,12 @@ namespace MonoDevelop.Deployment.Targets return new LocalFileCopyConfiguration (); } - public virtual void CopyFiles (IProgressMonitor monitor, IFileReplacePolicy replacePolicy, FileCopyConfiguration copyConfig, DeployFileCollection deployFiles, DeployContext context) + public virtual void CopyFiles (ProgressMonitor monitor, IFileReplacePolicy replacePolicy, FileCopyConfiguration copyConfig, DeployFileCollection deployFiles, DeployContext context) { InternalCopyFiles (monitor, replacePolicy, copyConfig, deployFiles, context, null); } - internal void InternalCopyFiles (IProgressMonitor monitor, IFileReplacePolicy replacePolicy, FileCopyConfiguration copyConfig, DeployFileCollection deployFiles, DeployContext context, string realPrefix) + internal void InternalCopyFiles (ProgressMonitor monitor, IFileReplacePolicy replacePolicy, FileCopyConfiguration copyConfig, DeployFileCollection deployFiles, DeployContext context, string realPrefix) { string targetDirectory = ((LocalFileCopyConfiguration) copyConfig).TargetDirectory; @@ -111,7 +111,7 @@ namespace MonoDevelop.Deployment.Targets long carry = 0; monitor.BeginTask (copyConfig.FriendlyLocation, progressBarLength); CopyReportCallback copyCallback = delegate (long bytes) { - if (monitor.IsCancelRequested) + if (monitor.CancellationToken.IsCancellationRequested) return false; int steps = (int) (bytes / stepSize); carry += bytes % stepSize; @@ -127,7 +127,7 @@ namespace MonoDevelop.Deployment.Targets //now the actual copy foreach (DeployFileConf file in files) { //abort the copy if cancelling - if (monitor.IsCancelRequested) + if (monitor.CancellationToken.IsCancellationRequested) break; EnsureDirectoryExists (Path.GetDirectoryName (file.InternalTargetFile)); diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/SourcesZipPackageBuilder.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/SourcesZipPackageBuilder.cs index 83c06ffc2d..6820ae2d8f 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/SourcesZipPackageBuilder.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/SourcesZipPackageBuilder.cs @@ -24,9 +24,9 @@ namespace MonoDevelop.Deployment.Targets get { return "Archive of Sources"; } } - public override bool CanBuild (SolutionItem entry) + public override bool CanBuild (SolutionFolderItem entry) { - return entry is SolutionFolder || entry is SolutionEntityItem; + return entry is SolutionFolder || entry is SolutionItem; } @@ -58,14 +58,14 @@ namespace MonoDevelop.Deployment.Targets set { targetFile = value; } } - protected override bool OnBuild (IProgressMonitor monitor, DeployContext ctx) + protected override bool OnBuild (ProgressMonitor monitor, DeployContext ctx) { string sourceFile; - SolutionItem entry = RootSolutionItem; + SolutionFolderItem entry = RootSolutionItem; if (entry is SolutionFolder) sourceFile = entry.ParentSolution.FileName; else - sourceFile = ((SolutionEntityItem)entry).FileName; + sourceFile = ((SolutionItem)entry).FileName; AggregatedProgressMonitor mon = new AggregatedProgressMonitor (); mon.AddSlaveMonitor (monitor, MonitorAction.WriteLog|MonitorAction.ReportError|MonitorAction.ReportWarning|MonitorAction.ReportSuccess); @@ -81,13 +81,13 @@ namespace MonoDevelop.Deployment.Targets // Export the project - SolutionItem[] ents = GetChildEntries (); + SolutionFolderItem[] ents = GetChildEntries (); string[] epaths = new string [ents.Length]; for (int n=0; n<ents.Length; n++) epaths [n] = ents [n].ItemId; - Services.ProjectService.Export (mon, sourceFile, epaths, folder, FileFormat); - if (!mon.AsyncOperation.Success) + var r = Services.ProjectService.Export (mon, sourceFile, epaths, folder, FileFormat).Result; + if (string.IsNullOrEmpty (r)) return false; // Create the archive @@ -99,12 +99,11 @@ namespace MonoDevelop.Deployment.Targets finally { Directory.Delete (tmpFolder, true); } - if (monitor.AsyncOperation.Success) - monitor.Log.WriteLine (GettextCatalog.GetString ("Created file: {0}", targetFile)); + monitor.Log.WriteLine (GettextCatalog.GetString ("Created file: {0}", targetFile)); return true; } - public override void InitializeSettings (SolutionItem entry) + public override void InitializeSettings (SolutionFolderItem entry) { targetFile = Path.Combine (entry.BaseDirectory, entry.Name) + ".tar.gz"; if (entry.ParentSolution != null) diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/SshFuseFileCopyHandler.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/SshFuseFileCopyHandler.cs index fef148d5c1..4029434912 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/SshFuseFileCopyHandler.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.Targets/SshFuseFileCopyHandler.cs @@ -42,7 +42,7 @@ namespace MonoDevelop.Deployment.Targets get { return "SSH (FUSE)"; } } - public override void MountTempDirectory (IProgressMonitor monitor, FileCopyConfiguration copyConfig, string tempPath) + public override void MountTempDirectory (ProgressMonitor monitor, FileCopyConfiguration copyConfig, string tempPath) { SshFuseFileCopyConfiguration config = (SshFuseFileCopyConfiguration) copyConfig; string fuseArgs = string.Format ("{0} {1} {2}", config.TargetDirectory, tempPath, config.ExtraMountArguments); diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DefaultDeployServiceExtension.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DefaultDeployServiceExtension.cs index 52715746d0..3b6554e7be 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DefaultDeployServiceExtension.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DefaultDeployServiceExtension.cs @@ -8,7 +8,7 @@ namespace MonoDevelop.Deployment { class DefaultDeployServiceExtension: DeployServiceExtension { - public override DeployFileCollection GetDeployFiles (DeployContext ctx, SolutionItem entry, ConfigurationSelector configuration) + public override DeployFileCollection GetDeployFiles (DeployContext ctx, SolutionFolderItem entry, ConfigurationSelector configuration) { if (entry is IDeployable) return new DeployFileCollection (((IDeployable)entry).GetDeployFiles (configuration)); diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DeployFile.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DeployFile.cs index b8287104a5..e03eb8b89d 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DeployFile.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DeployFile.cs @@ -44,7 +44,7 @@ namespace MonoDevelop.Deployment string targetDirectoryID; DeployContext deployContext; bool isTemplate; - SolutionItem sourceSolutionItem; + SolutionFolderItem sourceSolutionItem; string displayName; DeployFileAttributes attributes; @@ -60,12 +60,12 @@ namespace MonoDevelop.Deployment sourceSolutionItem = pfile.Project; }
- public DeployFile (SolutionItem sourceSolutionItem, FilePath sourcePath, FilePath relativeTargetPath) + public DeployFile (SolutionFolderItem sourceSolutionItem, FilePath sourcePath, FilePath relativeTargetPath) : this (sourceSolutionItem, sourcePath, relativeTargetPath, TargetDirectory.ProgramFiles) { }
- public DeployFile (SolutionItem sourceSolutionItem, FilePath sourcePath, FilePath relativeTargetPath, string targetDirectoryID) + public DeployFile (SolutionFolderItem sourceSolutionItem, FilePath sourcePath, FilePath relativeTargetPath, string targetDirectoryID) { this.targetDirectoryID = targetDirectoryID; this.sourcePath = sourcePath; @@ -78,7 +78,7 @@ namespace MonoDevelop.Deployment this.deployContext = deployContext; } - public SolutionItem SourceSolutionItem { + public SolutionFolderItem SourceSolutionItem { get { return sourceSolutionItem; } } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DeployService.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DeployService.cs index b6f9695245..51fbdf8329 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DeployService.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DeployService.cs @@ -48,6 +48,7 @@ using ICSharpCode.SharpZipLib.Zip; using System.Reflection;
using Mono.Unix.Native;
using Mono.Unix; +using System.Threading.Tasks; namespace MonoDevelop.Deployment { @@ -90,7 +91,7 @@ namespace MonoDevelop.Deployment return props; } - public static PackageBuilder[] GetSupportedPackageBuilders (SolutionItem entry) + public static PackageBuilder[] GetSupportedPackageBuilders (SolutionFolderItem entry) { object[] builders = AddinManager.GetExtensionObjects ("/MonoDevelop/DeployService/PackageBuilders", false); ArrayList list = new ArrayList (); @@ -110,13 +111,13 @@ namespace MonoDevelop.Deployment return (PackageBuilder[]) AddinManager.GetExtensionObjects ("/MonoDevelop/DeployService/PackageBuilders", typeof(PackageBuilder), false); } - public static void Install (IProgressMonitor monitor, SolutionItem entry, string prefix, string appName, ConfigurationSelector configuration) + public static void Install (ProgressMonitor monitor, SolutionFolderItem entry, string prefix, string appName, ConfigurationSelector configuration) { InstallResolver res = new InstallResolver (); res.Install (monitor, entry, appName, prefix, configuration); } - public static void CreateArchive (IProgressMonitor mon, string folder, string targetFile) + public static void CreateArchive (ProgressMonitor mon, string folder, string targetFile) { string tf = Path.GetFileNameWithoutExtension (targetFile); if (tf.EndsWith (".tar")) tf = Path.GetFileNameWithoutExtension (tf); @@ -235,27 +236,29 @@ namespace MonoDevelop.Deployment return null; } - public static bool BuildPackage (IProgressMonitor mon, Package package) + public static Task<bool> BuildPackage (ProgressMonitor mon, Package package) { return BuildPackage (mon, package.PackageBuilder); } - public static bool BuildPackage (IProgressMonitor mon, PackageBuilder builder) + public static Task<bool> BuildPackage (ProgressMonitor mon, PackageBuilder builder) { - DeployServiceExtension extensionChain = GetExtensionChain (); - return extensionChain.BuildPackage (mon, builder); + return Task<bool>.Factory.StartNew (delegate { + DeployServiceExtension extensionChain = GetExtensionChain (); + return extensionChain.BuildPackage (mon, builder); + }); } - public static DeployFileCollection GetDeployFiles (DeployContext ctx, SolutionItem[] entries, ConfigurationSelector configuration) + public static DeployFileCollection GetDeployFiles (DeployContext ctx, SolutionFolderItem[] entries, ConfigurationSelector configuration) { DeployFileCollection col = new DeployFileCollection (); - foreach (SolutionItem e in entries) { + foreach (SolutionFolderItem e in entries) { col.AddRange (GetDeployFiles (ctx, e, configuration)); } return col; } - public static DeployFileCollection GetDeployFiles (DeployContext ctx, SolutionItem entry, ConfigurationSelector configuration) + public static DeployFileCollection GetDeployFiles (DeployContext ctx, SolutionFolderItem entry, ConfigurationSelector configuration) { ArrayList todel = new ArrayList (); diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DeployServiceExtension.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DeployServiceExtension.cs index ef9335b420..4359230f6b 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DeployServiceExtension.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DeployServiceExtension.cs @@ -9,7 +9,7 @@ namespace MonoDevelop.Deployment { internal DeployServiceExtension Next; - public virtual bool BuildPackage (IProgressMonitor monitor, PackageBuilder builder) + public virtual bool BuildPackage (ProgressMonitor monitor, PackageBuilder builder) { if (Next != null) return Next.BuildPackage (monitor, builder); @@ -17,7 +17,7 @@ namespace MonoDevelop.Deployment return builder.Build (monitor); } - public virtual DeployFileCollection GetDeployFiles (DeployContext ctx, SolutionItem entry, ConfigurationSelector configuration) + public virtual DeployFileCollection GetDeployFiles (DeployContext ctx, SolutionFolderItem entry, ConfigurationSelector configuration) { if (entry is SolutionFolder) return GetCombineDeployFiles (ctx, (SolutionFolder) entry, configuration); diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/FileCopyConfiguration.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/FileCopyConfiguration.cs index 0149d1040d..53c916d787 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/FileCopyConfiguration.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/FileCopyConfiguration.cs @@ -69,7 +69,7 @@ namespace MonoDevelop.Deployment get; } - public void CopyFiles (IProgressMonitor monitor, IFileReplacePolicy replacePolicy, DeployFileCollection files, DeployContext context) + public void CopyFiles (ProgressMonitor monitor, IFileReplacePolicy replacePolicy, DeployFileCollection files, DeployContext context) { Handler.CopyFiles (monitor, replacePolicy, this, files, context); } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/FileCopyHandler.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/FileCopyHandler.cs index 38108b7ded..7b1f3c2f00 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/FileCopyHandler.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/FileCopyHandler.cs @@ -59,7 +59,7 @@ namespace MonoDevelop.Deployment return c; } - internal void CopyFiles (IProgressMonitor monitor, IFileReplacePolicy replacePolicy, FileCopyConfiguration copyConfig, DeployFileCollection files, DeployContext context) + internal void CopyFiles (ProgressMonitor monitor, IFileReplacePolicy replacePolicy, FileCopyConfiguration copyConfig, DeployFileCollection files, DeployContext context) { handler.CopyFiles (monitor, replacePolicy, copyConfig, files, context); } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/IFileCopyHandler.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/IFileCopyHandler.cs index 58f41c36c7..1aabddc49e 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/IFileCopyHandler.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/IFileCopyHandler.cs @@ -40,6 +40,6 @@ namespace MonoDevelop.Deployment string Id { get; } string Name { get; } FileCopyConfiguration CreateConfiguration (); - void CopyFiles (IProgressMonitor monitor, IFileReplacePolicy replacePolicy, FileCopyConfiguration copyConfig, DeployFileCollection files, DeployContext context); + void CopyFiles (ProgressMonitor monitor, IFileReplacePolicy replacePolicy, FileCopyConfiguration copyConfig, DeployFileCollection files, DeployContext context); } } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/InstallResolver.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/InstallResolver.cs index 50e1ca8951..778eb928ee 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/InstallResolver.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/InstallResolver.cs @@ -40,7 +40,7 @@ namespace MonoDevelop.Deployment { string appName; - public void Install (IProgressMonitor monitor, SolutionItem entry, string appName, string prefix, ConfigurationSelector configuration) + public void Install (ProgressMonitor monitor, SolutionFolderItem entry, string appName, string prefix, ConfigurationSelector configuration) { this.appName = appName; @@ -49,9 +49,9 @@ namespace MonoDevelop.Deployment } } - void InstallEntry (IProgressMonitor monitor, DeployContext ctx, SolutionItem entry, ConfigurationSelector configuration) + void InstallEntry (ProgressMonitor monitor, DeployContext ctx, SolutionFolderItem entry, ConfigurationSelector configuration) { - foreach (DeployFile df in DeployService.GetDeployFiles (ctx, new SolutionItem[] { entry }, configuration)) { + foreach (DeployFile df in DeployService.GetDeployFiles (ctx, new SolutionFolderItem[] { entry }, configuration)) { string targetPath = df.ResolvedTargetFile; if (targetPath == null) { monitor.ReportWarning ("Could not copy file '" + df.RelativeTargetPath + "': Unknown target directory."); @@ -64,7 +64,7 @@ namespace MonoDevelop.Deployment SolutionFolder c = entry as SolutionFolder; if (c != null) { monitor.BeginTask ("Installing solution '" + c.Name + "'", c.Items.Count); - foreach (SolutionItem ce in c.Items) { + foreach (SolutionFolderItem ce in c.Items) { InstallEntry (monitor, ctx, ce, configuration); monitor.Step (1); } @@ -72,7 +72,7 @@ namespace MonoDevelop.Deployment } } - void CopyFile (IProgressMonitor monitor, string src, string dest, DeployFileAttributes atts) + void CopyFile (ProgressMonitor monitor, string src, string dest, DeployFileAttributes atts) { dest = FileService.GetFullPath (dest); monitor.Log.WriteLine (GettextCatalog.GetString ("Deploying file {0}.", dest)); diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/Package.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/Package.cs index 8eeac21c76..22362fda36 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/Package.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/Package.cs @@ -6,6 +6,7 @@ using MonoDevelop.Core; using MonoDevelop.Core.ProgressMonitoring; using MonoDevelop.Projects; using MonoDevelop.Core.Serialization; +using System.Threading.Tasks; namespace MonoDevelop.Deployment { @@ -46,11 +47,11 @@ namespace MonoDevelop.Deployment set { builder = value; NotifyChanged (); } } - public bool Build (IProgressMonitor monitor) + public async Task<bool> Build (ProgressMonitor monitor) { - DeployService.BuildPackage (monitor, this); + var res = await DeployService.BuildPackage (monitor, this); needsBuilding = false; - return true; + return res; } public bool NeedsBuilding { @@ -62,7 +63,7 @@ namespace MonoDevelop.Deployment } } - public void Clean (IProgressMonitor monitor) + public void Clean (ProgressMonitor monitor) { needsBuilding = true; } diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/PackageBuilder.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/PackageBuilder.cs index 3df5f51486..4dfa51c332 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/PackageBuilder.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/PackageBuilder.cs @@ -34,6 +34,7 @@ using MonoDevelop.Core; using MonoDevelop.Core.ProgressMonitoring; using MonoDevelop.Projects; using MonoDevelop.Ide; +using System.Threading.Tasks; namespace MonoDevelop.Deployment { @@ -50,8 +51,8 @@ namespace MonoDevelop.Deployment [ItemProperty ("RootEntry")] SolutionItemReference rootEntry; - List<SolutionItem> childCombineEntries; - SolutionItem rootSolutionItem; + List<SolutionFolderItem> childCombineEntries; + SolutionFolderItem rootSolutionItem; public PackageBuilder () { @@ -76,7 +77,7 @@ namespace MonoDevelop.Deployment return null; } - internal bool Build (IProgressMonitor monitor) + internal bool Build (ProgressMonitor monitor) { monitor.BeginTask ("Package: " + Description, 1); DeployContext ctx = null; @@ -85,13 +86,11 @@ namespace MonoDevelop.Deployment if (ctx != null) ctx.FileFilter = this; if (!OnBuild (monitor, ctx)) { - monitor.AsyncOperation.Cancel (); return false; } } catch (Exception ex) { monitor.ReportError ("Package creation failed", ex); LoggingService.LogError ("Package creation failed", ex); - monitor.AsyncOperation.Cancel (); return false; } finally { monitor.EndTask (); @@ -101,12 +100,12 @@ namespace MonoDevelop.Deployment return true; } - public virtual bool CanBuild (SolutionItem entry) + public virtual bool CanBuild (SolutionFolderItem entry) { return true; } - public virtual void InitializeSettings (SolutionItem entry) + public virtual void InitializeSettings (SolutionFolderItem entry) { } @@ -123,7 +122,7 @@ namespace MonoDevelop.Deployment rootEntry = other.rootEntry; if (other.childCombineEntries != null) - childCombineEntries = new List<SolutionItem> (other.childCombineEntries); + childCombineEntries = new List<SolutionFolderItem> (other.childCombineEntries); else childCombineEntries = null; if (other.excludedFiles != null) @@ -138,7 +137,7 @@ namespace MonoDevelop.Deployment return new PackageBuilder [0]; } - protected virtual bool OnBuild (IProgressMonitor monitor, DeployContext ctx) + protected virtual bool OnBuild (ProgressMonitor monitor, DeployContext ctx) { return true; } @@ -158,15 +157,15 @@ namespace MonoDevelop.Deployment return new DeployContext (this, DeployService.CurrentPlatform, null); } - public void SetSolutionItem (SolutionItem entry) + public void SetSolutionItem (SolutionFolderItem entry) { SetSolutionItem (entry, null); } - public void SetSolutionItem (SolutionItem rootSolutionItem, IEnumerable<SolutionItem> childEntries) + public void SetSolutionItem (SolutionFolderItem rootSolutionItem, IEnumerable<SolutionFolderItem> childEntries) { this.rootSolutionItem = rootSolutionItem; - childCombineEntries = new List<SolutionItem> (); + childCombineEntries = new List<SolutionFolderItem> (); if (childEntries != null) childCombineEntries.AddRange (childEntries); @@ -187,11 +186,11 @@ namespace MonoDevelop.Deployment { this.rootEntry = new SolutionItemReference (rootSolutionItem); this.childEntries.Clear (); - foreach (SolutionItem e in childCombineEntries) + foreach (SolutionFolderItem e in childCombineEntries) childEntries.Add (new SolutionItemReference (e)); } - public SolutionItem RootSolutionItem { + public SolutionFolderItem RootSolutionItem { get { if (rootSolutionItem == null && rootEntry != null) rootSolutionItem = GetEntry (rootEntry); @@ -205,7 +204,7 @@ namespace MonoDevelop.Deployment } } - public void AddEntry (SolutionItem entry) + public void AddEntry (SolutionFolderItem entry) { SolutionItemReference fp = new SolutionItemReference (entry); foreach (SolutionItemReference s in childEntries) @@ -215,7 +214,7 @@ namespace MonoDevelop.Deployment if (rootEntry == fp) return; - List<SolutionItem> list = new List<SolutionItem> (); + List<SolutionFolderItem> list = new List<SolutionFolderItem> (); if (RootSolutionItem != null) list.Add (RootSolutionItem); list.AddRange (GetChildEntries()); @@ -224,8 +223,8 @@ namespace MonoDevelop.Deployment rootSolutionItem = GetCommonSolutionItem (list); list.Remove (rootSolutionItem); - foreach (SolutionItem e in list.ToArray ()) { - SolutionItem ce = e.ParentFolder; + foreach (SolutionFolderItem e in list.ToArray ()) { + SolutionFolderItem ce = e.ParentFolder; while (ce != rootSolutionItem) { if (!list.Contains (ce)) list.Add (ce); @@ -236,36 +235,36 @@ namespace MonoDevelop.Deployment UpdateEntryNames (); } - public SolutionItem[] GetChildEntries () + public SolutionFolderItem[] GetChildEntries () { if (childCombineEntries != null) return childCombineEntries.ToArray (); - childCombineEntries = new List<SolutionItem> (); + childCombineEntries = new List<SolutionFolderItem> (); foreach (SolutionItemReference en in childEntries) { - SolutionItem re = GetEntry (en); + SolutionFolderItem re = GetEntry (en); if (re != null && !(re is UnknownSolutionItem)) childCombineEntries.Add (re); } return childCombineEntries.ToArray (); } - public SolutionItem[] GetAllEntries () + public SolutionFolderItem[] GetAllEntries () { - List<SolutionItem> list = new List<SolutionItem> (); + List<SolutionFolderItem> list = new List<SolutionFolderItem> (); if (RootSolutionItem != null) list.Add (RootSolutionItem); list.AddRange (GetChildEntries ()); return list.ToArray (); } - SolutionItem GetEntry (SolutionItemReference reference) + SolutionFolderItem GetEntry (SolutionItemReference reference) { if (IdeApp.IsInitialized) - return Services.ProjectService.ReadSolutionItem (new NullProgressMonitor (), reference, IdeApp.Workspace.Items.ToArray ()); + return Services.ProjectService.ReadSolutionItem (new ProgressMonitor (), reference, IdeApp.Workspace.Items.ToArray ()).Result; else - return Services.ProjectService.ReadSolutionItem (new NullProgressMonitor (), reference); + return Services.ProjectService.ReadSolutionItem (new ProgressMonitor (), reference).Result; } public virtual DeployFileCollection GetDeployFiles (DeployContext ctx, ConfigurationSelector configuration) @@ -307,10 +306,10 @@ namespace MonoDevelop.Deployment } - internal static SolutionItem GetCommonSolutionItem (IEnumerable<SolutionItem> entries) + internal static SolutionFolderItem GetCommonSolutionItem (IEnumerable<SolutionFolderItem> entries) { - SolutionItem common = null; - foreach (SolutionItem it in entries) { + SolutionFolderItem common = null; + foreach (SolutionFolderItem it in entries) { if (common == null) common = it; else diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/PackagingProject.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/PackagingProject.cs index 184b2dee9f..6641fba97c 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/PackagingProject.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/PackagingProject.cs @@ -5,10 +5,11 @@ using System.Collections.Generic; using MonoDevelop.Core; using MonoDevelop.Projects; using MonoDevelop.Core.Serialization; +using System.Threading.Tasks; namespace MonoDevelop.Deployment { - public class PackagingProject: SolutionEntityItem + public class PackagingProject: SolutionItem { PackageCollection packages; @@ -40,21 +41,19 @@ namespace MonoDevelop.Deployment return conf; } - protected override void OnClean (IProgressMonitor monitor, ConfigurationSelector configuration) + protected override Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration) { foreach (Package p in packages) p.Clean (monitor); + return Task.FromResult (BuildResult.Success); } - protected override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration) + protected async override Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { foreach (Package p in packages) - p.Build (monitor); - return null; - } - - protected override void OnExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) - { + if (!await p.Build (monitor)) + break; + return BuildResult.Success; } protected override bool OnGetNeedsBuilding (ConfigurationSelector configuration) @@ -65,12 +64,6 @@ namespace MonoDevelop.Deployment return false; } - protected override void OnSetNeedsBuilding (bool val, ConfigurationSelector configuration) - { - foreach (Package p in packages) - p.NeedsBuilding = val; - } - internal void NotifyPackagesChanged () { if (PackagesChanged != null) diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/UnknownPackageBuilder.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/UnknownPackageBuilder.cs index 04d3e92770..72b356dc5d 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/UnknownPackageBuilder.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/UnknownPackageBuilder.cs @@ -54,7 +54,7 @@ namespace MonoDevelop.Deployment } } - protected override bool OnBuild (IProgressMonitor monitor, DeployContext ctx) + protected override bool OnBuild (ProgressMonitor monitor, DeployContext ctx) { monitor.ReportError ("Unknown package type. The package can't be generated.", null); return false; diff --git a/main/src/addins/GnomePlatform/GnomePlatform.cs b/main/src/addins/GnomePlatform/GnomePlatform.cs index beb5f8e4c0..556db7f7c9 100644 --- a/main/src/addins/GnomePlatform/GnomePlatform.cs +++ b/main/src/addins/GnomePlatform/GnomePlatform.cs @@ -208,7 +208,7 @@ namespace MonoDevelop.Platform TerminalRunnerHandler runner; TerminalOpenFolderRunnerHandler openDirectoryRunner; - public override IProcessAsyncOperation StartConsoleProcess (string command, string arguments, string workingDirectory, + public override ProcessAsyncOperation StartConsoleProcess (string command, string arguments, string workingDirectory, IDictionary<string, string> environmentVariables, string title, bool pauseWhenFinished) { diff --git a/main/src/addins/ILAsmBinding/ILAsmCompilerManager.cs b/main/src/addins/ILAsmBinding/ILAsmCompilerManager.cs index 1b334259ef..41da0dd356 100644 --- a/main/src/addins/ILAsmBinding/ILAsmCompilerManager.cs +++ b/main/src/addins/ILAsmBinding/ILAsmCompilerManager.cs @@ -48,7 +48,7 @@ namespace ILAsmBinding sb.Append ("\" "); } - public static BuildResult Compile (ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, IProgressMonitor monitor) + public static BuildResult Compile (ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, ProgressMonitor monitor) { // ILAsmCompilerParameters compilerParameters = (ILAsmCompilerParameters)configuration.CompilationParameters ?? new ILAsmCompilerParameters (); string outputName = configuration.CompiledOutputName; diff --git a/main/src/addins/ILAsmBinding/ILAsmLanguageBinding.cs b/main/src/addins/ILAsmBinding/ILAsmLanguageBinding.cs index c45ea65c3f..ed2156ad5b 100644 --- a/main/src/addins/ILAsmBinding/ILAsmLanguageBinding.cs +++ b/main/src/addins/ILAsmBinding/ILAsmLanguageBinding.cs @@ -52,12 +52,12 @@ namespace ILAsmBinding return String.Compare (Path.GetExtension (fileName), ".il", StringComparison.OrdinalIgnoreCase) == 0; } - public BuildResult Compile (ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, IProgressMonitor monitor) + public BuildResult Compile (ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, ProgressMonitor monitor) { return ILAsmCompilerManager.Compile (projectItems, configuration, configSelector, monitor); } - public ConfigurationParameters CreateCompilationParameters (XmlElement projectOptions) + public DotNetCompilerParameters CreateCompilationParameters (XmlElement projectOptions) { return new ILAsmCompilerParameters(); } diff --git a/main/src/addins/ILAsmBinding/Project/ILAsmCompilerParameters.cs b/main/src/addins/ILAsmBinding/Project/ILAsmCompilerParameters.cs index 80c1af76db..9b509a6112 100644 --- a/main/src/addins/ILAsmBinding/Project/ILAsmCompilerParameters.cs +++ b/main/src/addins/ILAsmBinding/Project/ILAsmCompilerParameters.cs @@ -26,7 +26,7 @@ namespace ILAsmBinding { - class ILAsmCompilerParameters : MonoDevelop.Projects.ConfigurationParameters + class ILAsmCompilerParameters : MonoDevelop.Projects.DotNetCompilerParameters { } } diff --git a/main/src/addins/MacPlatform/Dialogs/SelectEncodingPopUpButton.cs b/main/src/addins/MacPlatform/Dialogs/SelectEncodingPopUpButton.cs index 02ffe31e1a..5483cbbd78 100644 --- a/main/src/addins/MacPlatform/Dialogs/SelectEncodingPopUpButton.cs +++ b/main/src/addins/MacPlatform/Dialogs/SelectEncodingPopUpButton.cs @@ -25,12 +25,14 @@ // THE SOFTWARE. using System; +using System.Linq; using Foundation; using AppKit; using MonoDevelop.Core; using MonoDevelop.Ide; using MonoDevelop.Projects.Text; +using System.Linq; namespace MonoDevelop.MacIntegration { @@ -94,9 +96,7 @@ namespace MonoDevelop.MacIntegration if (clear) Menu.RemoveAllItems (); - encodings = SelectedEncodings.ConversionEncodings; - if (encodings == null || encodings.Length == 0) - encodings = SelectedEncodings.DefaultEncodings; + encodings = TextEncoding.ConversionEncodings.Select ((e) => e.CodePage).ToArray (); if (autoDetectedItem != null) { Menu.AddItem (autoDetectedItem); diff --git a/main/src/addins/MacPlatform/MacExternalConsoleProcess.cs b/main/src/addins/MacPlatform/MacExternalConsoleProcess.cs index dcafe4127f..b92f968216 100644 --- a/main/src/addins/MacPlatform/MacExternalConsoleProcess.cs +++ b/main/src/addins/MacPlatform/MacExternalConsoleProcess.cs @@ -36,7 +36,7 @@ using MonoDevelop.MacInterop; namespace MonoDevelop.MacIntegration { - internal class MacExternalConsoleProcess : IProcessAsyncOperation + internal class MacExternalConsoleProcess : ProcessAsyncOperation { /* NOTES ON CONTROLLING A TERMINAL WITH APPLESCRIPT @@ -80,11 +80,16 @@ bash pause on exit trick */ string tabId, windowId; bool cancelled; - + public MacExternalConsoleProcess (string command, string arguments, string workingDirectory, IDictionary<string, string> environmentVariables, string title, bool pauseWhenFinished) { + CancellationTokenSource = new CancellationTokenSource (); + CancellationTokenSource.Token.Register (CloseTerminal); + + // FIXME set value of ExitCode and ProcessId, if possible + RunTerminal ( command, arguments, workingDirectory, environmentVariables, title, pauseWhenFinished, out tabId, out windowId @@ -168,67 +173,15 @@ end tell", tabId, windowId); #endregion - #region IProcessAsyncOperation implementation - - public void Dispose () - { - } - - public int ExitCode { - get { - //FIXME: implement. is it possible? - return 0; - } - } - - public int ProcessId { - get { - //FIXME: implement. is it possible? - return 0; - } - } - - #endregion - #region IAsyncOperation implementation - public event OperationHandler Completed; - - public void Cancel () + void CloseTerminal () { cancelled = true; //FIXME: try to kill the process without closing the window, if pauseWhenFinished is true CloseTerminalWindow (tabId, windowId); } - - public void WaitForCompleted () - { - while (!IsCompleted) { - Thread.Sleep (1000); - } - } - - public bool IsCompleted { - get { - //FIXME: get the status of the process, not the whole script - return !TabExists (tabId, windowId); - } - } - - public bool Success { - get { - //FIXME: any way to get the real result? - return !cancelled; - } - } - - - public bool SuccessWithWarnings { - get { - return Success; - } - } - + #endregion } }
\ No newline at end of file diff --git a/main/src/addins/MacPlatform/MacMenu/MDMenuItem.cs b/main/src/addins/MacPlatform/MacMenu/MDMenuItem.cs index 2040fd91d4..84585c1f40 100644 --- a/main/src/addins/MacPlatform/MacMenu/MDMenuItem.cs +++ b/main/src/addins/MacPlatform/MacMenu/MDMenuItem.cs @@ -155,6 +155,8 @@ namespace MonoDevelop.MacIntegration.MacMenu void SetItemValues (NSMenuItem item, CommandInfo info, bool disabledVisible) { item.SetTitleWithMnemonic (GetCleanCommandText (info)); + if (!string.IsNullOrEmpty (info.Description) && item.ToolTip != info.Description) + item.ToolTip = info.Description; bool enabled = info.Enabled && (!IsGloballyDisabled || commandSource == CommandSource.ContextMenu); bool visible = info.Visible && (disabledVisible || info.Enabled); diff --git a/main/src/addins/MacPlatform/MacPlatform.cs b/main/src/addins/MacPlatform/MacPlatform.cs index 11eb1419ad..c8625333fa 100644 --- a/main/src/addins/MacPlatform/MacPlatform.cs +++ b/main/src/addins/MacPlatform/MacPlatform.cs @@ -349,7 +349,7 @@ namespace MonoDevelop.MacIntegration if (!Int32.TryParse (qs ["column"], out column)) column = 1; - return new FileOpenInformation (fileUri.AbsolutePath, + return new FileOpenInformation (Uri.UnescapeDataString(fileUri.AbsolutePath), line, column, OpenDocumentOptions.DefaultInternal); } catch (Exception ex) { LoggingService.LogError ("Invalid TextMate URI: " + url, ex); @@ -519,7 +519,7 @@ namespace MonoDevelop.MacIntegration return res != null ? res.ToXwtImage () : base.OnGetIconForFile (filename); } - public override IProcessAsyncOperation StartConsoleProcess (string command, string arguments, string workingDirectory, + public override ProcessAsyncOperation StartConsoleProcess (string command, string arguments, string workingDirectory, IDictionary<string, string> environmentVariables, string title, bool pauseWhenFinished) { @@ -736,5 +736,42 @@ namespace MonoDevelop.MacIntegration return toplevels.Any (t => t.Key.IsVisible && (t.Value == null || t.Value.Modal) && !t.Key.DebugDescription.StartsWith ("<NSStatusBarWindow", StringComparison.Ordinal)); } + + public override void AddChildWindow (Gtk.Window parent, Gtk.Window child) + { + NSWindow w = GtkQuartz.GetWindow (parent); + child.Realize (); + NSWindow overlay = GtkQuartz.GetWindow (child); + overlay.SetExcludedFromWindowsMenu (true); + w.AddChildWindow (overlay, NSWindowOrderingMode.Above); + } + + public override void PlaceWindow (Gtk.Window window, int x, int y, int width, int height) + { + NSWindow w = GtkQuartz.GetWindow (window); + var dr = FromDesktopRect (new Gdk.Rectangle (x, y, width, height)); + var r = w.FrameRectFor (dr); + w.SetFrame (r, true); + base.PlaceWindow (window, x, y, width, height); + } + + static CGRect FromDesktopRect (Gdk.Rectangle r) + { + var desktopBounds = CalcDesktopBounds (); + r.Y = desktopBounds.Height - r.Y - r.Height; + if (desktopBounds.Y < 0) + r.Y += desktopBounds.Y; + return new CGRect (desktopBounds.X + r.X, r.Y, r.Width, r.Height); + } + + static Gdk.Rectangle CalcDesktopBounds () + { + var desktopBounds = new Gdk.Rectangle (); + foreach (var s in NSScreen.Screens) { + var r = s.Frame; + desktopBounds = desktopBounds.Union (new Gdk.Rectangle ((int)r.X, (int)r.Y, (int)r.Width, (int)r.Height)); + } + return desktopBounds; + } } } diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs index 52cd6144e7..0483763f79 100644 --- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs +++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs @@ -158,10 +158,10 @@ namespace MonoDevelop.AssemblyBrowser }; languageCombobox = Gtk.ComboBox.NewText (); - //languageCombobox.AppendText (GettextCatalog.GetString ("Summary")); + languageCombobox.AppendText (GettextCatalog.GetString ("Summary")); languageCombobox.AppendText (GettextCatalog.GetString ("IL")); languageCombobox.AppendText (GettextCatalog.GetString ("C#")); - languageCombobox.Active = Math.Min (1, PropertyService.Get ("AssemblyBrowser.InspectLanguage", 1)); + languageCombobox.Active = Math.Min (0, PropertyService.Get ("AssemblyBrowser.Language", 0)); languageCombobox.Changed += LanguageComboboxhandleChanged; loader = new CecilLoader (true); @@ -338,7 +338,7 @@ namespace MonoDevelop.AssemblyBrowser void LanguageComboboxhandleChanged (object sender, EventArgs e) { this.notebook1.Page = 0; - PropertyService.Set ("AssemblyBrowser.InspectLanguage", this.languageCombobox.Active); + PropertyService.Set ("AssemblyBrowser.Language", this.languageCombobox.Active); FillInspectLabel (); } @@ -1112,10 +1112,15 @@ namespace MonoDevelop.AssemblyBrowser switch (this.languageCombobox.Active) { case 0: inspectEditor.Options.ShowFoldMargin = true; + this.inspectEditor.Document.MimeType = "text/x-csharp"; + SetReferencedSegments (builder.GetSummary (inspectEditor.GetTextEditorData (), nav, PublicApiOnly)); + break; + case 1: + inspectEditor.Options.ShowFoldMargin = true; this.inspectEditor.Document.MimeType = "text/x-ilasm"; SetReferencedSegments (builder.Disassemble (inspectEditor.GetTextEditorData (), nav)); break; - case 1: + case 2: inspectEditor.Options.ShowFoldMargin = true; this.inspectEditor.Document.MimeType = "text/x-csharp"; SetReferencedSegments (builder.Decompile (inspectEditor.GetTextEditorData (), nav, PublicApiOnly)); @@ -1188,10 +1193,14 @@ namespace MonoDevelop.AssemblyBrowser return; if (nav != null) return; - if (currentAssembly != null) { - OpenFromAssembly (url, currentAssembly); - } else { - OpenFromAssemblyNames (url); + try { + if (currentAssembly != null) { + OpenFromAssembly (url, currentAssembly); + } else { + OpenFromAssemblyNames (url); + } + } catch (Exception e) { + LoggingService.LogError ("Error while opening the assembly browser with id:" + url, e); } } @@ -1220,20 +1229,22 @@ namespace MonoDevelop.AssemblyBrowser t2.Wait (); if (definitions == null) // disposed return; - var nav = SearchMember (url); - if (nav == null) { - if (++i == references.Count) - LoggingService.LogError ("Assembly browser: Can't find: " + url + "."); - else - loadNext (); - } + Application.Invoke (delegate { + var nav = SearchMember (url); + if (nav == null) { + if (++i == references.Count) + LoggingService.LogError ("Assembly browser: Can't find: " + url + "."); + else + loadNext (); + } + }); }, TaskScheduler.Current); }; } void OpenFromAssemblyNames (string url) { - List<Task> tasks = new List<Task> (); + var tasks = new List<Task> (); foreach (var definition in definitions.ToArray ()) { var cecilObject = loader.GetCecilObject (definition.UnresolvedAssembly); if (cecilObject == null) { @@ -1259,14 +1270,22 @@ namespace MonoDevelop.AssemblyBrowser Task.Factory.ContinueWhenAll (tasks.ToArray (), tarr => { var exceptions = tarr.Where (t => t.IsFaulted).Select (t => t.Exception).ToArray (); if (exceptions != null) { - throw new AggregateException (exceptions).Flatten (); + var ex = new AggregateException (exceptions).Flatten (); + if (ex.InnerExceptions.Count > 0) { + foreach (var inner in ex.InnerExceptions) { + LoggingService.LogError ("Error while loading assembly in the browser.", inner); + } + throw ex; + } } if (definitions == null) // disposed return; - var nav = SearchMember (url); - if (nav == null) { - LoggingService.LogError ("Assembly browser: Can't find: " + url + "."); - } + Application.Invoke (delegate { + var nav = SearchMember (url); + if (nav == null) { + LoggingService.LogError ("Assembly browser: Can't find: " + url + "."); + } + }); }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current); } @@ -1437,13 +1456,17 @@ namespace MonoDevelop.AssemblyBrowser Application.Invoke (delegate { if (definitions == null) return; - ITreeBuilder builder; - if (definitions.Count + projects.Count == 1) { - builder = TreeView.LoadTree (result); - } else { - builder = TreeView.AddChild (result); + try { + ITreeBuilder builder; + if (definitions.Count + projects.Count == 1) { + builder = TreeView.LoadTree (result); + } else { + builder = TreeView.AddChild (result); + } + builder.Selected = builder.Expanded = selectReference; + } catch (Exception e) { + LoggingService.LogError ("Error while adding assembly to the assembly list", e); } - builder.Selected = builder.Expanded = selectReference; }); } ); diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyLoader.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyLoader.cs index c23bc5fc3f..71ebaa6b72 100644 --- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyLoader.cs +++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyLoader.cs @@ -75,9 +75,14 @@ namespace MonoDevelop.AssemblyBrowser if (!File.Exists (fileName)) throw new ArgumentException ("File doesn't exist.", "fileName"); this.assemblyLoaderTask = Task.Factory.StartNew<AssemblyDefinition> (() => { - return AssemblyDefinition.ReadAssembly (FileName, new ReaderParameters () { - AssemblyResolver = this - }); + try { + return AssemblyDefinition.ReadAssembly (FileName, new ReaderParameters { + AssemblyResolver = this + }); + } catch (Exception e) { + LoggingService.LogError ("Error while reading assembly " + FileName, e); + return null; + } }, src.Token); this.unresolvedAssembly = new Lazy<IUnresolvedAssembly> (delegate { diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/IAssemblyBrowserNodeBuilder.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/IAssemblyBrowserNodeBuilder.cs index 27529ebaa7..7a13a020b6 100644 --- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/IAssemblyBrowserNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/IAssemblyBrowserNodeBuilder.cs @@ -39,5 +39,6 @@ namespace MonoDevelop.AssemblyBrowser string GetDocumentationMarkup (ITreeNavigator navigator); List<ReferenceSegment> Disassemble (TextEditorData data, ITreeNavigator navigator); List<ReferenceSegment> Decompile (TextEditorData data, ITreeNavigator navigator, bool publicOnly); + List<ReferenceSegment> GetSummary (TextEditorData data, ITreeNavigator navigator, bool publicOnly); } } diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/AssemblyNodeBuilder.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/AssemblyNodeBuilder.cs index 6d9d6f7bc5..a9dd6a68ba 100644 --- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/AssemblyNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/AssemblyNodeBuilder.cs @@ -176,7 +176,21 @@ namespace MonoDevelop.AssemblyBrowser b.AddAssembly (compilationUnit, true); }); } - + + List<ReferenceSegment> IAssemblyBrowserNodeBuilder.GetSummary (TextEditorData data, ITreeNavigator navigator, bool publicOnly) + { + var assembly = ((AssemblyLoader)navigator.DataItem).UnresolvedAssembly; + var compilationUnit = Widget.CecilLoader.GetCecilObject (assembly); + if (compilationUnit == null) { + LoggingService.LogError ("Can't get cecil object for assembly:" + assembly); + return new List<ReferenceSegment> (); + } + return DomMethodNodeBuilder.GetSummary (data, DomMethodNodeBuilder.GetModule (navigator), null, b => { + if (b != null) + b.AddAssembly (compilationUnit, true); + }); + } + public string GetDocumentationMarkup (ITreeNavigator navigator) { return null; diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomEventNodeBuilder.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomEventNodeBuilder.cs index abccf4c5f8..d04c119022 100644 --- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomEventNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomEventNodeBuilder.cs @@ -105,7 +105,15 @@ namespace MonoDevelop.AssemblyBrowser var evt = CecilLoader.GetCecilObject ((IUnresolvedEvent)navigator.DataItem); return DomMethodNodeBuilder.Decompile (data, DomMethodNodeBuilder.GetModule (navigator), evt.DeclaringType, b => b.AddEvent (evt)); } - + + List<ReferenceSegment> IAssemblyBrowserNodeBuilder.GetSummary (TextEditorData data, ITreeNavigator navigator, bool publicOnly) + { + if (DomMethodNodeBuilder.HandleSourceCodeEntity (navigator, data)) + return null; + var evt = CecilLoader.GetCecilObject ((IUnresolvedEvent)navigator.DataItem); + return DomMethodNodeBuilder.GetSummary (data, DomMethodNodeBuilder.GetModule (navigator), evt.DeclaringType, b => b.AddEvent (evt)); + } + string IAssemblyBrowserNodeBuilder.GetDocumentationMarkup (ITreeNavigator navigator) { var evt = (IUnresolvedEvent)navigator.DataItem; diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomFieldNodeBuilder.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomFieldNodeBuilder.cs index 8206ac909b..f56ad572f6 100644 --- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomFieldNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomFieldNodeBuilder.cs @@ -92,7 +92,15 @@ namespace MonoDevelop.AssemblyBrowser var field = CecilLoader.GetCecilObject ((IUnresolvedField)navigator.DataItem); return DomMethodNodeBuilder.Decompile (data, DomMethodNodeBuilder.GetModule (navigator), field.DeclaringType, b => b.AddField (field)); } - + + List<ReferenceSegment> IAssemblyBrowserNodeBuilder.GetSummary (TextEditorData data, ITreeNavigator navigator, bool publicOnly) + { + if (DomMethodNodeBuilder.HandleSourceCodeEntity (navigator, data)) + return null; + var field = CecilLoader.GetCecilObject ((IUnresolvedField)navigator.DataItem); + return DomMethodNodeBuilder.GetSummary (data, DomMethodNodeBuilder.GetModule (navigator), field.DeclaringType, b => b.AddField (field)); + } + string IAssemblyBrowserNodeBuilder.GetDocumentationMarkup (ITreeNavigator navigator) { var field = (IUnresolvedField)navigator.DataItem; diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomMethodNodeBuilder.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomMethodNodeBuilder.cs index fd4b4afdd8..1a9b29e791 100644 --- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomMethodNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomMethodNodeBuilder.cs @@ -130,20 +130,58 @@ namespace MonoDevelop.AssemblyBrowser public static List<ReferenceSegment> Decompile (TextEditorData data, ModuleDefinition module, TypeDefinition currentType, Action<AstBuilder> setData, DecompilerSettings settings) { + var context = new DecompilerContext (module); + var source = new CancellationTokenSource (); + context.CancellationToken = source.Token; + context.CurrentType = currentType; + context.Settings = settings; try { + var astBuilder = new AstBuilder (context); + setData (astBuilder); + astBuilder.RunTransformations (o => false); + GeneratedCodeSettings.Default.Apply (astBuilder.SyntaxTree); + var output = new ColoredCSharpFormatter (data.Document); + astBuilder.GenerateCode (output); + output.SetDocumentData (); + return output.ReferencedSegments; + } catch (Exception e) { + // exception -> try to decompile without method bodies + try { + var astBuilder = new AstBuilder (context); + astBuilder.DecompileMethodBodies = false; + setData (astBuilder); + astBuilder.RunTransformations (o => false); + GeneratedCodeSettings.Default.Apply (astBuilder.SyntaxTree); + var output = new ColoredCSharpFormatter (data.Document); + astBuilder.GenerateCode (output); + output.SetDocumentData (); + data.Document.Insert (data.Document.TextLength, "/* body decompilation failed: \n" + e + " */"); + } catch (Exception e2) { + data.Text = "/* fallback decompilation failed: \n" + e2 +"*/"; + } + } + return null; + } - var context = new DecompilerContext (module); - var source = new CancellationTokenSource (); - - context.CancellationToken = source.Token; - context.CurrentType = currentType; - - context.Settings = settings; - - AstBuilder astBuilder = new AstBuilder (context); - + public static List<ReferenceSegment> GetSummary (TextEditorData data, ModuleDefinition module, TypeDefinition currentType, Action<AstBuilder> setData) + { + var types = DesktopService.GetMimeTypeInheritanceChain (data.Document.MimeType); + var codePolicy = MonoDevelop.Projects.Policies.PolicyService.GetDefaultPolicy<MonoDevelop.CSharp.Formatting.CSharpFormattingPolicy> (types); + var settings = DomTypeNodeBuilder.CreateDecompilerSettings (false, codePolicy); + return GetSummary (data, module, currentType, setData, settings); + } + + public static List<ReferenceSegment> GetSummary (TextEditorData data, ModuleDefinition module, TypeDefinition currentType, Action<AstBuilder> setData, DecompilerSettings settings) + { + var context = new DecompilerContext (module); + var source = new CancellationTokenSource (); + context.CancellationToken = source.Token; + context.CurrentType = currentType; + context.Settings = settings; + try { + var astBuilder = new AstBuilder (context); + astBuilder.DecompileMethodBodies = false; setData (astBuilder); - astBuilder.RunTransformations (o => false); GeneratedCodeSettings.Default.Apply (astBuilder.SyntaxTree); var output = new ColoredCSharpFormatter (data.Document); @@ -151,11 +189,11 @@ namespace MonoDevelop.AssemblyBrowser output.SetDocumentData (); return output.ReferencedSegments; } catch (Exception e) { - data.Text = "Decompilation failed: \n" + e; + data.Text = "/* decompilation failed: \n" + e +"*/"; } return null; } - + internal static string GetAttributes (Ambience ambience, IEnumerable<IAttribute> attributes) { StringBuilder result = new StringBuilder (); @@ -180,6 +218,17 @@ namespace MonoDevelop.AssemblyBrowser return DomMethodNodeBuilder.Decompile (data, DomMethodNodeBuilder.GetModule (navigator), cecilMethod.DeclaringType, b => b.AddMethod (cecilMethod)); } + List<ReferenceSegment> IAssemblyBrowserNodeBuilder.GetSummary (TextEditorData data, ITreeNavigator navigator, bool publicOnly) + { + var method = (IUnresolvedMethod)navigator.DataItem; + if (HandleSourceCodeEntity (navigator, data)) + return null; + var cecilMethod = CecilLoader.GetCecilObject (method); + if (cecilMethod == null) + return null; + return DomMethodNodeBuilder.GetSummary (data, DomMethodNodeBuilder.GetModule (navigator), cecilMethod.DeclaringType, b => b.AddMethod (cecilMethod)); + } + static void AppendLink (StringBuilder sb, string link, string text) { sb.Append ("<span style=\"text.link\"><u><a ref=\""); diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomPropertyNodeBuilder.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomPropertyNodeBuilder.cs index 01e7d3b412..465b41300b 100644 --- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomPropertyNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomPropertyNodeBuilder.cs @@ -115,6 +115,14 @@ namespace MonoDevelop.AssemblyBrowser return DomMethodNodeBuilder.Decompile (data, DomMethodNodeBuilder.GetModule (navigator), property.DeclaringType, b => b.AddProperty (property)); } + List<ReferenceSegment> IAssemblyBrowserNodeBuilder.GetSummary (TextEditorData data, ITreeNavigator navigator, bool publicOnly) + { + if (DomMethodNodeBuilder.HandleSourceCodeEntity (navigator, data)) + return null; + var property = CecilLoader.GetCecilObject ((IUnresolvedProperty)navigator.DataItem); + return DomMethodNodeBuilder.GetSummary (data, DomMethodNodeBuilder.GetModule (navigator), property.DeclaringType, b => b.AddProperty (property)); + } + string IAssemblyBrowserNodeBuilder.GetDocumentationMarkup (ITreeNavigator navigator) { var property = (IUnresolvedProperty)navigator.DataItem; diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomTypeNodeBuilder.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomTypeNodeBuilder.cs index 07568c4f9f..35ba03ed84 100644 --- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomTypeNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/DomTypeNodeBuilder.cs @@ -212,7 +212,23 @@ namespace MonoDevelop.AssemblyBrowser builder.AddType (type); }, settings); } - + + List<ReferenceSegment> IAssemblyBrowserNodeBuilder.GetSummary (TextEditorData data, ITreeNavigator navigator, bool publicOnly) + { + if (DomMethodNodeBuilder.HandleSourceCodeEntity (navigator, data)) + return null; + var type = CecilLoader.GetCecilObject ((IUnresolvedTypeDefinition)navigator.DataItem); + if (type == null) + return null; + var types = DesktopService.GetMimeTypeInheritanceChain (data.Document.MimeType); + var codePolicy = MonoDevelop.Projects.Policies.PolicyService.GetDefaultPolicy<MonoDevelop.CSharp.Formatting.CSharpFormattingPolicy> (types); + var settings = CreateDecompilerSettings (publicOnly, codePolicy); + return DomMethodNodeBuilder.GetSummary (data, DomMethodNodeBuilder.GetModule (navigator), type, builder => { + builder.AddType (type); + }, settings); + } + + string IAssemblyBrowserNodeBuilder.GetDocumentationMarkup (ITreeNavigator navigator) { var type = (IUnresolvedTypeDefinition)navigator.DataItem; diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/NamespaceBuilder.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/NamespaceBuilder.cs index 4073b4de9a..e19351f894 100644 --- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/NamespaceBuilder.cs +++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/TreeNodes/NamespaceBuilder.cs @@ -111,6 +111,12 @@ namespace MonoDevelop.AssemblyBrowser { return Disassemble (data, navigator); } + + List<ReferenceSegment> IAssemblyBrowserNodeBuilder.GetSummary (TextEditorData data, ITreeNavigator navigator, bool publicOnly) + { + return Disassemble (data, navigator); + } + string IAssemblyBrowserNodeBuilder.GetDocumentationMarkup (ITreeNavigator navigator) { return null; diff --git a/main/src/addins/MonoDevelop.Autotools/AutotoolsContext.cs b/main/src/addins/MonoDevelop.Autotools/AutotoolsContext.cs index 2b5465c414..99b3f1d937 100644 --- a/main/src/addins/MonoDevelop.Autotools/AutotoolsContext.cs +++ b/main/src/addins/MonoDevelop.Autotools/AutotoolsContext.cs @@ -45,7 +45,7 @@ namespace MonoDevelop.Autotools Set<SystemPackage> commonPackages; Set<string> globalFilesReferences = new Set<string>(); Set<string> compilers = new Set<string> (); - Set<SolutionItem> builtProjects = new Set<SolutionItem> (); + Set<SolutionFolderItem> builtProjects = new Set<SolutionFolderItem> (); // Useful for cleaning up in case of a problem in generation List<string> generatedFiles = new List<string> (); @@ -190,12 +190,12 @@ namespace MonoDevelop.Autotools globalFilesReferences.Add (filePath); } - public void RegisterBuiltProject (SolutionItem item) + public void RegisterBuiltProject (SolutionFolderItem item) { builtProjects.Add (item); } - public IEnumerable<SolutionItem> GetBuiltProjects () + public IEnumerable<SolutionFolderItem> GetBuiltProjects () { return builtProjects; } @@ -292,7 +292,7 @@ namespace MonoDevelop.Autotools // TODO: add an extension point with which addins can implement // autotools functionality. - public static IMakefileHandler GetMakefileHandler (SolutionItem entry, MakefileType mt) + public static IMakefileHandler GetMakefileHandler (SolutionFolderItem entry, MakefileType mt) { foreach (IMakefileHandler mh in AddinManager.GetExtensionObjects ("/MonoDevelop/Autotools/MakefileHandlers", typeof(IMakefileHandler), true)) { if (mh.CanDeploy (entry, mt)) diff --git a/main/src/addins/MonoDevelop.Autotools/Commands.cs b/main/src/addins/MonoDevelop.Autotools/Commands.cs index d3954156ae..d553c16ac0 100644 --- a/main/src/addins/MonoDevelop.Autotools/Commands.cs +++ b/main/src/addins/MonoDevelop.Autotools/Commands.cs @@ -39,7 +39,7 @@ namespace MonoDevelop.Autotools { public override bool CanBuildNode (Type dataType) { - return typeof (Solution).IsAssignableFrom (dataType) || typeof (SolutionItem).IsAssignableFrom (dataType); + return typeof (Solution).IsAssignableFrom (dataType) || typeof (SolutionFolderItem).IsAssignableFrom (dataType); } public override Type CommandHandlerType { @@ -52,25 +52,25 @@ namespace MonoDevelop.Autotools [CommandHandler (Commands.GenerateFiles)] protected void OnGenerate() { - SolutionItem entry = CurrentNode.DataItem as SolutionItem; + SolutionFolderItem entry = CurrentNode.DataItem as SolutionFolderItem; Solution solution = CurrentNode.DataItem as Solution; GenerateMakefiles (entry, solution); } - internal static void GenerateMakefiles (SolutionItem entry, Solution solution) + internal static void GenerateMakefiles (SolutionFolderItem entry, Solution solution) { if (solution == null) { AlertButton generateMakefilesButton = new AlertButton (GettextCatalog.GetString ("_Generate Makefiles")); if (MessageService.AskQuestion (GettextCatalog.GetString ("Generating Makefiles is not supported for single projects. Do you want to generate them for the full solution - '{0}' ?", entry.ParentSolution.Name), AlertButton.Cancel, generateMakefilesButton) == generateMakefilesButton) - solution = ((SolutionItem)entry).ParentSolution; + solution = ((SolutionFolderItem)entry).ParentSolution; else return; } DeployContext ctx = null; - IProgressMonitor monitor = null; + ProgressMonitor monitor = null; GenerateMakefilesDialog dialog = new GenerateMakefilesDialog (solution); try { diff --git a/main/src/addins/MonoDevelop.Autotools/FileNodeBuilderExtension.cs b/main/src/addins/MonoDevelop.Autotools/FileNodeBuilderExtension.cs index c586f3681e..1c90564ec3 100644 --- a/main/src/addins/MonoDevelop.Autotools/FileNodeBuilderExtension.cs +++ b/main/src/addins/MonoDevelop.Autotools/FileNodeBuilderExtension.cs @@ -44,7 +44,7 @@ namespace MonoDevelop.Autotools } } - Set<SolutionEntityItem> projects = new Set<SolutionEntityItem> (); + Set<SolutionItem> projects = new Set<SolutionItem> (); foreach (ITreeNavigator node in CurrentNodes) { ProjectFile file = (ProjectFile) node.DataItem; @@ -57,7 +57,7 @@ namespace MonoDevelop.Autotools } } - IdeApp.ProjectOperations.Save (projects); + IdeApp.ProjectOperations.SaveAsync (projects); } [CommandUpdateHandler (Commands.SynchWithMakefile)] diff --git a/main/src/addins/MonoDevelop.Autotools/Handler.cs b/main/src/addins/MonoDevelop.Autotools/Handler.cs index ccf029a7bd..a8622a6c59 100644 --- a/main/src/addins/MonoDevelop.Autotools/Handler.cs +++ b/main/src/addins/MonoDevelop.Autotools/Handler.cs @@ -76,18 +76,18 @@ namespace MonoDevelop.Autotools set { defaultConfig = value; } } - public override bool CanBuild (SolutionItem entry) + public override bool CanBuild (SolutionFolderItem entry) { SolutionDeployer deployer = new SolutionDeployer (generateAutotools); return deployer.CanDeploy ( entry ); } - public override void InitializeSettings (SolutionItem entry) + public override void InitializeSettings (SolutionFolderItem entry) { if (string.IsNullOrEmpty (targetDir)) targetDir = entry.BaseDirectory; if (string.IsNullOrEmpty (defaultConfig)) { - SolutionEntityItem se = entry as SolutionEntityItem; + SolutionItem se = entry as SolutionItem; defaultConfig = se != null ? se.GetConfigurations () [0] : null; } if (File.Exists (Path.Combine (entry.BaseDirectory, "autogen.sh")) || @@ -99,18 +99,18 @@ namespace MonoDevelop.Autotools } - protected override bool OnBuild (IProgressMonitor monitor, DeployContext ctx) + protected override bool OnBuild (ProgressMonitor monitor, DeployContext ctx) { string tmpFolder = FileService.CreateTempDirectory (); Solution solution = null; - SolutionItem entry = RootSolutionItem; + SolutionFolderItem entry = RootSolutionItem; try { if (generateFiles) { List<string> childEntries = new List<string> (); if (entry is SolutionFolder) { - SolutionItem[] ents = GetChildEntries (); - foreach (SolutionItem it in ents) + SolutionFolderItem[] ents = GetChildEntries (); + foreach (SolutionFolderItem it in ents) childEntries.Add (it.ItemId); } else { @@ -123,22 +123,21 @@ namespace MonoDevelop.Autotools if (entry is SolutionFolder) sourceFile = entry.ParentSolution.FileName; else - sourceFile = ((SolutionEntityItem)entry).FileName; + sourceFile = ((SolutionItem)entry).FileName; - string efile = Services.ProjectService.Export (new FilteredProgressMonitor (monitor), sourceFile, childEntries.ToArray (), tmpFolder, null); + string efile = Services.ProjectService.Export (new FilteredProgressMonitor (monitor), sourceFile, childEntries.ToArray (), tmpFolder, null).Result; if (efile == null) { monitor.ReportError (GettextCatalog.GetString ("The project could not be exported."), null); return false; } - solution = Services.ProjectService.ReadWorkspaceItem (new NullProgressMonitor (), efile) as Solution; + solution = Services.ProjectService.ReadWorkspaceItem (new ProgressMonitor (), efile).Result as Solution; } else { solution = entry.ParentSolution; } - solution.Build (monitor, (SolutionConfigurationSelector) defaultConfig); - - if (monitor.IsCancelRequested || !monitor.AsyncOperation.Success) + var res = solution.Build (monitor, (SolutionConfigurationSelector) defaultConfig).Result; + if (res.HasErrors || monitor.CancellationToken.IsCancellationRequested) return false; SolutionDeployer deployer = new SolutionDeployer (generateAutotools); diff --git a/main/src/addins/MonoDevelop.Autotools/IMakefileHandler.cs b/main/src/addins/MonoDevelop.Autotools/IMakefileHandler.cs index ac4a8ed108..31c6b18ccc 100644 --- a/main/src/addins/MonoDevelop.Autotools/IMakefileHandler.cs +++ b/main/src/addins/MonoDevelop.Autotools/IMakefileHandler.cs @@ -29,9 +29,9 @@ namespace MonoDevelop.Autotools { public interface IMakefileHandler { - bool CanDeploy (SolutionItem entry, MakefileType type); + bool CanDeploy (SolutionFolderItem entry, MakefileType type); - Makefile Deploy (AutotoolsContext ctx, SolutionItem entry, IProgressMonitor monitor); + Makefile Deploy (AutotoolsContext ctx, SolutionFolderItem entry, ProgressMonitor monitor); } public enum MakefileType diff --git a/main/src/addins/MonoDevelop.Autotools/MakefileData.cs b/main/src/addins/MonoDevelop.Autotools/MakefileData.cs index 8101bcfe67..01a6b1cb51 100644 --- a/main/src/addins/MonoDevelop.Autotools/MakefileData.cs +++ b/main/src/addins/MonoDevelop.Autotools/MakefileData.cs @@ -38,6 +38,7 @@ using MonoDevelop.Core.Serialization; using MonoDevelop.Projects; using MonoDevelop.Core.Assemblies; using MonoDevelop.Ide; +using System.Xml; namespace MonoDevelop.Autotools { @@ -70,6 +71,24 @@ namespace MonoDevelop.Autotools if (assemblyContext == null) integrationEnabled = false; } + + public static MakefileData Read (XmlElement ext) + { + XmlDataSerializer ser = new XmlDataSerializer (new DataContext ()); + return (MakefileData) ser.Deserialize (new XmlNodeReader (ext), typeof(MakefileData)); + } + + public XmlElement Write () + { + XmlDataSerializer ser = new XmlDataSerializer (new DataContext ()); + var sw = new StringWriter (); + ser.Serialize (new XmlTextWriter (sw), this); + XmlDocument doc = new XmlDocument (); + doc.LoadXml (sw.ToString ()); + var elem = doc.DocumentElement; + doc.RemoveChild (elem); + return elem; + } internal static IAssemblyContext GetMonoRuntimeContext () { @@ -613,7 +632,7 @@ namespace MonoDevelop.Autotools return customRegex [index]; } - IProgressMonitor monitor = null; + ProgressMonitor monitor = null; // VarName -> Encode filenames Eg. $(srcdir) Dictionary<string, bool> encodeValues; @@ -651,7 +670,7 @@ namespace MonoDevelop.Autotools } //use events.. - public void UpdateProject (IProgressMonitor monitor, bool promptForRemoval) + public void UpdateProject (ProgressMonitor monitor, bool promptForRemoval) { if (!IntegrationEnabled) return; @@ -1177,7 +1196,7 @@ namespace MonoDevelop.Autotools return pref; } - public static void ResolveProjectReferences (SolutionFolder folder, IProgressMonitor monitor) + public static void ResolveProjectReferences (SolutionFolder folder, ProgressMonitor monitor) { Dictionary<string, DotNetProject> projects = new Dictionary<string, DotNetProject> (); foreach (DotNetProject p in folder.GetAllItems<DotNetProject> ()) { @@ -1325,7 +1344,7 @@ namespace MonoDevelop.Autotools //Writing methods - public void UpdateMakefile (IProgressMonitor monitor) + public void UpdateMakefile (ProgressMonitor monitor) { //FIXME: AssemblyName & OutputDir diff --git a/main/src/addins/MonoDevelop.Autotools/MakefileGeneratorTool.cs b/main/src/addins/MonoDevelop.Autotools/MakefileGeneratorTool.cs index 8c483aff93..76af27790c 100644 --- a/main/src/addins/MonoDevelop.Autotools/MakefileGeneratorTool.cs +++ b/main/src/addins/MonoDevelop.Autotools/MakefileGeneratorTool.cs @@ -50,7 +50,7 @@ namespace MonoDevelop.Autotools Console.WriteLine (GettextCatalog.GetString ("Loading solution file {0}", filename)); ConsoleProgressMonitor monitor = new ConsoleProgressMonitor (); - Solution solution = Services.ProjectService.ReadWorkspaceItem (monitor, filename) as Solution; + Solution solution = Services.ProjectService.ReadWorkspaceItem (monitor, filename).Result as Solution; if (solution == null) { Console.WriteLine (GettextCatalog.GetString ("Error: Makefile generation supported only for solutions.\n")); return 1; diff --git a/main/src/addins/MonoDevelop.Autotools/MakefileIntegrationFeature.cs b/main/src/addins/MonoDevelop.Autotools/MakefileIntegrationFeature.cs index 8c08e1dc0f..df3511903f 100644 --- a/main/src/addins/MonoDevelop.Autotools/MakefileIntegrationFeature.cs +++ b/main/src/addins/MonoDevelop.Autotools/MakefileIntegrationFeature.cs @@ -17,7 +17,7 @@ namespace MonoDevelop.Autotools get { return string.Empty; } } - public FeatureSupportLevel GetSupportLevel (SolutionFolder parentCombine, SolutionItem entry) + public FeatureSupportLevel GetSupportLevel (SolutionFolder parentCombine, SolutionFolderItem entry) { if (entry is Project) return FeatureSupportLevel.SupportedByDefault; @@ -25,17 +25,17 @@ namespace MonoDevelop.Autotools return FeatureSupportLevel.NotSupported; } - public Widget CreateFeatureEditor (SolutionFolder parentCombine, SolutionItem entry) + public Widget CreateFeatureEditor (SolutionFolder parentCombine, SolutionFolderItem entry) { return new MakefileIntegrationFeatureWidget ((Project)entry); } - public void ApplyFeature (SolutionFolder parentCombine, SolutionItem entry, Widget editor) + public void ApplyFeature (SolutionFolder parentCombine, SolutionFolderItem entry, Widget editor) { ((MakefileIntegrationFeatureWidget)editor).Store (); } - public string Validate (SolutionFolder parentCombine, SolutionItem entry, Gtk.Widget editor) + public string Validate (SolutionFolder parentCombine, SolutionFolderItem entry, Gtk.Widget editor) { return null; } diff --git a/main/src/addins/MonoDevelop.Autotools/MakefileOptionPanelWidget.cs b/main/src/addins/MonoDevelop.Autotools/MakefileOptionPanelWidget.cs index c003789327..447b16994e 100644 --- a/main/src/addins/MonoDevelop.Autotools/MakefileOptionPanelWidget.cs +++ b/main/src/addins/MonoDevelop.Autotools/MakefileOptionPanelWidget.cs @@ -268,7 +268,7 @@ namespace MonoDevelop.Autotools //FIXME: Do this only if there are changes b/w tmpData and Data project.ExtendedProperties ["MonoDevelop.Autotools.MakefileInfo"] = tmpData; - using (IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor ( + using (ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor ( GettextCatalog.GetString ("Updating project"), "gtk-run", true)) { tmpData.UpdateProject (monitor, oldData == null || (!oldData.IntegrationEnabled && tmpData.IntegrationEnabled)); diff --git a/main/src/addins/MonoDevelop.Autotools/MakefileProject.cs b/main/src/addins/MonoDevelop.Autotools/MakefileProject.cs index 91dd984bd9..23a9125a6c 100644 --- a/main/src/addins/MonoDevelop.Autotools/MakefileProject.cs +++ b/main/src/addins/MonoDevelop.Autotools/MakefileProject.cs @@ -17,10 +17,10 @@ namespace MonoDevelop.Autotools conf.Name = name; return conf; } - - public override IEnumerable<string> GetProjectTypes () + + protected override void OnGetProjectTypes (HashSet<string> types) { - yield return "MakefileProject"; + types.Add ("MakefileProject"); } } diff --git a/main/src/addins/MonoDevelop.Autotools/MakefileProjectServiceExtension.cs b/main/src/addins/MonoDevelop.Autotools/MakefileProjectServiceExtension.cs index 5c71be9a49..1ca531fbaa 100644 --- a/main/src/addins/MonoDevelop.Autotools/MakefileProjectServiceExtension.cs +++ b/main/src/addins/MonoDevelop.Autotools/MakefileProjectServiceExtension.cs @@ -38,15 +38,17 @@ using System.Collections.Generic; using System.IO; using System.Text; using System.Text.RegularExpressions; +using System.Linq; +using System.Threading.Tasks; namespace MonoDevelop.Autotools { public class MakefileProjectServiceExtension : ProjectServiceExtension { - public override WorkspaceItem LoadWorkspaceItem (IProgressMonitor monitor, string fileName) + public async override Task<WorkspaceItem> LoadWorkspaceItem (ProgressMonitor monitor, string fileName) { - WorkspaceItem item = base.LoadWorkspaceItem (monitor, fileName); - + WorkspaceItem item = await base.LoadWorkspaceItem (monitor, fileName); + Solution sol = item as Solution; if (sol != null) { //Resolve project references @@ -59,68 +61,65 @@ namespace MonoDevelop.Autotools "Error resolving Makefile based project references for solution {0}", sol.Name), e); } } - + return item; } + } - - protected override SolutionEntityItem LoadSolutionItem (IProgressMonitor monitor, string fileName) + [RegisterProjectModelExtension] + public class MakefileProjectExtension: ProjectExtension + { + MakefileData data; + + protected override void OnReadProject (ProgressMonitor monitor, MonoDevelop.Projects.Formats.MSBuild.MSBuildProject msproject) { - SolutionEntityItem entry = base.LoadSolutionItem (monitor, fileName); - if (entry == null) - return null; - - Project project = entry as Project; - if (project == null) - return entry; + base.OnReadProject (monitor, msproject); + var ext = msproject.GetMonoDevelopProjectExtension ("MonoDevelop.Autotools.MakefileInfo"); + if (ext == null) + return; - //Project - MakefileData data = entry.ExtendedProperties ["MonoDevelop.Autotools.MakefileInfo"] as MakefileData; + data = MakefileData.Read (ext); if (data == null) - return entry; + return; monitor.BeginTask (GettextCatalog.GetString ("Updating project from Makefile"), 1); try { - data.OwnerProject = project;
+ data.OwnerProject = Project; if (data.SupportsIntegration) data.UpdateProject (monitor, false); monitor.Step (1); } catch (Exception e) { monitor.ReportError (GettextCatalog.GetString ( - "Error loading Makefile for project {0}", project.Name), e); + "\tError loading Makefile for project {0}", Project.Name), e); } finally { monitor.EndTask (); } - return entry; } - public override void Save (IProgressMonitor monitor, SolutionEntityItem entry) + protected override void OnWriteProject (ProgressMonitor monitor, MonoDevelop.Projects.Formats.MSBuild.MSBuildProject msproject) { - base.Save (monitor, entry); - - Project project = entry as Project; - if (project == null) - return; - - MakefileData data = project.ExtendedProperties ["MonoDevelop.Autotools.MakefileInfo"] as MakefileData;
+ base.OnWriteProject (monitor, msproject); + if (data == null || !data.SupportsIntegration) return; + msproject.SetProjectExtension ("MonoDevelop.Autotools.MakefileInfo", data.Write ()); + try { data.UpdateMakefile (monitor); } catch (Exception e) { LoggingService.LogError (GettextCatalog.GetString ("Error saving to Makefile ({0}) for project {1}", - data.AbsoluteMakefileName, project.Name, e)); + data.AbsoluteMakefileName, Project.Name, e)); monitor.ReportError (GettextCatalog.GetString ( - "Error saving to Makefile ({0}) for project {1}", data.AbsoluteMakefileName, project.Name), e); + "Error saving to Makefile ({0}) for project {1}", data.AbsoluteMakefileName, Project.Name), e); } }
- public override List<FilePath> GetItemFiles (SolutionEntityItem entry, bool includeReferencedFiles) + protected override IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles) {
- List<FilePath> col = base.GetItemFiles (entry, includeReferencedFiles); + List<FilePath> col = base.OnGetItemFiles (includeReferencedFiles).ToList (); - MakefileData data = entry.ExtendedProperties ["MonoDevelop.Autotools.MakefileInfo"] as MakefileData;
+ MakefileData data = Project.ExtendedProperties ["MonoDevelop.Autotools.MakefileInfo"] as MakefileData;
if (data == null || !data.SupportsIntegration || string.IsNullOrEmpty (data.AbsoluteMakefileName)) return col; @@ -136,31 +135,21 @@ namespace MonoDevelop.Autotools } - //TODO - protected override bool GetNeedsBuilding (SolutionEntityItem entry, ConfigurationSelector configuration) - { - return base.GetNeedsBuilding (entry, configuration); - } - //FIXME: Check whether autogen.sh is required or not - protected override BuildResult Build (IProgressMonitor monitor, SolutionEntityItem entry, ConfigurationSelector configuration) + protected async override Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { - Project project = entry as Project; - if (project == null) - return base.Build (monitor, entry, configuration); - - MakefileData data = project.ExtendedProperties ["MonoDevelop.Autotools.MakefileInfo"] as MakefileData;
+ MakefileData data = Project.ExtendedProperties ["MonoDevelop.Autotools.MakefileInfo"] as MakefileData;
if (data == null || !data.SupportsIntegration || String.IsNullOrEmpty (data.BuildTargetName)) - return base.Build (monitor, entry, configuration); + return await base.OnBuild (monitor, configuration); //FIXME: Gen autofoo ? autoreconf? string output = String.Empty; int exitCode = 0; - monitor.BeginTask (GettextCatalog.GetString ("Building {0}", project.Name), 1); + monitor.BeginTask (GettextCatalog.GetString ("Building {0}", Project.Name), 1); try { - string baseDir = project.BaseDirectory; + string baseDir = Project.BaseDirectory; string args = string.Format ("-j {0} {1}", data.ParallelProcesses, data.BuildTargetName); using (var swOutput = new StringWriter ()) { @@ -174,7 +163,8 @@ namespace MonoDevelop.Autotools chainedOutput, chainedOutput, null)) { - process.WaitForOutput (); + + await process.Task; chainedOutput.UnchainWriter (monitor.Log); chainedOutput.UnchainWriter (swOutput); @@ -200,7 +190,7 @@ namespace MonoDevelop.Autotools Regex regexError = data.GetErrorRegex (false); Regex regexWarning = data.GetWarningRegex (false); - BuildResult cr = ParseOutput (tf, output, project.BaseDirectory, regexError, regexWarning); + BuildResult cr = ParseOutput (tf, output, Project.BaseDirectory, regexError, regexWarning); if (exitCode != 0 && cr.FailedBuildCount == 0) cr.AddError (GettextCatalog.GetString ("Build failed. See Build Output panel.")); @@ -330,24 +320,17 @@ namespace MonoDevelop.Autotools return null; } - protected override void Clean (IProgressMonitor monitor, SolutionEntityItem entry, ConfigurationSelector configuration) + protected async override Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration) { - Project proj = entry as Project; - if (proj == null) { - base.Clean (monitor, entry, configuration); - return; - } - - MakefileData data = proj.ExtendedProperties ["MonoDevelop.Autotools.MakefileInfo"] as MakefileData;
+ MakefileData data = Project.ExtendedProperties ["MonoDevelop.Autotools.MakefileInfo"] as MakefileData;
if (data == null || !data.SupportsIntegration || String.IsNullOrEmpty (data.CleanTargetName)) { - base.Clean (monitor, entry, configuration); - return; + return await base.OnClean (monitor, configuration); } monitor.BeginTask ( GettextCatalog.GetString( "Cleaning project"), 1); try { - string baseDir = proj.BaseDirectory; + string baseDir = Project.BaseDirectory; ProcessWrapper process = Runtime.ProcessService.StartProcess ( "make", data.CleanTargetName, @@ -355,7 +338,8 @@ namespace MonoDevelop.Autotools monitor.Log, monitor.Log, null ); - process.WaitForOutput (); + + await process.Task; if ( process.ExitCode > 0 ) throw new Exception ( GettextCatalog.GetString ("An unspecified error occurred while running '{0}'", "make " + data.CleanTargetName) ); @@ -365,52 +349,47 @@ namespace MonoDevelop.Autotools catch ( Exception e ) { monitor.ReportError ( GettextCatalog.GetString ("Project could not be cleaned: "), e ); - return; + var res = new BuildResult (); + res.AddError (GettextCatalog.GetString ("Project could not be cleaned: ") + e.Message); + return res; } finally { monitor.EndTask (); } monitor.ReportSuccess ( GettextCatalog.GetString ( "Project successfully cleaned")); + return BuildResult.Success; } - protected override bool CanExecute (SolutionEntityItem item, ExecutionContext context, ConfigurationSelector configuration) + protected override bool OnGetCanExecute (ExecutionContext context, ConfigurationSelector configuration) { - Project project = item as Project; - if (project != null) { - MakefileData data = project.ExtendedProperties ["MonoDevelop.Autotools.MakefileInfo"] as MakefileData;
- if (data != null && data.SupportsIntegration && !String.IsNullOrEmpty (data.ExecuteTargetName)) - return true; - } - return base.CanExecute (item, context, configuration); + MakefileData data = Project.ExtendedProperties ["MonoDevelop.Autotools.MakefileInfo"] as MakefileData;
+ if (data != null && data.SupportsIntegration && !String.IsNullOrEmpty (data.ExecuteTargetName)) + return true; + return base.OnGetCanExecute (context, configuration); } - protected override void Execute (IProgressMonitor monitor, SolutionEntityItem entry, ExecutionContext context, ConfigurationSelector configuration) + protected async override Task OnExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { - Project project = entry as Project; - if (project == null) { - base.Execute (monitor, entry, context, configuration); - return; - } - - MakefileData data = project.ExtendedProperties ["MonoDevelop.Autotools.MakefileInfo"] as MakefileData;
+ MakefileData data = Project.ExtendedProperties ["MonoDevelop.Autotools.MakefileInfo"] as MakefileData;
if (data == null || !data.SupportsIntegration || String.IsNullOrEmpty (data.ExecuteTargetName)) { - base.Execute (monitor, entry, context, configuration); + base.OnExecute (monitor, context, configuration); return; } IConsole console = context.ConsoleFactory.CreateConsole (true); - monitor.BeginTask (GettextCatalog.GetString ("Executing {0}", project.Name), 1); + monitor.BeginTask (GettextCatalog.GetString ("Executing {0}", Project.Name), 1); try { ProcessWrapper process = Runtime.ProcessService.StartProcess ("make", - data.ExecuteTargetName, - project.BaseDirectory, - console.Out, - console.Error, - null); - process.WaitForOutput (); + data.ExecuteTargetName, + Project.BaseDirectory, + console.Out, + console.Error, + null); + + await process.Task; monitor.Log.WriteLine (GettextCatalog.GetString ("The application exited with code: {0}", process.ExitCode)); monitor.Step (1); diff --git a/main/src/addins/MonoDevelop.Autotools/MonoDevelop.Autotools.addin.xml b/main/src/addins/MonoDevelop.Autotools/MonoDevelop.Autotools.addin.xml index 0ed738152b..2388eb28f7 100644 --- a/main/src/addins/MonoDevelop.Autotools/MonoDevelop.Autotools.addin.xml +++ b/main/src/addins/MonoDevelop.Autotools/MonoDevelop.Autotools.addin.xml @@ -29,6 +29,12 @@ </Condition> </Extension> + <Extension path = "/MonoDevelop/ProjectModel/ProjectModelExtensions"> + <Condition id="Platform" value="!windows"> + <ProjectExtension class = "MonoDevelop.Autotools.MakefileProjectExtension" id="MakefileProjectServiceExtension" insertafter="FinalStep"/> + </Condition> + </Extension> + <Extension path = "/MonoDevelop/Ide/Commands"> <Condition id="Platform" value="!windows"> <Category _name = "Autotools" id = "Autotools"> diff --git a/main/src/addins/MonoDevelop.Autotools/MonoDevelop.Autotools.csproj b/main/src/addins/MonoDevelop.Autotools/MonoDevelop.Autotools.csproj index 47387c921d..84c712ed90 100644 --- a/main/src/addins/MonoDevelop.Autotools/MonoDevelop.Autotools.csproj +++ b/main/src/addins/MonoDevelop.Autotools/MonoDevelop.Autotools.csproj @@ -85,6 +85,7 @@ <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> <SpecificVersion>False</SpecificVersion> </Reference> + <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <Compile Include="AssemblyInfo.cs" /> diff --git a/main/src/addins/MonoDevelop.Autotools/SimpleProjectMakefileHandler.cs b/main/src/addins/MonoDevelop.Autotools/SimpleProjectMakefileHandler.cs index 6f4d39496f..b3bc53e342 100644 --- a/main/src/addins/MonoDevelop.Autotools/SimpleProjectMakefileHandler.cs +++ b/main/src/addins/MonoDevelop.Autotools/SimpleProjectMakefileHandler.cs @@ -71,7 +71,7 @@ namespace MonoDevelop.Autotools // store all refs for easy access Set<SystemPackage> pkgs; - public bool CanDeploy (SolutionItem entry, MakefileType type) + public bool CanDeploy (SolutionFolderItem entry, MakefileType type) { Project project = entry as Project; if ( project == null ) return false; @@ -89,7 +89,7 @@ namespace MonoDevelop.Autotools return null; } - public Makefile Deploy (AutotoolsContext ctx, SolutionItem entry, IProgressMonitor monitor) + public Makefile Deploy (AutotoolsContext ctx, SolutionFolderItem entry, ProgressMonitor monitor) { generateAutotools = ctx.MakefileType == MakefileType.AutotoolsMakefile; @@ -324,7 +324,7 @@ namespace MonoDevelop.Autotools ctx.AddBuiltFile (Path.Combine (config.OutputDirectory, bfile)); DeployFileCollection deployFiles = DeployService.GetDeployFiles ( - ctx.DeployContext, new SolutionItem[] { project }, config.Selector); + ctx.DeployContext, new SolutionFolderItem[] { project }, config.Selector); ProcessDeployFilesForConfig (deployFiles, project, configSection, ctx, config); configSections.Add (configSection); @@ -677,7 +677,7 @@ endif", s.SwitchName.Replace ('-', '_').ToUpperInvariant (), s.Define)); return dir; } - void EmitCustomCommandTargets (CustomCommandCollection commands, Project project, StringBuilder builder, string configName, CustomCommandType[] types, IProgressMonitor monitor) + void EmitCustomCommandTargets (CustomCommandCollection commands, Project project, StringBuilder builder, string configName, CustomCommandType[] types, ProgressMonitor monitor) { bool warned = false; configName = configName.ToUpper (); @@ -735,7 +735,7 @@ endif", s.SwitchName.Replace ('-', '_').ToUpperInvariant (), s.Define)); } // Get the Project config corresponding to its @parentConfig - internal static SolutionItemConfiguration GetProjectConfig (string parentConfig, SolutionEntityItem entry, out bool enabled) + internal static SolutionItemConfiguration GetProjectConfig (string parentConfig, SolutionItem entry, out bool enabled) { enabled = false; SolutionConfiguration solutionConfig = entry.ParentSolution.Configurations [parentConfig] as SolutionConfiguration; diff --git a/main/src/addins/MonoDevelop.Autotools/SolutionDeployer.cs b/main/src/addins/MonoDevelop.Autotools/SolutionDeployer.cs index 3bb43a271b..16d1bd6081 100644 --- a/main/src/addins/MonoDevelop.Autotools/SolutionDeployer.cs +++ b/main/src/addins/MonoDevelop.Autotools/SolutionDeployer.cs @@ -71,14 +71,14 @@ namespace MonoDevelop.Autotools } } - public bool CanDeploy (SolutionItem entry) + public bool CanDeploy (SolutionFolderItem entry) { MakefileType mt = generateAutotools ? MakefileType.AutotoolsMakefile : MakefileType.SimpleMakefile; IMakefileHandler handler = AutotoolsContext.GetMakefileHandler (entry, mt); return handler != null; } - public bool GenerateFiles (DeployContext ctx, Solution solution, string defaultConf, IProgressMonitor monitor ) + public bool GenerateFiles (DeployContext ctx, Solution solution, string defaultConf, ProgressMonitor monitor ) { string filesString = generateAutotools ? "Autotools files" : "Makefiles"; monitor.BeginTask ( GettextCatalog.GetString ("Generating {0} for Solution {1}", filesString, solution.Name), 1 ); @@ -153,7 +153,7 @@ namespace MonoDevelop.Autotools return true; } - public bool Deploy ( DeployContext ctx, Solution solution, string defaultConf, string targetDir, bool generateFiles, IProgressMonitor monitor ) + public bool Deploy ( DeployContext ctx, Solution solution, string defaultConf, string targetDir, bool generateFiles, ProgressMonitor monitor ) { if (generateFiles) { if ( !GenerateFiles ( ctx, solution, defaultConf, monitor ) ) @@ -231,7 +231,7 @@ namespace MonoDevelop.Autotools if ( File.Exists ( file ) ) FileService.DeleteFile ( file ); } - void AddTopLevelMakefileVars ( Makefile makefile, IProgressMonitor monitor) + void AddTopLevelMakefileVars ( Makefile makefile, ProgressMonitor monitor) { monitor.Log.WriteLine ( GettextCatalog.GetString ("Adding variables to top-level Makefile") ); @@ -251,7 +251,7 @@ namespace MonoDevelop.Autotools // makefile.AppendToVariable ( "pkglib_DATA", "$(DLL_REFERENCES)" ); } - void CreateAutoGenDotSH (AutotoolsContext context, IProgressMonitor monitor) + void CreateAutoGenDotSH (AutotoolsContext context, ProgressMonitor monitor) { monitor.Log.WriteLine ( GettextCatalog.GetString ("Creating autogen.sh") ); @@ -278,7 +278,7 @@ namespace MonoDevelop.Autotools Syscall.chmod ( fileName , FilePermissions.S_IXOTH | FilePermissions.S_IROTH | FilePermissions.S_IRWXU | FilePermissions.S_IRWXG ); } - void CreateConfigureDotAC (Solution solution, string defaultConf, IProgressMonitor monitor, AutotoolsContext context) + void CreateConfigureDotAC (Solution solution, string defaultConf, ProgressMonitor monitor, AutotoolsContext context) { monitor.Log.WriteLine ( GettextCatalog.GetString ("Creating configure.ac") ); TemplateEngine templateEngine = new TemplateEngine(); @@ -394,7 +394,7 @@ AM_CONDITIONAL(ENABLE_{3}, test x$enable_{2} = xyes)", context.AddGeneratedFile (configureFileName); } - void CreateConfigureScript (Solution solution, string defaultConf, AutotoolsContext ctx, IProgressMonitor monitor) + void CreateConfigureScript (Solution solution, string defaultConf, AutotoolsContext ctx, ProgressMonitor monitor) { monitor.Log.WriteLine ( GettextCatalog.GetString ("Creating configure script") ); @@ -469,7 +469,7 @@ AM_CONDITIONAL(ENABLE_{3}, test x$enable_{2} = xyes)", return builder.ToString (); } - void CreateMakefileInclude (AutotoolsContext context, IProgressMonitor monitor) + void CreateMakefileInclude (AutotoolsContext context, ProgressMonitor monitor) { monitor.Log.WriteLine ( GettextCatalog.GetString ("Creating Makefile.include") ); diff --git a/main/src/addins/MonoDevelop.Autotools/SolutionMakefileHandler.cs b/main/src/addins/MonoDevelop.Autotools/SolutionMakefileHandler.cs index b31e5ddba0..ab70a6472d 100644 --- a/main/src/addins/MonoDevelop.Autotools/SolutionMakefileHandler.cs +++ b/main/src/addins/MonoDevelop.Autotools/SolutionMakefileHandler.cs @@ -33,12 +33,12 @@ namespace MonoDevelop.Autotools bool generateAutotools = true; // Recurses into children and tests if they are deployable. - public bool CanDeploy (SolutionItem entry, MakefileType type) + public bool CanDeploy (SolutionFolderItem entry, MakefileType type) { return entry is SolutionFolder; } - public Makefile Deploy (AutotoolsContext ctx, SolutionItem entry, IProgressMonitor monitor) + public Makefile Deploy (AutotoolsContext ctx, SolutionFolderItem entry, ProgressMonitor monitor) { generateAutotools = ctx.MakefileType == MakefileType.AutotoolsMakefile; @@ -78,10 +78,10 @@ namespace MonoDevelop.Autotools subdirs.Append (" SUBDIRS = "); - foreach (SolutionItem ce in CalculateSubDirOrder (ctx, solutionFolder, config)) + foreach (SolutionFolderItem ce in CalculateSubDirOrder (ctx, solutionFolder, config)) { string baseDirectory; - if (!(ce is SolutionEntityItem) && !(ce is SolutionFolder)) + if (!(ce is SolutionItem) && !(ce is SolutionFolder)) continue; // Ignore projects which can't be deployed @@ -118,7 +118,7 @@ namespace MonoDevelop.Autotools string includedProject = null; // deploy recursively - foreach (SolutionItem ce in children) + foreach (SolutionFolderItem ce in children) { IMakefileHandler handler = AutotoolsContext.GetMakefileHandler ( ce, ctx.MakefileType ); Makefile makefile; @@ -206,11 +206,11 @@ namespace MonoDevelop.Autotools } // utility function for finding the correct order to process directories - List<SolutionItem> CalculateSubDirOrder (AutotoolsContext ctx, SolutionFolder folder, SolutionConfiguration config) + List<SolutionFolderItem> CalculateSubDirOrder (AutotoolsContext ctx, SolutionFolder folder, SolutionConfiguration config) { - List<SolutionItem> resultOrder = new List<SolutionItem>(); - Set<SolutionItem> dependenciesMet = new Set<SolutionItem>(); - Set<SolutionItem> inResult = new Set<SolutionItem>(); + List<SolutionFolderItem> resultOrder = new List<SolutionFolderItem>(); + Set<SolutionFolderItem> dependenciesMet = new Set<SolutionFolderItem>(); + Set<SolutionFolderItem> inResult = new Set<SolutionFolderItem>(); // We don't have to worry about projects built in parent combines dependenciesMet.Union (ctx.GetBuiltProjects ()); @@ -222,24 +222,24 @@ namespace MonoDevelop.Autotools added = false; notMet = null; - List<SolutionItem> items = new List<SolutionItem> (); + List<SolutionFolderItem> items = new List<SolutionFolderItem> (); GetSubItems (items, folder); - foreach (SolutionItem item in items) + foreach (SolutionFolderItem item in items) { - Set<SolutionItem> references, provides; + Set<SolutionFolderItem> references, provides; if (inResult.Contains (item)) continue; - if (item is SolutionEntityItem) + if (item is SolutionItem) { - SolutionEntityItem entry = (SolutionEntityItem) item; + SolutionItem entry = (SolutionItem) item; if (!config.BuildEnabledForItem (entry)) continue; - references = new Set<SolutionItem> (); - provides = new Set<SolutionItem>(); + references = new Set<SolutionFolderItem> (); + provides = new Set<SolutionFolderItem>(); references.Union (entry.GetReferencedItems (config.Selector)); provides.Add (entry); } @@ -266,12 +266,12 @@ namespace MonoDevelop.Autotools return resultOrder; } - void GetSubItems (List<SolutionItem> list, SolutionFolder folder) + void GetSubItems (List<SolutionFolderItem> list, SolutionFolder folder) { // This method returns the subitems of a folder. // If a folder does not match a phisical folder, it will be ignored. - foreach (SolutionItem item in folder.Items) { + foreach (SolutionFolderItem item in folder.Items) { if (item is SolutionFolder) { if (item.BaseDirectory != folder.BaseDirectory) list.Add (item); @@ -290,25 +290,25 @@ namespace MonoDevelop.Autotools * returns a set of projects that a combine contains and a set of projects * that are referenced from combine projects but not part of the combine */ - void GetAllProjects (SolutionFolder folder, SolutionConfiguration config, out Set<SolutionItem> projects, out Set<SolutionItem> references) + void GetAllProjects (SolutionFolder folder, SolutionConfiguration config, out Set<SolutionFolderItem> projects, out Set<SolutionFolderItem> references) { - List<SolutionItem> subitems = new List<SolutionItem> (); + List<SolutionFolderItem> subitems = new List<SolutionFolderItem> (); GetSubItems (subitems, folder); - projects = (Set<SolutionItem>) combineProjects [folder]; + projects = (Set<SolutionFolderItem>) combineProjects [folder]; if (projects != null) { - references = (Set<SolutionItem>) combineReferences [folder]; + references = (Set<SolutionFolderItem>) combineReferences [folder]; return; } - projects = new Set<SolutionItem>(); - references = new Set<SolutionItem>(); + projects = new Set<SolutionFolderItem>(); + references = new Set<SolutionFolderItem>(); - foreach (SolutionItem item in subitems) + foreach (SolutionFolderItem item in subitems) { - if (item is SolutionEntityItem) + if (item is SolutionItem) { - SolutionEntityItem entry = (SolutionEntityItem) item; + SolutionItem entry = (SolutionItem) item; if (!config.BuildEnabledForItem (entry)) continue; projects.Add (entry); @@ -316,8 +316,8 @@ namespace MonoDevelop.Autotools } else if (item is SolutionFolder) { - Set<SolutionItem> subProjects; - Set<SolutionItem> subReferences; + Set<SolutionFolderItem> subProjects; + Set<SolutionFolderItem> subReferences; GetAllProjects ((SolutionFolder)item, config, out subProjects, out subReferences); projects.Union (subProjects); references.Union (subReferences); diff --git a/main/src/addins/MonoDevelop.Autotools/TarballBuilderEditorWidget.cs b/main/src/addins/MonoDevelop.Autotools/TarballBuilderEditorWidget.cs index edd2eebbdd..0ef6aaaf30 100644 --- a/main/src/addins/MonoDevelop.Autotools/TarballBuilderEditorWidget.cs +++ b/main/src/addins/MonoDevelop.Autotools/TarballBuilderEditorWidget.cs @@ -17,7 +17,7 @@ namespace MonoDevelop.Autotools alignment1.Xscale = 0.04f; this.target = target; - SolutionItem targetCombine = target.RootSolutionItem; + SolutionFolderItem targetCombine = target.RootSolutionItem; folderEntry.Path = target.TargetDir; if (string.IsNullOrEmpty (target.DefaultConfiguration)) { diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/GdbSession.cs b/main/src/addins/MonoDevelop.Debugger.Gdb/GdbSession.cs index f7ad8dfa67..44dc1f91e1 100644 --- a/main/src/addins/MonoDevelop.Debugger.Gdb/GdbSession.cs +++ b/main/src/addins/MonoDevelop.Debugger.Gdb/GdbSession.cs @@ -45,7 +45,7 @@ namespace MonoDevelop.Debugger.Gdb Process proc; StreamReader sout; StreamWriter sin; - IProcessAsyncOperation console; + ProcessAsyncOperation console; GdbCommandResult lastResult; bool running; Thread thread; diff --git a/main/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/CustomSoftDebuggerEngine.cs b/main/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/CustomSoftDebuggerEngine.cs index ca3f329233..134809e69f 100644 --- a/main/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/CustomSoftDebuggerEngine.cs +++ b/main/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/CustomSoftDebuggerEngine.cs @@ -98,7 +98,7 @@ namespace MonoDevelop.Debugger.Soft class CustomSoftDebuggerSession : SoftDebuggerSession { - IProcessAsyncOperation process; + ProcessAsyncOperation process; bool usingExternalConsole; protected override void OnRun (DebuggerStartInfo startInfo) @@ -138,7 +138,7 @@ namespace MonoDevelop.Debugger.Soft foreach (KeyValuePair<string,string> kvp in info.EnvironmentVariables) psi.EnvironmentVariables [kvp.Key] = kvp.Value; - process = Runtime.ProcessService.StartProcess (psi, ProcessOutput, ProcessError, null); + process = Runtime.ProcessService.StartProcess (psi, ProcessOutput, ProcessError, null).ProcessAsyncOperation; } } diff --git a/main/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/SoftDebuggerEngine.cs b/main/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/SoftDebuggerEngine.cs index f04bc311f4..190ab55c6a 100644 --- a/main/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/SoftDebuggerEngine.cs +++ b/main/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/SoftDebuggerEngine.cs @@ -86,7 +86,7 @@ namespace MonoDevelop.Debugger.Soft var varsCopy = new Dictionary<string, string> (cmd.EnvironmentVariables); var startArgs = (SoftDebuggerLaunchArgs) dsi.StartArgs; startArgs.ExternalConsoleLauncher = delegate (System.Diagnostics.ProcessStartInfo info) { - IProcessAsyncOperation oper; + ProcessAsyncOperation oper; oper = Runtime.ProcessService.StartConsoleProcess (info.FileName, info.Arguments, info.WorkingDirectory, varsCopy, ExternalConsoleFactory.Instance.CreateConsole (dsi.CloseExternalConsoleOnExit), null); return new ProcessAdapter (oper, Path.GetFileName (info.FileName)); @@ -158,17 +158,17 @@ namespace MonoDevelop.Debugger.Soft class ProcessAdapter: Mono.Debugger.Soft.ITargetProcess { - IProcessAsyncOperation oper; + ProcessAsyncOperation oper; string name; - public ProcessAdapter (IProcessAsyncOperation oper, string name) + public ProcessAdapter (ProcessAsyncOperation oper, string name) { this.oper = oper; this.name = name; - oper.Completed += delegate { + oper.Task.ContinueWith (t => { if (Exited != null) Exited (this, EventArgs.Empty); - }; + }); } #region IProcess implementation diff --git a/main/src/addins/MonoDevelop.Debugger.Win32/MonoDevelop.Debugger.Win32/CorObjectAdaptor.cs b/main/src/addins/MonoDevelop.Debugger.Win32/MonoDevelop.Debugger.Win32/CorObjectAdaptor.cs index 5caa63f289..23dd037508 100644 --- a/main/src/addins/MonoDevelop.Debugger.Win32/MonoDevelop.Debugger.Win32/CorObjectAdaptor.cs +++ b/main/src/addins/MonoDevelop.Debugger.Win32/MonoDevelop.Debugger.Win32/CorObjectAdaptor.cs @@ -64,6 +64,8 @@ namespace MonoDevelop.Debugger.Win32 public override bool IsEnum (EvaluationContext ctx, object val)
{
+ if (!(val is CorValRef))
+ return false;
CorType type = (CorType) GetValueType (ctx, val);
return IsEnum (ctx, type);
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Visualizer/TextVisualizer.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Visualizer/TextVisualizer.cs index cb2b881229..64b1153aea 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Visualizer/TextVisualizer.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Visualizer/TextVisualizer.cs @@ -106,12 +106,12 @@ namespace MonoDevelop.Debugger.Visualizer void PopulateTextView (ObjectValue value) { - var ops = DebuggingService.DebuggerSession.EvaluationOptions.Clone (); - ops.AllowTargetInvoke = true; - ops.ChunkRawStrings = true; + var options = DebuggingService.DebuggerSession.EvaluationOptions.Clone (); + options.AllowTargetInvoke = true; + options.ChunkRawStrings = true; if (value.TypeName == "string") { - rawString = value.GetRawValue (ops) as RawValueString; + rawString = value.GetRawValue (options) as RawValueString; length = rawString.Length; offset = 0; @@ -125,7 +125,7 @@ namespace MonoDevelop.Debugger.Visualizer }; } } else if (value.TypeName == "char[]") { - rawArray = value.GetRawValue (ops) as RawValueArray; + rawArray = value.GetRawValue (options) as RawValueArray; length = rawArray.Length; offset = 0; @@ -173,12 +173,15 @@ namespace MonoDevelop.Debugger.Visualizer public override bool StoreValue (ObjectValue val) { + var options = DebuggingService.DebuggerSession.EvaluationOptions.Clone (); + options.AllowTargetInvoke = true; + switch (val.TypeName) { case "char[]": - val.SetRawValue (textView.Buffer.Text.ToCharArray ()); + val.SetRawValue (textView.Buffer.Text.ToCharArray (), options); return true; case "string": - val.SetRawValue (textView.Buffer.Text); + val.SetRawValue (textView.Buffer.Text, options); return true; default: return false; diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.addin.xml b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.addin.xml index 402df196c7..19045ebe26 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.addin.xml +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.addin.xml @@ -102,8 +102,20 @@ icon="md-step-out-debug"/> <Command id = "MonoDevelop.Debugger.DebugCommands.NewBreakpoint" defaultHandler = "MonoDevelop.Debugger.NewBreakpointHandler" - _label = "New Breakpoint..." + _label = "New Breakpoint" icon = "md-breakpoint-new" /> + <Command id = "MonoDevelop.Debugger.DebugCommands.NewFunctionBreakpoint" + defaultHandler = "MonoDevelop.Debugger.NewFunctionBreakpointHandler" + _label = "New Function Breakpoint" + icon = "md-breakpoint-new" /> + <Command id = "MonoDevelop.Debugger.DebugCommands.NewCatchpoint" + defaultHandler = "MonoDevelop.Debugger.NewCatchpointHandler" + _label = "New Exception Catchpoint" + icon = "md-breakpoint-new" /> + <Command id = "MonoDevelop.Debugger.DebugCommands.ShowBreakpoints" + defaultHandler = "MonoDevelop.Debugger.ShowBreakpointsHandler" + _label = "View Breakpoints" + icon = "md-view-debug-breakpoints" /> <Command id = "MonoDevelop.Debugger.DebugCommands.RemoveBreakpoint" defaultHandler = "MonoDevelop.Debugger.RemoveBreakpointHandler" _label = "Remove Breakpoint" /> @@ -183,6 +195,9 @@ <CommandItem id = "MonoDevelop.Debugger.DebugCommands.ShowCurrentExecutionLine" /> <SeparatorItem id = "MonoDevelop.Debugger.BreakpointsSection" /> <CommandItem id = "MonoDevelop.Debugger.DebugCommands.NewBreakpoint" /> + <CommandItem id = "MonoDevelop.Debugger.DebugCommands.NewFunctionBreakpoint" /> + <CommandItem id = "MonoDevelop.Debugger.DebugCommands.NewCatchpoint" /> + <CommandItem id = "MonoDevelop.Debugger.DebugCommands.ShowBreakpoints" /> <CommandItem id = "MonoDevelop.Debugger.DebugCommands.ToggleBreakpoint" /> <CommandItem id = "MonoDevelop.Debugger.DebugCommands.EnableDisableBreakpoint" /> <CommandItem id = "MonoDevelop.Debugger.DebugCommands.DisableAllBreakpoints" /> diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs index 29742d7fd4..f468753ed1 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs @@ -98,6 +98,9 @@ namespace MonoDevelop.Debugger toolbarSet.AddItem (EditCommands.Delete); toolbarSet.AddSeparator (); toolbarSet.Add (propertiesCmd); + toolbarSet.AddSeparator (); + toolbarSet.Add (new CommandEntry (DebugCommands.NewFunctionBreakpoint){ DispayType = CommandEntryDisplayType.IconAndText }); + toolbarSet.Add (new CommandEntry (DebugCommands.NewCatchpoint){ DispayType = CommandEntryDisplayType.IconAndText }); // The breakpoint list diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPropertiesDialog.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPropertiesDialog.cs index 683bc1d2e2..1df779cacc 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPropertiesDialog.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPropertiesDialog.cs @@ -46,6 +46,13 @@ namespace MonoDevelop.Debugger ExpressionChanges
}
+ public enum BreakpointType
+ {
+ Location,
+ Function,
+ Catchpoint
+ }
+
sealed class BreakpointPropertiesDialog : Dialog
{
// For button sensitivity.
@@ -193,15 +200,29 @@ namespace MonoDevelop.Debugger string parsedFunction;
readonly HashSet<string> classes = new HashSet<string> ();
-
- public BreakpointPropertiesDialog (BreakEvent be)
+ public BreakpointPropertiesDialog (BreakEvent be, BreakpointType breakpointType)
{
this.be = be;
-
LoadExceptionList ();
Initialize ();
SetInitialData ();
SetLayout ();
+ if (be == null) {
+ switch (breakpointType) {
+ case BreakpointType.Location:
+ stopOnLocation.Active = true;
+ entryLocationFile.SetFocus ();
+ break;
+ case BreakpointType.Function:
+ stopOnFunction.Active = true;
+ entryFunctionName.SetFocus ();
+ break;
+ case BreakpointType.Catchpoint:
+ stopOnException.Active = true;
+ entryExceptionType.SetFocus ();
+ break;
+ }
+ }
}
void Initialize ()
@@ -258,8 +279,46 @@ namespace MonoDevelop.Debugger entryPrintExpression.Changed += OnUpdateText;
buttonOk.Clicked += OnSave;
+
+ CompletionWindowManager.WindowShown += HandleCompletionWindowShown;
+ CompletionWindowManager.WindowClosed += HandleCompletionWindowClosed;
}
+ #region Modal and Dialog.Run workaround
+ /*
+ * If Dialog is ran with Dialog.Run and Modal=true it takes all events like mouse, keyboard... from other windows.
+ * So when CodeCompletionList window appears mouse events don't work on it(except if CodeCompletionList.Modal=true, but then
+ * events don't work on BreakpointPropertiesDialog(can't type rest of exception type name)).
+ * So what this workaround does is disables Modal on BreakpointProperties so CodeCompletionList mouse events work fine. But if user
+ * tries to access anything outside this two windows(e.g. MainWindow). CodeCompletionList loses focus and closes itself. Resulting
+ * in BreakpointProperties.Modal = true and user can't do anything on MainWindow.
+ * All this is done so fast(or in correct order) that user can't notice this Modal switching.
+ */
+
+ void HandleCompletionWindowClosed (object sender, EventArgs e)
+ {
+ var gtkWidget = Xwt.Toolkit.CurrentEngine.GetNativeWidget (vboxLocation) as Gtk.Widget;//Any widget is fine
+ if (gtkWidget != null) {
+ var topWindow = gtkWidget.Toplevel as Gtk.Window;
+ if (topWindow != null) {
+ topWindow.Modal = true;
+ }
+ }
+ }
+
+ void HandleCompletionWindowShown (object sender, EventArgs e)
+ {
+ var gtkWidget = Xwt.Toolkit.CurrentEngine.GetNativeWidget (vboxLocation) as Gtk.Widget;//Any widget is fine
+ if (gtkWidget != null) {
+ var topWindow = gtkWidget.Toplevel as Gtk.Window;
+ if (topWindow != null) {
+ topWindow.Modal = false;
+ }
+ }
+ }
+
+ #endregion
+
void SetInitialFunctionBreakpointData (FunctionBreakpoint fb)
{
stopOnLocation.Visible = false;
@@ -292,7 +351,7 @@ namespace MonoDevelop.Debugger if (project != null) {
// Check the startup project of the solution too, since the current project may be a library
- SolutionEntityItem startup = project.ParentSolution.StartupItem;
+ SolutionItem startup = project.ParentSolution.StartupItem;
entryConditionalExpression.Sensitive = DebuggingService.IsFeatureSupported (project, DebuggerFeatures.ConditionalBreakpoints) ||
DebuggingService.IsFeatureSupported (startup, DebuggerFeatures.ConditionalBreakpoints);
@@ -758,5 +817,11 @@ namespace MonoDevelop.Debugger OnUpdateControls (null, null);
}
+ protected override void Dispose (bool disposing)
+ {
+ CompletionWindowManager.WindowShown -= HandleCompletionWindowShown;
+ CompletionWindowManager.WindowClosed -= HandleCompletionWindowClosed;
+ base.Dispose (disposing);
+ }
}
}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs index 56c6f5cb5a..9c311dc928 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs @@ -34,6 +34,7 @@ using MonoDevelop.Ide.Gui; using MonoDevelop.Components.Commands; using MonoDevelop.Projects; using MonoDevelop.Ide; +using System.Linq; namespace MonoDevelop.Debugger { @@ -63,7 +64,9 @@ namespace MonoDevelop.Debugger StopEvaluation, RunToCursor, SetNextStatement, - ShowNextStatement + ShowNextStatement, + NewCatchpoint, + NewFunctionBreakpoint } class DebugHandler: CommandHandler @@ -75,7 +78,7 @@ namespace MonoDevelop.Debugger IdeApp.ProjectOperations.CurrentSelectedBuildTarget; } - internal static void BuildAndDebug () + internal async static void BuildAndDebug () { if (!DebuggingService.IsDebuggingSupported && !IdeApp.ProjectOperations.CurrentRunOperation.IsCompleted) { MonoDevelop.Ide.Commands.StopHandler.StopBuildOperations (); @@ -94,33 +97,14 @@ namespace MonoDevelop.Debugger } // Else continue building } - else { - ExecuteDocument (IdeApp.Workbench.ActiveDocument); - return; - } } if (IdeApp.Workspace.IsOpen) { var it = GetRunTarget (); - IAsyncOperation op = IdeApp.ProjectOperations.Build (it); - op.Completed += delegate { - if (op.SuccessWithWarnings && !IdeApp.Preferences.RunWithWarnings) - return; - if (op.Success) - ExecuteSolution (it); - }; - } else { - Document doc = IdeApp.Workbench.ActiveDocument; - if (doc != null) { - doc.Save (); - IAsyncOperation op = doc.Build (); - op.Completed += delegate { - if (op.SuccessWithWarnings && !IdeApp.Preferences.RunWithWarnings) - return; - if (op.Success) - ExecuteDocument (doc); - }; - } + var res = await IdeApp.ProjectOperations.Build (it).Task; + if (res.HasErrors || (res.HasWarnings && !IdeApp.Preferences.RunWithWarnings)) + return; + ExecuteSolution (it); } } @@ -132,14 +116,6 @@ namespace MonoDevelop.Debugger IdeApp.ProjectOperations.Execute (target); } - static void ExecuteDocument (Document doc) - { - if (doc.CanDebug ()) - doc.Debug (); - else - doc.Run (); - } - protected override void Run () { if (DebuggingService.IsPaused) { @@ -180,8 +156,7 @@ namespace MonoDevelop.Debugger info.Enabled = canExecute && (IdeApp.ProjectOperations.CurrentRunOperation.IsCompleted || !DebuggingService.IsDebuggingSupported); } else { - Document doc = IdeApp.Workbench.ActiveDocument; - info.Enabled = (doc != null && doc.IsBuildTarget) && (doc.CanRun () || doc.CanDebug ()); + info.Enabled = false; } } @@ -226,19 +201,16 @@ namespace MonoDevelop.Debugger class DebugEntryHandler: CommandHandler { - protected override void Run () + protected async override void Run () { IBuildTarget entry = IdeApp.ProjectOperations.CurrentSelectedBuildTarget; DebugHandler.CheckResult cr = DebugHandler.CheckBeforeDebugging (entry); if (cr == DebugHandler.CheckResult.BuildBeforeRun) { - IAsyncOperation op = IdeApp.ProjectOperations.Build (entry); - op.Completed += delegate { - if (op.SuccessWithWarnings && !IdeApp.Preferences.RunWithWarnings) - return; - if (op.Success) - IdeApp.ProjectOperations.Debug (entry); - }; + var res = await IdeApp.ProjectOperations.Build (entry).Task; + if (res.HasErrors || (res.HasWarnings && !IdeApp.Preferences.RunWithWarnings)) + return; + IdeApp.ProjectOperations.Debug (entry); } else if (cr == DebugHandler.CheckResult.Run) IdeApp.ProjectOperations.Debug (entry); } @@ -535,7 +507,7 @@ namespace MonoDevelop.Debugger } } } - + class NewBreakpointHandler: CommandHandler { protected override void Run () @@ -548,7 +520,27 @@ namespace MonoDevelop.Debugger breakpoints.Add (bp); } } - + + protected override void Update (CommandInfo info) + { + info.Visible = DebuggingService.IsFeatureSupported (DebuggerFeatures.Breakpoints); + info.Enabled = !DebuggingService.Breakpoints.IsReadOnly; + } + } + + class NewFunctionBreakpointHandler: CommandHandler + { + protected override void Run () + { + BreakEvent bp = null; + if (DebuggingService.ShowBreakpointProperties (ref bp, BreakpointType.Function)) { + var breakpoints = DebuggingService.Breakpoints; + + lock (breakpoints) + breakpoints.Add (bp); + } + } + protected override void Update (CommandInfo info) { info.Visible = DebuggingService.IsFeatureSupported (DebuggerFeatures.Breakpoints); @@ -556,6 +548,37 @@ namespace MonoDevelop.Debugger } } + class NewCatchpointHandler: CommandHandler + { + protected override void Run () + { + BreakEvent bp = null; + if (DebuggingService.ShowBreakpointProperties (ref bp, BreakpointType.Catchpoint)) { + var breakpoints = DebuggingService.Breakpoints; + + lock (breakpoints) + breakpoints.Add (bp); + } + } + + protected override void Update (CommandInfo info) + { + info.Visible = DebuggingService.IsFeatureSupported (DebuggerFeatures.Catchpoints); + info.Enabled = !DebuggingService.Breakpoints.IsReadOnly; + } + } + + class ShowBreakpointsHandler: CommandHandler + { + protected override void Run () + { + var breakpointsPad = IdeApp.Workbench.Pads.FirstOrDefault (p => p.Id == "MonoDevelop.Debugger.BreakpointPad"); + if (breakpointsPad != null) { + breakpointsPad.BringToFront (); + } + } + } + class RunToCursorHandler : CommandHandler { protected override void Run () @@ -589,7 +612,7 @@ namespace MonoDevelop.Debugger info.Enabled = target != null && IdeApp.ProjectOperations.CanDebug (target); } else { - info.Enabled = doc.IsBuildTarget && doc.CanDebug (); + info.Enabled = false; } } else { info.Enabled = false; diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugExecutionHandlerFactory.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugExecutionHandlerFactory.cs index 55cc770269..df9f1806d2 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugExecutionHandlerFactory.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugExecutionHandlerFactory.cs @@ -34,6 +34,7 @@ using MonoDevelop.Core.Execution; using Mono.Debugging.Client; using MonoDevelop.Ide.Gui; using Mono.Debugging; +using System.Threading.Tasks; namespace MonoDevelop.Debugger { @@ -44,103 +45,36 @@ namespace MonoDevelop.Debugger return DebuggingService.CanDebugCommand (command); } - public IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) + public ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) { if (!CanExecute (command)) return null; - DebugExecutionHandler h = new DebugExecutionHandler (null); - return h.Execute (command, console); + return DebuggingService.Run (command, console); } } - - class DebugExecutionHandler: IProcessAsyncOperation + + class DebugAsyncOperation: ProcessAsyncOperation { - bool done; ManualResetEvent stopEvent; - DebuggerEngine factory; - - public DebugExecutionHandler (DebuggerEngine factory) - { - this.factory = factory; - DebuggingService.StoppedEvent += new EventHandler (OnStopDebug); - } - - public IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) - { - DebuggingService.InternalRun (command, factory, console); - return this; - } - - public void Cancel () - { - DebuggingService.Stop (); - } - - public void WaitForCompleted () + + public DebugAsyncOperation () { - lock (this) { - if (done) return; - if (stopEvent == null) - stopEvent = new ManualResetEvent (false); - } - stopEvent.WaitOne (); - } - - public int ExitCode { - get { return 0; } - } - - public bool IsCompleted { - get { return done; } - } - - public bool Success { - get { return true; } + stopEvent = new ManualResetEvent (false); + DebuggingService.StoppedEvent += OnStopDebug; + CancellationTokenSource = new CancellationTokenSource (); + CancellationTokenSource.Token.Register (DebuggingService.Stop); + Task = Task.Factory.StartNew (() => stopEvent.WaitOne ()); } - public bool SuccessWithWarnings { - get { return true; } + public void Cleanup () + { + stopEvent.Set (); // Just in case there was something running + DebuggingService.StoppedEvent -= OnStopDebug; } void OnStopDebug (object sender, EventArgs args) { - lock (this) { - done = true; - if (stopEvent != null) - stopEvent.Set (); - if (completedEvent != null) - completedEvent (this); - } - - DebuggingService.StoppedEvent -= new EventHandler (OnStopDebug); - } - - event OperationHandler IAsyncOperation.Completed { - add { - bool raiseNow = false; - lock (this) { - if (done) - raiseNow = true; - else - completedEvent += value; - } - if (raiseNow) - value (this); - } - remove { - lock (this) { - completedEvent -= value; - } - } - } - - //FIXME: - public int ProcessId { - get { return -1; } + stopEvent.Set (); } - - event OperationHandler completedEvent; - - void IDisposable.Dispose () {} } } diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs index 31b1c55808..05050e81b0 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs @@ -46,6 +46,7 @@ using ICSharpCode.NRefactory.Semantics; */ using MonoDevelop.Ide.TextEditing; using System.Linq; +using System.Threading.Tasks; namespace MonoDevelop.Debugger { @@ -76,6 +77,8 @@ namespace MonoDevelop.Debugger static StatusBarIcon busyStatusIcon; static bool isBusy; + static DebugAsyncOperation currentDebugOperation = new DebugAsyncOperation (); + static public event EventHandler DebugSessionStarted; static public event EventHandler PausedEvent; static public event EventHandler ResumedEvent; @@ -187,9 +190,9 @@ namespace MonoDevelop.Debugger MessageService.ShowCustomDialog (dlg); } - public static bool ShowBreakpointProperties (ref BreakEvent bp) + public static bool ShowBreakpointProperties (ref BreakEvent bp, BreakpointType breakpointType = BreakpointType.Location) { - using (var dlg = new BreakpointPropertiesDialog (bp)) { + using (var dlg = new BreakpointPropertiesDialog (bp, breakpointType)) { Xwt.Command response = dlg.Run (); if (bp == null) bp = dlg.GetBreakEvent (); @@ -303,6 +306,7 @@ namespace MonoDevelop.Debugger session.ConnectionDialogCreator = delegate { return new StatusBarConnectionDialog (); }; + currentDebugOperation = new DebugAsyncOperation (); console.CancelRequested += OnCancelRequested; @@ -353,7 +357,8 @@ namespace MonoDevelop.Debugger currentSession.TypeResolverHandler = null; currentSession.OutputWriter = null; currentSession.LogWriter = null; - + currentDebugOperation.Cleanup (); + if (currentConsole != null) { currentConsole.CancelRequested -= OnCancelRequested; currentConsole.Dispose (); @@ -460,20 +465,24 @@ namespace MonoDevelop.Debugger NotifyLocationChanged (); } - public static IProcessAsyncOperation Run (string file, IConsole console) + public static ProcessAsyncOperation Run (string file, IConsole console) { - var h = new DebugExecutionHandler (null); var cmd = Runtime.ProcessService.CreateCommand (file); + return Run (cmd, console); + } - return h.Execute (cmd, console); + public static ProcessAsyncOperation Run (ExecutionCommand cmd, IConsole console, DebuggerEngine engine = null) + { + InternalRun (cmd, engine, console); + return currentDebugOperation; } - public static IAsyncOperation AttachToProcess (DebuggerEngine debugger, ProcessInfo proc) + public static AsyncOperation AttachToProcess (DebuggerEngine debugger, ProcessInfo proc) { currentEngine = debugger; session = debugger.CreateSession (); session.ExceptionHandler = ExceptionHandler; - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor (); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor (); console = monitor as IConsole; SetupSession (); session.TargetExited += delegate { @@ -481,7 +490,7 @@ namespace MonoDevelop.Debugger }; SetDebugLayout (); session.AttachToProcess (proc, GetUserOptions ()); - return monitor.AsyncOperation; + return currentDebugOperation; } public static DebuggerSessionOptions GetUserOptions () @@ -1022,7 +1031,7 @@ namespace MonoDevelop.Debugger return SupportedFeatures != DebuggerFeatures.None; } - public IProcessAsyncOperation Execute (ExecutionCommand cmd, IConsole console) + public ProcessAsyncOperation Execute (ExecutionCommand cmd, IConsole console) { // Never called throw new NotImplementedException (); @@ -1043,10 +1052,9 @@ namespace MonoDevelop.Debugger return engine.CanDebugCommand (command); } - public IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) + public ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) { - var h = new DebugExecutionHandler (engine); - return h.Execute (command, console); + return DebuggingService.Run (command, console, engine); } } diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs index b8dc53e274..6b65ff6c34 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs @@ -27,6 +27,7 @@ using System; using System.IO; +using System.Linq; using Gtk; @@ -74,8 +75,8 @@ namespace MonoDevelop.Debugger Widget CreateExceptionInfoHeader () { - ExceptionMessageLabel = new Label () { UseMarkup = true, Selectable = true, Wrap = true, WidthRequest = 500, Xalign = 0.0f, Yalign = 0.0f }; - ExceptionTypeLabel = new Label () { UseMarkup = true, Xalign = 0.0f }; + ExceptionMessageLabel = new Label { UseMarkup = true, Selectable = true, Wrap = true, WidthRequest = 500, Xalign = 0.0f, Yalign = 0.0f }; + ExceptionTypeLabel = new Label { UseMarkup = true, Xalign = 0.0f }; ExceptionMessageLabel.Show (); ExceptionTypeLabel.Show (); @@ -124,7 +125,7 @@ namespace MonoDevelop.Debugger ExceptionValueTreeView.Selection.Changed += ExceptionValueSelectionChanged; ExceptionValueTreeView.Show (); - var scrolled = new ScrolledWindow () { HeightRequest = 180 }; + var scrolled = new ScrolledWindow { HeightRequest = 180, HscrollbarPolicy = PolicyType.Automatic, VscrollbarPolicy = PolicyType.Automatic }; scrolled.ShadowType = ShadowType.None; scrolled.Add (ExceptionValueTreeView); @@ -138,17 +139,21 @@ namespace MonoDevelop.Debugger var frame = (ExceptionStackFrame) model.GetValue (iter, (int) ModelColumn.StackFrame); var renderer = (StackFrameCellRenderer) cr; - if (!(renderer.IsStackFrame = frame != null)) + renderer.Markup = (string) model.GetValue (iter, (int) ModelColumn.Markup); + + if (!(renderer.IsStackFrame = frame != null)) { + renderer.IsUserCode = false; + renderer.LineNumber = -1; return; + } renderer.IsUserCode = (bool) model.GetValue (iter, (int) ModelColumn.IsUserCode); renderer.LineNumber = !string.IsNullOrEmpty (frame.File) ? frame.Line : -1; - renderer.Markup = (string) model.GetValue (iter, (int) ModelColumn.Markup); } Widget CreateStackTraceTreeView () { - var store = new ListStore (typeof (ExceptionStackFrame), typeof (string), typeof (bool), typeof (int), typeof (int)); + var store = new ListStore (typeof (ExceptionStackFrame), typeof (string), typeof (bool)); StackTraceTreeView = new TreeView (store); StackTraceTreeView.FixedHeightMode = false; StackTraceTreeView.HeadersVisible = false; @@ -164,7 +169,7 @@ namespace MonoDevelop.Debugger StackTraceTreeView.SizeAllocated += (o, args) => renderer.Width = args.Allocation.Width; StackTraceTreeView.RowActivated += StackFrameActivated; - var scrolled = new ScrolledWindow () { HeightRequest = 180 }; + var scrolled = new ScrolledWindow { HeightRequest = 180, HscrollbarPolicy = PolicyType.Automatic, VscrollbarPolicy = PolicyType.Automatic }; scrolled.ShadowType = ShadowType.None; scrolled.Add (StackTraceTreeView); scrolled.Show (); @@ -174,7 +179,7 @@ namespace MonoDevelop.Debugger Widget CreateButtonBox () { - var buttons = new HButtonBox () { Layout = ButtonBoxStyle.End, Spacing = 12 }; + var buttons = new HButtonBox { Layout = ButtonBoxStyle.End, Spacing = 12 }; var copy = new Button (Stock.Copy); copy.Clicked += CopyClicked; @@ -194,7 +199,7 @@ namespace MonoDevelop.Debugger return buttons; } - Widget CreateSeparator () + static Widget CreateSeparator () { var separator = new HSeparator (); separator.Show (); @@ -297,7 +302,7 @@ namespace MonoDevelop.Debugger if (frame != null && !string.IsNullOrEmpty (frame.File) && File.Exists (frame.File)) { try { - IdeApp.Workbench.OpenDocument (frame.File, null, frame.Line, frame.Column); + IdeApp.Workbench.OpenDocument (frame.File, null, frame.Line, frame.Column, MonoDevelop.Ide.Gui.OpenDocumentOptions.Debugger); } catch (FileNotFoundException) { } } @@ -308,7 +313,7 @@ namespace MonoDevelop.Debugger if (frame == null || string.IsNullOrEmpty (frame.File)) return false; - return IdeApp.Workspace.GetProjectContainingFile (frame.File) != null; + return IdeApp.Workspace.GetProjectsContainingFile (frame.File).Any (); } void ShowStackTrace (ExceptionInfo ex) @@ -633,11 +638,11 @@ namespace MonoDevelop.Debugger class ExceptionCaughtButton: TopLevelWidgetExtension { + readonly Xwt.Drawing.Image closeSelOverImage; + readonly Xwt.Drawing.Image closeSelImage; readonly ExceptionCaughtMessage dlg; readonly ExceptionInfo exception; - Gtk.Label messageLabel; - readonly Xwt.Drawing.Image closeSelImage; - readonly Xwt.Drawing.Image closeSelOverImage; + Label messageLabel; public ExceptionCaughtButton (ExceptionInfo val, ExceptionCaughtMessage dlg, FilePath file, int line) { @@ -667,23 +672,23 @@ namespace MonoDevelop.Debugger var icon = Xwt.Drawing.Image.FromResource ("lightning-light-16.png"); var image = new Xwt.ImageView (icon).ToGtkWidget (); - HBox box = new HBox (false, 6); - VBox vb = new VBox (); + var box = new HBox (false, 6); + var vb = new VBox (); vb.PackStart (image, false, false, 0); box.PackStart (vb, false, false, 0); vb = new VBox (false, 6); - vb.PackStart (new Gtk.Label () { + vb.PackStart (new Label { Markup = GettextCatalog.GetString ("<b>{0}</b> has been thrown", exception.Type), Xalign = 0 }); - messageLabel = new Gtk.Label () { + messageLabel = new Label { Xalign = 0, NoShowAll = true }; vb.PackStart (messageLabel); var detailsBtn = new Xwt.LinkLabel (GettextCatalog.GetString ("Show Details")); - HBox hh = new HBox (); + var hh = new HBox (); detailsBtn.NavigateToUrl += (o,e) => dlg.ShowDialog (); hh.PackStart (detailsBtn.ToGtkWidget (), false, false, 0); vb.PackStart (hh, false, false, 0); @@ -691,7 +696,7 @@ namespace MonoDevelop.Debugger box.PackStart (vb, true, true, 0); vb = new VBox (); - var closeButton = new ImageButton () { + var closeButton = new ImageButton { InactiveImage = closeSelImage, Image = closeSelOverImage }; @@ -708,7 +713,7 @@ namespace MonoDevelop.Debugger }; LoadData (); - PopoverWidget eb = new PopoverWidget (); + var eb = new PopoverWidget (); eb.ShowArrow = true; eb.EnableAnimation = true; eb.PopupPosition = PopupPosition.Left; @@ -758,12 +763,12 @@ namespace MonoDevelop.Debugger public override Widget CreateWidget () { - Gtk.EventBox box = new EventBox (); + var box = new EventBox (); box.VisibleWindow = false; var icon = Xwt.Drawing.Image.FromResource ("lightning-light-16.png"); box.Add (new Xwt.ImageView (icon).ToGtkWidget ()); box.ButtonPressEvent += (o,e) => dlg.ShowButton (); - PopoverWidget eb = new PopoverWidget (); + var eb = new PopoverWidget (); eb.Theme.Padding = 2; eb.ShowArrow = true; eb.EnableAnimation = true; diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs index 12d1eb8c51..3d929f96c0 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs @@ -42,14 +42,14 @@ namespace MonoDevelop.Debugger return opers.CanExecute (entry, context); } - public static IAsyncOperation Debug (this ProjectOperations opers, IBuildTarget entry) + public static AsyncOperation Debug (this ProjectOperations opers, IBuildTarget entry) { if (opers.CurrentRunOperation != null && !opers.CurrentRunOperation.IsCompleted) return opers.CurrentRunOperation; ExecutionContext context = new ExecutionContext (DebuggingService.GetExecutionHandler (), IdeApp.Workbench.ProgressMonitors, IdeApp.Workspace.ActiveExecutionTarget); - IAsyncOperation op = opers.Execute (entry, context); + AsyncOperation op = opers.Execute (entry, context); SwitchToDebugLayout (op); return op; } @@ -60,13 +60,13 @@ namespace MonoDevelop.Debugger return opers.CanExecuteFile (file, context); } - public static IAsyncOperation DebugFile (this ProjectOperations opers, string file) + public static AsyncOperation DebugFile (this ProjectOperations opers, string file) { var context = new ExecutionContext (DebuggingService.GetExecutionHandler (), IdeApp.Workbench.ProgressMonitors, IdeApp.Workspace.ActiveExecutionTarget); return opers.ExecuteFile (file, context); } - public static IAsyncOperation DebugApplication (this ProjectOperations opers, string executableFile) + public static AsyncOperation DebugApplication (this ProjectOperations opers, string executableFile) { if (opers.CurrentRunOperation != null && !opers.CurrentRunOperation.IsCompleted) return opers.CurrentRunOperation; @@ -77,18 +77,17 @@ namespace MonoDevelop.Debugger var monitor = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor (); var oper = DebuggingService.Run (executableFile, (IConsole) monitor); - oper.Completed += delegate { + opers.CurrentRunOperation = oper; + + oper.Task.ContinueWith (t => { monitor.Dispose (); - Gtk.Application.Invoke (delegate { - IdeApp.Workbench.CurrentLayout = oldLayout; - }); - }; + IdeApp.Workbench.CurrentLayout = oldLayout; + }); - opers.CurrentRunOperation = monitor.AsyncOperation; - return opers.CurrentRunOperation; + return oper; } - public static IAsyncOperation AttachToProcess (this ProjectOperations opers, DebuggerEngine debugger, ProcessInfo proc) + public static AsyncOperation AttachToProcess (this ProjectOperations opers, DebuggerEngine debugger, ProcessInfo proc) { if (opers.CurrentRunOperation != null && !opers.CurrentRunOperation.IsCompleted) return opers.CurrentRunOperation; @@ -100,26 +99,14 @@ namespace MonoDevelop.Debugger return opers.CurrentRunOperation; } - public static IAsyncOperation Debug (this Document doc) - { - return IdeApp.ProjectOperations.DebugFile (doc.FileName); - } - - public static bool CanDebug (this Document doc) - { - return doc.FileName != FilePath.Null && IdeApp.ProjectOperations.CanDebugFile (doc.FileName); - } - - static void SwitchToDebugLayout (IAsyncOperation oper) + static void SwitchToDebugLayout (AsyncOperation oper) { string oldLayout = IdeApp.Workbench.CurrentLayout; IdeApp.Workbench.CurrentLayout = "Debug"; - oper.Completed += delegate { - DispatchService.GuiDispatch (delegate { - IdeApp.Workbench.CurrentLayout = oldLayout; - }); - }; + oper.Task.ContinueWith (t => { + IdeApp.Workbench.CurrentLayout = oldLayout; + }); } } } diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs index 04a92599ca..892f150861 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs @@ -558,14 +558,14 @@ namespace MonoDevelop.Debugger parent = TreeIter.Zero; if (CanQueryDebugger && frame != null) { - EvaluationOptions ops = frame.DebuggerSession.Options.EvaluationOptions.Clone (); - ops.AllowMethodEvaluation = true; - ops.AllowToStringCalls = true; - ops.AllowTargetInvoke = true; - ops.EllipsizeStrings = false; + var options = frame.DebuggerSession.Options.EvaluationOptions.Clone (); + options.AllowMethodEvaluation = true; + options.AllowToStringCalls = true; + options.AllowTargetInvoke = true; + options.EllipsizeStrings = false; string oldName = val.Name; - val.Refresh (ops); + val.Refresh (options); // Don't update the name for the values entered by the user if (store.IterDepth (iter) == 0) diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs index b20d6f1952..85c087e1b5 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs @@ -186,13 +186,14 @@ namespace MonoDevelop.Debugger foreach (var thread in threads) { ThreadInfo activeThread = DebuggingService.DebuggerSession.ActiveThread; + var name = thread.Name == null && thread.Id == 1 ? "Main Thread" : thread.Name; var weight = thread == activeThread ? Pango.Weight.Bold : Pango.Weight.Normal; var icon = thread == activeThread ? Gtk.Stock.GoForward : null; if (iter.Equals (TreeIter.Zero)) - store.AppendValues (icon, thread.Id.ToString (), thread.Name, thread, (int) weight, thread.Location); + store.AppendValues (icon, thread.Id.ToString (), name, thread, (int) weight, thread.Location); else - store.AppendValues (iter, icon, thread.Id.ToString (), thread.Name, thread, (int) weight, thread.Location); + store.AppendValues (iter, icon, thread.Id.ToString (), name, thread, (int) weight, thread.Location); } } @@ -233,7 +234,7 @@ namespace MonoDevelop.Debugger void OnRowActivated (object s, RowActivatedArgs args) { - TreeIter iter, selected; + TreeIter selected; if (!tree.Selection.GetSelected (out selected)) return; diff --git a/main/src/addins/MonoDevelop.Debugger/gtk-gui/MonoDevelop.Debugger.BusyEvaluatorDialog.cs b/main/src/addins/MonoDevelop.Debugger/gtk-gui/MonoDevelop.Debugger.BusyEvaluatorDialog.cs index d496a65960..20c77c6ed8 100644 --- a/main/src/addins/MonoDevelop.Debugger/gtk-gui/MonoDevelop.Debugger.BusyEvaluatorDialog.cs +++ b/main/src/addins/MonoDevelop.Debugger/gtk-gui/MonoDevelop.Debugger.BusyEvaluatorDialog.cs @@ -56,7 +56,10 @@ namespace MonoDevelop.Debugger this.labelMethod = new global::Gtk.Label (); this.labelMethod.Name = "labelMethod"; this.labelMethod.Xalign = 0F; - this.labelMethod.LabelProp = "<mehtod>"; + this.labelMethod.LabelProp = "<method>"; + this.labelMethod.Wrap = true; + this.labelMethod.Selectable = true; + this.labelMethod.MaxWidthChars = 120; this.hbox1.Add (this.labelMethod); global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.labelMethod])); w4.Position = 1; diff --git a/main/src/addins/MonoDevelop.Debugger/gtk-gui/gui.stetic b/main/src/addins/MonoDevelop.Debugger/gtk-gui/gui.stetic index 0516e36cc0..009262703f 100644 --- a/main/src/addins/MonoDevelop.Debugger/gtk-gui/gui.stetic +++ b/main/src/addins/MonoDevelop.Debugger/gtk-gui/gui.stetic @@ -336,7 +336,10 @@ <widget class="Gtk.Label" id="labelMethod"> <property name="MemberName" /> <property name="Xalign">0</property> - <property name="LabelProp"><mehtod></property> + <property name="LabelProp"><method></property> + <property name="Wrap">True</property> + <property name="Selectable">True</property> + <property name="MaxWidthChars">120</property> </widget> <packing> <property name="Position">1</property> diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/ComponentNodeBuilder.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/ComponentNodeBuilder.cs index 2505bd214e..eec13371ac 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/ComponentNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/ComponentNodeBuilder.cs @@ -42,9 +42,9 @@ namespace MonoDevelop.DesignerSupport.Projects // Don't use the CurrentNode property here since it may not be properly initialized when the event is fired. ITreeNavigator nav = Tree.GetNodeAtObject (obj); if (nav != null) { - IWorkspaceFileObject ce = (IWorkspaceFileObject) nav.GetParentDataItem (typeof(IWorkspaceFileObject), true); + var ce = nav.GetParentDataItem<WorkspaceObject> (true); if (ce != null) { - IdeApp.ProjectOperations.Save (ce); + IdeApp.ProjectOperations.SaveAsync (ce); return; } } diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/PropertyPadTextEditorExtension.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/PropertyPadTextEditorExtension.cs index d97b8c2284..f4e140d29e 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/PropertyPadTextEditorExtension.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/PropertyPadTextEditorExtension.cs @@ -62,7 +62,7 @@ namespace MonoDevelop.DesignerSupport.Projects public void OnChanged (object obj) { if (Document.HasProject) - IdeApp.ProjectOperations.Save (Document.Project); + IdeApp.ProjectOperations.SaveAsync (Document.Project); } } } diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/SolutionItemDescriptor.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/SolutionItemDescriptor.cs index 95721e4e71..d4f6d500fa 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/SolutionItemDescriptor.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/SolutionItemDescriptor.cs @@ -33,9 +33,9 @@ namespace MonoDevelop.DesignerSupport.Projects { class SolutionItemDescriptor: CustomDescriptor { - SolutionItem entry; + SolutionFolderItem entry; - public SolutionItemDescriptor (SolutionItem entry) + public SolutionItemDescriptor (SolutionFolderItem entry) { this.entry = entry; } @@ -58,8 +58,8 @@ namespace MonoDevelop.DesignerSupport.Projects [LocalizedDescription ("File path of the solution item.")] public string FilePath { get { - if (entry is SolutionEntityItem) - return ((SolutionEntityItem) entry).FileName; + if (entry is SolutionItem) + return ((SolutionItem) entry).FileName; else return ""; } diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/SolutionItemPropertyProvider.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/SolutionItemPropertyProvider.cs index bfa8ea1faf..2753614d1a 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/SolutionItemPropertyProvider.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/SolutionItemPropertyProvider.cs @@ -38,12 +38,12 @@ namespace MonoDevelop.DesignerSupport.Projects if (obj is WorkspaceItem) return new WorkspaceItemDescriptor ((WorkspaceItem)obj); else - return new SolutionItemDescriptor ((SolutionItem)obj); + return new SolutionItemDescriptor ((SolutionFolderItem)obj); } public bool SupportsObject (object obj) { - return obj is SolutionItem || obj is WorkspaceItem; + return obj is SolutionFolderItem || obj is WorkspaceItem; } } } diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/ComponentSelectorDialog.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/ComponentSelectorDialog.cs index a257f5a9ca..153d62b0dd 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/ComponentSelectorDialog.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/ComponentSelectorDialog.cs @@ -57,7 +57,7 @@ namespace MonoDevelop.DesignerSupport.Toolbox public ComponentSelectorDialog (IToolboxConsumer currentConsumer) { - using (IProgressMonitor monitor = new MessageDialogProgressMonitor (true, true, false, true)) { + using (ProgressMonitor monitor = new MessageDialogProgressMonitor (true, true, false, true)) { index = DesignerSupport.Service.ToolboxService.GetComponentIndex (monitor); } diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/CodeBehindWriter.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/CodeBehindWriter.cs index 44d2c1bc8f..891b6377e9 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/CodeBehindWriter.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/CodeBehindWriter.cs @@ -44,7 +44,7 @@ namespace MonoDevelop.DesignerSupport List<KeyValuePair<FilePath,string>> filesToWrite = new List<KeyValuePair<FilePath,string>> (); CodeDomProvider provider; CodeGeneratorOptions options; - IProgressMonitor monitor; + ProgressMonitor monitor; public CodeDomProvider Provider { get { return provider; } } public CodeGeneratorOptions GeneratorOptions { get { return options; } } @@ -59,14 +59,14 @@ namespace MonoDevelop.DesignerSupport { } - CodeBehindWriter (IProgressMonitor monitor, CodeDomProvider provider, CodeGeneratorOptions options) + CodeBehindWriter (ProgressMonitor monitor, CodeDomProvider provider, CodeGeneratorOptions options) { this.provider = provider; this.options = options; this.monitor = monitor; } - public static CodeBehindWriter CreateForProject (IProgressMonitor monitor, DotNetProject project) + public static CodeBehindWriter CreateForProject (ProgressMonitor monitor, DotNetProject project) { var pol = project.Policies.Get<TextStylePolicy> (); var options = new CodeGeneratorOptions () { diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/ToolboxService.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/ToolboxService.cs index 2c9c66e956..0c5cf4194e 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/ToolboxService.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/ToolboxService.cs @@ -545,7 +545,7 @@ namespace MonoDevelop.DesignerSupport throw new InvalidOperationException ("Unexpected ToolboxItemFilterType value."); } - internal ComponentIndex GetComponentIndex (IProgressMonitor monitor) + internal ComponentIndex GetComponentIndex (ProgressMonitor monitor) { // Returns an index of all components that can be added to the toolbox. @@ -562,7 +562,7 @@ namespace MonoDevelop.DesignerSupport todelete.Add (ia); if (ia.NeedsUpdate) toupdate.Add (ia); - if (monitor.IsCancelRequested) + if (monitor.CancellationToken.IsCancellationRequested) return index; } @@ -575,7 +575,7 @@ namespace MonoDevelop.DesignerSupport index.Files.Add (c); toupdate.Add (c); } - if (monitor.IsCancelRequested) + if (monitor.CancellationToken.IsCancellationRequested) return index; } } @@ -591,7 +591,7 @@ namespace MonoDevelop.DesignerSupport foreach (ComponentIndexFile ia in toupdate) { ia.Update (ctx); monitor.Step (1); - if (monitor.IsCancelRequested) + if (monitor.CancellationToken.IsCancellationRequested) return index; } } finally { diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.Editor/GettextEditorDisplayBinding.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.Editor/GettextEditorDisplayBinding.cs index 9a7d402c95..a572e7b707 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.Editor/GettextEditorDisplayBinding.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.Editor/GettextEditorDisplayBinding.cs @@ -49,7 +49,7 @@ namespace MonoDevelop.Gettext public IViewContent CreateContent (FilePath filePath, string mimeType, Project project) { - foreach (TranslationProject tp in IdeApp.Workspace.GetAllSolutionItems<TranslationProject> ()) + foreach (TranslationProject tp in IdeApp.Workspace.GetAllItems<TranslationProject> ()) if (tp.BaseDirectory == Path.GetDirectoryName (filePath)) return new Editor.CatalogEditorView (tp, filePath); diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.Editor/POEditorWidget.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.Editor/POEditorWidget.cs index 45747f5bb0..c39a8e1ede 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.Editor/POEditorWidget.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.Editor/POEditorWidget.cs @@ -976,7 +976,7 @@ namespace MonoDevelop.Gettext base.OnDestroyed (); } #region Tasks - public class TranslationTask : Task + public class TranslationTask : UserTask { POEditorWidget widget; CatalogEntry entry; @@ -1000,7 +1000,7 @@ namespace MonoDevelop.Gettext TaskService.Errors.ClearByOwner (this); } - static bool CompareTasks (List<Task> list1, List<Task> list2) + static bool CompareTasks (List<UserTask> list1, List<UserTask> list2) { if (list1.Count != list2.Count) return false; @@ -1128,7 +1128,7 @@ namespace MonoDevelop.Gettext } - List<Task> currentTasks = new List<Task> (); + List<UserTask> currentTasks = new List<UserTask> (); BackgroundWorker updateTaskThread = null; @@ -1140,7 +1140,7 @@ namespace MonoDevelop.Gettext return; } - List<Task> tasks = new List<Task> (); + List<UserTask> tasks = new List<UserTask> (); try { foreach (CatalogEntryRule rule in rules) { foreach (CatalogEntry entry in catalog) { diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/ProjectFileNodeBuilderExtension.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/ProjectFileNodeBuilderExtension.cs index 4d051544cb..e87629a944 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/ProjectFileNodeBuilderExtension.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/ProjectFileNodeBuilderExtension.cs @@ -68,7 +68,7 @@ namespace MonoDevelop.Gettext.NodeBuilders } } - Set<SolutionEntityItem> projects = new Set<SolutionEntityItem> (); + Set<SolutionItem> projects = new Set<SolutionItem> (); foreach (ITreeNavigator node in CurrentNodes) { ProjectFile file = (ProjectFile) node.DataItem; @@ -80,7 +80,7 @@ namespace MonoDevelop.Gettext.NodeBuilders } } - IdeApp.ProjectOperations.Save (projects); + IdeApp.ProjectOperations.SaveAsync (projects); } [CommandUpdateHandler (Commands.ScanForTranslations)] diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationNodeBuilder.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationNodeBuilder.cs index 029efd19d4..a1d3c3aacd 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationNodeBuilder.cs @@ -33,6 +33,7 @@ using MonoDevelop.Core; using MonoDevelop.Components.Commands; using MonoDevelop.Ide.Gui.Components; using MonoDevelop.Ide; +using System.Threading.Tasks; namespace MonoDevelop.Gettext.NodeBuilders { @@ -111,7 +112,7 @@ namespace MonoDevelop.Gettext.NodeBuilders } project.RemoveTranslation (translation.IsoCode); - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); } } @@ -125,14 +126,10 @@ namespace MonoDevelop.Gettext.NodeBuilders UpdateTranslations (project, translation); } - static IAsyncOperation currentUpdateTranslationOperation = MonoDevelop.Core.ProgressMonitoring.NullAsyncOperation.Success; + static Task currentUpdateTranslationOperation = Task.FromResult (0); - void UpdateTranslationsAsync (object ob) + void UpdateTranslationsAsync (ProgressMonitor monitor, TranslationProject project, Translation translation) { - object[] data = (object[]) ob; - IProgressMonitor monitor = (IProgressMonitor) data [0]; - TranslationProject project = (TranslationProject) data [1]; - Translation translation = (Translation) data [2]; try { project.UpdateTranslations (monitor, translation); Gtk.Application.Invoke (delegate { @@ -151,9 +148,8 @@ namespace MonoDevelop.Gettext.NodeBuilders { if (currentUpdateTranslationOperation != null && !currentUpdateTranslationOperation.IsCompleted) return; - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBuildProgressMonitor (); - currentUpdateTranslationOperation = monitor.AsyncOperation; - DispatchService.BackgroundDispatch (new StatefulMessageHandler (UpdateTranslationsAsync), new object[] {monitor, project, translation}); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBuildProgressMonitor (); + currentUpdateTranslationOperation = Task.Factory.StartNew (() => UpdateTranslationsAsync (monitor, project, translation)); } } } diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationProjectNodeBuilder.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationProjectNodeBuilder.cs index cdfdc78f73..938ce3a94b 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationProjectNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationProjectNodeBuilder.cs @@ -32,6 +32,7 @@ using MonoDevelop.Core; using MonoDevelop.Components.Commands; using MonoDevelop.Ide.Gui.Components; using MonoDevelop.Ide; +using System.Threading.Tasks; namespace MonoDevelop.Gettext.NodeBuilders { @@ -122,7 +123,7 @@ namespace MonoDevelop.Gettext.NodeBuilders if (project == null) return; MessageService.ShowCustomDialog (new TranslationProjectOptionsDialog (project)); - IdeApp.Workspace.Save (); + IdeApp.Workspace.SaveAsync (); } [CommandUpdateHandler (Commands.AddTranslation)] @@ -144,7 +145,7 @@ namespace MonoDevelop.Gettext.NodeBuilders if (MessageService.RunCustomDialog (chooser) == (int)ResponseType.Ok) { string language = chooser.Language + (chooser.HasCountry ? "_" + chooser.Country : ""); - using (IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetOutputProgressMonitor (monitorTitle, "md-package", true, true)) { + using (ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetOutputProgressMonitor (monitorTitle, "md-package", true, true)) { project.AddNewTranslation (language, monitor); UpdateTranslations (project); } @@ -154,14 +155,10 @@ namespace MonoDevelop.Gettext.NodeBuilders chooser.Destroy (); } } - static IAsyncOperation currentUpdateTranslationOperation = MonoDevelop.Core.ProgressMonitoring.NullAsyncOperation.Success; + static Task currentUpdateTranslationOperation = Task.FromResult (0); - void UpdateTranslationsAsync (object ob) + void UpdateTranslationsAsync (ProgressMonitor monitor, TranslationProject project) { - object[] data = (object[]) ob; - IProgressMonitor monitor = (IProgressMonitor) data [0]; - TranslationProject project = (TranslationProject) data [1]; - try { project.UpdateTranslations (monitor); Gtk.Application.Invoke (delegate { @@ -180,9 +177,8 @@ namespace MonoDevelop.Gettext.NodeBuilders { if (currentUpdateTranslationOperation != null && !currentUpdateTranslationOperation.IsCompleted) return; - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBuildProgressMonitor (); - currentUpdateTranslationOperation = monitor.AsyncOperation; - DispatchService.BackgroundDispatch (new StatefulMessageHandler (UpdateTranslationsAsync), new object[] {monitor, project}); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBuildProgressMonitor (); + currentUpdateTranslationOperation = Task.Factory.StartNew (() => UpdateTranslationsAsync (monitor, project)); } [CommandHandler (Commands.UpdateTranslations)] diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/Catalog.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/Catalog.cs index a6322e961b..6171e5533f 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/Catalog.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/Catalog.cs @@ -201,7 +201,7 @@ namespace MonoDevelop.Gettext /// <summary> /// Loads catalog from .po file. /// </summary> - public bool Load (IProgressMonitor monitor, string poFile) + public bool Load (ProgressMonitor monitor, string poFile) { Clear (); isOk = false; @@ -439,7 +439,7 @@ namespace MonoDevelop.Gettext } // Updates the catalog from POT file. - public bool UpdateFromPOT (IProgressMonitor mon, string potFile, bool summary) + public bool UpdateFromPOT (ProgressMonitor mon, string potFile, bool summary) { if (! isOk) return false; @@ -685,7 +685,7 @@ namespace MonoDevelop.Gettext // (in the sense of msgmerge -- this catalog is old one with // translations, \a refcat is reference catalog created by Update().) // return true if the merge was successfull, false otherwise. - public bool Merge (IProgressMonitor mon, Catalog refCat) + public bool Merge (ProgressMonitor mon, Catalog refCat) { // TODO: implement via monitor, not in a GUI thread... // But mind about it as it would be used during build. diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextFeature.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextFeature.cs index acf0ff8cbe..b7f431b9cf 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextFeature.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextFeature.cs @@ -46,7 +46,7 @@ namespace MonoDevelop.Gettext get { return GettextCatalog.GetString ("Add a Translation Project to the solution that will use gettext to generate a set of PO files for the new project."); } } - public FeatureSupportLevel GetSupportLevel (SolutionFolder parentCombine, SolutionItem entry) + public FeatureSupportLevel GetSupportLevel (SolutionFolder parentCombine, SolutionFolderItem entry) { if (entry is TranslationProject && parentCombine != null) return FeatureSupportLevel.Enabled; @@ -56,22 +56,22 @@ namespace MonoDevelop.Gettext return FeatureSupportLevel.NotSupported; } - public Widget CreateFeatureEditor (SolutionFolder parentCombine, SolutionItem entry) + public Widget CreateFeatureEditor (SolutionFolder parentCombine, SolutionFolderItem entry) { return new GettextFeatureWidget (); } - public void ApplyFeature (SolutionFolder parentCombine, SolutionItem entry, Widget editor) + public void ApplyFeature (SolutionFolder parentCombine, SolutionFolderItem entry, Widget editor) { ((GettextFeatureWidget)editor).ApplyFeature (parentCombine, entry); } - public string Validate (SolutionFolder parentCombine, SolutionItem entry, Gtk.Widget editor) + public string Validate (SolutionFolder parentCombine, SolutionFolderItem entry, Gtk.Widget editor) { return null; } - public bool IsEnabled (SolutionFolder parentCombine, SolutionItem entry) + public bool IsEnabled (SolutionFolder parentCombine, SolutionFolderItem entry) { return entry is TranslationProject; } diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextFeatureWidget.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextFeatureWidget.cs index 130f9c5c8a..c103ee2939 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextFeatureWidget.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextFeatureWidget.cs @@ -31,7 +31,7 @@ using Gtk; using MonoDevelop.Projects; using MonoDevelop.Gettext.Translator; -using MonoDevelop.Core.ProgressMonitoring; +using MonoDevelop.Core; using MonoDevelop.Ide; namespace MonoDevelop.Gettext @@ -74,7 +74,7 @@ namespace MonoDevelop.Gettext }; } - public void ApplyFeature (SolutionFolder parentCombine, SolutionItem entry) + public void ApplyFeature (SolutionFolder parentCombine, SolutionFolderItem entry) { TranslationProject newProject; if (entry is TranslationProject) @@ -93,7 +93,7 @@ namespace MonoDevelop.Gettext if (store.GetIterFirst (out iter)) { do { string code = (string)store.GetValue (iter, 1); - newProject.AddNewTranslation (code, new NullProgressMonitor ()); + newProject.AddNewTranslation (code, new ProgressMonitor ()); } while (store.IterNext (ref iter)); } } diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextTool.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextTool.cs index 96bf769a7a..b530133bc6 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextTool.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextTool.cs @@ -74,7 +74,7 @@ namespace MonoDevelop.Gettext ConsoleProgressMonitor monitor = new ConsoleProgressMonitor (); monitor.IgnoreLogMessages = true; - WorkspaceItem centry = Services.ProjectService.ReadWorkspaceItem (monitor, file); + WorkspaceItem centry = Services.ProjectService.ReadWorkspaceItem (monitor, file).Result; monitor.IgnoreLogMessages = false; Solution solution = centry as Solution; @@ -84,7 +84,7 @@ namespace MonoDevelop.Gettext } if (project != null) { - SolutionEntityItem item = solution.FindProjectByName (project); + SolutionItem item = solution.FindProjectByName (project); if (item == null) { Console.WriteLine ("The project '" + project + "' could not be found in " + file); @@ -98,7 +98,7 @@ namespace MonoDevelop.Gettext tp.UpdateTranslations (monitor); } else { - foreach (TranslationProject p in solution.GetAllSolutionItems <TranslationProject>()) + foreach (TranslationProject p in solution.GetAllItems <TranslationProject>()) p.UpdateTranslations (monitor); } diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/IFileScanner.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/IFileScanner.cs index 3f722b7b16..fabcabb70e 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/IFileScanner.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/IFileScanner.cs @@ -33,6 +33,6 @@ namespace MonoDevelop.Gettext interface IFileScanner { bool CanScan (TranslationProject project, Catalog catalog, string fileName, string mimeType); - void UpdateCatalog (TranslationProject project, Catalog catalog, IProgressMonitor monitor, string fileName); + void UpdateCatalog (TranslationProject project, Catalog catalog, ProgressMonitor monitor, string fileName); } } diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/MakefileHandler.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/MakefileHandler.cs index baca1511d0..72ddc7c24e 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/MakefileHandler.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/MakefileHandler.cs @@ -39,12 +39,12 @@ namespace MonoDevelop.Gettext { class MakefileHandler: IMakefileHandler { - public bool CanDeploy (SolutionItem entry, MakefileType type) + public bool CanDeploy (SolutionFolderItem entry, MakefileType type) { return entry is TranslationProject; } - public Makefile Deploy (AutotoolsContext ctx, SolutionItem entry, IProgressMonitor monitor) + public Makefile Deploy (AutotoolsContext ctx, SolutionFolderItem entry, ProgressMonitor monitor) { Makefile mkfile = new Makefile (); TranslationProject project = (TranslationProject) entry; diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/RegexFileScanner.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/RegexFileScanner.cs index 0e84bc1ee1..144d1b69c1 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/RegexFileScanner.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/RegexFileScanner.cs @@ -118,7 +118,7 @@ namespace MonoDevelop.Gettext return r; } - public virtual void UpdateCatalog (TranslationProject project, Catalog catalog, IProgressMonitor monitor, string fileName) + public virtual void UpdateCatalog (TranslationProject project, Catalog catalog, ProgressMonitor monitor, string fileName) { string text = File.ReadAllText (fileName); string relativeFileName = MonoDevelop.Core.FileService.AbsoluteToRelativePath (project.BaseDirectory, fileName); diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/Translation.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/Translation.cs index 84a8ecf5cd..178a069000 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/Translation.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/Translation.cs @@ -84,7 +84,7 @@ namespace MonoDevelop.Gettext return Path.Combine (moDirectory, parentProject.PackageName + ".mo"); } - public BuildResult Build (IProgressMonitor monitor, ConfigurationSelector configuration) + public BuildResult Build (ProgressMonitor monitor, ConfigurationSelector configuration) { BuildResult results = new BuildResult ("", 0, 0); diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/TranslationProject.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/TranslationProject.cs index fcef46a792..d77a23bcc8 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/TranslationProject.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/TranslationProject.cs @@ -38,10 +38,12 @@ using MonoDevelop.Core.Serialization; using MonoDevelop.Deployment; using MonoDevelop.Ide; using MonoDevelop.Core.Execution; +using System.Linq; +using System.Threading.Tasks; namespace MonoDevelop.Gettext { - class TranslationProject : SolutionEntityItem, IDeployable + class TranslationProject : SolutionItem, IDeployable { [ItemProperty("packageName")] string packageName = null; @@ -94,9 +96,9 @@ namespace MonoDevelop.Gettext Configurations.Add (new TranslationProjectConfiguration (config)); } - protected override List<FilePath> OnGetItemFiles (bool includeReferencedFiles) + protected override IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles) {
- List<FilePath> col = base.OnGetItemFiles (includeReferencedFiles); + List<FilePath> col = base.OnGetItemFiles (includeReferencedFiles).ToList(); if (includeReferencedFiles) { foreach (Translation tr in translations) col.Add (tr.PoFile); @@ -104,7 +106,7 @@ namespace MonoDevelop.Gettext return col; } - public TranslationProjectInformation GetProjectInformation (SolutionItem entry, bool force) + public TranslationProjectInformation GetProjectInformation (SolutionFolderItem entry, bool force) { foreach (TranslationProjectInformation info in this.projectInformations) { if (info.ProjectName == entry.Name) @@ -118,7 +120,7 @@ namespace MonoDevelop.Gettext return null; } - public bool IsIncluded (SolutionItem entry) + public bool IsIncluded (SolutionFolderItem entry) { TranslationProjectInformation info = GetProjectInformation (entry, false); if (info != null) @@ -126,7 +128,7 @@ namespace MonoDevelop.Gettext return true; } - public override void InitializeFromTemplate (XmlElement template) + protected override void OnInitializeFromTemplate (XmlElement template) { OutputType = (TranslationOutputType)Enum.Parse (typeof(TranslationOutputType), template.GetAttribute ("outputType")); PackageName = template.GetAttribute ("packageName"); @@ -169,7 +171,7 @@ namespace MonoDevelop.Gettext } - public Translation AddNewTranslation (string isoCode, IProgressMonitor monitor) + public Translation AddNewTranslation (string isoCode, ProgressMonitor monitor) { try { Translation tr = new Translation (this, isoCode); @@ -236,7 +238,7 @@ namespace MonoDevelop.Gettext return Path.Combine (this.ParentSolution.StartupItem.BaseDirectory, RelPath); } - void CreateDefaultCatalog (IProgressMonitor monitor) + void CreateDefaultCatalog (ProgressMonitor monitor) { IFileScanner[] scanners = TranslationService.GetFileScanners (); @@ -259,19 +261,19 @@ namespace MonoDevelop.Gettext } } } - if (monitor.IsCancelRequested) + if (monitor.CancellationToken.IsCancellationRequested) return; monitor.Step (1); } catalog.Save (Path.Combine (this.BaseDirectory, "messages.po")); } - public void UpdateTranslations (IProgressMonitor monitor) + public void UpdateTranslations (ProgressMonitor monitor) { UpdateTranslations (monitor, translations.ToArray ()); } - public void UpdateTranslations (IProgressMonitor monitor, params Translation[] translations) + public void UpdateTranslations (ProgressMonitor monitor, params Translation[] translations) { monitor.BeginTask (null, Translations.Count + 1); @@ -288,7 +290,7 @@ namespace MonoDevelop.Gettext monitor.EndTask (); monitor.Step (1); } - if (monitor.IsCancelRequested) { + if (monitor.CancellationToken.IsCancellationRequested) { monitor.Log.WriteLine (GettextCatalog.GetString ("Operation cancelled.")); return; } @@ -324,7 +326,7 @@ namespace MonoDevelop.Gettext monitor.EndTask (); monitor.Step (1); } - if (monitor.IsCancelRequested) { + if (monitor.CancellationToken.IsCancellationRequested) { monitor.Log.WriteLine (GettextCatalog.GetString ("Operation cancelled.")); return; } @@ -335,7 +337,7 @@ namespace MonoDevelop.Gettext foreach (Translation translation in this.Translations) { string poFileName = translation.PoFile; Catalog catalog = new Catalog (this); - catalog.Load (new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor (), poFileName); + catalog.Load (new MonoDevelop.Core.ProgressMonitor (), poFileName); CatalogEntry entry = catalog.FindItem (msgstr); if (entry != null) { catalog.RemoveItem (entry); @@ -344,40 +346,43 @@ namespace MonoDevelop.Gettext } } - protected override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration) + protected async override Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { + var toBuild = Translations.Where (t => t.NeedsBuilding(configuration)).ToArray (); BuildResult results = new BuildResult ("", 1, 0); string outputDirectory = GetOutputDirectory (configuration); if (!string.IsNullOrEmpty (outputDirectory)) { - foreach (Translation translation in this.Translations) { - if (translation.NeedsBuilding (configuration)) { - BuildResult res = translation.Build (monitor, configuration); - results.Append (res); + await Task.Factory.StartNew (delegate { + foreach (Translation translation in toBuild) { + if (translation.NeedsBuilding (configuration)) { + BuildResult res = translation.Build (monitor, configuration); + results.Append (res); + } } - } - isDirty = false; + isDirty = false; + }); } return results; } - protected override void OnClean (IProgressMonitor monitor, ConfigurationSelector configuration) + protected async override Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration) { isDirty = true; monitor.Log.WriteLine (GettextCatalog.GetString ("Removing all .mo files.")); string outputDirectory = GetOutputDirectory (configuration); if (string.IsNullOrEmpty (outputDirectory)) - return; - foreach (Translation translation in this.Translations) { - string moFileName = translation.GetOutFile (configuration); - if (File.Exists (moFileName)) - File.Delete (moFileName); - } - } - - protected override void OnExecute (IProgressMonitor monitor, MonoDevelop.Projects.ExecutionContext context, ConfigurationSelector configuration) - { + return BuildResult.Success; + + var toClean = Translations.Select (t => t.GetOutFile (configuration)).ToArray (); + await Task.Factory.StartNew (delegate { + foreach (string moFileName in toClean) { + if (File.Exists (moFileName)) + File.Delete (moFileName); + } + }); + return BuildResult.Success; } - + #region Deployment public DeployFileCollection GetDeployFiles (ConfigurationSelector configuration) { @@ -410,11 +415,6 @@ namespace MonoDevelop.Gettext return false; } - protected override void OnSetNeedsBuilding (bool val, ConfigurationSelector configuration) - { - isDirty = val; - } - protected virtual void OnTranslationAdded (EventArgs e) { if (TranslationAdded != null) diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/TranslationProjectOptionsDialog.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/TranslationProjectOptionsDialog.cs index 185e521dc7..b1199da866 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/TranslationProjectOptionsDialog.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/TranslationProjectOptionsDialog.cs @@ -67,7 +67,7 @@ namespace MonoDevelop.Gettext this.Destroy (); }; - store = new TreeStore (typeof(string), typeof(bool), typeof(string), typeof(SolutionItem), typeof(bool)); + store = new TreeStore (typeof(string), typeof(bool), typeof(string), typeof(SolutionFolderItem), typeof(bool)); treeviewProjectList.Model = store; treeviewProjectList.HeadersVisible = false; @@ -98,7 +98,7 @@ namespace MonoDevelop.Gettext TreeIter iter; if (store.GetIterFromString (out iter, e.Path)) { bool isTogglod = (bool)store.GetValue (iter, 1); - SolutionItem entry = (SolutionItem)store.GetValue (iter, 3); + SolutionFolderItem entry = (SolutionFolderItem)store.GetValue (iter, 3); if (entry is Project) { TranslationProjectInformation info = project.GetProjectInformation (entry, true); info.IsIncluded = !isTogglod; @@ -108,7 +108,7 @@ namespace MonoDevelop.Gettext } TreeStore store; - string GetIcon (SolutionItem entry) + string GetIcon (SolutionFolderItem entry) { if (entry is SolutionFolder) return MonoDevelop.Ide.Gui.Stock.Solution; @@ -119,10 +119,10 @@ namespace MonoDevelop.Gettext return MonoDevelop.Ide.Gui.Stock.Project; } - bool IsIncluded (SolutionItem entry) + bool IsIncluded (SolutionFolderItem entry) { if (entry is SolutionFolder) { - foreach (SolutionItem childEntry in ((SolutionFolder)entry).Items) + foreach (SolutionFolderItem childEntry in ((SolutionFolder)entry).Items) if (!IsIncluded (childEntry)) return false; return true; @@ -134,7 +134,7 @@ namespace MonoDevelop.Gettext return true; } - void FillTree (TreeIter iter, SolutionItem entry) + void FillTree (TreeIter iter, SolutionFolderItem entry) { TreeIter curIter; if (!iter.Equals (TreeIter.Zero)) { @@ -144,10 +144,10 @@ namespace MonoDevelop.Gettext } if (entry is SolutionFolder) { // Add solutions first, then projects - foreach (SolutionItem childEntry in ((SolutionFolder)entry).Items) + foreach (SolutionFolderItem childEntry in ((SolutionFolder)entry).Items) if (childEntry is SolutionFolder) FillTree (curIter, childEntry); - foreach (SolutionItem childEntry in ((SolutionFolder)entry).Items) + foreach (SolutionFolderItem childEntry in ((SolutionFolder)entry).Items) if (!(childEntry is TranslationProject) && (childEntry is Project)) FillTree (curIter, childEntry); } diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs index 0b6e913dc9..1496e4cba0 100644 --- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs +++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs @@ -48,7 +48,7 @@ namespace MonoDevelop.GtkCore.Dialogs get { return GettextCatalog.GetString ("Enables support for GTK# in the project. Allows the visual design of GTK# windows, and the creation of a GTK# widget library."); } } - public FeatureSupportLevel GetSupportLevel (SolutionFolder parentCombine, SolutionItem entry) + public FeatureSupportLevel GetSupportLevel (SolutionFolder parentCombine, SolutionFolderItem entry) { if (!(entry is DotNetProject) || !GtkDesignInfo.SupportsRefactoring (entry as DotNetProject)) return FeatureSupportLevel.NotSupported; @@ -59,18 +59,18 @@ namespace MonoDevelop.GtkCore.Dialogs if (GtkDesignInfo.SupportsDesigner ((Project)entry)) return FeatureSupportLevel.Enabled; - else if (entry is DotNetAssemblyProject) + else if (entry is DotNetProject) return FeatureSupportLevel.SupportedByDefault; else return FeatureSupportLevel.Supported; } - public Widget CreateFeatureEditor (SolutionFolder parentCombine, SolutionItem entry) + public Widget CreateFeatureEditor (SolutionFolder parentCombine, SolutionFolderItem entry) { return new GtkFeatureWidget ((DotNetProject) entry); } - public void ApplyFeature (SolutionFolder parentCombine, SolutionItem entry, Widget editor) + public void ApplyFeature (SolutionFolder parentCombine, SolutionFolderItem entry, Widget editor) { GtkFeatureWidget fw = (GtkFeatureWidget) editor; ReferenceManager refmgr = new ReferenceManager ((DotNetProject) entry); @@ -78,7 +78,7 @@ namespace MonoDevelop.GtkCore.Dialogs refmgr.Dispose (); } - public string Validate (SolutionFolder parentCombine, SolutionItem entry, Gtk.Widget editor) + public string Validate (SolutionFolder parentCombine, SolutionFolderItem entry, Gtk.Widget editor) { return null; } diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs index 191037ecd8..35cbbfb921 100644 --- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs +++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs @@ -4,12 +4,13 @@ using System.Threading; using MonoDevelop.Core; using MonoDevelop.Projects; using MonoDevelop.Ide; +using System.Threading.Tasks; namespace MonoDevelop.GtkCore.GuiBuilder { - public class GtkProjectServiceExtension: ProjectServiceExtension + public class GtkProjectServiceExtension: DotNetProjectExtension { - public override bool SupportsItem (IBuildTarget item) + protected override bool SupportsObject (WorkspaceObject item) { if (!IdeApp.IsInitialized) return false; @@ -18,20 +19,19 @@ namespace MonoDevelop.GtkCore.GuiBuilder return project != null && GtkDesignInfo.HasDesignedObjects (project); } - protected override BuildResult Build (IProgressMonitor monitor, SolutionEntityItem entry, ConfigurationSelector configuration) + protected async override Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { - DotNetProject project = (DotNetProject) entry; - GtkDesignInfo info = GtkDesignInfo.FromProject (project); + GtkDesignInfo info = GtkDesignInfo.FromProject (Project); - // The code generator must run in the GUI thread since it needs to - // access to Gtk classes Generator gen = new Generator (); - lock (gen) { - Gtk.Application.Invoke (delegate { gen.Run (monitor, project, configuration); }); - Monitor.Wait (gen); + if (!await gen.Run (monitor, Project, configuration)) { + BuildResult gr = new BuildResult (); + foreach (string s in gen.Messages) + gr.AddError (info.GuiBuilderProject.File, 0, 0, null, s); + return gr; } - BuildResult res = base.Build (monitor, entry, configuration); + BuildResult res = await base.OnBuild (monitor, configuration); if (gen.Messages != null) { foreach (string s in gen.Messages) @@ -43,7 +43,7 @@ namespace MonoDevelop.GtkCore.GuiBuilder if (res.Failed && !Platform.IsWindows && !Platform.IsMac) { // Some gtk# packages don't include the .pc file unless you install gtk-sharp-devel - if (project.AssemblyContext.GetPackage ("gtk-sharp-2.0") == null) { + if (Project.AssemblyContext.GetPackage ("gtk-sharp-2.0") == null) { string msg = GettextCatalog.GetString ( "ERROR: MonoDevelop could not find the Gtk# 2.0 development package. " + "Compilation of projects depending on Gtk# libraries will fail. " + @@ -59,19 +59,22 @@ namespace MonoDevelop.GtkCore.GuiBuilder class Generator { - public void Run (IProgressMonitor monitor, DotNetProject project, ConfigurationSelector configuration) + public async Task<bool> Run (ProgressMonitor monitor, DotNetProject project, ConfigurationSelector configuration) { - lock (this) { - try { - Stetic.CodeGenerationResult res = GuiBuilderService.GenerateSteticCode (monitor, project, configuration); - if (res != null) - Messages = res.Warnings; - } catch (Exception ex) { - Error = ex; - LoggingService.LogError (ex.ToString ()); - Messages = new string [] { Error.Message }; + try { + Stetic.CodeGenerationResult res = await GuiBuilderService.GenerateSteticCode (monitor, project, configuration); + if (res != null) { + Messages = res.Warnings; + return true; + } else { + Messages = new [] { GettextCatalog.GetString ("Code generation failed") }; + return false; } - Monitor.PulseAll (this); + } catch (Exception ex) { + Error = ex; + LoggingService.LogError (ex.ToString ()); + Messages = new [] { Error.Message }; + return false; } } public string[] Messages; diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs index 6a23250d36..9c381c600d 100644 --- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs +++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs @@ -219,7 +219,7 @@ namespace MonoDevelop.GtkCore.GuiBuilder } if (GtkDesignInfo.FromProject (project).UpdateGtkFolder () && saveMdProject) - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); } public string File { diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs index 28dac4d37e..601733e9d3 100644 --- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs +++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs @@ -42,6 +42,7 @@ using MonoDevelop.Projects.Policies; using MonoDevelop.Ide; using MonoDevelop.Ide.Gui.Content; using MonoDevelop.Ide.TypeSystem; +using System.Threading.Tasks; namespace MonoDevelop.GtkCore.GuiBuilder @@ -385,7 +386,7 @@ namespace MonoDevelop.GtkCore.GuiBuilder } - public static Stetic.CodeGenerationResult GenerateSteticCode (IProgressMonitor monitor, DotNetProject project, ConfigurationSelector configuration) + public async static Task<Stetic.CodeGenerationResult> GenerateSteticCode (ProgressMonitor monitor, DotNetProject project, ConfigurationSelector configuration) { if (generating || !GtkDesignInfo.HasDesignedObjects (project)) return null; @@ -423,7 +424,6 @@ namespace MonoDevelop.GtkCore.GuiBuilder if (info.GuiBuilderProject.HasError) { monitor.ReportError (GettextCatalog.GetString ("GUI code generation failed for project '{0}'. The file '{1}' could not be loaded.", project.Name, info.SteticFile), null); - monitor.AsyncOperation.Cancel (); return null; } @@ -454,8 +454,7 @@ namespace MonoDevelop.GtkCore.GuiBuilder if (!canGenerateInProcess) { timer.Trace ("Generating out of process"); - // Run the generation in another thread to avoid freezing the GUI - System.Threading.ThreadPool.QueueUserWorkItem (delegate { + await Task.Factory.StartNew (delegate { try { // Generate the code in another process if stetic is not isolated CodeGeneratorProcess cob = (CodeGeneratorProcess)Runtime.ProcessService.CreateExternalProcessObject (typeof(CodeGeneratorProcess), false); @@ -469,10 +468,6 @@ namespace MonoDevelop.GtkCore.GuiBuilder } }); - while (generating) { - DispatchService.RunPendingEvents (); - System.Threading.Thread.Sleep (100); - } } else { timer.Trace ("Generating in-process"); // No need to create another process, since stetic has its own backend process @@ -544,7 +539,7 @@ namespace MonoDevelop.GtkCore.GuiBuilder // Make sure the generated files are added to the project if (info.UpdateGtkFolder ()) { Gtk.Application.Invoke (delegate { - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); }); } diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs index b83e9e7a11..5b0fd87a2f 100644 --- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs @@ -136,7 +136,7 @@ namespace MonoDevelop.GtkCore.NodeBuilders } gproject.RemoveActionGroup (group); gproject.SaveProject (false); - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); } } } diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs index 59c1529d1a..42cfbd603d 100644 --- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs +++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs @@ -182,7 +182,7 @@ namespace MonoDevelop.GtkCore.NodeBuilders IdeApp.ProjectOperations.CreateProjectFile (project, path, id); - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); ITreeNavigator nav = Tree.GetNodeAtObject (dataItem); if (nav != null) diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs index 79e0b00d81..c0d692977c 100644 --- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs @@ -141,7 +141,7 @@ namespace MonoDevelop.GtkCore.NodeBuilders } w.Project.Remove (w); w.Project.SaveProject (false); - IdeApp.ProjectOperations.Save (w.Project.Project); + IdeApp.ProjectOperations.SaveAsync (w.Project.Project); } } } diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.addin.xml b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.addin.xml index 8cf80f0493..a892ef2a5b 100644 --- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.addin.xml +++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.addin.xml @@ -146,8 +146,8 @@ <StockIcon stockid = "md-gtkcore-actiongroup" resource = "actiongroup.png" /> </Extension> - <Extension path = "/MonoDevelop/ProjectModel/ProjectServiceExtensions"> - <Class class = "MonoDevelop.GtkCore.GuiBuilder.GtkProjectServiceExtension" insertafter="MidStep"/> + <Extension path = "/MonoDevelop/ProjectModel/ProjectModelExtensions"> + <ProjectExtension class = "MonoDevelop.GtkCore.GuiBuilder.GtkProjectServiceExtension" insertafter="MidStep"/> </Extension> <Extension path = "/MonoDevelop/DesignerSupport/ToolboxProviders"> diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore/ProjectResourceProvider.cs b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore/ProjectResourceProvider.cs index e1c46517d8..6128a6a9bf 100644 --- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore/ProjectResourceProvider.cs +++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore/ProjectResourceProvider.cs @@ -65,7 +65,7 @@ namespace MonoDevelop.GtkCore public Stetic.ResourceInfo AddResource (string fileName) { ProjectFile file = project.AddFile (fileName, BuildAction.EmbeddedResource); - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); return new Stetic.ResourceInfo (file.ResourceId, fileName); } @@ -74,7 +74,7 @@ namespace MonoDevelop.GtkCore foreach (ProjectFile file in project.Files) { if (resourceName == file.ResourceId) { project.Files.Remove (file); - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); return; } } diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs index 68161a0a33..e9642c0d0e 100644 --- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs +++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs @@ -77,7 +77,7 @@ namespace MonoDevelop.GtkCore return (project is DotNetProject) && GtkDesignInfo.SupportsRefactoring (project as DotNetProject); } - public override bool AddToProject (SolutionItem policyParent, Project project, string language, string directory, string name) + public override bool AddToProject (SolutionFolderItem policyParent, Project project, string language, string directory, string name) { if (!GtkDesignInfo.SupportsDesigner (project)) { ReferenceManager mgr = new ReferenceManager (project as DotNetProject); @@ -114,7 +114,7 @@ namespace MonoDevelop.GtkCore gproject.AddNewComponent (doc.DocumentElement); gproject.SaveAll (false); - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); return true; } @@ -128,7 +128,7 @@ namespace MonoDevelop.GtkCore gproject.SteticProject.AddNewActionGroup (doc.DocumentElement); gproject.SaveAll (false); - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); return true; } diff --git a/main/src/addins/MonoDevelop.GtkCore/libstetic/ImageInfo.cs b/main/src/addins/MonoDevelop.GtkCore/libstetic/ImageInfo.cs index 90e6e17c7b..0a766731d3 100644 --- a/main/src/addins/MonoDevelop.GtkCore/libstetic/ImageInfo.cs +++ b/main/src/addins/MonoDevelop.GtkCore/libstetic/ImageInfo.cs @@ -117,6 +117,8 @@ namespace Stetic } catch { // Not a valid image return WidgetUtils.MissingIcon; + } finally { + s.Dispose (); } case ImageSource.Theme: diff --git a/main/src/addins/MonoDevelop.GtkCore/libstetic/editor/SelectImageDialog.cs b/main/src/addins/MonoDevelop.GtkCore/libstetic/editor/SelectImageDialog.cs index 3f64c92369..c4f6330cb6 100644 --- a/main/src/addins/MonoDevelop.GtkCore/libstetic/editor/SelectImageDialog.cs +++ b/main/src/addins/MonoDevelop.GtkCore/libstetic/editor/SelectImageDialog.cs @@ -207,13 +207,14 @@ namespace Stetic.Editor { try { Gdk.Pixbuf pix = new Gdk.Pixbuf (stream); - stream.Close (); string txt = name + "\n<span foreground='darkgrey' size='x-small'>" + pix.Width + " x " + pix.Height + "</span>"; pix = GetThumbnail (pix); resourceListStore.AppendValues (pix, txt, name); resources [name] = pix; } catch { // Doesn't look like a valid image. Just ignore it. + } finally { + stream.Dispose (); } } diff --git a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/ButtonFunction.cs b/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/ButtonFunction.cs deleted file mode 100644 index 9fa8ef4907..0000000000 --- a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/ButtonFunction.cs +++ /dev/null @@ -1,20 +0,0 @@ -// This file was generated by the Gtk# code generator. -// Any changes made will be lost if regenerated. - -namespace Stetic.Metacity -{ - - using System; - using System.Runtime.InteropServices; - -#region Autogenerated code - internal enum ButtonFunction { - - Menu, - Minimize, - Maximize, - Close, - Last, - } -#endregion -} diff --git a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/ButtonLayout.cs b/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/ButtonLayout.cs deleted file mode 100644 index e954c20a3e..0000000000 --- a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/ButtonLayout.cs +++ /dev/null @@ -1,36 +0,0 @@ -// This file was generated by the Gtk# code generator. -// Any changes made will be lost if regenerated. - -namespace Stetic.Metacity -{ - - using System; - using System.Collections; - using System.Runtime.InteropServices; - -#region Autogenerated code - [StructLayout(LayoutKind.Sequential)] - internal struct ButtonLayout { - - [MarshalAs (UnmanagedType.ByValArray, SizeConst=4)] - public Metacity.ButtonFunction[] LeftButtons; - [MarshalAs (UnmanagedType.ByValArray, SizeConst=4)] - public Metacity.ButtonFunction[] RightButtons; - - public static Metacity.ButtonLayout Zero = new Metacity.ButtonLayout (); - - public static Metacity.ButtonLayout New(IntPtr raw) { - if (raw == IntPtr.Zero) { - return Metacity.ButtonLayout.Zero; - } - Metacity.ButtonLayout self = new Metacity.ButtonLayout(); - self = (Metacity.ButtonLayout) Marshal.PtrToStructure (raw, self.GetType ()); - return self; - } - - internal static GLib.GType GType { - get { return GLib.GType.Pointer; } - } -#endregion - } -} diff --git a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/FrameFlags.cs b/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/FrameFlags.cs deleted file mode 100644 index bc6172fbe8..0000000000 --- a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/FrameFlags.cs +++ /dev/null @@ -1,30 +0,0 @@ -// This file was generated by the Gtk# code generator. -// Any changes made will be lost if regenerated. - -namespace Stetic.Metacity -{ - - using System; - using System.Runtime.InteropServices; - -#region Autogenerated code - [Flags] - internal enum FrameFlags { - - AllowsDelete = 1 << 0, - AllowsMenu = 1 << 1, - AllowsMinimize = 1 << 2, - AllowsMaximize = 1 << 3, - AllowsVerticalResize = 1 << 4, - AllowsHorizontalResize = 1 << 5, - HasFocus = 1 << 6, - Shaded = 1 << 7, - Stuck = 1 << 8, - Maximized = 1 << 9, - AllowsShade = 1 << 10, - AllowsMove = 1 << 11, - Fullscreen = 1 << 12, - IsFlashing = 1 << 13, - } -#endregion -} diff --git a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/FrameType.cs b/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/FrameType.cs deleted file mode 100644 index 7ecc08d277..0000000000 --- a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/FrameType.cs +++ /dev/null @@ -1,22 +0,0 @@ -// This file was generated by the Gtk# code generator. -// Any changes made will be lost if regenerated. - -namespace Stetic.Metacity -{ - - using System; - using System.Runtime.InteropServices; - -#region Autogenerated code - internal enum FrameType { - - Normal, - Dialog, - ModalDialog, - Utility, - Menu, - Border, - Last, - } -#endregion -} diff --git a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/ObjectManager.cs b/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/ObjectManager.cs deleted file mode 100644 index 201c52370e..0000000000 --- a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/ObjectManager.cs +++ /dev/null @@ -1,19 +0,0 @@ -// This file was generated by the Gtk# code generator. -// Any changes made will be lost if regenerated. - -namespace GtkSharp.MetacitySharp { - - class ObjectManager { - - static bool initialized = false; - // Call this method from the appropriate module init function. - public static void Initialize () - { - if (initialized) - return; - - initialized = true; - GLib.GType.Register (Stetic.Metacity.Preview.GType, typeof (Stetic.Metacity.Preview)); - } - } -} diff --git a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/Preview.cs b/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/Preview.cs deleted file mode 100644 index b0bd5ba026..0000000000 --- a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/Preview.cs +++ /dev/null @@ -1,226 +0,0 @@ -// This file was generated by the Gtk# code generator. -// Any changes made will be lost if regenerated. - -namespace Stetic.Metacity { - - using System; - using System.Reflection; - using System.Collections; - using System.Runtime.InteropServices; - - internal class Preview : Gtk.Bin - { - const string LIBMETACITY = "libmetacity-private.so.0"; - static Theme theme; - public static bool ThemeError = false; - - public static Metacity.Preview Create (TopLevelWindow window) - { - Metacity.Preview metacityPreview; - - try { - Metacity.Preview.Init (); - metacityPreview = new Metacity.Preview (); - } - catch { - return null; - } - - switch (window.TypeHint) { - case Gdk.WindowTypeHint.Normal: - metacityPreview.FrameType = Metacity.FrameType.Normal; - break; - case Gdk.WindowTypeHint.Dialog: - metacityPreview.FrameType = window.Modal ? Metacity.FrameType.ModalDialog : Metacity.FrameType.Dialog; - break; - case Gdk.WindowTypeHint.Menu: - metacityPreview.FrameType = Metacity.FrameType.Menu; - break; - case Gdk.WindowTypeHint.Splashscreen: - metacityPreview.FrameType = Metacity.FrameType.Border; - break; - case Gdk.WindowTypeHint.Utility: - metacityPreview.FrameType = Metacity.FrameType.Utility; - break; - default: - metacityPreview.FrameType = Metacity.FrameType.Normal; - break; - } - - Metacity.FrameFlags flags = - Metacity.FrameFlags.AllowsDelete | - Metacity.FrameFlags.AllowsVerticalResize | - Metacity.FrameFlags.AllowsHorizontalResize | - Metacity.FrameFlags.AllowsMove | - Metacity.FrameFlags.AllowsShade | - Metacity.FrameFlags.HasFocus; - - if (window.Resizable) - flags = flags | Metacity.FrameFlags.AllowsMaximize; - - metacityPreview.FrameFlags = flags; - metacityPreview.ShowAll (); - metacityPreview.AddWindow (window); - - metacityPreview.Theme = GetTheme (); - - return metacityPreview; - } - - public void AddWindow (TopLevelWindow window) - { - base.Add (window); - - Title = window.Title ?? string.Empty; - window.PropertyChanged += OnWindowPropChange; - Destroyed += delegate { - window.PropertyChanged -= OnWindowPropChange; - }; - } - - void OnWindowPropChange (object ob, EventArgs e) - { - Title = ((TopLevelWindow)ob).Title ?? string.Empty; - } - - static Theme GetTheme () - { - if (theme == null) { - try { - Assembly assm = Assembly.LoadWithPartialName ("gconf-sharp"); - Type client_type = assm.GetType ("GConf.Client"); - MethodInfo method = client_type.GetMethod ("Get", BindingFlags.Instance | BindingFlags.Public); - object client = Activator.CreateInstance (client_type, new object[] { - - }); - string themeName = (string)method.Invoke (client, new object[] { "/apps/metacity/general/theme" }); - theme = Metacity.Theme.Load (themeName); - } catch { - // Set theme error flag - in case of a theme error a solid background needs to be drawn. - ThemeError = true; - // Don't crash if metacity is not available - return null; - } - } - return theme; - } - - /* static void GConfNotify (object obj, GConf.NotifyEventArgs args) - { - if (args.Key == "/apps/metacity/general/theme") { - theme = Metacity.Theme.Load ((string)args.Value); - foreach (Metacity.Preview prev in wrappers.Values) - prev.Theme = Theme; - } - } - */ - - ~Preview ( ) - { - Dispose(); - } - - public Preview(IntPtr raw) : base(raw) {} - - [DllImport(LIBMETACITY)] - static extern IntPtr meta_preview_new(); - - public Preview () : base (IntPtr.Zero) - { - if (GetType () != typeof (Preview)) { - CreateNativeObject (new string [0], new GLib.Value[0]); - return; - } - Raw = meta_preview_new(); - } - - [DllImport(LIBMETACITY)] - static extern void meta_preview_set_title(IntPtr raw, IntPtr title); - - public string Title { - set { - IntPtr title_as_native = GLib.Marshaller.StringToPtrGStrdup (value); - meta_preview_set_title(Handle, title_as_native); - GLib.Marshaller.Free (title_as_native); - } - } - - [DllImport(LIBMETACITY)] - static extern void meta_preview_set_button_layout(IntPtr raw, ref Stetic.Metacity.ButtonLayout button_layout); - - public Stetic.Metacity.ButtonLayout ButtonLayout - { - set { - meta_preview_set_button_layout(Handle, ref value); - } - } - - [DllImport(LIBMETACITY)] - static extern void meta_preview_set_theme(IntPtr raw, IntPtr theme); - - public Metacity.Theme Theme { - set { - meta_preview_set_theme(Handle, (value == null ? IntPtr.Zero : value.Handle)); - } - } - - [DllImport(LIBMETACITY)] - static extern IntPtr meta_preview_get_mini_icon(); - - public static Gdk.Pixbuf MiniIcon { - get { - IntPtr raw_ret = meta_preview_get_mini_icon(); - Gdk.Pixbuf ret = GLib.Object.GetObject(raw_ret) as Gdk.Pixbuf; - return ret; - } - } - - [DllImport(LIBMETACITY)] - static extern IntPtr meta_preview_get_icon(); - - public static Gdk.Pixbuf Icon { - get { - IntPtr raw_ret = meta_preview_get_icon(); - Gdk.Pixbuf ret = GLib.Object.GetObject(raw_ret) as Gdk.Pixbuf; - return ret; - } - } - - [DllImport(LIBMETACITY)] - static extern void meta_preview_set_frame_type(IntPtr raw, int type); - - public Stetic.Metacity.FrameType FrameType - { - set { - meta_preview_set_frame_type(Handle, (int) value); - } - } - - [DllImport(LIBMETACITY)] - static extern IntPtr meta_preview_get_type(); - - public static new GLib.GType GType { - get { - IntPtr raw_ret = meta_preview_get_type(); - GLib.GType ret = new GLib.GType(raw_ret); - return ret; - } - } - - [DllImport(LIBMETACITY)] - static extern void meta_preview_set_frame_flags(IntPtr raw, int flags); - - public Stetic.Metacity.FrameFlags FrameFlags - { - set { - meta_preview_set_frame_flags(Handle, (int) value); - } - } - - - public static void Init() - { - GtkSharp.MetacitySharp.ObjectManager.Initialize (); - } - } -} diff --git a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/Theme.cs b/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/Theme.cs deleted file mode 100644 index b9254d710d..0000000000 --- a/main/src/addins/MonoDevelop.GtkCore/libsteticui/Metacity/Theme.cs +++ /dev/null @@ -1,41 +0,0 @@ - -namespace Stetic.Metacity -{ - using System; - using System.Runtime.InteropServices; - - internal class Theme : GLib.Opaque { - - public Theme (IntPtr raw) : base (raw) {} - - [DllImport("libmetacity-private.so.0")] - static extern IntPtr meta_theme_get_current (); - - public static Theme Current { - get { - IntPtr raw = meta_theme_get_current (); - return (Theme)GetOpaque (raw, typeof (Metacity.Theme), true); - } - } - - [DllImport("libmetacity-private.so.0")] - static extern IntPtr meta_theme_load (string theme_name, IntPtr err); - - public static Theme Load (string name) - { - IntPtr raw = meta_theme_load (name, IntPtr.Zero); - if (raw == IntPtr.Zero) - return null; - else - return (Theme)GetOpaque (raw, typeof (Metacity.Theme), true); - } - - [DllImport("libmetacity-private.so.0")] - static extern void meta_theme_free (IntPtr raw); - - protected override void Free (IntPtr raw) - { - meta_theme_free (Raw); - } - } -} diff --git a/main/src/addins/MonoDevelop.GtkCore/libsteticui/WidgetDesignerBackend.cs b/main/src/addins/MonoDevelop.GtkCore/libsteticui/WidgetDesignerBackend.cs index aad811474c..e3d6864c2c 100644 --- a/main/src/addins/MonoDevelop.GtkCore/libsteticui/WidgetDesignerBackend.cs +++ b/main/src/addins/MonoDevelop.GtkCore/libsteticui/WidgetDesignerBackend.cs @@ -78,9 +78,7 @@ namespace Stetic TopLevelWindow window = container as TopLevelWindow; if (window != null) { - preview = Stetic.Metacity.Preview.Create (window); - if (preview == null) - preview = Stetic.Windows.Preview.Create (window); + preview = Stetic.Windows.Preview.Create (window); if (preview == null) { // Use a regular box. EventBox eventBox = new EventBox (); @@ -660,8 +658,7 @@ namespace Stetic PropagateExpose (cw, ev);*/ Gdk.Rectangle rect = child.Allocation; - if (Stetic.Metacity.Preview.ThemeError) - GdkWindow.DrawRectangle (this.Style.BackgroundGC (StateType.Normal), true, rect.X, rect.Y, rect.Width, rect.Height); + GdkWindow.DrawRectangle (this.Style.BackgroundGC (StateType.Normal), true, rect.X, rect.Y, rect.Width, rect.Height); Pixbuf sh = Shadow.AddShadow (rect.Width, rect.Height); GdkWindow.DrawPixbuf (this.Style.BackgroundGC (StateType.Normal), sh, 0, 0, rect.X - 5, rect.Y - 5, sh.Width, sh.Height, RgbDither.None, 0, 0); diff --git a/main/src/addins/MonoDevelop.GtkCore/libsteticui/libsteticui.csproj b/main/src/addins/MonoDevelop.GtkCore/libsteticui/libsteticui.csproj index fc38b4c1e5..fb9b52a59d 100644 --- a/main/src/addins/MonoDevelop.GtkCore/libsteticui/libsteticui.csproj +++ b/main/src/addins/MonoDevelop.GtkCore/libsteticui/libsteticui.csproj @@ -109,13 +109,6 @@ <Compile Include="GuiDispatchServerSink.cs" /> <Compile Include="GuiDispatchServerSinkProvider.cs" /> <Compile Include="LibraryCache.cs" /> - <Compile Include="Metacity\ButtonFunction.cs" /> - <Compile Include="Metacity\ButtonLayout.cs" /> - <Compile Include="Metacity\FrameFlags.cs" /> - <Compile Include="Metacity\FrameType.cs" /> - <Compile Include="Metacity\ObjectManager.cs" /> - <Compile Include="Metacity\Preview.cs" /> - <Compile Include="Metacity\Theme.cs" /> <Compile Include="Palette.cs" /> <Compile Include="PaletteBackend.cs" /> <Compile Include="PluggableWidget.cs" /> diff --git a/main/src/addins/MonoDevelop.HexEditor/Mono.MHex.Rendering/TextEditorMargin.cs b/main/src/addins/MonoDevelop.HexEditor/Mono.MHex.Rendering/TextEditorMargin.cs index 4a376c3fea..da22d92f36 100644 --- a/main/src/addins/MonoDevelop.HexEditor/Mono.MHex.Rendering/TextEditorMargin.cs +++ b/main/src/addins/MonoDevelop.HexEditor/Mono.MHex.Rendering/TextEditorMargin.cs @@ -71,7 +71,7 @@ namespace Mono.MHex.Rendering for (int i = 0; i < lineBytes.Length; i++) { byte b = lineBytes[i]; char ch = (char)b; - if (b < 128 && (Char.IsLetterOrDigit (ch) || Char.IsPunctuation (ch))) { + if (!char.IsControl (ch)) { sb.Append (ch); } else { sb.Append ("."); diff --git a/main/src/addins/MonoDevelop.HexEditor/MonoDevelop.HexEditor/HexEditorVisualizer.cs b/main/src/addins/MonoDevelop.HexEditor/MonoDevelop.HexEditor/HexEditorVisualizer.cs index 002444879c..9ea23c4739 100644 --- a/main/src/addins/MonoDevelop.HexEditor/MonoDevelop.HexEditor/HexEditorVisualizer.cs +++ b/main/src/addins/MonoDevelop.HexEditor/MonoDevelop.HexEditor/HexEditorVisualizer.cs @@ -81,12 +81,16 @@ namespace MonoDevelop.HexEditor public override Widget GetVisualizerWidget (ObjectValue val) { - hexEditor = new Mono.MHex.HexEditor (); + var options = DebuggingService.DebuggerSession.EvaluationOptions.Clone (); + options.AllowTargetInvoke = true; + options.ChunkRawStrings = true; IBuffer buffer = null; + hexEditor = new Mono.MHex.HexEditor (); + if (val.TypeName != "string") { - var raw = (RawValueArray) val.GetRawValue (); + var raw = (RawValueArray) val.GetRawValue (options); switch (val.TypeName) { case "sbyte[]": @@ -100,10 +104,7 @@ namespace MonoDevelop.HexEditor break; } } else { - var ops = DebuggingService.DebuggerSession.EvaluationOptions.Clone (); - ops.ChunkRawStrings = true; - - buffer = new RawStringBuffer ((RawValueString) val.GetRawValue (ops)); + buffer = new RawStringBuffer ((RawValueString) val.GetRawValue (options)); } hexEditor.HexEditorData.Buffer = buffer; @@ -119,13 +120,17 @@ namespace MonoDevelop.HexEditor public override bool StoreValue (ObjectValue val) { + var options = DebuggingService.DebuggerSession.EvaluationOptions.Clone (); + options.AllowTargetInvoke = true; + switch (val.TypeName) { case "byte[]": // HACK: make sure to load the full byte stream... long length = hexEditor.HexEditorData.Length; + hexEditor.HexEditorData.GetBytes (length - 1, 1); - val.SetRawValue (hexEditor.HexEditorData.Bytes); + val.SetRawValue (hexEditor.HexEditorData.Bytes, options); return true; default: return false; diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CSharpProjectParameters.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/RestorePackagesInProjectHandler.cs index 7e010c0de6..cd12b8ef75 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CSharpProjectParameters.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/RestorePackagesInProjectHandler.cs @@ -1,84 +1,63 @@ -// -// ProjectParameters.cs -// -// Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using MonoDevelop.Core.Serialization; -using MonoDevelop.Projects; - -namespace MonoDevelop.CSharp.Project -{ - public class CSharpProjectParameters: ProjectParameters - { - [ItemProperty ("StartupObject", DefaultValue = "")] - string mainclass = string.Empty; - - [ProjectPathItemProperty ("ApplicationIcon", DefaultValue = "")] - string win32Icon = String.Empty; - - [ProjectPathItemProperty ("Win32Resource", DefaultValue = "")] - string win32Resource = String.Empty; - - [ItemProperty ("CodePage", DefaultValue = 0)] - int codePage; - - public string MainClass { - get { - return mainclass; - } - set { - mainclass = value ?? string.Empty; - } - } - - public int CodePage { - get { - return codePage; - } - set { - codePage = value; - } - } - - public string Win32Icon { - get { - return win32Icon; - } - set { - win32Icon = value ?? string.Empty; - } - } - - public string Win32Resource { - get { - return win32Resource; - } - set { - win32Resource = value ?? string.Empty; - } - } - - } -} +//
+// RestorePackagesInProjectHandler.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using MonoDevelop.Components.Commands;
+using MonoDevelop.Ide;
+using MonoDevelop.Projects;
+
+namespace MonoDevelop.PackageManagement.Commands
+{
+ public class RestorePackagesInProjectHandler : PackagesCommandHandler
+ {
+ protected override void Run ()
+ {
+ IDotNetProject project = GetSelectedProject ();
+ if (project == null)
+ return;
+
+ ProgressMonitorStatusMessage progressMessage = ProgressMonitorStatusMessageFactory.CreateRestoringPackagesInProjectMessage ();
+ var runner = new PackageRestoreRunner ();
+ DispatchService.BackgroundDispatch (() => {
+ runner.Run (project, progressMessage);
+ });
+ }
+
+ IDotNetProject GetSelectedProject ()
+ {
+ DotNetProject project = GetSelectedDotNetProject ();
+ if (project != null) {
+ return new DotNetProjectProxy (project);
+ }
+ return null;
+ }
+
+ protected override void Update (CommandInfo info)
+ {
+ info.Enabled = SelectedDotNetProjectOrSolutionHasPackages ();
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.cs index 642b59906e..ec8e0f7f69 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.cs @@ -289,7 +289,7 @@ namespace MonoDevelop.PackageManagement this.packageVersionLabel.Text = packageViewModel.Version.ToString ();
this.packageAuthor.Text = packageViewModel.GetAuthors ();
this.packagePublishedDate.Text = packageViewModel.GetLastPublishedDisplayText ();
- this.packageDownloads.Text = packageViewModel.GetDownloadCountOrVersionDisplayText ();
+ this.packageDownloads.Text = packageViewModel.GetDownloadCountDisplayText ();
this.packageDescription.Text = packageViewModel.Description;
this.packageId.Text = packageViewModel.Id;
this.packageId.Visible = packageViewModel.HasNoGalleryUrl;
@@ -532,6 +532,7 @@ namespace MonoDevelop.PackageManagement void PackageSearchEntryChanged (object sender, EventArgs e)
{
+ ClearErrorMessage ();
ClearPackages ();
UpdateAddPackagesButton ();
SearchAfterDelay ();
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/PackageReferenceNode.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/PackageReferenceNode.cs index 84928ce419..915328acfd 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/PackageReferenceNode.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/PackageReferenceNode.cs @@ -27,8 +27,8 @@ using System;
using System.Runtime.Versioning;
using MonoDevelop.Core;
-using MonoDevelop.Core.Serialization;
using MonoDevelop.Ide.Gui;
+using MonoDevelop.Ide.Tasks;
using NuGet;
namespace MonoDevelop.PackageManagement.NodeBuilders
@@ -91,15 +91,10 @@ namespace MonoDevelop.PackageManagement.NodeBuilders public string GetLabel ()
{
if (UpdatedVersion != null) {
- return GetIdText () + GetUpdatedVersionLabelText ();
+ return Id + GetUpdatedVersionLabelText ();
}
- return GetIdText ();
- }
-
- string GetIdText ()
- {
- if (!Installed || IsReinstallNeeded) {
- return "<span color='#c99c00'>" + Id + "</span>";
+ if (IsInstallPending) {
+ return Id + GetInstallingLabelText ();
}
return Id;
}
@@ -111,19 +106,47 @@ namespace MonoDevelop.PackageManagement.NodeBuilders GettextCatalog.GetString ("available"));
}
+ string GetInstallingLabelText ()
+ {
+ return String.Format (" ({0})", GettextCatalog.GetString ("installing"));
+ }
+
public IconId GetIconId ()
{
+ return Stock.Reference;
+ }
+
+ public string GetPackageVersionLabel ()
+ {
+ return GettextCatalog.GetString ("Version {0}", Version);
+ }
+
+ public TaskSeverity? GetStatusSeverity ()
+ {
if (!Installed || IsReinstallNeeded) {
if (!IsInstallPending) {
- return Stock.ReferenceWarning;
+ return TaskSeverity.Warning;
}
}
- return Stock.Reference;
+
+ return null;
}
- public string GetPackageVersionLabel ()
+ public string GetStatusMessage ()
{
- return GettextCatalog.GetString ("Version {0}", Version);
+ if (IsInstallPending) {
+ return null;
+ } else if (!Installed) {
+ return GettextCatalog.GetString ("Package is not restored");
+ } else if (IsReinstallNeeded) {
+ return GettextCatalog.GetString ("Package needs retargeting");
+ }
+ return null;
+ }
+
+ public bool IsDisabled ()
+ {
+ return (!Installed || IsInstallPending);
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/PackageReferenceNodeBuilder.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/PackageReferenceNodeBuilder.cs index 0af1f56798..149b61f265 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/PackageReferenceNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/PackageReferenceNodeBuilder.cs @@ -58,6 +58,9 @@ namespace MonoDevelop.PackageManagement.NodeBuilders var packageReferenceNode = (PackageReferenceNode)dataObject;
nodeInfo.Label = packageReferenceNode.GetLabel ();
nodeInfo.Icon = Context.GetIcon (packageReferenceNode.GetIconId ());
+ nodeInfo.StatusSeverity = packageReferenceNode.GetStatusSeverity ();
+ nodeInfo.StatusMessage = packageReferenceNode.GetStatusMessage ();
+ nodeInfo.DisabledStyle = packageReferenceNode.IsDisabled ();
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/ProjectPackagesFolderNodeBuilder.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/ProjectPackagesFolderNodeBuilder.cs index 631b33e9b2..0fd8f7242f 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/ProjectPackagesFolderNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/ProjectPackagesFolderNodeBuilder.cs @@ -81,7 +81,7 @@ namespace MonoDevelop.PackageManagement.NodeBuilders List<PackageReferenceNode> nodes = projectPackagesNode.GetPackageReferencesNodes ().ToList ();
foreach (InstallPackageAction installAction in GetPendingInstallActions (projectPackagesNode.Project)) {
- if (!nodes.Any (node => node.Id == installAction.Package.Id)) {
+ if (!nodes.Any (node => node.Id == installAction.GetPackageId ())) {
nodes.Add (CreatePackageReferenceNode (installAction));
}
}
@@ -99,7 +99,7 @@ namespace MonoDevelop.PackageManagement.NodeBuilders PackageReferenceNode CreatePackageReferenceNode (InstallPackageAction installAction)
{
return new PackageReferenceNode (
- new PackageReference (installAction.Package.Id, installAction.Package.Version, null, null, false),
+ new PackageReference (installAction.GetPackageId (), installAction.GetPackageVersion (), null, null, false),
false,
true);
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/ProjectPackagesProjectNodeBuilderExtension.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/ProjectPackagesProjectNodeBuilderExtension.cs index 3bdec1ec1c..b30f68b1c5 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/ProjectPackagesProjectNodeBuilderExtension.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.NodeBuilders/ProjectPackagesProjectNodeBuilderExtension.cs @@ -144,16 +144,7 @@ namespace MonoDevelop.PackageManagement.NodeBuilders bool IsPackagesConfigFileChanged (FileEventArgs fileEventArgs)
{
- return fileEventArgs.Any (file => IsPackagesConfigFileName (file.FileName));
- }
-
- bool IsPackagesConfigFileName (FilePath filePath)
- {
- if (filePath == null) {
- return false;
- }
-
- return Constants.PackageReferenceFile.Equals (filePath.FileName, StringComparison.OrdinalIgnoreCase);
+ return fileEventArgs.Any (file => file.FileName.IsPackagesConfigFileName ());
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/ExceptionThrowingPackageRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/ExceptionThrowingPackageRepository.cs new file mode 100644 index 0000000000..b5308eaa74 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/ExceptionThrowingPackageRepository.cs @@ -0,0 +1,53 @@ +//
+// ExceptionThrowingPackageRepository.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Linq;
+using NuGet;
+
+namespace MonoDevelop.PackageManagement.Tests.Helpers
+{
+ public class ExceptionThrowingPackageRepository : FakePackageRepository
+ {
+ public Exception GetPackagesException;
+
+ public ExceptionThrowingPackageRepository ()
+ : this (new Exception ("Error"))
+ {
+ }
+
+ public ExceptionThrowingPackageRepository (Exception exception)
+ {
+ GetPackagesException = exception;
+ }
+
+ public override IQueryable<IPackage> GetPackages ()
+ {
+ throw GetPackagesException;
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeFileRemover.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeFileRemover.cs new file mode 100644 index 0000000000..7f80fec744 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeFileRemover.cs @@ -0,0 +1,41 @@ +//
+// FakeFileRemover.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace MonoDevelop.PackageManagement.Tests.Helpers
+{
+ public class FakeFileRemover : IFileRemover
+ {
+ public string FileRemoved;
+
+ public void RemoveFile (string fileName)
+ {
+ FileRemoved = fileName;
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeOperationAwareRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeOperationAwareRepository.cs index 7bbdce5119..e3e769d494 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeOperationAwareRepository.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeOperationAwareRepository.cs @@ -34,11 +34,13 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers {
public string OperationStarted;
public string MainPackageIdForOperationStarted;
+ public string MainPackageVersionForOperationStarted;
public IDisposable StartOperation (string operationName, string mainPackageId, string mainPackageVersion)
{
OperationStarted = operationName;
MainPackageIdForOperationStarted = mainPackageId;
+ MainPackageVersionForOperationStarted = mainPackageVersion;
return this;
}
@@ -49,6 +51,14 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers AssertOperationIsDisposed ();
}
+ public void AssertOperationWasStartedAndDisposed (string expectedOperationName, string expectedMainPackageId, string expectedMainPackageVersion)
+ {
+ Assert.AreEqual (expectedOperationName, OperationStarted);
+ Assert.AreEqual (expectedMainPackageId, MainPackageIdForOperationStarted);
+ Assert.AreEqual (expectedMainPackageVersion, MainPackageVersionForOperationStarted);
+ AssertOperationIsDisposed ();
+ }
+
void AssertOperationIsDisposed ()
{
Assert.IsTrue (IsDisposed);
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackage.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackage.cs index 4601469c9b..1a22b06d86 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackage.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackage.cs @@ -63,6 +63,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers this.Version = new SemanticVersion (version);
this.Listed = true;
this.IsLatestVersion = true;
+ IsValid = true;
}
public static FakePackage CreatePackageWithVersion (string version)
@@ -228,6 +229,8 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public Uri GalleryUrl { get; set; }
public bool DevelopmentDependency { get; set; }
+
+ public bool IsValid { get; set; }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagementProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagementProject.cs index 6eb845018a..9e3e9e141b 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagementProject.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagementProject.cs @@ -51,7 +51,17 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers return FakePackages.FirstOrDefault (package => package.Id == packageId);
};
+ UpdatePackageAction = (package, updateAction) => {
+ PackagePassedToUpdatePackage = package;
+ PackageOperationsPassedToUpdatePackage = updateAction.Operations;
+ UpdateDependenciesPassedToUpdatePackage = updateAction.UpdateDependencies;
+ AllowPrereleaseVersionsPassedToUpdatePackage = updateAction.AllowPrereleaseVersions;
+ IsUpdatePackageCalled = true;
+ };
+
this.Name = name;
+
+ ConstraintProvider = NullConstraintProvider.Instance;
}
public FakeUninstallPackageAction FakeUninstallPackageAction;
@@ -156,13 +166,11 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public void UpdatePackage (IPackage package, UpdatePackageAction updateAction)
{
- PackagePassedToUpdatePackage = package;
- PackageOperationsPassedToUpdatePackage = updateAction.Operations;
- UpdateDependenciesPassedToUpdatePackage = updateAction.UpdateDependencies;
- AllowPrereleaseVersionsPassedToUpdatePackage = updateAction.AllowPrereleaseVersions;
- IsUpdatePackageCalled = true;
+ UpdatePackageAction (package, updateAction);
}
+ public Action<IPackage, UpdatePackageAction> UpdatePackageAction;
+
public FakeInstallPackageAction LastInstallPackageCreated;
public virtual InstallPackageAction CreateInstallPackageAction ()
@@ -248,6 +256,11 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers FakeSourceRepository.AddFakePackage (packageId);
}
+ public FakePackage AddFakePackageToSourceRepository (string packageId, string version)
+ {
+ return FakeSourceRepository.AddFakePackageWithVersion (packageId, version);
+ }
+
public void UpdatePackages (UpdatePackagesAction action)
{
}
@@ -364,6 +377,8 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers {
throw new NotImplementedException ();
}
+
+ public IPackageConstraintProvider ConstraintProvider { get; set; }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagementSolution.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagementSolution.cs index 7185d1c5d4..adfddb3d8e 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagementSolution.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagementSolution.cs @@ -198,6 +198,26 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers {
throw new NotImplementedException ();
}
+
+ public FakeSolutionPackageRepository SolutionPackageRepository = new FakeSolutionPackageRepository ();
+
+ public ISolutionPackageRepository GetRepository ()
+ {
+ return SolutionPackageRepository;
+ }
+
+ public bool IsPackageRestored (string packageId, SemanticVersion packageVersion)
+ {
+ return FakeInstalledPackages.Any (package => {
+ return (package.Id == packageId) &&
+ (package.Version == packageVersion);
+ });
+ }
+
+ public void AddPackageReference (string packageId, string packageVersion)
+ {
+ SolutionPackageRepository.AddPackageReference (packageId, packageVersion);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManager.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManager.cs index a9a722a48a..a6a3c7787c 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManager.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManager.cs @@ -214,11 +214,23 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers SettingsPassedToUpdatePackageReference = settings;
}
+ public bool IgnoreWalkInfoPassedToInstallPackage;
+ public bool IsPackageInstalled;
+
public void InstallPackage (IPackage package, bool ignoreDependencies, bool allowPrereleaseVersions, bool ignoreWalkInfo)
{
- throw new NotImplementedException ();
+ IsPackageInstalled = true;
+
+ PackagePassedToInstallPackage = package;
+ IgnoreDependenciesPassedToInstallPackage = ignoreDependencies;
+ AllowPrereleaseVersionsPassedToInstallPackage = allowPrereleaseVersions;
+ IgnoreWalkInfoPassedToInstallPackage = ignoreWalkInfo;
+
+ PackagesInstalled.Add (package);
}
+ public List<IPackage> PackagesInstalled = new List<IPackage> ();
+
public DependencyVersion DependencyVersion {
get {
throw new NotImplementedException ();
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagerFactory.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagerFactory.cs index bb98bc2097..e66d160c69 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagerFactory.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagerFactory.cs @@ -36,6 +36,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public FakePackageManager FakePackageManager = new FakePackageManager ();
public IPackageRepository PackageRepositoryPassedToCreatePackageManager;
public IDotNetProject ProjectPassedToCreateRepository;
+ public ISolutionPackageRepository SolutionPackageRepositoryPassedToCreatePackageManager;
public ISharpDevelopPackageManager CreatePackageManager (IPackageRepository sourceRepository, IDotNetProject project)
{
@@ -43,6 +44,13 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers ProjectPassedToCreateRepository = project;
return FakePackageManager;
}
+
+ public IPackageManager CreatePackageManager (IPackageRepository sourceRepository, ISolutionPackageRepository solutionPackageRepository)
+ {
+ PackageRepositoryPassedToCreatePackageManager = sourceRepository;
+ SolutionPackageRepositoryPassedToCreatePackageManager = solutionPackageRepository;
+ return FakePackageManager;
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageRepository.cs index 2e7bffe160..93dea0d78d 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageRepository.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageRepository.cs @@ -42,7 +42,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers get { return PackagesAdded [0]; }
}
- public IQueryable<IPackage> GetPackages ()
+ public virtual IQueryable<IPackage> GetPackages ()
{
return FakePackages.AsQueryable ();
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageRepositoryFactory.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageRepositoryFactory.cs index c55a3679a4..cf406c1fd5 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageRepositoryFactory.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageRepositoryFactory.cs @@ -117,6 +117,13 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public IRecentPackageRepository RecentPackageRepository {
get { return FakeRecentPackageRepository; }
}
+
+ public FakePackageRepository FakePriorityPackageRepository = new FakePackageRepository ();
+
+ public IPackageRepository CreateAggregateWithPriorityMachineCacheRepository ()
+ {
+ return FakePriorityPackageRepository;
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageRepositoryWithConstraintProvider.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageRepositoryWithConstraintProvider.cs new file mode 100644 index 0000000000..a39b13097a --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageRepositoryWithConstraintProvider.cs @@ -0,0 +1,47 @@ +//
+// FakePackageRepositoryWithConstraintProvider.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using NuGet;
+
+namespace MonoDevelop.PackageManagement.Tests.Helpers
+{
+ public class FakePackageRepositoryWithConstraintProvider : FakePackageRepository, IPackageConstraintProvider
+ {
+ DefaultConstraintProvider constraintProvider = new DefaultConstraintProvider ();
+
+ public IVersionSpec GetConstraint (string packageId)
+ {
+ return constraintProvider.GetConstraint (packageId);
+ }
+
+ public void AddConstraint (string packageId, IVersionSpec versionSpec)
+ {
+ constraintProvider.AddConstraint (packageId, versionSpec);
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeProgressMonitor.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeProgressMonitor.cs index a06a2dc3df..3f00df6491 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeProgressMonitor.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeProgressMonitor.cs @@ -29,14 +29,15 @@ using System.IO; using System.Text;
using MonoDevelop.Core;
using NUnit.Framework;
+using System.Threading;
namespace MonoDevelop.PackageManagement.Tests.Helpers
{
- public class FakeProgressMonitor : IProgressMonitor
+ public class FakeProgressMonitor : ProgressMonitor
{
public event MonitorHandler CancelRequested;
- protected virtual void OnCancelRequested (IProgressMonitor monitor)
+ protected virtual void OnCancelRequested (ProgressMonitor monitor)
{
var handler = CancelRequested;
if (handler != null)
@@ -48,7 +49,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers Log = new StringWriter (LoggedMessages);
}
- public void BeginTask (string name, int totalWork)
+ protected override void OnBeginTask (string name, int totalWork, int stepWork)
{
BeginTaskTotalWork = totalWork;
}
@@ -59,14 +60,14 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers {
}
- public void EndTask ()
+ protected override void OnEndTask (string name, int totalWork, int stepWork)
{
IsTaskEnded = true;
}
public bool IsTaskEnded;
- public void Step (int work)
+ protected override void OnStep (string message, int work)
{
StepCalledCount++;
TotalStepWork += work;
@@ -75,21 +76,21 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public int StepCalledCount;
public int TotalStepWork;
- public void ReportWarning (string message)
+ protected override void OnWarningReported (string message)
{
ReportedWarningMessage = message;
}
public string ReportedWarningMessage;
- public void ReportSuccess (string message)
+ protected override void OnSuccessReported (string message)
{
ReportedSuccessMessage = message;
}
public string ReportedSuccessMessage;
- public void ReportError (string message, Exception exception)
+ protected override void OnErrorReported (string message, Exception exception)
{
ReportedErrorMessage = message;
}
@@ -110,13 +111,13 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers Assert.IsFalse (log.Contains (message), log);
}
- public TextWriter Log { get; set; }
public bool IsCancelRequested { get; set; }
- public IAsyncOperation AsyncOperation { get; set; }
+ public AsyncOperation AsyncOperation { get; set; }
public object SyncRoot { get; set; }
- public void Dispose ()
+ public override void Dispose ()
{
+ base.Dispose ();
IsDisposed = true;
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeProgressMonitorFactory.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeProgressMonitorFactory.cs index 90e62b3268..f7b28eb358 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeProgressMonitorFactory.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeProgressMonitorFactory.cs @@ -34,7 +34,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public FakeProgressMonitor ProgressMonitor = new FakeProgressMonitor ();
public string StatusText;
- public IProgressMonitor CreateProgressMonitor (string statusText)
+ public ProgressMonitor CreateProgressMonitor (string statusText)
{
StatusText = statusText;
return ProgressMonitor;
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeProject.cs index 18971e4641..cdab5a07b6 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeProject.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeProject.cs @@ -27,6 +27,7 @@ using System;
using System.Collections;
using MonoDevelop.Core;
+using System.Collections.Generic;
namespace MonoDevelop.PackageManagement.Tests.Helpers
{
@@ -61,6 +62,10 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers {
IsSaved = true;
}
+
+ public IEnumerable<string> FlavorGuids {
+ get { yield break; }
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolutionPackageRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolutionPackageRepository.cs index 26be2ad35d..eaf9dcf505 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolutionPackageRepository.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolutionPackageRepository.cs @@ -81,6 +81,33 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public IFileSystem FileSystem { get; set; }
public IPackagePathResolver PackagePathResolver { get; set; }
+
+ public bool IsRestored (PackageReference packageReference)
+ {
+ return FakeSharedRepository.FakePackages.Any (package => {
+ return (package.Id == packageReference.Id) &&
+ (package.Version == packageReference.Version);
+ });
+ }
+
+ public List<PackageReference> PackageReferences = new List<PackageReference> ();
+
+ public void AddPackageReference (string packageId, string packageVersion)
+ {
+ var packageReference = new PackageReference (
+ packageId,
+ new SemanticVersion (packageVersion),
+ null,
+ null,
+ false,
+ false);
+ PackageReferences.Add (packageReference);
+ }
+
+ public IEnumerable<PackageReference> GetPackageReferences ()
+ {
+ return PackageReferences;
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableBackgroundPackageActionRunner.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableBackgroundPackageActionRunner.cs index 66439b08e1..d4b11accde 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableBackgroundPackageActionRunner.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableBackgroundPackageActionRunner.cs @@ -60,7 +60,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers }
protected override PackageManagementEventsMonitor CreateEventMonitor (
- IProgressMonitor monitor,
+ ProgressMonitor monitor,
IPackageManagementEvents packageManagementEvents,
IProgressProvider progressProvider)
{
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableLocalPackageRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableLocalPackageRepository.cs new file mode 100644 index 0000000000..81fe190099 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableLocalPackageRepository.cs @@ -0,0 +1,59 @@ +//
+// TestableLocalPackageRepository.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using NuGet;
+
+namespace MonoDevelop.PackageManagement.Tests.Helpers
+{
+ public class TestableLocalPackageRepository : LocalPackageRepository
+ {
+ public TestableLocalPackageRepository ()
+ : base (@"d:\projects\MySolution\packages".ToNativePath ())
+ {
+ }
+
+ public override IEnumerable<string> GetPackageLookupPaths (string packageId, SemanticVersion version)
+ {
+ var packageName = new PackageName (packageId, version);
+ List<string> filePaths = null;
+ if (packageLookupPaths.TryGetValue (packageName, out filePaths)) {
+ return filePaths;
+ }
+ return Enumerable.Empty<string> ();
+ }
+
+ Dictionary<PackageName, List<string>> packageLookupPaths = new Dictionary<PackageName, List<string>> ();
+
+ public void AddPackageLookupPath (PackageName packageName, params string[] filePaths)
+ {
+ packageLookupPaths.Add (packageName, filePaths.ToList ());
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestablePackageCompatibilityRunner.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestablePackageCompatibilityRunner.cs index 2ebee582a5..7045d5acf2 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestablePackageCompatibilityRunner.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestablePackageCompatibilityRunner.cs @@ -65,7 +65,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers }
protected override PackageManagementEventsMonitor CreateEventMonitor (
- IProgressMonitor monitor,
+ ProgressMonitor monitor,
IPackageManagementEvents packageManagementEvents,
IProgressProvider progressProvider)
{
@@ -97,7 +97,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public bool PackageConsoleIsShown;
- protected override void ShowPackageConsole (IProgressMonitor progressMonitor)
+ protected override void ShowPackageConsole (ProgressMonitor progressMonitor)
{
PackageConsoleIsShown = true;
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestablePackageManagementEventsMonitor.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestablePackageManagementEventsMonitor.cs index 451310dd19..995fa795cb 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestablePackageManagementEventsMonitor.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestablePackageManagementEventsMonitor.cs @@ -36,7 +36,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public class TestablePackageManagementEventsMonitor : PackageManagementEventsMonitor
{
public TestablePackageManagementEventsMonitor (
- IProgressMonitor progressMonitor,
+ ProgressMonitor progressMonitor,
IPackageManagementEvents packageManagementEvents,
IProgressProvider progressProvider)
: base (progressMonitor, packageManagementEvents, progressProvider)
@@ -55,14 +55,14 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers handler.Invoke ();
}
- protected override void ShowPackageConsole (IProgressMonitor progressMonitor)
+ protected override void ShowPackageConsole (ProgressMonitor progressMonitor)
{
IsPackageConsoleShown = true;
ProgressMonitorPassedToShowPackageConsole = progressMonitor;
}
public bool IsPackageConsoleShown;
- public IProgressMonitor ProgressMonitorPassedToShowPackageConsole;
+ public ProgressMonitor ProgressMonitorPassedToShowPackageConsole;
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableSolutionPackageRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableSolutionPackageRepository.cs new file mode 100644 index 0000000000..78cbae75c9 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableSolutionPackageRepository.cs @@ -0,0 +1,51 @@ +//
+// TestableSolutionPackageRepository.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using ICSharpCode.PackageManagement;
+using NuGet;
+
+namespace MonoDevelop.PackageManagement.Tests.Helpers
+{
+ public class TestableSolutionPackageRepository : SolutionPackageRepository
+ {
+ public TestableSolutionPackageRepository (
+ ISolution solution,
+ ISharpDevelopPackageRepositoryFactory repositoryFactory,
+ PackageManagementOptions options)
+ : base (solution, repositoryFactory, options)
+ {
+ }
+
+ public TestableLocalPackageRepository LocalPackageRepository = new TestableLocalPackageRepository ();
+
+ protected override LocalPackageRepository CreateLocalPackageRepository ()
+ {
+ return LocalPackageRepository;
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj index 8545b6caed..f7d81fb679 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj @@ -122,7 +122,6 @@ <Compile Include="MonoDevelop.PackageManagement.Tests\UpdateAllPackagesInSolutionTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests\UserAgentGeneratorForRepositoryRequestsTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakePackageRepositoryWithHttpClientEvents.cs" /> - <Compile Include="MonoDevelop.PackageManagement.Tests\NuGetPackageRestoreCommandLineTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests\ReducedPackageOperationsTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestPackageHelper.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakePackageOperationResolver.cs" /> @@ -193,6 +192,13 @@ <Compile Include="MonoDevelop.PackageManagement.Tests\PackagesViewModelTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestablePackagesViewModel.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\PageCollectionAssert.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\ExceptionThrowingPackageRepository.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests\MonoDevelopAggregateRepositoryTests.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests\RestorePackagesActionTests.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableLocalPackageRepository.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableSolutionPackageRepository.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeFileRemover.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakePackageRepositoryWithConstraintProvider.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj"> diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/AvailablePackagesViewModelTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/AvailablePackagesViewModelTests.cs index 664e6fa424..75f49fdc55 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/AvailablePackagesViewModelTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/AvailablePackagesViewModelTests.cs @@ -60,6 +60,7 @@ namespace MonoDevelop.PackageManagement.Tests ExceptionThrowingRegisteredPackageRepositories exceptionThrowingRegisteredPackageRepositories;
FakeTaskFactory taskFactory;
FakeRecentPackageRepository recentPackageRepository;
+ FakePackageManagementSolution solution;
void CreateViewModel ()
{
@@ -77,8 +78,10 @@ namespace MonoDevelop.PackageManagement.Tests taskFactory = new FakeTaskFactory ();
var packageViewModelFactory = new FakePackageViewModelFactory ();
recentPackageRepository = new FakeRecentPackageRepository ();
+ solution = new FakePackageManagementSolution ();
viewModel = new AvailablePackagesViewModel (
+ solution,
registeredPackageRepositories,
recentPackageRepository,
packageViewModelFactory,
@@ -172,6 +175,39 @@ namespace MonoDevelop.PackageManagement.Tests viewModel.SearchTerms = string.Format ("{0} version:{1}", packageId, versions).TrimEnd ();
}
+ void AddAggregateRepositoryWithOneFailingRepository ()
+ {
+ AddAggregateRepository (new ExceptionThrowingPackageRepository (), new FakePackageRepository ());
+ }
+
+ void AddAggregateRepository (params IPackageRepository[] repositories)
+ {
+ var repository = new MonoDevelopAggregateRepository (repositories);
+ registeredPackageRepositories.ActivePackageSource = registeredPackageRepositories.PackageSources [0];
+ registeredPackageRepositories.GetActiveRepositoryAction = () => {
+ return repository;
+ };
+ }
+
+ void AddAggregateRepositoryWithJustFailingRepositories ()
+ {
+ AddAggregateRepository (new ExceptionThrowingPackageRepository (), new ExceptionThrowingPackageRepository ());
+ }
+
+ void AddAggregateRepositoryWithTwoFailingRepositories (Exception exception1, Exception exception2)
+ {
+ AddAggregateRepository (
+ new ExceptionThrowingPackageRepository (exception1),
+ new ExceptionThrowingPackageRepository (exception2));
+ }
+
+ FakePackage AddPackageToSolution (string packageId, string packageVersion)
+ {
+ var package = FakePackage.CreatePackageWithVersion (packageId, packageVersion);
+ solution.SolutionPackageRepository.FakePackages.Add (package);
+ return package;
+ }
+
[Test]
public void ReadPackages_RepositoryHasThreePackagesWithSameIdButDifferentVersions_HasLatestPackageVersionOnly ()
{
@@ -809,9 +845,6 @@ namespace MonoDevelop.PackageManagement.Tests viewModel.ReadPackages ();
CompleteReadPackagesTask ();
- var expectedPackages = new FakePackage[] {
- package2, package1
- };
Assert.IsTrue (viewModel.PackageViewModels [0].ShowVersionInsteadOfDownloadCount);
Assert.IsTrue (viewModel.PackageViewModels [1].ShowVersionInsteadOfDownloadCount);
}
@@ -831,9 +864,6 @@ namespace MonoDevelop.PackageManagement.Tests viewModel.ReadPackages ();
CompleteReadPackagesTask ();
- var expectedPackages = new FakePackage[] {
- package2, package1
- };
Assert.IsFalse (viewModel.PackageViewModels [0].ShowVersionInsteadOfDownloadCount);
Assert.IsFalse (viewModel.PackageViewModels [1].ShowVersionInsteadOfDownloadCount);
}
@@ -911,5 +941,276 @@ namespace MonoDevelop.PackageManagement.Tests };
PackageCollectionAssert.AreEqual (expectedPackages, viewModel.PackageViewModels);
}
+
+ [Test]
+ public void ReadPackages_ActivePackageSourceIsAggregatePackageRepositoryWithOneFailingRepository_HasErrorIsTrueAndErrorMessageHasWarning ()
+ {
+ CreateRegisteredPackageRepositories ();
+ AddAggregateRepositoryWithOneFailingRepository ();
+ CreateViewModel (registeredPackageRepositories);
+
+ viewModel.ReadPackages ();
+ CompleteReadPackagesTask ();
+
+ Assert.IsTrue (viewModel.HasError);
+ Assert.That (viewModel.ErrorMessage, Contains.Substring ("Some package sources could not be reached."));
+ }
+
+ [Test]
+ public void ReadPackages_ActivePackageSourceIsAggregatePackageRepositoryWithAllRepositoriesFailing_HasErrorIsTrueAndErrorMessageHasWarning ()
+ {
+ CreateRegisteredPackageRepositories ();
+ AddAggregateRepositoryWithJustFailingRepositories ();
+ CreateViewModel (registeredPackageRepositories);
+
+ viewModel.ReadPackages ();
+ CompleteReadPackagesTask ();
+
+ Assert.IsTrue (viewModel.HasError);
+ Assert.That (viewModel.ErrorMessage, Contains.Substring ("All package sources could not be reached."));
+ }
+
+ [Test]
+ public void ReadPackages_ActivePackageSourceIsAggregatePackageRepositoryWithAllRepositoriesFailing_RepositoryErrorIsDisplayed ()
+ {
+ CreateRegisteredPackageRepositories ();
+ var exception1 = new Exception ("Error1");
+ var exception2 = new Exception ("Error2");
+ AddAggregateRepositoryWithTwoFailingRepositories (exception1, exception2);
+ CreateViewModel (registeredPackageRepositories);
+
+ viewModel.ReadPackages ();
+ CompleteReadPackagesTask ();
+
+ Assert.IsTrue (viewModel.HasError);
+ Assert.That (viewModel.ErrorMessage, Contains.Substring ("Error1"));
+ Assert.That (viewModel.ErrorMessage, Contains.Substring ("Error2"));
+ }
+
+ [Test]
+ public void ReadPackages_ActivePackageSourceIsAggregatePackageRepositoryWithOneFailingRepository_RepositoryErrorIsDisplayed ()
+ {
+ CreateRegisteredPackageRepositories ();
+ var repository = new ExceptionThrowingPackageRepository (new Exception ("Error1"));
+ AddAggregateRepository (new FakePackageRepository (), repository);
+ CreateViewModel (registeredPackageRepositories);
+
+ viewModel.ReadPackages ();
+ CompleteReadPackagesTask ();
+
+ Assert.IsTrue (viewModel.HasError);
+ Assert.That (viewModel.ErrorMessage, Contains.Substring ("Error1"));
+ }
+
+ [Test]
+ public void ReadPackages_OneRecentPackageIsAvailable_RecentPackageIsDisplayedBeforeAnyOtherPackages ()
+ {
+ CreateViewModel ();
+ AddOnePackageSourceToRegisteredSources ();
+ var package1 = new FakePackage ("A", "0.2.0.0");
+ var package2 = new FakePackage ("Aa", "0.3.0.0");
+ var packages = new [] {
+ package1, package2
+ };
+ registeredPackageRepositories.FakeActiveRepository.FakePackages.AddRange (packages);
+ var recentPackage = new FakePackage ("B", "1.0.0.0");
+ recentPackageRepository.AddPackage (recentPackage);
+
+ viewModel.ReadPackages ();
+ CompleteReadPackagesTask ();
+
+ var expectedPackages = new [] {
+ recentPackage, package1, package2
+ };
+ PackageCollectionAssert.AreEqual (expectedPackages, viewModel.PackageViewModels);
+ }
+
+ [Test]
+ public void ReadPackages_OneRecentPackageIsAvailableWhichMatchesPackageFromActiveSource_DuplicatePackageWithSameVersionFromActivePackageSourceIsNotDisplayed ()
+ {
+ CreateViewModel ();
+ AddOnePackageSourceToRegisteredSources ();
+ var package1 = new FakePackage ("A", "1.0.0.0");
+ var package2 = new FakePackage ("B", "0.3.0.0");
+ var packages = new [] {
+ package1, package2
+ };
+ registeredPackageRepositories.FakeActiveRepository.FakePackages.AddRange (packages);
+ var recentPackage = new FakePackage ("A", "1.0.0.0");
+ recentPackageRepository.AddPackage (recentPackage);
+
+ viewModel.ReadPackages ();
+ CompleteReadPackagesTask ();
+
+ var expectedPackages = new [] {
+ recentPackage, package2
+ };
+ PackageCollectionAssert.AreEqual (expectedPackages, viewModel.PackageViewModels);
+ }
+
+ [Test]
+ public void ReadPackages_TwoRecentPackageAndSearchTextEntered_RecentPackagesAreFilteredBySearch ()
+ {
+ CreateViewModel ();
+ AddOnePackageSourceToRegisteredSources ();
+ var package1 = new FakePackage ("A", "1.0.0.0");
+ var package2 = new FakePackage ("B", "0.3.0.0");
+ var packages = new [] {
+ package1, package2
+ };
+ registeredPackageRepositories.FakeActiveRepository.FakePackages.AddRange (packages);
+ var recentPackage = new FakePackage ("Aa", "1.0.0.0");
+ recentPackageRepository.AddPackage (recentPackage);
+ recentPackageRepository.AddPackage (new FakePackage ("Bb", "1.0.0.0"));
+ viewModel.SearchTerms = "a";
+
+ viewModel.ReadPackages ();
+ CompleteReadPackagesTask ();
+
+ var expectedPackages = new [] {
+ recentPackage, package1
+ };
+ PackageCollectionAssert.AreEqual (expectedPackages, viewModel.PackageViewModels);
+ }
+
+ [Test]
+ public void ReadPackages_SolutionHasOnePackageInstalled_SolutionPackageDisplayedBeforeActivePackageSourcePackages ()
+ {
+ CreateViewModel ();
+ AddOnePackageSourceToRegisteredSources ();
+ var package1 = new FakePackage ("A", "1.0.0.0");
+ var package2 = new FakePackage ("B", "0.3.0.0");
+ var packages = new [] {
+ package1, package2
+ };
+ registeredPackageRepositories.FakeActiveRepository.FakePackages.AddRange (packages);
+ FakePackage installedPackage = AddPackageToSolution ("ZZ", "1.0.0.0");
+
+ viewModel.ReadPackages ();
+ CompleteReadPackagesTask ();
+
+ var expectedPackages = new [] {
+ installedPackage, package1, package2
+ };
+ PackageCollectionAssert.AreEqual (expectedPackages, viewModel.PackageViewModels);
+ }
+
+ [Test]
+ public void ReadPackages_SolutionHasOnePackageInstalledAndSecondPageOfPackagesIsReadWhenInfiniteScrollIsEnabled_SolutionPackageIsNotAddedTwice ()
+ {
+ CreateViewModel ();
+ AddOnePackageSourceToRegisteredSources ();
+ var package1 = new FakePackage ("A", "1.0.0.0");
+ var package2 = new FakePackage ("B", "0.3.0.0");
+ var package3 = new FakePackage ("C", "0.1.0.0");
+ var package4 = new FakePackage ("D", "0.1.0.0");
+ var packages = new [] {
+ package1, package2, package3, package4
+ };
+ registeredPackageRepositories.FakeActiveRepository.FakePackages.AddRange (packages);
+ FakePackage installedPackage = AddPackageToSolution ("ZZ", "1.0.0.0");
+ viewModel.PageSize = 2;
+ viewModel.ClearPackagesOnPaging = false;
+ viewModel.ReadPackages ();
+ CompleteReadPackagesTask ();
+ viewModel.ShowNextPage ();
+ CompleteReadPackagesTask ();
+
+ var expectedPackages = new [] {
+ installedPackage, package1, package2, package3, package4
+ };
+ PackageCollectionAssert.AreEqual (expectedPackages, viewModel.PackageViewModels);
+ }
+
+ [Test]
+ public void ReadPackages_OneSolutionPackageMatchesPackageFromActiveSource_DuplicatePackageWithSameVersionFromActiveSourceIsNotDisplayed ()
+ {
+ CreateViewModel ();
+ AddOnePackageSourceToRegisteredSources ();
+ var package1 = new FakePackage ("A", "1.0.0.0");
+ var package2 = new FakePackage ("B", "0.3.0.0");
+ var packages = new [] {
+ package1, package2
+ };
+ registeredPackageRepositories.FakeActiveRepository.FakePackages.AddRange (packages);
+ FakePackage installedPackage = AddPackageToSolution ("A", "1.0.0.0");
+
+ viewModel.ReadPackages ();
+ CompleteReadPackagesTask ();
+
+ var expectedPackages = new [] {
+ installedPackage, package2
+ };
+ PackageCollectionAssert.AreEqual (expectedPackages, viewModel.PackageViewModels);
+ }
+
+ [Test]
+ public void ReadPackages_OneSolutionPackageMatchesRecentPackage_DuplicateSolutionPackageWithSameVersionIsNotDisplayed ()
+ {
+ CreateViewModel ();
+ AddOnePackageSourceToRegisteredSources ();
+ var package1 = new FakePackage ("A", "1.0.0.0");
+ var package2 = new FakePackage ("B", "0.3.0.0");
+ var packages = new [] {
+ package1, package2
+ };
+ var recentPackage = new FakePackage ("A", "1.0.0.0");
+ recentPackageRepository.AddPackage (recentPackage);
+ registeredPackageRepositories.FakeActiveRepository.FakePackages.AddRange (packages);
+ FakePackage installedPackage = AddPackageToSolution ("A", "1.0.0.0");
+
+ viewModel.ReadPackages ();
+ CompleteReadPackagesTask ();
+
+ var expectedPackages = new [] {
+ recentPackage, package2
+ };
+ PackageCollectionAssert.AreEqual (expectedPackages, viewModel.PackageViewModels);
+ }
+
+ [Test]
+ public void ReadPackages_SearchForAllPackageVersionsWhenOneSolutionPackageAvailable_SolutionPackageIsNotDisplayed ()
+ {
+ CreateViewModel ();
+ AddOnePackageSourceToRegisteredSources ();
+ var package1 = new FakePackage ("A", "0.1.0.0") { IsLatestVersion = false };
+ var package2 = new FakePackage ("A", "0.2.0.0");
+ FakePackage installedPackage = AddPackageToSolution ("A", "1.0.0.0");
+ var packages = new [] { package1, package2 };
+ registeredPackageRepositories.FakeActiveRepository.FakePackages.AddRange (packages);
+ SearchForAllPackageVersions ("A");
+
+ viewModel.ReadPackages ();
+ CompleteReadPackagesTask ();
+
+ var expectedPackages = new FakePackage[] {
+ package2, package1
+ };
+ PackageCollectionAssert.AreEqual (expectedPackages, viewModel.PackageViewModels);
+ }
+
+ [Test]
+ public void ReadPackages_TwoSolutionPackagesAndSearchTextEntered_SolutionPackagesAreFilteredBySearch ()
+ {
+ CreateViewModel ();
+ AddOnePackageSourceToRegisteredSources ();
+ var package1 = new FakePackage ("A", "1.0.0.0");
+ var package2 = new FakePackage ("B", "0.3.0.0");
+ var packages = new [] {
+ package1, package2
+ };
+ registeredPackageRepositories.FakeActiveRepository.FakePackages.AddRange (packages);
+ FakePackage installedPackage = AddPackageToSolution ("Aa", "1.0.0.0");
+ AddPackageToSolution ("Bb", "1.0.0.0");
+ viewModel.SearchTerms = "a";
+
+ viewModel.ReadPackages ();
+ CompleteReadPackagesTask ();
+
+ var expectedPackages = new [] {
+ installedPackage, package1
+ };
+ PackageCollectionAssert.AreEqual (expectedPackages, viewModel.PackageViewModels);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/InstallPackageActionTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/InstallPackageActionTests.cs index da59bdb7c8..758341f3a6 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/InstallPackageActionTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/InstallPackageActionTests.cs @@ -438,7 +438,6 @@ namespace MonoDevelop.PackageManagement.Tests CreateAction ();
FakePackage expectedPackage = fakeProject.FakeSourceRepository.AddFakePackageWithVersion ("Test", "1.0");
expectedPackage.RequireLicenseAcceptance = true;
- var expectedPackages = new IPackage [] { expectedPackage };
var operation = new FakePackageOperation (expectedPackage, PackageAction.Install);
action.PackageId = expectedPackage.Id;
action.PackageVersion = expectedPackage.Version;
@@ -460,7 +459,6 @@ namespace MonoDevelop.PackageManagement.Tests CreateAction ();
FakePackage expectedPackage = fakeProject.FakeSourceRepository.AddFakePackageWithVersion ("Test", "1.0");
expectedPackage.RequireLicenseAcceptance = true;
- var expectedPackages = new IPackage [] { expectedPackage };
var operation = new FakePackageOperation (expectedPackage, PackageAction.Install);
action.PackageId = expectedPackage.Id;
action.PackageVersion = expectedPackage.Version;
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MonoDevelopAggregateRepositoryTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MonoDevelopAggregateRepositoryTests.cs new file mode 100644 index 0000000000..b972f4a812 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MonoDevelopAggregateRepositoryTests.cs @@ -0,0 +1,194 @@ +//
+// AggregateRepositoryTests.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using NUnit.Framework;
+using NuGet;
+using System.Collections.Generic;
+using MonoDevelop.PackageManagement.Tests.Helpers;
+using System.Linq;
+
+namespace MonoDevelop.PackageManagement.Tests
+{
+ [TestFixture]
+ public class MonoDevelopAggregateRepositoryTests
+ {
+ MonoDevelopAggregateRepository aggregateRepository;
+ List<IPackageRepository> repositories;
+
+ [SetUp]
+ public void Init ()
+ {
+ repositories = new List<IPackageRepository> ();
+ }
+
+ FakePackageRepository AddRepository ()
+ {
+ var repository = new FakePackageRepository ();
+ repositories.Add (repository);
+ return repository;
+ }
+
+ FakePackage AddRepositoryWithOnePackage (string packageId)
+ {
+ FakePackageRepository repository = AddRepository ();
+ return repository.AddFakePackage (packageId);
+ }
+
+ void CreateAggregateRepository ()
+ {
+ aggregateRepository = new MonoDevelopAggregateRepository (repositories);
+ aggregateRepository.IgnoreFailingRepositories = true;
+ }
+
+ ExceptionThrowingPackageRepository AddFailingPackageRepository ()
+ {
+ return AddFailingPackageRepository (new Exception ("Error"));
+ }
+
+ ExceptionThrowingPackageRepository AddFailingPackageRepository (Exception exception)
+ {
+ var repository = new ExceptionThrowingPackageRepository {
+ GetPackagesException = exception
+ };
+ repositories.Add (repository);
+ return repository;
+ }
+
+ List<IPackage> Search ()
+ {
+ return aggregateRepository.Search (null, false).ToList ();
+ }
+
+ [Test]
+ public void Search_IgnoreFailingRepositoriesAndOnePackageSourceFails_ErrorFromFailingRepositoryIsSupressed ()
+ {
+ FakePackage package1 = AddRepositoryWithOnePackage ("Package1");
+ FakePackage package2 = AddRepositoryWithOnePackage ("Package2");
+ AddFailingPackageRepository ();
+ CreateAggregateRepository ();
+ aggregateRepository.IgnoreFailingRepositories = true;
+
+ List<IPackage> packages = Search ();
+
+ Assert.AreEqual (2, packages.Count);
+ Assert.That (packages, Contains.Item (package1));
+ Assert.That (packages, Contains.Item (package2));
+ }
+
+ [Test]
+ public void Search_TwoPackageRepositoriesOneFailingWhenGetPackagesCalled_AnyFailuresReturnsTrueAndAllFailedReturnsFalse ()
+ {
+ AddRepository ();
+ AddFailingPackageRepository ();
+ CreateAggregateRepository ();
+ Search ();
+
+ bool failures = aggregateRepository.AnyFailures ();
+ bool allFailed = aggregateRepository.AllFailed ();
+
+ Assert.IsTrue (failures);
+ Assert.IsFalse (allFailed);
+ }
+
+ [Test]
+ public void Search_TwoPackageRepositoriesBothFailingWhenGetPackagesCalled_AllFailedReturnsTrue ()
+ {
+ AddFailingPackageRepository ();
+ AddFailingPackageRepository ();
+ CreateAggregateRepository ();
+ Search ();
+
+ bool failures = aggregateRepository.AnyFailures ();
+ bool allFailed = aggregateRepository.AllFailed ();
+
+ Assert.IsTrue (failures);
+ Assert.IsTrue (allFailed);
+ }
+
+ [Test]
+ public void Search_TwoPackageRepositoriesNoneFailingWhenGetPackagesCalled_AnyFailuresAndAllFailedReturnFalse ()
+ {
+ AddRepository ();
+ AddRepository ();
+ CreateAggregateRepository ();
+ Search ();
+
+ bool failures = aggregateRepository.AnyFailures ();
+ bool allFailed = aggregateRepository.AllFailed ();
+
+ Assert.IsFalse (failures);
+ Assert.IsFalse (allFailed);
+ }
+
+ [Test]
+ public void Search_TwoPackageRepositoriesOneFailingWhenGetPackagesCalled_GetAggregateExceptionIncludesRepositoryException ()
+ {
+ AddRepository ();
+ var exception = new Exception ("Error");
+ AddFailingPackageRepository (exception);
+ CreateAggregateRepository ();
+ Search ();
+
+ AggregateException aggregateException = aggregateRepository.GetAggregateException ();
+
+ Assert.That (aggregateException.InnerExceptions, Contains.Item (exception));
+ }
+
+ [Test]
+ public void Search_TwoPackageRepositoriesBothFailingWhenGetPackagesCalled_GetAggregateExceptionIncludesBothRepositoryExceptions ()
+ {
+ var exception1 = new Exception ("Error1");
+ AddFailingPackageRepository (exception1);
+ var exception2 = new Exception ("Error2");
+ AddFailingPackageRepository (exception2);
+ CreateAggregateRepository ();
+ Search ();
+
+ AggregateException aggregateException = aggregateRepository.GetAggregateException ();
+
+ Assert.That (aggregateException.InnerExceptions, Contains.Item (exception1));
+ Assert.That (aggregateException.InnerExceptions, Contains.Item (exception2));
+ }
+
+ [Test]
+ public void Search_TwoPackageRepositoriesBothFailingWhenGetPackagesCalledFirstThenSecondTimeNewRepositoryAddedToRepositories_AllFailedReturnsFalseSecondTime ()
+ {
+ AddFailingPackageRepository ();
+ AddFailingPackageRepository ();
+ CreateAggregateRepository ();
+ Search ();
+ AddRepository ();
+
+ bool failures = aggregateRepository.AnyFailures ();
+ bool allFailed = aggregateRepository.AllFailed ();
+
+ Assert.IsTrue (failures);
+ Assert.IsFalse (allFailed);
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/NuGetPackageRestoreCommandLineTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/NuGetPackageRestoreCommandLineTests.cs deleted file mode 100644 index 47154fcf57..0000000000 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/NuGetPackageRestoreCommandLineTests.cs +++ /dev/null @@ -1,86 +0,0 @@ -//
-// NuGetPackageRestoreCommandLineTests.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-using ICSharpCode.PackageManagement;
-using NUnit.Framework;
-using MonoDevelop.Core.Assemblies;
-using MonoDevelop.PackageManagement.Tests.Helpers;
-using System.IO;
-
-namespace MonoDevelop.PackageManagement.Tests
-{
- [TestFixture]
- public class NuGetPackageRestoreCommandLineTests
- {
- NuGetPackageRestoreCommandLine commandLine;
-
- void CreateCommandLineWithSolution (string fileName)
- {
- CreateCommandLineWithSolution (fileName, null, false);
- }
-
- void CreateCommandLineWithSolution (string fileName, MonoRuntimeInfo monoRuntimeInfo)
- {
- CreateCommandLineWithSolution (fileName, monoRuntimeInfo, true);
- }
-
- void CreateCommandLineWithSolution (string fileName, MonoRuntimeInfo monoRuntimeInfo, bool isMonoRuntime)
- {
- var solution = new FakePackageManagementSolution ();
- solution.FileName = fileName;
- commandLine = new NuGetPackageRestoreCommandLine (
- solution,
- monoRuntimeInfo,
- isMonoRuntime);
- }
-
- [Test]
- public void Arguments_RestoreSolution_SolutionFullFileNameUsed ()
- {
- CreateCommandLineWithSolution (@"d:\projects\MySolution\MySolution.sln");
-
- string arguments = commandLine.Arguments;
-
- string expectedArguments = "restore -NonInteractive \"d:\\projects\\MySolution\\MySolution.sln\"";
- Assert.AreEqual (expectedArguments, arguments);
- }
-
- [Test]
- public void CommandLine_RestoreSolutionOnMono_MonoUsedFromCurrentPrefix ()
- {
- var monoRuntime = new MonoRuntimeInfo (@"c:\Users\Prefix");
- CreateCommandLineWithSolution (@"d:\projects\MySolution\MySolution.sln", monoRuntime);
-
- string arguments = commandLine.Arguments;
-
- string expectedCommandLine = Path.Combine (@"c:\Users\Prefix", "bin", "mono");
- Assert.IsTrue (arguments.StartsWith ("--runtime=v4.0 "), arguments);
- Assert.IsTrue (arguments.EndsWith ("restore -NonInteractive \"d:\\projects\\MySolution\\MySolution.sln\""), arguments);
- Assert.AreEqual (expectedCommandLine, commandLine.Command);
- }
- }
-}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageManagementProjectTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageManagementProjectTests.cs index cf3356d5b5..bad7bed11b 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageManagementProjectTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageManagementProjectTests.cs @@ -818,6 +818,28 @@ namespace MonoDevelop.PackageManagement.Tests Assert.IsTrue (result);
}
+
+ [Test]
+ public void ConstraintProvider_LocalRepositoryDoesNotImplementIConstraintProvider_ReturnsNullConstraintProviderInstance ()
+ {
+ CreateProject ();
+
+ IPackageConstraintProvider provider = project.ConstraintProvider;
+
+ Assert.AreEqual (NullConstraintProvider.Instance, provider);
+ }
+
+ [Test]
+ public void ConstraintProvider_LocalRepositoryImplementsIConstraintProvider_ReturnsLocalRepository ()
+ {
+ CreateProject ();
+ var localRepository = new FakePackageRepositoryWithConstraintProvider ();
+ fakeProjectManager.FakeLocalRepository = localRepository;
+
+ IPackageConstraintProvider provider = project.ConstraintProvider;
+
+ Assert.AreEqual (localRepository, provider);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageManagementSolutionTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageManagementSolutionTests.cs index 5a640acf0e..d7d5b380ca 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageManagementSolutionTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageManagementSolutionTests.cs @@ -699,6 +699,20 @@ namespace MonoDevelop.PackageManagement.Tests var expectedPackages = new FakePackage [0];
Assert.AreEqual (expectedPackages, packages);
}
+
+ [Test]
+ public void GetRepository_OpenSolution_ReturnsRepositoryForSolution ()
+ {
+ CreateSolution ();
+ var fakeSolution = new FakeSolution (@"d:\projects\MyProject\MySolution.sln");
+ fakeProjectService.OpenSolution = fakeSolution;
+
+ ISolutionPackageRepository repository = solution.GetRepository ();
+
+ Assert.IsNotNull (repository);
+ Assert.AreEqual (fakeSolutionPackageRepositoryFactory.SolutionPassedToCreateSolutionPackageRepository, fakeSolution);
+ Assert.AreEqual (fakeSolutionPackageRepositoryFactory.FakeSolutionPackageRepository, repository);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageReferenceNodeTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageReferenceNodeTests.cs index 34e246d9c5..3f7609c3d1 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageReferenceNodeTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageReferenceNodeTests.cs @@ -30,6 +30,7 @@ using NUnit.Framework; using NuGet;
using MonoDevelop.Core;
using MonoDevelop.Ide.Gui;
+using MonoDevelop.Ide.Tasks;
namespace MonoDevelop.PackageManagement.Tests
{
@@ -85,25 +86,36 @@ namespace MonoDevelop.PackageManagement.Tests }
[Test]
- public void GetLabel_PackageReferenceIsNotInstalled_ReturnsPackageIdInsideErrorColouredSpan ()
+ public void GetLabel_PackageReferenceIsNotInstalled_ReturnsPackageId ()
{
CreatePackageReference (packageId: "MyPackage");
CreatePackageReferenceNode (installed: false);
string label = node.GetLabel ();
- Assert.AreEqual ("<span color='#c99c00'>MyPackage</span>", label);
+ Assert.AreEqual ("MyPackage", label);
}
[Test]
- public void GetLabel_PackageReferenceNeedsReinstallation_ReturnsPackageIdInsideErrorColouredSpan ()
+ public void GetLabel_PackageReferenceNeedsReinstallation_ReturnsPackageId ()
{
CreatePackageReference (packageId: "MyPackage", requireReinstallation: true);
CreatePackageReferenceNode (installed: true);
string label = node.GetLabel ();
- Assert.AreEqual ("<span color='#c99c00'>MyPackage</span>", label);
+ Assert.AreEqual ("MyPackage", label);
+ }
+
+ [Test]
+ public void GetLabel_PackageReferenceIsPendingInstall_ReturnsPackageIdFollowedByInstallingText ()
+ {
+ CreatePackageReference (packageId: "MyPackage");
+ CreatePackageReferenceNode (installed: false, installPending: true);
+
+ string label = node.GetLabel ();
+
+ Assert.AreEqual ("MyPackage (installing)", label);
}
[Test]
@@ -118,14 +130,14 @@ namespace MonoDevelop.PackageManagement.Tests }
[Test]
- public void GetIconId_PackageReferenceNeedsReinstallation_ReturnsReferenceWarningIcon ()
+ public void GetIconId_PackageReferenceNeedsReinstallation_ReturnsReferenceIcon ()
{
CreatePackageReference (requireReinstallation: true);
CreatePackageReferenceNode ();
IconId icon = node.GetIconId ();
- Assert.AreEqual (Stock.ReferenceWarning, icon);
+ Assert.AreEqual (Stock.Reference, icon);
}
[Test]
@@ -140,7 +152,7 @@ namespace MonoDevelop.PackageManagement.Tests }
[Test]
- public void GetLabel_PackageReferenceNeedsReinstallationButHasUpdate_ReturnsPackageIdInsideErrorColouredSpanAndUpdatedPackageVersionInGreySpan ()
+ public void GetLabel_PackageReferenceNeedsReinstallationButHasUpdate_ReturnsPackageIdInBlackTextAndUpdatedPackageVersionInGreySpan ()
{
CreatePackageReference (
packageId: "MyPackage",
@@ -151,7 +163,128 @@ namespace MonoDevelop.PackageManagement.Tests string label = node.GetLabel ();
- Assert.AreEqual ("<span color='#c99c00'>MyPackage</span> <span color='grey'>(1.2.3.4 available)</span>", label);
+ Assert.AreEqual ("MyPackage <span color='grey'>(1.2.3.4 available)</span>", label);
+ }
+
+ [Test]
+ public void IsDisabled_PackageReferenceHasInstallPending_ReturnsTrue ()
+ {
+ CreatePackageReference ();
+ CreatePackageReferenceNode (installed: false, installPending: true);
+
+ bool result = node.IsDisabled ();
+
+ Assert.IsTrue (result);
+ }
+
+ [Test]
+ public void IsDisabled_PackageReferenceIsInstalled_ReturnsFalse ()
+ {
+ CreatePackageReference ();
+ CreatePackageReferenceNode ();
+
+ bool result = node.IsDisabled ();
+
+ Assert.IsFalse (result);
+ }
+
+ [Test]
+ public void IsDisabled_PackageReferenceIsNotInstalled_ReturnsTrue ()
+ {
+ CreatePackageReference (packageId: "MyPackage");
+ CreatePackageReferenceNode (installed: false);
+
+ bool result = node.IsDisabled ();
+
+ Assert.IsTrue (result);
+ }
+
+ [Test]
+ public void GetStatusSeverity_PackageReferenceIsInstalled_ReturnsNull ()
+ {
+ CreatePackageReference ();
+ CreatePackageReferenceNode ();
+
+ TaskSeverity? status = node.GetStatusSeverity ();
+
+ Assert.IsNull (status);
+ }
+
+ [Test]
+ public void GetStatusSeverity_PackageReferenceIsNotInstalled_ReturnsWarning ()
+ {
+ CreatePackageReference (packageId: "MyPackage");
+ CreatePackageReferenceNode (installed: false);
+
+ TaskSeverity? status = node.GetStatusSeverity ();
+
+ Assert.AreEqual (TaskSeverity.Warning, status);
+ }
+
+ [Test]
+ public void GetStatusSeverity_PackageReferenceNeedsReinstallation_ReturnsWarning ()
+ {
+ CreatePackageReference (requireReinstallation: true);
+ CreatePackageReferenceNode ();
+
+ TaskSeverity? status = node.GetStatusSeverity ();
+
+ Assert.AreEqual (TaskSeverity.Warning, status);
+ }
+
+ [Test]
+ public void GetStatusSeverity_PackageReferenceHasInstallPending_ReturnsNull ()
+ {
+ CreatePackageReference ();
+ CreatePackageReferenceNode (installed: false, installPending: true);
+
+ TaskSeverity? status = node.GetStatusSeverity ();
+
+ Assert.IsNull (status);
+ }
+
+ [Test]
+ public void GetStatusMessage_PackageReferenceIsInstalled_ReturnsNull ()
+ {
+ CreatePackageReference ();
+ CreatePackageReferenceNode ();
+
+ string message = node.GetStatusMessage ();
+
+ Assert.IsNull (message);
+ }
+
+ [Test]
+ public void GetStatusMessage_PackageReferenceIsNotInstalled_ReturnsPackageNotRestoredMessage ()
+ {
+ CreatePackageReference (packageId: "MyPackage");
+ CreatePackageReferenceNode (installed: false);
+
+ string message = node.GetStatusMessage ();
+
+ Assert.AreEqual ("Package is not restored", message);
+ }
+
+ [Test]
+ public void GetStatusMessage_PackageReferenceNeedsReinstallation_ReturnsPackageNeedsRetargetingMessage ()
+ {
+ CreatePackageReference (requireReinstallation: true);
+ CreatePackageReferenceNode ();
+
+ string message = node.GetStatusMessage ();
+
+ Assert.AreEqual ("Package needs retargeting", message);
+ }
+
+ [Test]
+ public void GetStatusMessage_PackageReferenceHasInstallPending_ReturnsNull ()
+ {
+ CreatePackageReference ();
+ CreatePackageReferenceNode (installed: false, installPending: true);
+
+ string message = node.GetStatusMessage ();
+
+ Assert.IsNull (message);
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageRepositoryCacheTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageRepositoryCacheTests.cs index 8520911df4..6c02e947bc 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageRepositoryCacheTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageRepositoryCacheTests.cs @@ -43,6 +43,7 @@ namespace MonoDevelop.PackageManagement.Tests OneRegisteredPackageSourceHelper packageSourcesHelper;
RecentPackageInfo[] recentPackagesPassedToCreateRecentPackageRepository;
FakePackageRepository fakeAggregateRepositoryPassedToCreateRecentPackageRepository;
+ FakePackageRepository machineCache;
void CreateCache ()
{
@@ -57,9 +58,15 @@ namespace MonoDevelop.PackageManagement.Tests void CreateCacheUsingPackageSources ()
{
- nuGetPackageSource = new PackageSource ("http://nuget.org", "NuGet");
fakePackageRepositoryFactory = new FakePackageRepositoryFactory ();
- cache = new PackageRepositoryCache (packageSourcesHelper.Options, fakePackageRepositoryFactory);
+ CreateCacheUsingPackageSources (fakePackageRepositoryFactory);
+ }
+
+ void CreateCacheUsingPackageSources (ISharpDevelopPackageRepositoryFactory repositoryFactory)
+ {
+ nuGetPackageSource = new PackageSource ("http://nuget.org", "NuGet");
+ machineCache = new FakePackageRepository ();
+ cache = new PackageRepositoryCache (packageSourcesHelper.Options, machineCache, repositoryFactory);
}
FakePackageRepository AddFakePackageRepositoryForPackageSource (string source)
@@ -409,6 +416,70 @@ namespace MonoDevelop.PackageManagement.Tests CollectionAssert.AreEqual (expectedInitialRepositories, actualInitialRepositories);
CollectionAssert.AreEqual (expectedRepositories, actualRepositories);
}
+
+ [Test]
+ public void CreateAggregatePriorityRepository_NoAggregatePackageSources_ReturnsPriorityPackageRepositoryThatUsesMachineCache ()
+ {
+ CreateCache ();
+ machineCache.AddFakePackageWithVersion ("MyPackage", "1.0");
+
+ IPackageRepository repository = cache.CreateAggregateWithPriorityMachineCacheRepository ();
+ bool exists = repository.Exists ("MyPackage", new SemanticVersion ("1.0"));
+
+ Assert.IsInstanceOf<PriorityPackageRepository> (repository);
+ Assert.IsTrue (exists);
+ }
+
+ [Test]
+ public void CreateAggregatePriorityRepository_NoAggregatePackageSources_ReturnsPriorityPackageRepositoryThatUsesAggregateRepository ()
+ {
+ CreatePackageSources ();
+ packageSourcesHelper.AddTwoPackageSources ("Source1", "Source2");
+ CreateCacheUsingPackageSources ();
+ fakePackageRepositoryFactory.FakeAggregateRepository.AddFakePackageWithVersion ("MyPackage", "1.0");
+
+ IPackageRepository repository = cache.CreateAggregateWithPriorityMachineCacheRepository ();
+ bool exists = repository.Exists ("MyPackage", new SemanticVersion ("1.0"));
+
+ Assert.IsTrue (exists);
+ }
+
+ [Test]
+ public void CreateAggregateRepository_OnePackageSourceHasInvalidUri_NoExceptionThrownWhenCreatingAggregateRepositoryAndSearchingForPackages ()
+ {
+ CreatePackageSources ();
+ packageSourcesHelper.RegisteredPackageSources.Clear ();
+ var invalidPackageSource = new PackageSource (String.Empty, "InvalidSource");
+ packageSourcesHelper.RegisteredPackageSources.Add (invalidPackageSource);
+ var factory = new SharpDevelopPackageRepositoryFactory ();
+ CreateCacheUsingPackageSources (factory);
+ IPackageRepository repository = cache.CreateAggregateRepository ();
+ var aggregateRepository = (MonoDevelopAggregateRepository)repository;
+
+ Assert.IsFalse (aggregateRepository.AnyFailures ());
+ Assert.DoesNotThrow (() => repository.Search ("abc", false));
+ Assert.IsTrue (aggregateRepository.AnyFailures ());
+ }
+
+ [Test]
+ public void CreateAggregateRepository_OnePackageSourceHasInvalidUriAndSearchExecutedMultipleTimes_ExceptionThrownByPackageRepositoryIsOnlyRecordedOnce ()
+ {
+ CreatePackageSources ();
+ packageSourcesHelper.RegisteredPackageSources.Clear ();
+ var invalidPackageSource = new PackageSource (String.Empty, "InvalidSource");
+ packageSourcesHelper.RegisteredPackageSources.Add (invalidPackageSource);
+ var factory = new SharpDevelopPackageRepositoryFactory ();
+ CreateCacheUsingPackageSources (factory);
+ IPackageRepository repository = cache.CreateAggregateRepository ();
+ var aggregateRepository = (MonoDevelopAggregateRepository)repository;
+
+ repository.Search ("abc", false);
+ repository.Search ("abc", false);
+ repository.Search ("abc", false);
+
+ Assert.IsTrue (aggregateRepository.AnyFailures ());
+ Assert.AreEqual (1, aggregateRepository.GetAggregateException ().InnerExceptions.Count);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageViewModelTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageViewModelTests.cs index 9b0fffb681..b406395815 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageViewModelTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageViewModelTests.cs @@ -60,7 +60,7 @@ namespace MonoDevelop.PackageManagement.Tests void CreateViewModel (FakePackageManagementSolution solution)
{
- viewModelParent = CreateViewModelParent ();
+ viewModelParent = CreateViewModelParent (solution);
viewModel = new TestablePackageViewModel (viewModelParent, solution);
fakePackage = viewModel.FakePackage;
this.fakeSolution = solution;
@@ -69,7 +69,7 @@ namespace MonoDevelop.PackageManagement.Tests fakeUninstallPackageAction = solution.FakeProjectToReturnFromGetProject.FakeUninstallPackageAction;
}
- AvailablePackagesViewModel CreateViewModelParent ()
+ AvailablePackagesViewModel CreateViewModelParent (FakePackageManagementSolution solution)
{
var taskFactory = new FakeTaskFactory ();
var registeredPackageRepositories = new FakeRegisteredPackageRepositories ();
@@ -77,6 +77,7 @@ namespace MonoDevelop.PackageManagement.Tests var recentPackageRepository = new FakeRecentPackageRepository ();
return new AvailablePackagesViewModel (
+ solution,
registeredPackageRepositories,
recentPackageRepository,
packageViewModelFactory,
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackagesViewModelTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackagesViewModelTests.cs index 57c1db3c49..1dd3518bb4 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackagesViewModelTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackagesViewModelTests.cs @@ -941,7 +941,7 @@ namespace MonoDevelop.PackageManagement.Tests viewModel.ReadPackages ();
- PackagesForSelectedPageResult result = taskFactory.FirstFakeTaskCreated.ExecuteTaskButNotContinueWith ();
+ taskFactory.FirstFakeTaskCreated.ExecuteTaskButNotContinueWith ();
Assert.IsFalse (viewModel.IsPaged);
}
@@ -1420,7 +1420,7 @@ namespace MonoDevelop.PackageManagement.Tests public void CheckedPackageViewModels_OnePackageIsCheckedAndThenUnchecked_ReturnsNoCheckedPackages ()
{
CreateViewModel ();
- FakePackage package = viewModel.AddFakePackage ("MyPackage");
+ viewModel.AddFakePackage ("MyPackage");
viewModel.AddFakePackage ("Z-Package");
viewModel.ReadPackages ();
CompleteReadPackagesTask ();
@@ -1537,5 +1537,24 @@ namespace MonoDevelop.PackageManagement.Tests PackageCollectionAssert.AreEqual (expectedPackages, viewModel.CheckedPackageViewModels);
Assert.IsFalse (oldPackageVersionViewModel.IsChecked);
}
+
+ [Test]
+ public void ReadPackages_ReadPackagesCalledAgainAfterFirstOneFailed_ErrorIsCleared ()
+ {
+ CreateViewModel ();
+ viewModel.ReadPackages ();
+ var ex = new Exception ("Test");
+ var aggregateEx = new AggregateException (ex);
+ taskFactory.FirstFakeTaskCreated.Exception = aggregateEx;
+ taskFactory.FirstFakeTaskCreated.IsFaulted = true;
+ CompleteReadPackagesTask ();
+ bool hasErrorAfterFirstRead = viewModel.HasError;
+
+ viewModel.ReadPackages ();
+
+ Assert.IsTrue (hasErrorAfterFirstRead);
+ Assert.IsFalse (viewModel.HasError);
+ Assert.AreEqual (String.Empty, viewModel.ErrorMessage);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ProjectPackagesFolderNodeTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ProjectPackagesFolderNodeTests.cs index d040d29175..844fe26dc4 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ProjectPackagesFolderNodeTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ProjectPackagesFolderNodeTests.cs @@ -169,7 +169,7 @@ namespace MonoDevelop.PackageManagement.Tests PackageReferenceNode referenceNode = nodes.FirstOrDefault ();
Assert.AreEqual (1, nodes.Count);
Assert.IsFalse (referenceNode.Installed);
- Assert.AreEqual ("<span color='#c99c00'>MyPackage</span>", referenceNode.GetLabel ());
+ Assert.AreEqual ("MyPackage", referenceNode.GetLabel ());
}
[Test]
@@ -192,7 +192,7 @@ namespace MonoDevelop.PackageManagement.Tests public void GetPackageReferencesNodes_OnePackageReferenceWithUpdatedPackagesButPackageNotRestored_ReturnsOneNodeWithUpdatedVersionInformationInLabel ()
{
CreateNode ();
- PackageReference packageReference = AddPackageReferenceToProject ("MyPackage", "1.0");
+ AddPackageReferenceToProject ("MyPackage", "1.0");
AddUpdatedPackageForProject ("MyPackage", "1.2");
List<PackageReferenceNode> nodes = packagesFolderNode.GetPackageReferencesNodes ().ToList ();
@@ -200,8 +200,9 @@ namespace MonoDevelop.PackageManagement.Tests PackageReferenceNode referenceNode = nodes.FirstOrDefault ();
Assert.AreEqual (1, nodes.Count);
Assert.AreEqual ("1.2", referenceNode.UpdatedVersion.ToString ());
- Assert.AreEqual ("<span color='#c99c00'>MyPackage</span> <span color='grey'>(1.2 available)</span>", referenceNode.GetLabel ());
- Assert.AreEqual (Stock.ReferenceWarning, referenceNode.GetIconId ());
+ Assert.AreEqual ("MyPackage <span color='grey'>(1.2 available)</span>", referenceNode.GetLabel ());
+ Assert.AreEqual (Stock.Reference, referenceNode.GetIconId ());
+ Assert.IsTrue (referenceNode.IsDisabled ());
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentPackageRepositoryTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentPackageRepositoryTests.cs index 52f8577756..ab9d358517 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentPackageRepositoryTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentPackageRepositoryTests.cs @@ -212,5 +212,20 @@ namespace MonoDevelop.PackageManagement.Tests Assert.IsTrue (hasRecentPackages);
}
+
+ [Test]
+ public void GetPackages_TwoRecentPackagesButOneIsInvalid_OnlyValidPackageIsReturned ()
+ {
+ CreateRepository ();
+ FakePackage package1 = AddOnePackageToRepository ("Test1");
+ FakePackage package2 = AddOnePackageToRepository ("Test2");
+ package2.IsValid = false;
+
+ var expectedPackages = new IPackage[] {
+ package1
+ };
+
+ PackageCollectionAssert.AreEqual (expectedPackages, repository.GetPackages ());
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RegisteredPackageRepositoriesTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RegisteredPackageRepositoriesTests.cs index 1986c835e6..9cf27599b3 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RegisteredPackageRepositoriesTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RegisteredPackageRepositoriesTests.cs @@ -25,6 +25,7 @@ // THE SOFTWARE.
using System;
+using System.Linq;
using ICSharpCode.PackageManagement;
using MonoDevelop.PackageManagement.Tests.Helpers;
using NuGet;
@@ -56,6 +57,17 @@ namespace MonoDevelop.PackageManagement.Tests registeredRepositories = new RegisteredPackageRepositories (fakeRepositoryCache, packageSourcesHelper.Options);
}
+ void AddPackageSourcesToSettings (params string[] sources)
+ {
+ var packageSources = sources.Select (source => new PackageSource (source));
+ packageSourcesHelper.FakeSettings.AddFakePackageSources (packageSources);
+ }
+
+ void SetActivePackageSourceInSettings (PackageSource packageSource)
+ {
+ packageSourcesHelper.FakeSettings.SetFakeActivePackageSource (packageSource);
+ }
+
[Test]
public void RecentPackageRepository_PropertyAccessed_ReturnsRecentPackageRepositoryFromCache ()
{
@@ -309,6 +321,48 @@ namespace MonoDevelop.PackageManagement.Tests Assert.IsNull (activePackageSource);
}
+
+ [Test]
+ public void UpdatePackageSources_SolutionLoadedAggregatePackageSourceIsActiveThenAllSourcesDisabledApartFromOne_ActivePackageSourceIsNotAggregatePackageSource ()
+ {
+ CreateRegisteredPackageRepositories ();
+ packageSourcesHelper.AddTwoPackageSources ("One", "Two");
+ var expectedPackageSource = new PackageSource ("Two") { IsEnabled = true };
+ var updatedPackageSources = new PackageSource [] {
+ new PackageSource ("One") { IsEnabled = false },
+ expectedPackageSource
+ };
+ AddPackageSourcesToSettings ("One", "Two");
+ SetActivePackageSourceInSettings (RegisteredPackageSourceSettings.AggregatePackageSource);
+ packageSourcesHelper.Options.ProjectService.RaiseSolutionLoadedEvent ();
+ registeredRepositories.ActivePackageSource = RegisteredPackageSourceSettings.AggregatePackageSource;
+
+ registeredRepositories.UpdatePackageSources (updatedPackageSources);
+
+ Assert.AreEqual (expectedPackageSource, registeredRepositories.ActivePackageSource);
+ }
+
+ [Test]
+ public void UpdatePackageSources_PackageSourcesUpdatedInPreferencesWhenAggregatePackageSourceIsActive_ActiveRepositoryIsRecreated ()
+ {
+ CreateRegisteredPackageRepositories ();
+ packageSourcesHelper.AddTwoPackageSources ("One", "Two");
+ var updatedPackageSources = new PackageSource [] {
+ new PackageSource ("One"),
+ new PackageSource ("Two")
+ };
+ AddPackageSourcesToSettings ("One", "Two");
+ SetActivePackageSourceInSettings (RegisteredPackageSourceSettings.AggregatePackageSource);
+ registeredRepositories.ActivePackageSource = RegisteredPackageSourceSettings.AggregatePackageSource;
+ IPackageRepository firstAggregateRepository = registeredRepositories.ActiveRepository;
+ fakeRepositoryCache.FakeAggregateRepository = new FakePackageRepository ();
+
+ registeredRepositories.UpdatePackageSources (updatedPackageSources);
+ IPackageRepository secondAggregateRepository = registeredRepositories.ActiveRepository;
+
+ Assert.AreNotSame (firstAggregateRepository, secondAggregateRepository);
+ Assert.AreSame (secondAggregateRepository, fakeRepositoryCache.FakeAggregateRepository);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ReinstallPackageActionTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ReinstallPackageActionTests.cs index 959e514b3c..a29f34d06c 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ReinstallPackageActionTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ReinstallPackageActionTests.cs @@ -42,7 +42,7 @@ namespace MonoDevelop.PackageManagement.Tests void CreateAction (string packageId = "MyPackage", string packageVersion = "1.2.3.4")
{
project = new FakePackageManagementProject ();
- FakePackageOperation operation = project.AddFakeInstallOperation ();
+ project.AddFakeInstallOperation ();
packageManagementEvents = new PackageManagementEvents ();
@@ -84,7 +84,7 @@ namespace MonoDevelop.PackageManagement.Tests public void Execute_PackageExistsInSourceRepository_PackageIsForcefullyRemovedSoItDoesNotFailIfOtherPackagesDependOnIt ()
{
CreateAction ("MyPackage", "1.2.3.4");
- FakePackage package = AddPackageToSourceRepository ("MyPackage", "1.2.3.4");
+ AddPackageToSourceRepository ("MyPackage", "1.2.3.4");
action.Execute ();
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ReinstallProjectPackagesActionTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ReinstallProjectPackagesActionTests.cs index 2ec6b28ac3..61ff6616d5 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ReinstallProjectPackagesActionTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ReinstallProjectPackagesActionTests.cs @@ -152,9 +152,9 @@ namespace MonoDevelop.PackageManagement.Tests {
CreateAction ();
AddPackageToProject ("MyPackage", "1.0");
- FakePackage sourceRepositoryPackage = AddPackageToSourceRepository ("MyPackage", "1.0");
+ AddPackageToSourceRepository ("MyPackage", "1.0");
var expectedPackages = new FakePackage[] { FakePackage.CreatePackageWithVersion ("MyPackage", "1.0") };
- ReinstallPackageOperations operations = AddReinstallOperationsToProject (expectedPackages);
+ AddReinstallOperationsToProject (expectedPackages);
action.Execute ();
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RestorePackagesActionTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RestorePackagesActionTests.cs new file mode 100644 index 0000000000..f247203e80 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RestorePackagesActionTests.cs @@ -0,0 +1,322 @@ +//
+// RestorePackagesAction.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using ICSharpCode.PackageManagement;
+using MonoDevelop.PackageManagement.Tests.Helpers;
+using NUnit.Framework;
+using NuGet;
+
+namespace MonoDevelop.PackageManagement.Tests
+{
+ [TestFixture]
+ public class RestorePackagesActionTests
+ {
+ RestorePackagesAction action;
+ FakePackageManagementSolution solution;
+ FakePackageManagerFactory packageManagerFactory;
+ FakePackageRepositoryFactory packageRepositoryCache;
+ PackageManagementEvents packageEvents;
+ List<PackageOperationMessage> messagesLogged;
+
+ void CreateSolution ()
+ {
+ packageManagerFactory = new FakePackageManagerFactory ();
+ packageRepositoryCache = new FakePackageRepositoryFactory ();
+ packageEvents = new PackageManagementEvents ();
+ solution = new FakePackageManagementSolution ();
+ }
+
+ FakePackageManagementProject CreateSolutionWithOneProject ()
+ {
+ CreateSolution ();
+ return solution.AddFakeProject ("MyProject");
+ }
+
+ void CreateAction ()
+ {
+ action = new RestorePackagesAction (
+ solution,
+ packageEvents,
+ packageRepositoryCache,
+ packageManagerFactory);
+ }
+
+ FakePackage AddPackageToPriorityRepository (string packageId, string packageVersion)
+ {
+ return packageRepositoryCache
+ .FakePriorityPackageRepository
+ .AddFakePackageWithVersion (packageId, packageVersion);
+ }
+
+ void CaptureMessagesLogged ()
+ {
+ messagesLogged = new List<PackageOperationMessage> ();
+ packageEvents.PackageOperationMessageLogged += (sender, e) => {
+ messagesLogged.Add (e.Message);
+ };
+ }
+
+ FakeOperationAwarePackageRepository MakePriorityRepositoryOperationAware ()
+ {
+ var repository = new FakeOperationAwarePackageRepository ();
+ packageRepositoryCache.FakePriorityPackageRepository = repository;
+ return repository;
+ }
+
+ void PackageIsRestored (FakePackage package)
+ {
+ solution.SolutionPackageRepository.FakePackages.Add (package);
+ }
+
+ void AssertMessageLogged (string expectedMessage)
+ {
+ List<string> allMessages = messagesLogged.Select (message => message.ToString ()).ToList ();
+ Assert.That (allMessages, Contains.Item (expectedMessage));
+ }
+
+ void AssertMessageIsNotLogged (string expectedMessage)
+ {
+ List<string> allMessages = messagesLogged.Select (message => message.ToString ()).ToList ();
+ Assert.That (allMessages, Has.No.Contains (expectedMessage));
+ }
+
+ void AssertNoMessageLoggedThatContains (string expectedMessage)
+ {
+ List<string> allMessages = messagesLogged.Select (message => message.ToString ()).ToList ();
+ Assert.That (allMessages, Has.No.ContainsSubstring (expectedMessage));
+ }
+
+ [Test]
+ public void Execute_ProjectHasOneUnrestoredPackage_PackageFromPriorityRepositoryIsInstalled ()
+ {
+ FakePackageManagementProject project = CreateSolutionWithOneProject ();
+ project.AddPackageReference ("MyPackage", "1.0");
+ FakePackage package = AddPackageToPriorityRepository ("MyPackage", "1.0");
+ CreateAction ();
+
+ action.Execute ();
+
+ Assert.AreEqual (package, packageManagerFactory.FakePackageManager.PackagePassedToInstallPackage);
+ Assert.IsTrue (packageManagerFactory.FakePackageManager.IgnoreWalkInfoPassedToInstallPackage);
+ Assert.IsTrue (packageManagerFactory.FakePackageManager.IgnoreDependenciesPassedToInstallPackage);
+ Assert.IsTrue (packageManagerFactory.FakePackageManager.AllowPrereleaseVersionsPassedToInstallPackage);
+ Assert.AreEqual (packageRepositoryCache.FakePriorityPackageRepository, packageManagerFactory.PackageRepositoryPassedToCreatePackageManager);
+ Assert.AreEqual (solution.SolutionPackageRepository, packageManagerFactory.SolutionPackageRepositoryPassedToCreatePackageManager);
+ }
+
+ [Test]
+ public void Execute_ProjectHasOneUnrestoredPackage_PackageManagerHasLoggerConfigured ()
+ {
+ FakePackageManagementProject project = CreateSolutionWithOneProject ();
+ project.AddPackageReference ("MyPackage", "1.0");
+ AddPackageToPriorityRepository ("MyPackage", "1.0");
+ CreateAction ();
+
+ action.Execute ();
+
+ Assert.IsInstanceOf<PackageManagementLogger> (packageManagerFactory.FakePackageManager.Logger);
+ }
+
+ [Test]
+ public void Execute_ProjectHasOneUnrestoredPackage_RestoringPackagesMessageLogged ()
+ {
+ FakePackageManagementProject project = CreateSolutionWithOneProject ();
+ project.AddPackageReference ("MyPackage", "1.0");
+ AddPackageToPriorityRepository ("MyPackage", "1.0");
+ CreateAction ();
+ CaptureMessagesLogged ();
+
+ action.Execute ();
+
+ Assert.AreEqual ("Restoring packages...", messagesLogged [0].ToString ());
+ }
+
+ [Test]
+ public void Execute_ProjectHasOneUnrestoredPackage_RestoreOperationAddedToHttpHeader ()
+ {
+ FakePackageManagementProject project = CreateSolutionWithOneProject ();
+ project.AddPackageReference ("MyPackage", "1.0");
+ FakeOperationAwarePackageRepository repository = MakePriorityRepositoryOperationAware ();
+ AddPackageToPriorityRepository ("MyPackage", "1.0");
+ CreateAction ();
+
+ action.Execute ();
+
+ repository.AssertOperationWasStartedAndDisposed (
+ RepositoryOperationNames.Restore,
+ "MyPackage",
+ "1.0");
+ }
+
+ [Test]
+ public void Execute_ProjectHasOnePackageWhichIsRestored_PackageIsNotInstalledAgain ()
+ {
+ FakePackageManagementProject project = CreateSolutionWithOneProject ();
+ project.AddPackageReference ("MyPackage", "1.0");
+ FakePackage package = AddPackageToPriorityRepository ("MyPackage", "1.0");
+ PackageIsRestored (package);
+ CreateAction ();
+
+ action.Execute ();
+
+ Assert.IsFalse (packageManagerFactory.FakePackageManager.IsPackageInstalled);
+ }
+
+ [Test]
+ public void Execute_ProjectHasOnePackageWhichIsRestored_AllPackagesAlreadyRestoredMessageIsLogged ()
+ {
+ FakePackageManagementProject project = CreateSolutionWithOneProject ();
+ project.AddPackageReference ("MyPackage", "1.2.3.4");
+ FakePackage package = AddPackageToPriorityRepository ("MyPackage", "1.2.3.4");
+ PackageIsRestored (package);
+ CreateAction ();
+ CaptureMessagesLogged ();
+
+ action.Execute ();
+
+ AssertMessageLogged ("All packages are already restored.");
+ AssertMessageLogged ("Skipping 'MyPackage 1.2.3.4' because it is already restored.");
+ }
+
+ [Test]
+ public void Execute_ProjectHasOnePackageWhichIsNotRestored_AllPackagesAreAlreadyRestoredMessageIsNotLogged ()
+ {
+ FakePackageManagementProject project = CreateSolutionWithOneProject ();
+ project.AddPackageReference ("MyPackage", "1.0");
+ AddPackageToPriorityRepository ("MyPackage", "1.0");
+ CreateAction ();
+ CaptureMessagesLogged ();
+
+ action.Execute ();
+
+ AssertMessageIsNotLogged ("All packages are already restored.");
+ AssertMessageLogged ("1 package restored successfully.");
+ }
+
+ [Test]
+ public void Execute_ProjectHasTwoMissingPackages_PackagesRestoredSuccessfullyMessageIsLogged ()
+ {
+ FakePackageManagementProject project = CreateSolutionWithOneProject ();
+ project.AddPackageReference ("MyPackage", "1.0");
+ project.AddPackageReference ("MyOtherPackage", "1.2");
+ AddPackageToPriorityRepository ("MyPackage", "1.0");
+ AddPackageToPriorityRepository ("MyOtherPackage", "1.2");
+ CreateAction ();
+ CaptureMessagesLogged ();
+
+ action.Execute ();
+
+ AssertMessageIsNotLogged ("All packages are already restored.");
+ AssertMessageLogged ("2 packages restored successfully.");
+ }
+
+ [Test]
+ public void Execute_TwoProjectsEachWithSameMissingPackage_PackageIsRestoredOnce ()
+ {
+ CreateSolution ();
+ FakePackageManagementProject project1 = solution.AddFakeProject ("MyProject1");
+ FakePackageManagementProject project2 = solution.AddFakeProject ("MyProject2");
+ project1.AddPackageReference ("MyPackage", "1.2.3.4");
+ project2.AddPackageReference ("MyPackage", "1.2.3.4");
+ AddPackageToPriorityRepository ("MyPackage", "1.2.3.4");
+ CreateAction ();
+ CaptureMessagesLogged ();
+
+ action.Execute ();
+
+ Assert.AreEqual (1, packageManagerFactory.FakePackageManager.PackagesInstalled.Count);
+ Assert.AreEqual ("MyPackage", packageManagerFactory.FakePackageManager.PackagePassedToInstallPackage.Id);
+ Assert.AreEqual ("1.2.3.4", packageManagerFactory.FakePackageManager.PackagePassedToInstallPackage.Version.ToString ());
+ AssertMessageLogged ("1 package restored successfully.");
+ }
+
+ [Test]
+ public void Execute_ProjectHasOneUnrestoredSolutionLevelPackage_PackageIsInstalled ()
+ {
+ CreateSolutionWithOneProject ();
+ solution.AddPackageReference ("MyPackage", "1.0");
+ FakePackage package = AddPackageToPriorityRepository ("MyPackage", "1.0");
+ CreateAction ();
+
+ action.Execute ();
+
+ Assert.AreEqual (package, packageManagerFactory.FakePackageManager.PackagePassedToInstallPackage);
+ Assert.IsTrue (packageManagerFactory.FakePackageManager.IgnoreWalkInfoPassedToInstallPackage);
+ Assert.IsTrue (packageManagerFactory.FakePackageManager.IgnoreDependenciesPassedToInstallPackage);
+ Assert.IsTrue (packageManagerFactory.FakePackageManager.AllowPrereleaseVersionsPassedToInstallPackage);
+ }
+
+ [Test]
+ public void Execute_SolutionHasTwoProjectsWithMissingPackagesButOneProjectAddedToActionForRestore_OnlyOneProjectIsRestored ()
+ {
+ CreateSolution ();
+ FakePackageManagementProject project1 = solution.AddFakeProject ("MyProject1");
+ FakePackageManagementProject project2 = solution.AddFakeProject ("MyProject2");
+ project1.AddPackageReference ("MyPackage1", "1.2.3.4");
+ project2.AddPackageReference ("MyPackage2", "1.2.3.4");
+ AddPackageToPriorityRepository ("MyPackage1", "1.2.3.4");
+ AddPackageToPriorityRepository ("MyPackage2", "1.2.3.4");
+ CreateAction ();
+ var dotNetProject = new FakeDotNetProject ();
+ dotNetProject.Name = "MyProject1";
+ solution.FakeProjectsToReturnFromGetProject.Add ("MyProject1", project1);
+ action.Project = dotNetProject;
+
+ action.Execute ();
+
+ Assert.AreEqual (1, packageManagerFactory.FakePackageManager.PackagesInstalled.Count);
+ Assert.AreEqual ("MyPackage1", packageManagerFactory.FakePackageManager.PackagePassedToInstallPackage.Id);
+ }
+
+ [Test]
+ public void Execute_OneUnrestoredSolutionLevelPackageButOneProjectAddedToActionForRestore_SolutionLevelPackageIsNotRestored ()
+ {
+ CreateSolutionWithOneProject ();
+ solution.AddPackageReference ("MyPackage", "1.0");
+ FakePackage package = AddPackageToPriorityRepository ("MyPackage", "1.0");
+ FakePackageManagementProject project1 = solution.AddFakeProject ("MyProject1");
+ FakePackageManagementProject project2 = solution.AddFakeProject ("MyProject2");
+ project1.AddPackageReference ("MyPackage1", "1.2.3.4");
+ project2.AddPackageReference ("MyPackage2", "1.2.3.4");
+ AddPackageToPriorityRepository ("MyPackage1", "1.2.3.4");
+ AddPackageToPriorityRepository ("MyPackage2", "1.2.3.4");
+ CreateAction ();
+ var dotNetProject = new FakeDotNetProject ();
+ dotNetProject.Name = "MyProject1";
+ solution.FakeProjectsToReturnFromGetProject.Add ("MyProject1", project1);
+ action.Project = dotNetProject;
+
+ action.Execute ();
+
+ Assert.AreEqual (1, packageManagerFactory.FakePackageManager.PackagesInstalled.Count);
+ Assert.AreEqual ("MyPackage1", packageManagerFactory.FakePackageManager.PackagePassedToInstallPackage.Id);
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/SettingProviderTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/SettingProviderTests.cs index 9661a2650f..6ce4d4f783 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/SettingProviderTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/SettingProviderTests.cs @@ -98,5 +98,19 @@ namespace MonoDevelop.PackageManagement.Tests Assert.AreEqual (@"d:\projects\MyProject\.nuget".ToNativePath (), fileSystemUsedToLoadSettings.Root);
Assert.AreEqual (fakeSettings, settings);
}
+
+ [Test]
+ public void LoadSettings_NuGetSettingsThrowsUnauthorizedAccessException_ExceptionHandledAndSettingsNullObjectReturned ()
+ {
+ fileSystemUsedToLoadSettings = new FakeFileSystem ();
+ configFileUsedToLoadSettings = "configFile";
+ SettingsProvider.LoadDefaultSettings = (fileSystem, configFile, machineSettings) => {
+ throw new UnauthorizedAccessException ();
+ };
+
+ ISettings settings = settingsProvider.LoadSettings ();
+
+ Assert.IsInstanceOf<NullSettings> (settings);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/SolutionPackageRepositoryTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/SolutionPackageRepositoryTests.cs index 6e0d17e198..7980a7767a 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/SolutionPackageRepositoryTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/SolutionPackageRepositoryTests.cs @@ -38,7 +38,7 @@ namespace MonoDevelop.PackageManagement.Tests [TestFixture]
public class SolutionPackageRepositoryTests
{
- SolutionPackageRepository repository;
+ TestableSolutionPackageRepository repository;
TestablePackageManagementOptions options;
FakeSolution solution;
FakePackageRepositoryFactory fakeRepositoryFactory;
@@ -63,7 +63,7 @@ namespace MonoDevelop.PackageManagement.Tests void CreateRepository (ISolution solution, TestablePackageManagementOptions options)
{
CreateFakeRepositoryFactory ();
- repository = new SolutionPackageRepository (solution, fakeRepositoryFactory, options);
+ repository = new TestableSolutionPackageRepository (solution, fakeRepositoryFactory, options);
}
void CreateRepository (ISolution solution)
@@ -90,6 +90,30 @@ namespace MonoDevelop.PackageManagement.Tests return sharedRepository.AddFakePackageWithVersion (packageId, version);
}
+ PackageReference CreatePackageReference (string packageId, string packageVersion)
+ {
+ SemanticVersion version = null;
+ if (packageVersion != null) {
+ version = new SemanticVersion (packageVersion);
+ }
+
+ return new PackageReference (
+ packageId,
+ version,
+ null,
+ null,
+ false,
+ false
+ );
+ }
+
+ void AddFileToLocalRepositoryLookupPath (PackageReference packageReference, string filePath)
+ {
+ filePath = filePath.ToNativePath ();
+ var packageName = new PackageName (packageReference.Id, packageReference.Version);
+ repository.LocalPackageRepository.AddPackageLookupPath (packageName, filePath);
+ }
+
[Test]
public void GetInstallPath_GetInstallPathForPackage_ReturnsPackagePathInsideSolutionPackagesRepository ()
{
@@ -243,5 +267,44 @@ namespace MonoDevelop.PackageManagement.Tests PackageCollectionAssert.AreEqual (expectedPackages, packages);
}
+
+ [Test]
+ public void IsRestored_PackageReferenceHasNullVersion_ReturnsFalse ()
+ {
+ CreateSolution (@"d:\projects\myproject\myproject.sln");
+ CreateRepository (solution);
+ PackageReference packageReference = CreatePackageReference ("MyPackage", null);
+
+ bool restored = repository.IsRestored (packageReference);
+
+ Assert.IsFalse (restored);
+ }
+
+ [Test]
+ public void IsRestored_OnePackageLookupPathForPackageReference_ReturnTrue ()
+ {
+ CreateSolution (@"d:\projects\myproject\myproject.sln");
+ CreateRepository (solution);
+ PackageReference packageReference = CreatePackageReference ("MyPackage", "1.2.3.4");
+ AddFileToLocalRepositoryLookupPath (
+ packageReference,
+ @"d:\projects\myproject\packages\MyPackage.1.2.3.4\MyPackage.1.2.3.4.nupkg");
+
+ bool restored = repository.IsRestored (packageReference);
+
+ Assert.IsTrue (restored);
+ }
+
+ [Test]
+ public void IsRestored_NoPackageLookupPathsForPackageReference_ReturnFalse ()
+ {
+ CreateSolution (@"d:\projects\myproject\myproject.sln");
+ CreateRepository (solution);
+ PackageReference packageReference = CreatePackageReference ("MyPackage", "1.2.3.4");
+
+ bool restored = repository.IsRestored (packageReference);
+
+ Assert.IsFalse (restored);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatePackageActionTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatePackageActionTests.cs index b1da8e5976..7fb925db3d 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatePackageActionTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatePackageActionTests.cs @@ -40,12 +40,14 @@ namespace MonoDevelop.PackageManagement.Tests PackageManagementEvents packageManagementEvents;
FakePackageManagementProject fakeProject;
UpdatePackageHelper updatePackageHelper;
+ FakeFileRemover fileRemover;
void CreateSolution ()
{
packageManagementEvents = new PackageManagementEvents ();
fakeProject = new FakePackageManagementProject ();
- action = new UpdatePackageAction (fakeProject, packageManagementEvents);
+ fileRemover = new FakeFileRemover ();
+ action = new UpdatePackageAction (fakeProject, packageManagementEvents, fileRemover);
updatePackageHelper = new UpdatePackageHelper (action);
}
@@ -366,6 +368,61 @@ namespace MonoDevelop.PackageManagement.Tests Assert.AreEqual (expectedPackage, actualPackage);
}
+
+ [Test]
+ public void Execute_PackagesConfigFileDeletedDuringUpdate_FileServicePackagesConfigFileDeletionIsCancelled ()
+ {
+ CreateSolution ();
+ action.Package = new FakePackage ("Test");
+ string expectedFileName = @"d:\projects\MyProject\packages.config".ToNativePath ();
+ bool? fileRemovedResult = null;
+ fakeProject.UpdatePackageAction = (p, a) => {
+ fileRemovedResult = packageManagementEvents.OnFileRemoving (expectedFileName);
+ };
+ action.Execute ();
+
+ Assert.AreEqual (expectedFileName, fileRemover.FileRemoved);
+ Assert.IsFalse (fileRemovedResult.Value);
+ }
+
+ [Test]
+ public void Execute_ScriptFileDeletedDuringUpdate_FileDeletionIsNotCancelled ()
+ {
+ CreateSolution ();
+ action.Package = new FakePackage ("Test");
+ string fileName = @"d:\projects\MyProject\scripts\myscript.js".ToNativePath ();
+ bool? fileRemovedResult = null;
+ fakeProject.UpdatePackageAction = (p, a) => {
+ fileRemovedResult = packageManagementEvents.OnFileRemoving (fileName);
+ };
+ action.Execute ();
+
+ Assert.IsTrue (fileRemovedResult.Value);
+ Assert.IsNull (fileRemover.FileRemoved);
+ }
+
+ [Test]
+ public void Execute_PackageHasConstraint_LatestPackageIsNotUpdatedButPackageWithHighestVersionThatMatchesConstraint ()
+ {
+ CreateSolution ();
+ var constraintProvider = new DefaultConstraintProvider ();
+ var versionSpec = new VersionSpec ();
+ versionSpec.MinVersion = new SemanticVersion ("1.0");
+ versionSpec.IsMinInclusive = true;
+ versionSpec.IsMaxInclusive = true;
+ versionSpec.MaxVersion = new SemanticVersion ("2.0");
+ constraintProvider.AddConstraint ("MyPackage", versionSpec);
+ fakeProject.ConstraintProvider = constraintProvider;
+ fakeProject.AddFakePackageToSourceRepository ("MyPackage", "1.0");
+ FakePackage packageVersion2 = fakeProject.AddFakePackageToSourceRepository ("MyPackage", "2.0");
+ fakeProject.AddFakePackageToSourceRepository ("MyPackage", "3.0");
+ fakeProject.FakePackages.Add (new FakePackage ("MyPackage", "1.0"));
+ action.PackageId = "MyPackage";
+
+ action.Execute ();
+
+ Assert.AreEqual (packageVersion2, fakeProject.PackagePassedToUpdatePackage);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatedPackagesInSolutionTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatedPackagesInSolutionTests.cs index 5399737b3b..b105a94a50 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatedPackagesInSolutionTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatedPackagesInSolutionTests.cs @@ -97,10 +97,10 @@ namespace MonoDevelop.PackageManagement.Tests CreateUpdatedPackagesInSolution ();
FakePackageManagementProject project = AddProjectToSolution ();
project.AddPackageReference ("MyPackage", "1.0");
- FakePackage updatedPackage = AddUpdatedPackageToAggregateSourceRepository ("MyPackage", "1.1");
+ AddUpdatedPackageToAggregateSourceRepository ("MyPackage", "1.1");
updatedPackagesInSolution.CheckForUpdates ();
- UpdatedPackagesInProject updatedPackages = updatedPackagesInSolution.GetUpdatedPackages (project.Project);
+ updatedPackagesInSolution.GetUpdatedPackages (project.Project);
Assert.AreEqual (registeredPackageRepositories.FakeAggregateRepository, solution.SourceRepositoryPassedToGetProjects);
}
@@ -144,7 +144,7 @@ namespace MonoDevelop.PackageManagement.Tests CreateUpdatedPackagesInSolution ();
FakePackageManagementProject project = AddProjectToSolution ();
project.AddPackageReference ("MyPackage", "1.0");
- FakePackage updatedPackage = AddUpdatedPackageToAggregateSourceRepository ("MyPackage", "1.1");
+ AddUpdatedPackageToAggregateSourceRepository ("MyPackage", "1.1");
bool fired = false;
packageManagementEvents.UpdatedPackagesAvailable += (sender, e) => {
fired = true;
@@ -285,7 +285,7 @@ namespace MonoDevelop.PackageManagement.Tests FakePackageManagementProject project = AddProjectToSolution ();
project.AddPackageReference ("MyPackage", "1.0");
var package = FakePackage.CreatePackageWithVersion ("MyPackage", "1.0");
- FakePackage updatedPackage = AddUpdatedPackageToAggregateSourceRepository ("MyPackage", "1.1");
+ AddUpdatedPackageToAggregateSourceRepository ("MyPackage", "1.1");
updatedPackagesInSolution.CheckForUpdates ();
packageManagementEvents.OnParentPackageUninstalled (package, project);
@@ -293,6 +293,19 @@ namespace MonoDevelop.PackageManagement.Tests Assert.AreEqual (0, updatedPackages.GetPackages ().Count ());
}
+
+ [Test]
+ public void CheckForUpdates_NoPackagesUpdated_LoggerConfiguredForProject ()
+ {
+ CreateUpdatedPackagesInSolution ();
+ FakePackageManagementProject project = AddProjectToSolution ();
+ project.AddPackageReference ("MyPackage", "1.0");
+
+ updatedPackagesInSolution.CheckForUpdates ();
+ UpdatedPackagesInProject updatedPackages = updatedPackagesInSolution.GetUpdatedPackages (project.Project);
+
+ Assert.IsInstanceOf<PackageManagementLogger> (project.Logger);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatedPackagesTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatedPackagesTests.cs index 245c075cbc..31407117ee 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatedPackagesTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatedPackagesTests.cs @@ -40,7 +40,6 @@ namespace MonoDevelop.PackageManagement.Tests {
UpdatedPackages updatedPackages;
FakeServiceBasedRepository sourceRepository;
- List<FakePackage> installedPackages;
List<FakePackage> sourceRepositoryPackages;
List<IPackageName> packageNamesUsedWhenCheckingForUpdates;
bool includePreleaseUsedWhenCheckingForUpdates;
@@ -50,7 +49,6 @@ namespace MonoDevelop.PackageManagement.Tests public void Init ()
{
sourceRepository = new FakeServiceBasedRepository ();
- installedPackages = new List<FakePackage> ();
sourceRepositoryPackages = new List<FakePackage> ();
packageNamesUsedWhenCheckingForUpdates = new List<IPackageName> ();
project = new FakePackageManagementProject ();
@@ -63,7 +61,12 @@ namespace MonoDevelop.PackageManagement.Tests packageNamesUsedWhenCheckingForUpdates.AddRange (packagesNames.Select (p => (IPackageName)p));
return sourceRepositoryPackages.AsQueryable ();
};
- updatedPackages = new UpdatedPackages (project, sourceRepository);
+ CreateUpdatedPackages (sourceRepository);
+ }
+
+ void CreateUpdatedPackages (IPackageRepository repository)
+ {
+ updatedPackages = new UpdatedPackages (project, repository);
}
FakePackage AddPackageToSourceRepository (string id, string version)
@@ -106,7 +109,7 @@ namespace MonoDevelop.PackageManagement.Tests AddPackageToSourceRepository ("Test", "1.1");
CreateUpdatedPackages ();
- IEnumerable<IPackage> packages = updatedPackages.GetUpdatedPackages ();
+ updatedPackages.GetUpdatedPackages ();
IPackageName packageChecked = packageNamesUsedWhenCheckingForUpdates.FirstOrDefault ();
Assert.AreSame ("Test", packageChecked.Id);
@@ -167,5 +170,31 @@ namespace MonoDevelop.PackageManagement.Tests Assert.IsFalse (includePreleaseUsedWhenCheckingForUpdates);
}
+
+ [Test]
+ public void GetUpdatedPackages_OnePackageReferencedWithConstraintAndUpdatesAvailable_LatestVersionReturnedBasedOnConstraint ()
+ {
+ AddPackageReference ("Test", "1.0");
+ FakePackage package = AddPackageToSourceRepository ("Test", "2.0");
+ FakePackage [] expectedPackages = new [] {
+ package
+ };
+ AddPackageToSourceRepository ("Test", "3.0");
+ var versionSpec = new VersionSpec ();
+ versionSpec.MinVersion = new SemanticVersion ("1.0");
+ versionSpec.IsMinInclusive = true;
+ versionSpec.MaxVersion = new SemanticVersion ("2.0");
+ versionSpec.IsMaxInclusive = true;
+ var constraintProvider = new DefaultConstraintProvider ();
+ constraintProvider.AddConstraint ("Test", versionSpec);
+ project.ConstraintProvider = constraintProvider;
+ var repository = new FakePackageRepository ();
+ repository.FakePackages = sourceRepositoryPackages;
+ CreateUpdatedPackages (repository);
+
+ IEnumerable<IPackage> packages = updatedPackages.GetUpdatedPackages ();
+
+ PackageCollectionAssert.AreEqual (expectedPackages, packages);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml index 22c0ce5ad2..fd9a79ccc2 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml @@ -4,7 +4,6 @@ <Import assembly="MonoDevelop.PackageManagement.dll" />
<Import assembly="Microsoft.Web.XmlTransform.dll" />
<Import assembly="NuGet.Core.dll" />
- <Import file="NuGet.exe" />
</Runtime>
<Extension path = "/MonoDevelop/Ide/Commands">
@@ -22,7 +21,7 @@ id="MonoDevelop.PackageManagement.Commands.Restore"
_description="Restore missing packages"
_label="_Restore"
- defaultHandler="MonoDevelop.PackageManagement.Commands.RestorePackagesHandler" />
+ defaultHandler="MonoDevelop.PackageManagement.Commands.RestorePackagesInProjectHandler" />
<Command
id="MonoDevelop.PackageManagement.Commands.PackageReferenceNodeCommands.ShowPackageVersion"
_description="Current package version"
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj index e33649710f..55e16bc4de 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj @@ -131,8 +131,6 @@ <Compile Include="MonoDevelop.PackageManagement\ManagePackagesViewTitle.cs" /> <Compile Include="MonoDevelop.PackageManagement\MonoDevelopCredentialProvider.cs" /> <Compile Include="MonoDevelop.PackageManagement\MSBuildProjectExtensions.cs" /> - <Compile Include="MonoDevelop.PackageManagement\NuGetExePath.cs" /> - <Compile Include="MonoDevelop.PackageManagement\NuGetPackageRestoreCommandLine.cs" /> <Compile Include="MonoDevelop.PackageManagement\PackageActionRunner.cs" /> <Compile Include="MonoDevelop.PackageManagement\PackageFromRepository.cs" /> <Compile Include="MonoDevelop.PackageManagement\PackageLicenseViewModel.cs" /> @@ -348,6 +346,19 @@ <Compile Include="MonoDevelop.PackageManagement\UpdatePackagesProgressMonitorStatusMessage.cs" /> <Compile Include="MonoDevelop.PackageManagement\CheckForUpdatedPackagesAction.cs" /> <Compile Include="MonoDevelop.PackageManagement\RestoreBeforeUpdateAction.cs" /> + <Compile Include="MonoDevelop.PackageManagement\MonoDevelopAggregateRepository.cs" /> + <Compile Include="MonoDevelop.PackageManagement\RestorePackagesAction.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Commands\RestorePackagesInProjectHandler.cs" /> + <Compile Include="MonoDevelop.PackageManagement\FailingPackageRepository.cs" /> + <Compile Include="MonoDevelop.PackageManagement\FileRemovingEventArgs.cs" /> + <Compile Include="MonoDevelop.PackageManagement\PreventPackagesConfigFileBeingRemovedOnUpdateMonitor.cs" /> + <Compile Include="MonoDevelop.PackageManagement\FilePathExtensions.cs" /> + <Compile Include="MonoDevelop.PackageManagement\FileRemover.cs" /> + <Compile Include="MonoDevelop.PackageManagement\IFileRemover.cs" /> + <Compile Include="MonoDevelop.PackageManagement\IPackageManagementProjectOperations.cs" /> + <Compile Include="MonoDevelop.PackageManagement\PackageManagementPackageReference.cs" /> + <Compile Include="MonoDevelop.PackageManagement\PackageManagementProjectOperations.cs" /> + <Compile Include="MonoDevelop.PackageManagement\PackageManagementPackageReferenceEventArgs.cs" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="MonoDevelop.PackageManagement.addin.xml" /> @@ -424,10 +435,6 @@ <Folder Include="MonoDevelop.PackageManagement.NodeBuilders\" /> </ItemGroup> <ItemGroup> - <None Include="..\..\..\external\nuget-binary\NuGet.exe"> - <Link>NuGet.exe</Link> - <CopyToOutputDirectory>Always</CopyToOutputDirectory> - </None> <None Include="..\..\..\external\nuget-binary\NuGet-LICENSE.txt"> <Link>NuGet-LICENSE.txt</Link> <CopyToOutputDirectory>Always</CopyToOutputDirectory> diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AggregateExceptionErrorMessage.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AggregateExceptionErrorMessage.cs index 35248deea3..c8e33a8997 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AggregateExceptionErrorMessage.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AggregateExceptionErrorMessage.cs @@ -36,15 +36,23 @@ namespace ICSharpCode.PackageManagement {
AggregateException ex;
StringBuilder errorMessage = new StringBuilder();
-
+
public AggregateExceptionErrorMessage(AggregateException ex)
+ : this (null, ex)
+ {
+ }
+
+ public AggregateExceptionErrorMessage (string message, AggregateException ex)
{
this.ex = ex;
- BuildErrorMessage();
+ BuildErrorMessage (message);
}
- void BuildErrorMessage()
+ void BuildErrorMessage (string message)
{
+ if (!String.IsNullOrEmpty (message)) {
+ errorMessage.AppendLine (message);
+ }
BuildErrorMessage(ex.InnerExceptions);
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AvailablePackagesViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AvailablePackagesViewModel.cs index bfe93e3fbf..555e55f567 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AvailablePackagesViewModel.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AvailablePackagesViewModel.cs @@ -32,22 +32,26 @@ using System.Linq; using MonoDevelop.PackageManagement;
using NuGet;
+using MonoDevelop.Core;
namespace ICSharpCode.PackageManagement
{
public class AvailablePackagesViewModel : PackagesViewModel
{
+ ISolutionPackageRepository solutionPackageRepository;
IPackageRepository repository;
string errorMessage;
IRecentPackageRepository recentPackageRepository;
- public AvailablePackagesViewModel(
+ public AvailablePackagesViewModel (
+ IPackageManagementSolution solution,
IRegisteredPackageRepositories registeredPackageRepositories,
IRecentPackageRepository recentPackageRepository,
IPackageViewModelFactory packageViewModelFactory,
ITaskFactory taskFactory)
: base(registeredPackageRepositories, packageViewModelFactory, taskFactory)
{
+ this.solutionPackageRepository = solution.GetRepository ();
this.recentPackageRepository = recentPackageRepository;
IsSearchable = true;
@@ -120,36 +124,93 @@ namespace ICSharpCode.PackageManagement .DistinctLast<IPackage>(PackageEqualityComparer.Id);
}
+ /// <summary>
+ /// Package prioritization:
+ ///
+ /// Recent packages first.
+ /// Packages in solution.
+ /// Packages from active package source.
+ /// </summary>
protected override IEnumerable<IPackage> PrioritizePackages (IEnumerable<IPackage> packages, PackageSearchCriteria search)
{
- List<IPackage> recentPackages = GetRecentPackages (search).ToList ();
+ List<IPackage> prioritizedPackages = GetPrioritizedPackages (search).ToList ();
- if (PackageViewModels.Count == 0) {
- foreach (IPackage package in recentPackages) {
- yield return package;
- }
+ foreach (IPackage package in prioritizedPackages) {
+ yield return package;
}
foreach (IPackage package in packages) {
- if (!recentPackages.Contains (package, PackageEqualityComparer.IdAndVersion)) {
+ if (!prioritizedPackages.Contains (package, PackageEqualityComparer.IdAndVersion)) {
yield return package;
}
}
}
- IEnumerable<IPackage> GetRecentPackages (PackageSearchCriteria search)
+ IEnumerable<IPackage> GetPrioritizedPackages (PackageSearchCriteria search)
{
if (search.IsPackageVersionSearch) {
- return Enumerable.Empty<IPackage> ();
+ yield break;
+ }
+
+ List<IPackage> prioritizedPackages = GetRecentPackages (search).ToList ();
+
+ if (PackageViewModels.Count == 0) {
+ foreach (IPackage package in prioritizedPackages) {
+ yield return package;
+ }
+
+ foreach (IPackage package in GetSolutionPackages (search)) {
+ if (!prioritizedPackages.Contains (package, PackageEqualityComparer.IdAndVersion)) {
+ prioritizedPackages.Add (package);
+ yield return package;
+ }
+ }
}
+ }
+
+ IEnumerable<IPackage> GetRecentPackages (PackageSearchCriteria search)
+ {
return recentPackageRepository.Search (search.SearchText, IncludePrerelease);
}
+ IEnumerable<IPackage> GetSolutionPackages (PackageSearchCriteria search)
+ {
+ return solutionPackageRepository
+ .GetPackages ()
+ .Find (search.SearchText)
+ .FilterByPrerelease (IncludePrerelease);
+ }
+
protected override PackageViewModel CreatePackageViewModel (IPackage package, PackageSearchCriteria search)
{
PackageViewModel viewModel = base.CreatePackageViewModel (package, search);
viewModel.ShowVersionInsteadOfDownloadCount = search.IsPackageVersionSearch;
return viewModel;
}
+
+ protected override string GetWarningMessage ()
+ {
+ var aggregateRepository = repository as MonoDevelopAggregateRepository;
+ if (aggregateRepository != null) {
+ if (aggregateRepository.AllFailed ()) {
+ return GetAllPackageSourcesCouldNotBeReachedErrorMessage (aggregateRepository);
+ } else if (aggregateRepository.AnyFailures ()) {
+ return GetSomePackageSourcesCouldNotBeReachedErrorMessage (aggregateRepository);
+ }
+ }
+ return String.Empty;
+ }
+
+ string GetAllPackageSourcesCouldNotBeReachedErrorMessage (MonoDevelopAggregateRepository repository)
+ {
+ string message = GettextCatalog.GetString ("All package sources could not be reached.");
+ return new AggregateExceptionErrorMessage (message, repository.GetAggregateException ()).ToString ();
+ }
+
+ string GetSomePackageSourcesCouldNotBeReachedErrorMessage (MonoDevelopAggregateRepository repository)
+ {
+ string message = GettextCatalog.GetString ("Some package sources could not be reached.");
+ return new AggregateExceptionErrorMessage (message, repository.GetAggregateException ()).ToString ();
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/BackgroundPackageActionRunner.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/BackgroundPackageActionRunner.cs index d02f01385f..9ba0d464d1 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/BackgroundPackageActionRunner.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/BackgroundPackageActionRunner.cs @@ -80,9 +80,16 @@ namespace MonoDevelop.PackageManagement }
}
+ public void RunAndWait (ProgressMonitorStatusMessage progressMessage, IEnumerable<IPackageAction> actions)
+ {
+ AddInstallActionsToPendingQueue (actions);
+ packageManagementEvents.OnPackageOperationsStarting ();
+ DispatchService.BackgroundDispatchAndWait (() => RunActionsWithProgressMonitor (progressMessage, actions.ToList ()));
+ }
+
void RunActionsWithProgressMonitor (ProgressMonitorStatusMessage progressMessage, IList<IPackageAction> installPackageActions)
{
- using (IProgressMonitor monitor = progressMonitorFactory.CreateProgressMonitor (progressMessage.Status)) {
+ using (ProgressMonitor monitor = progressMonitorFactory.CreateProgressMonitor (progressMessage.Status)) {
using (PackageManagementEventsMonitor eventMonitor = CreateEventMonitor (monitor)) {
try {
monitor.BeginTask (null, installPackageActions.Count);
@@ -102,20 +109,20 @@ namespace MonoDevelop.PackageManagement }
}
- PackageManagementEventsMonitor CreateEventMonitor (IProgressMonitor monitor)
+ PackageManagementEventsMonitor CreateEventMonitor (ProgressMonitor monitor)
{
return CreateEventMonitor (monitor, packageManagementEvents, progressProvider);
}
protected virtual PackageManagementEventsMonitor CreateEventMonitor (
- IProgressMonitor monitor,
+ ProgressMonitor monitor,
IPackageManagementEvents packageManagementEvents,
IProgressProvider progressProvider)
{
return new PackageManagementEventsMonitor (monitor, packageManagementEvents, progressProvider);
}
- void RunActionsWithProgressMonitor (IProgressMonitor monitor, IList<IPackageAction> packageActions)
+ void RunActionsWithProgressMonitor (ProgressMonitor monitor, IList<IPackageAction> packageActions)
{
foreach (IPackageAction action in packageActions) {
action.Execute ();
@@ -138,7 +145,7 @@ namespace MonoDevelop.PackageManagement public void ShowError (ProgressMonitorStatusMessage progressMessage, string error)
{
- using (IProgressMonitor monitor = progressMonitorFactory.CreateProgressMonitor (progressMessage.Status)) {
+ using (ProgressMonitor monitor = progressMonitorFactory.CreateProgressMonitor (progressMessage.Status)) {
monitor.Log.WriteLine (error);
monitor.ReportError (progressMessage.Error, null);
monitor.ShowPackageConsole ();
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectExtensions.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectExtensions.cs index 3d38c585c2..9d771745d9 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectExtensions.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectExtensions.cs @@ -33,6 +33,7 @@ using MonoDevelop.PackageManagement; using MonoDevelop.Projects;
using MonoDevelop.Projects.Formats.MSBuild;
using NuGet;
+using System.Linq;
namespace ICSharpCode.PackageManagement
{
@@ -43,23 +44,7 @@ namespace ICSharpCode.PackageManagement public static bool IsWebProject(this IDotNetProject project)
{
- return project.HasProjectType(WebApplication) || project.HasProjectType(WebSite);
- }
-
- public static bool HasProjectType(this IDotNetProject project, Guid projectTypeGuid)
- {
- foreach (string guid in project.GetProjectTypeGuids()) {
- if (IsMatch(projectTypeGuid, guid)) {
- return true;
- }
- }
- return false;
- }
-
- public static string[] GetProjectTypeGuids(this IDotNetProject project)
- {
- string projectTypeGuids = project.GetProjectTypeGuidPropertyValue();
- return projectTypeGuids.Split(new char[] {';'}, StringSplitOptions.RemoveEmptyEntries);
+ return project.FlavorGuids.Any (id => IsMatch (WebApplication, id) || IsMatch (WebSite, id));
}
static bool IsMatch(Guid guid, string guidStringToMatch)
@@ -71,15 +56,6 @@ namespace ICSharpCode.PackageManagement return false;
}
- public static string GetProjectTypeGuidPropertyValue (this IDotNetProject project)
- {
- string propertyValue = null;
- if (project.ExtendedProperties.Contains("ProjectTypeGuids")) {
- propertyValue = project.ExtendedProperties["ProjectTypeGuids"] as String;
- }
- return propertyValue ?? String.Empty;
- }
-
public static bool HasPackages (this DotNetProject project)
{
return File.Exists (project.GetPackagesConfigFilePath ());
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FailingPackageRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FailingPackageRepository.cs new file mode 100644 index 0000000000..e45a612994 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FailingPackageRepository.cs @@ -0,0 +1,76 @@ +//
+// FailingPackageRepository.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Linq;
+using NuGet;
+
+namespace MonoDevelop.PackageManagement
+{
+ /// <summary>
+ /// Wraps access to a package repository that could not be created due to an invalid
+ /// Url. A call to any method will return the original exception that was thrown.
+ /// This is only used when creating an AggregateRepository so it does not prevent packages
+ /// being returned from other valid package repositories.
+ /// </summary>
+ public class FailingPackageRepository : IPackageRepository
+ {
+ string source;
+ Exception exception;
+
+ public FailingPackageRepository (string source, Exception exception)
+ {
+ this.source = source;
+ this.exception = exception;
+ }
+
+ public IQueryable<IPackage> GetPackages ()
+ {
+ throw exception;
+ }
+
+ public void AddPackage (IPackage package)
+ {
+ throw exception;
+ }
+
+ public void RemovePackage (IPackage package)
+ {
+ throw exception;
+ }
+
+ public string Source {
+ get { return source; }
+ }
+
+ public PackageSaveModes PackageSaveMode { get; set; }
+
+ public bool SupportsPrereleasePackages {
+ get { return true; }
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FilePathExtensions.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FilePathExtensions.cs new file mode 100644 index 0000000000..38faa5f7de --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FilePathExtensions.cs @@ -0,0 +1,45 @@ +//
+// FilePathExtensions.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using MonoDevelop.Core;
+using NuGet;
+
+namespace MonoDevelop.PackageManagement
+{
+ public static class FilePathExtensions
+ {
+ public static bool IsPackagesConfigFileName (this FilePath filePath)
+ {
+ if (filePath == null) {
+ return false;
+ }
+
+ return Constants.PackageReferenceFile.Equals (filePath.FileName, StringComparison.OrdinalIgnoreCase);
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FileRemover.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FileRemover.cs new file mode 100644 index 0000000000..96849ca9d0 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FileRemover.cs @@ -0,0 +1,40 @@ +//
+// FileRemover.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.IO;
+
+namespace MonoDevelop.PackageManagement
+{
+ public class FileRemover : IFileRemover
+ {
+ public void RemoveFile (string fileName)
+ {
+ File.Delete (fileName);
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FileRemovingEventArgs.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FileRemovingEventArgs.cs new file mode 100644 index 0000000000..557b185dca --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FileRemovingEventArgs.cs @@ -0,0 +1,47 @@ +//
+// FileRemovingEventArgs.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using MonoDevelop.Core;
+
+namespace MonoDevelop.PackageManagement
+{
+ public class FileRemovingEventArgs : EventArgs
+ {
+ public FileRemovingEventArgs (string fileName)
+ {
+ FileName = new FilePath (fileName);
+ }
+
+ public FilePath FileName { get; private set; }
+
+ /// <summary>
+ /// Stops the file from being removed.
+ /// </summary>
+ public bool IsCancelled { get; set; }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IFileRemover.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IFileRemover.cs new file mode 100644 index 0000000000..b9a19bb0d4 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IFileRemover.cs @@ -0,0 +1,36 @@ +//
+// IFileRemover.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace MonoDevelop.PackageManagement
+{
+ public interface IFileRemover
+ {
+ void RemoveFile (string fileName);
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageFromRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageFromRepository.cs index 4e3b61a589..947bed8b9f 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageFromRepository.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageFromRepository.cs @@ -37,5 +37,6 @@ namespace ICSharpCode.PackageManagement bool HasDependencies { get; }
DateTime? LastUpdated { get; }
Uri GalleryUrl { get; }
+ bool IsValid { get; }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementEvents.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementEvents.cs index 53abfe8c8b..0e476e576f 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementEvents.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementEvents.cs @@ -29,6 +29,7 @@ using System;
using System.Collections.Generic;
using MonoDevelop.Core;
+using MonoDevelop.PackageManagement;
using NuGet;
namespace ICSharpCode.PackageManagement
@@ -47,6 +48,7 @@ namespace ICSharpCode.PackageManagement event EventHandler<PackageOperationMessageLoggedEventArgs> PackageOperationMessageLogged;
event EventHandler PackagesRestored;
event EventHandler<FileEventArgs> FileChanged;
+ event EventHandler<FileRemovingEventArgs> FileRemoving;
event EventHandler UpdatedPackagesAvailable;
void OnPackageOperationsStarting();
@@ -62,5 +64,6 @@ namespace ICSharpCode.PackageManagement void OnPackagesRestored();
void OnFileChanged(string path);
void OnUpdatedPackagesAvailable ();
+ bool OnFileRemoving (string path);
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementProgressMonitorFactory.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementProgressMonitorFactory.cs index efecca66e2..ff0d07af86 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementProgressMonitorFactory.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementProgressMonitorFactory.cs @@ -31,7 +31,7 @@ namespace MonoDevelop.PackageManagement {
public interface IPackageManagementProgressMonitorFactory
{
- IProgressMonitor CreateProgressMonitor (string statusText);
+ ProgressMonitor CreateProgressMonitor (string statusText);
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementProject.cs index 1e0d1c1a9a..5c325681e4 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementProject.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementProject.cs @@ -52,6 +52,8 @@ namespace ICSharpCode.PackageManagement DotNetProject DotNetProject { get; }
IDotNetProject Project { get; }
+ IPackageConstraintProvider ConstraintProvider { get; }
+
bool IsPackageInstalled(IPackage package);
bool IsPackageInstalled(string packageId);
bool HasOlderPackageInstalled(IPackage package);
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementProjectOperations.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementProjectOperations.cs new file mode 100644 index 0000000000..f47cbe3c0b --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementProjectOperations.cs @@ -0,0 +1,48 @@ +//
+// IPackageManagementProjectOperations.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using MonoDevelop.Projects;
+using System.Collections.Generic;
+
+namespace MonoDevelop.PackageManagement
+{
+ /// <summary>
+ /// Provides a simplified interface for working with NuGet packages in a project.
+ ///
+ /// Used by the ComponentReferencingProjectAdaptor in Xamarin.Ide so keep the NuGet
+ /// package management logic in the NuGet addin.
+ /// </summary>
+ public interface IPackageManagementProjectOperations
+ {
+ void InstallPackages (string packageSourceUrl, Project project, IEnumerable<PackageManagementPackageReference> packages);
+ IEnumerable<PackageManagementPackageReference> GetInstalledPackages (Project project);
+
+ event EventHandler<PackageManagementPackageReferenceEventArgs> PackageReferenceAdded;
+ event EventHandler<PackageManagementPackageReferenceEventArgs> PackageReferenceRemoved;
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementSolution.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementSolution.cs index 03f279d604..f7c0036588 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementSolution.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementSolution.cs @@ -53,6 +53,7 @@ namespace ICSharpCode.PackageManagement IQueryable<IPackage> GetPackages();
IEnumerable<IPackage> GetPackagesInReverseDependencyOrder();
string GetInstallPath(IPackage package);
+ ISolutionPackageRepository GetRepository ();
bool IsOpen { get; }
string FileName { get; }
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagerFactory.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagerFactory.cs index 0428fa1a84..49b0f81ba2 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagerFactory.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagerFactory.cs @@ -37,5 +37,9 @@ namespace ICSharpCode.PackageManagement ISharpDevelopPackageManager CreatePackageManager (
IPackageRepository sourceRepository,
IDotNetProject project);
+
+ IPackageManager CreatePackageManager (
+ IPackageRepository sourceRepository,
+ ISolutionPackageRepository solutionPackageRepository);
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageRepositoryCache.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageRepositoryCache.cs index 5384a70332..8524d1a07a 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageRepositoryCache.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageRepositoryCache.cs @@ -35,5 +35,6 @@ namespace ICSharpCode.PackageManagement {
IRecentPackageRepository RecentPackageRepository { get; }
IPackageRepository CreateAggregateRepository();
+ IPackageRepository CreateAggregateWithPriorityMachineCacheRepository ();
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageRepositoryExtensions.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageRepositoryExtensions.cs index 8a498fee44..fce99ffbc0 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageRepositoryExtensions.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageRepositoryExtensions.cs @@ -42,5 +42,10 @@ namespace ICSharpCode.PackageManagement {
return repository.StartOperation(RepositoryOperationNames.Update, mainPackageId, mainPackageVersion);
}
+
+ public static IDisposable StartRestoreOperation (this IPackageRepository repository, string mainPackageId = null, string mainPackageVersion = null)
+ {
+ return repository.StartOperation (RepositoryOperationNames.Restore, mainPackageId, mainPackageVersion);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IProject.cs index d359be3c57..4455e85c76 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IProject.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IProject.cs @@ -27,6 +27,7 @@ using System;
using System.Collections;
using MonoDevelop.Core;
+using System.Collections.Generic;
namespace MonoDevelop.PackageManagement
{
@@ -37,6 +38,7 @@ namespace MonoDevelop.PackageManagement FilePath BaseDirectory { get; }
ISolution ParentSolution { get; }
IDictionary ExtendedProperties { get; }
+ IEnumerable<string> FlavorGuids { get; }
void Save ();
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ISolutionPackageRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ISolutionPackageRepository.cs index e73cd209f5..3c00c845e5 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ISolutionPackageRepository.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ISolutionPackageRepository.cs @@ -41,7 +41,9 @@ namespace ICSharpCode.PackageManagement IEnumerable<IPackage> GetPackagesByReverseDependencyOrder();
IQueryable<IPackage> GetPackages();
bool IsInstalled(IPackage package);
-
+ bool IsRestored (PackageReference packageReference);
+ IEnumerable<PackageReference> GetPackageReferences ();
+
ISharedPackageRepository Repository { get; }
IFileSystem FileSystem { get; }
IPackagePathResolver PackagePathResolver { get; }
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopAggregateRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopAggregateRepository.cs new file mode 100644 index 0000000000..3a140e6802 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopAggregateRepository.cs @@ -0,0 +1,68 @@ +//
+// MonoDevelopAggregateRepository.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using MonoDevelop.Core;
+using NuGet;
+
+namespace MonoDevelop.PackageManagement
+{
+ public class MonoDevelopAggregateRepository : AggregateRepository
+ {
+ ConcurrentQueue<Exception> failures = new ConcurrentQueue<Exception> ();
+
+ public MonoDevelopAggregateRepository (IEnumerable<IPackageRepository> repositories)
+ : base (repositories)
+ {
+ }
+
+ public override void LogRepository (IPackageRepository repository, Exception ex)
+ {
+ base.LogRepository (repository, ex);
+ LoggingService.LogInfo ("PackageRepository failure.", ex);
+ failures.Enqueue (ex);
+ }
+
+ public bool AnyFailures ()
+ {
+ return failures.Count > 0;
+ }
+
+ public bool AllFailed ()
+ {
+ return failures.Count >= Repositories.Count ();
+ }
+
+ public AggregateException GetAggregateException ()
+ {
+ return new AggregateException (failures);
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetExePath.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetExePath.cs deleted file mode 100644 index e4646e019b..0000000000 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetExePath.cs +++ /dev/null @@ -1,46 +0,0 @@ -//
-// NuGetExePath.cs
-//
-// Author:
-// Matt Ward <ward.matt@gmail.com>
-//
-// Copyright (C) 2013 Matthew Ward
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.IO;
-
-namespace ICSharpCode.PackageManagement
-{
- public static class NuGetExePath
- {
- public static string GetPath()
- {
- return Path.Combine(GetDirectory(), "NuGet.exe");
- }
-
- static string GetDirectory()
- {
- return Path.GetDirectoryName(typeof(NuGetExePath).Assembly.Location);
- }
- }
-}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetPackageRestoreCommandLine.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetPackageRestoreCommandLine.cs deleted file mode 100644 index 068061bbf4..0000000000 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetPackageRestoreCommandLine.cs +++ /dev/null @@ -1,108 +0,0 @@ -//
-// NuGetPackageRestoreCommandLine.cs
-//
-// Author:
-// Matt Ward <ward.matt@gmail.com>
-//
-// Copyright (C) 2013 Matthew Ward
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.IO;
-using MonoDevelop.Core.Assemblies;
-using NuGet;
-
-namespace ICSharpCode.PackageManagement
-{
- public class NuGetPackageRestoreCommandLine
- {
- MonoRuntimeInfo monoRuntime;
- bool isMonoRuntime;
-
- public NuGetPackageRestoreCommandLine (IPackageManagementSolution solution)
- : this (
- solution,
- MonoRuntimeInfo.FromCurrentRuntime (),
- EnvironmentUtility.IsMonoRuntime)
- {
- }
-
- public NuGetPackageRestoreCommandLine (
- IPackageManagementSolution solution,
- MonoRuntimeInfo monoRuntime,
- bool isMonoRuntime)
- {
- this.monoRuntime = monoRuntime;
- this.isMonoRuntime = isMonoRuntime;
-
- GenerateCommandLine(solution);
- GenerateWorkingDirectory(solution);
- }
-
- public string Command { get; set; }
- public string Arguments { get; private set; }
- public string WorkingDirectory { get; private set; }
-
- void GenerateCommandLine(IPackageManagementSolution solution)
- {
- if (isMonoRuntime) {
- GenerateMonoCommandLine(solution);
- } else {
- GenerateWindowsCommandLine(solution);
- }
- }
-
- void GenerateMonoCommandLine(IPackageManagementSolution solution)
- {
- Arguments = String.Format(
- "--runtime=v4.0 \"{0}\" restore -NonInteractive \"{1}\"",
- NuGetExePath.GetPath(),
- solution.FileName);
-
- Command = Path.Combine (monoRuntime.Prefix, "bin", "mono");
- }
-
- void GenerateWindowsCommandLine(IPackageManagementSolution solution)
- {
- Arguments = String.Format("restore -NonInteractive \"{0}\"", solution.FileName);
- Command = NuGetExePath.GetPath();
- }
-
- void GenerateWorkingDirectory(IPackageManagementSolution solution)
- {
- WorkingDirectory = Path.GetDirectoryName(solution.FileName);
- }
-
- public override string ToString()
- {
- return String.Format("{0} {1}", GetQuotedCommand(), Arguments);
- }
-
- string GetQuotedCommand()
- {
- if (Command.Contains(" ")) {
- return String.Format("\"{0}\"", Command);
- }
- return Command;
- }
- }
-}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageCompatibilityHandler.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageCompatibilityHandler.cs index 71ac6498f1..07d943a34b 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageCompatibilityHandler.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageCompatibilityHandler.cs @@ -32,7 +32,7 @@ namespace MonoDevelop.PackageManagement {
public class PackageCompatibilityHandler
{
- public PackageCompatibilityHandler (ProjectTargetFrameworkMonitor projectTargetFrameworkMonitor)
+ public void MonitorTargetFrameworkChanges (ProjectTargetFrameworkMonitor projectTargetFrameworkMonitor)
{
projectTargetFrameworkMonitor.ProjectTargetFrameworkChanged += ProjectTargetFrameworkChanged;
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageCompatibilityRunner.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageCompatibilityRunner.cs index 8a7092cbc3..aced2f1bd1 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageCompatibilityRunner.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageCompatibilityRunner.cs @@ -40,7 +40,7 @@ namespace MonoDevelop.PackageManagement IRegisteredPackageRepositories registeredRepositories;
IPackageManagementProgressMonitorFactory progressMonitorFactory;
ProgressMonitorStatusMessage progressMessage;
- IProgressMonitor progressMonitor;
+ ProgressMonitor progressMonitor;
IPackageManagementEvents packageManagementEvents;
IProgressProvider progressProvider;
@@ -101,18 +101,18 @@ namespace MonoDevelop.PackageManagement return ProgressMonitorStatusMessageFactory.CreateCheckingPackageCompatibilityMessage ();
}
- IProgressMonitor CreateProgressMonitor ()
+ ProgressMonitor CreateProgressMonitor ()
{
return progressMonitorFactory.CreateProgressMonitor (progressMessage.Status);
}
- PackageManagementEventsMonitor CreateEventMonitor (IProgressMonitor monitor)
+ PackageManagementEventsMonitor CreateEventMonitor (ProgressMonitor monitor)
{
return CreateEventMonitor (monitor, packageManagementEvents, progressProvider);
}
protected virtual PackageManagementEventsMonitor CreateEventMonitor (
- IProgressMonitor monitor,
+ ProgressMonitor monitor,
IPackageManagementEvents packageManagementEvents,
IProgressProvider progressProvider)
{
@@ -157,7 +157,7 @@ namespace MonoDevelop.PackageManagement ShowPackageConsole (progressMonitor);
}
- protected virtual void ShowPackageConsole (IProgressMonitor progressMonitor)
+ protected virtual void ShowPackageConsole (ProgressMonitor progressMonitor)
{
progressMonitor.ShowPackageConsole ();
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageFromRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageFromRepository.cs index 90ea1cb78e..56a5227376 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageFromRepository.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageFromRepository.cs @@ -221,5 +221,15 @@ namespace ICSharpCode.PackageManagement public bool DevelopmentDependency {
get { return package.DevelopmentDependency; }
}
+
+ public bool IsValid {
+ get {
+ var zipPackage = package as OptimizedZipPackage;
+ if (zipPackage != null) {
+ return zipPackage.IsValid;
+ }
+ return true;
+ }
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEvents.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEvents.cs index 4b7f318e1d..4500ce5cd2 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEvents.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEvents.cs @@ -30,6 +30,7 @@ using System; using System.Collections.Generic;
using MonoDevelop.Core;
using NuGet;
+using MonoDevelop.PackageManagement;
namespace ICSharpCode.PackageManagement
{
@@ -161,5 +162,17 @@ namespace ICSharpCode.PackageManagement UpdatedPackagesAvailable (this, new EventArgs ());
}
}
+
+ public event EventHandler<FileRemovingEventArgs> FileRemoving;
+
+ public bool OnFileRemoving (string path)
+ {
+ if (FileRemoving != null) {
+ var eventArgs = new FileRemovingEventArgs (path);
+ FileRemoving (this, eventArgs);
+ return !eventArgs.IsCancelled;
+ }
+ return true;
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEventsMonitor.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEventsMonitor.cs index 7594cb305e..b313ae98f0 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEventsMonitor.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEventsMonitor.cs @@ -36,7 +36,7 @@ namespace MonoDevelop.PackageManagement {
public class PackageManagementEventsMonitor : IDisposable
{
- IProgressMonitor progressMonitor;
+ ProgressMonitor progressMonitor;
IPackageManagementEvents packageManagementEvents;
IProgressProvider progressProvider;
FileConflictResolution lastFileConflictResolution;
@@ -45,7 +45,7 @@ namespace MonoDevelop.PackageManagement List<FileEventArgs> fileChangedEvents = new List<FileEventArgs> ();
public PackageManagementEventsMonitor (
- IProgressMonitor progressMonitor,
+ ProgressMonitor progressMonitor,
IPackageManagementEvents packageManagementEvents,
IProgressProvider progressProvider)
{
@@ -190,7 +190,7 @@ namespace MonoDevelop.PackageManagement packageManagementEvents.OnPackageOperationError (ex);
}
- protected virtual void ShowPackageConsole (IProgressMonitor progressMonitor)
+ protected virtual void ShowPackageConsole (ProgressMonitor progressMonitor)
{
progressMonitor.ShowPackageConsole ();
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementFileService.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementFileService.cs index 4c8b99917e..990ddabfdc 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementFileService.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementFileService.cs @@ -48,7 +48,9 @@ namespace ICSharpCode.PackageManagement public void RemoveFile(string path)
{
- FileService.DeleteFile(path);
+ if (packageManagementEvents.OnFileRemoving (path)) {
+ FileService.DeleteFile (path);
+ }
}
public void RemoveDirectory(string path)
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementPackageReference.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementPackageReference.cs new file mode 100644 index 0000000000..08cd591c28 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementPackageReference.cs @@ -0,0 +1,43 @@ +//
+// PackageManagementPackageReference.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace MonoDevelop.PackageManagement
+{
+ public class PackageManagementPackageReference
+ {
+ public PackageManagementPackageReference (string id, string version)
+ {
+ Id = id;
+ Version = version;
+ }
+
+ public string Id { get; set; }
+ public string Version { get; set; }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementPackageReferenceEventArgs.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementPackageReferenceEventArgs.cs new file mode 100644 index 0000000000..16e565e8df --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementPackageReferenceEventArgs.cs @@ -0,0 +1,44 @@ +//
+// PackageManagementPackageReferenceEventArgs.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using MonoDevelop.Projects;
+
+namespace MonoDevelop.PackageManagement
+{
+ public class PackageManagementPackageReferenceEventArgs : EventArgs
+ {
+ public PackageManagementPackageReferenceEventArgs (Project project, string id, string version)
+ {
+ Project = project;
+ PackageReference = new PackageManagementPackageReference (id, version);
+ }
+
+ public Project Project { get; private set; }
+ public PackageManagementPackageReference PackageReference { get; private set; }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProgressMonitor.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProgressMonitor.cs index 74076d6d47..6b73844a49 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProgressMonitor.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProgressMonitor.cs @@ -1,4 +1,4 @@ -//
+//
// PackageManagementProgressMonitor.cs
//
// Author:
@@ -26,21 +26,21 @@ using System;
using System.Collections.Generic;
+using System.IO;
+using System.Linq;
using MonoDevelop.Core;
using MonoDevelop.Core.Execution;
-using MonoDevelop.Core.ProgressMonitoring;
-using System.IO;
+using System.Threading;
namespace MonoDevelop.PackageManagement
{
- public class PackageManagementProgressMonitor : IProgressMonitor, IAsyncOperation
+ public class PackageManagementProgressMonitor : ProgressMonitor
{
- IProgressMonitor consoleMonitor;
- IProgressMonitor statusMonitor;
- List<string> warnings = new List<string> ();
- List<string> errors = new List<string> ();
+ ProgressMonitor consoleMonitor;
+ CancellationTokenRegistration consoleMonitorReg;
+ CancellationTokenRegistration statusMonitorReg;
- public IProgressMonitor ConsoleMonitor {
+ public ProgressMonitor ConsoleMonitor {
get { return consoleMonitor; }
}
@@ -48,146 +48,73 @@ namespace MonoDevelop.PackageManagement get { return (IConsole)this.consoleMonitor; }
}
- public PackageManagementProgressMonitor (IProgressMonitor consoleMonitor, IProgressMonitor statusMonitor)
+ public PackageManagementProgressMonitor (ProgressMonitor consoleMonitor, ProgressMonitor statusMonitor)
{
+ AddSlaveMonitor (statusMonitor);
this.consoleMonitor = consoleMonitor;
- this.statusMonitor = statusMonitor;
-
- consoleMonitor.CancelRequested += OnCancelRequested;
- statusMonitor.CancelRequested += OnCancelRequested;
- }
-
- public void BeginTask (string name, int totalWork)
- {
- statusMonitor.BeginTask (name, totalWork);
- }
-
- public void BeginStepTask (string name, int totalWork, int stepSize)
- {
- statusMonitor.BeginStepTask (name, totalWork, stepSize);
- }
- public void EndTask ()
- {
- statusMonitor.EndTask ();
+ consoleMonitorReg = consoleMonitor.CancellationToken.Register (OnCancelRequested);
+ statusMonitorReg = statusMonitor.CancellationToken.Register (OnCancelRequested);
}
- public void Step (int work)
+ protected override void OnWriteLog (string message)
{
- statusMonitor.Step (work);
+ consoleMonitor.Log.Write (message);
}
- public TextWriter Log
+ protected override void OnWriteErrorLog (string message)
{
- get { return consoleMonitor.Log; }
+ consoleMonitor.ErrorLog.Write (message);
}
- public void ReportSuccess (string message)
+ public override void Dispose ()
{
- consoleMonitor.ReportSuccess (message);
- statusMonitor.ReportSuccess (message);
- }
+ consoleMonitorReg.Dispose ();
+ statusMonitorReg.Dispose ();
- public void ReportWarning (string message)
- {
- warnings.Add (message);
- statusMonitor.ReportWarning (message);
- }
-
- public void ReportError (string message, Exception ex)
- {
- errors.Add (message);
- statusMonitor.ReportError (message, ex);
- }
-
- public void Dispose ()
- {
- consoleMonitor.CancelRequested -= OnCancelRequested;
- statusMonitor.CancelRequested -= OnCancelRequested;
+ foreach (var m in SuccessMessages)
+ consoleMonitor.ReportSuccess (m);
// Do not report warnings if there are errors otherwise the warnings will
// appear at the end of the Package Console and hide the error which
// should be the last line of text visible to the user.
- if (errors.Count == 0) {
+ if (Errors.Length == 0) {
ReportAllWarningsButLastToConsole ();
}
ReportAllErrorsButLastToConsole ();
consoleMonitor.Dispose ();
- statusMonitor.Dispose ();
}
void ReportAllWarningsButLastToConsole ()
{
+ var warnings = Warnings.Distinct ().ToList ();
RemoveLastItem (warnings);
warnings.ForEach (warning => consoleMonitor.ReportWarning (warning));
}
void ReportAllErrorsButLastToConsole ()
{
+ var errors = Errors.ToList ();
RemoveLastItem (errors);
- errors.ForEach (error => consoleMonitor.ReportError (error, null));
+ errors.ForEach (error => consoleMonitor.ReportError (error.Message, error.Exception));
}
- static void RemoveLastItem (List<string> items)
+ static void RemoveLastItem<T> (List<T> items)
{
if (items.Count > 0) {
items.RemoveAt (items.Count - 1);
}
}
- public bool IsCancelRequested
- {
- get {
- return consoleMonitor.IsCancelRequested || statusMonitor.IsCancelRequested;
- }
- }
-
public object SyncRoot {
get { return this; }
}
- void OnCancelRequested (IProgressMonitor sender)
- {
- AsyncOperation.Cancel ();
- }
-
- public IAsyncOperation AsyncOperation
- {
- get { return this; }
- }
-
- void IAsyncOperation.Cancel ()
- {
- consoleMonitor.AsyncOperation.Cancel ();
- }
-
- void IAsyncOperation.WaitForCompleted ()
+ void OnCancelRequested ()
{
- consoleMonitor.AsyncOperation.WaitForCompleted ();
- }
-
- public bool IsCompleted {
- get { return consoleMonitor.AsyncOperation.IsCompleted; }
- }
-
- bool IAsyncOperation.Success {
- get { return consoleMonitor.AsyncOperation.Success; }
- }
-
- bool IAsyncOperation.SuccessWithWarnings {
- get { return consoleMonitor.AsyncOperation.SuccessWithWarnings; }
- }
-
- public event MonitorHandler CancelRequested {
- add { consoleMonitor.CancelRequested += value; }
- remove { consoleMonitor.CancelRequested -= value; }
- }
-
- public event OperationHandler Completed {
- add { consoleMonitor.AsyncOperation.Completed += value; }
- remove { consoleMonitor.AsyncOperation.Completed -= value; }
+ CancellationTokenSource.Cancel ();
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProgressMonitorFactory.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProgressMonitorFactory.cs index d15afde849..98dae1d2a6 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProgressMonitorFactory.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProgressMonitorFactory.cs @@ -34,13 +34,13 @@ namespace MonoDevelop.PackageManagement {
public class PackageManagementProgressMonitorFactory : IPackageManagementProgressMonitorFactory
{
- public IProgressMonitor CreateProgressMonitor (string title)
+ public ProgressMonitor CreateProgressMonitor (string title)
{
- IProgressMonitor consoleMonitor = CreatePackageConsoleOutputMonitor ();
+ ProgressMonitor consoleMonitor = CreatePackageConsoleOutputMonitor ();
Pad pad = IdeApp.Workbench.ProgressMonitors.GetPadForMonitor (consoleMonitor);
- IProgressMonitor statusMonitor = IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor (
+ ProgressMonitor statusMonitor = IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor (
title,
Stock.StatusSolutionOperation,
false,
@@ -51,7 +51,7 @@ namespace MonoDevelop.PackageManagement return new PackageManagementProgressMonitor (consoleMonitor, statusMonitor);
}
- IProgressMonitor CreatePackageConsoleOutputMonitor ()
+ ProgressMonitor CreatePackageConsoleOutputMonitor ()
{
return IdeApp.Workbench.ProgressMonitors.GetOutputProgressMonitor (
"PackageConsole",
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProgressProvider.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProgressProvider.cs index 4c2353b194..5ca37f109a 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProgressProvider.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProgressProvider.cs @@ -36,7 +36,7 @@ namespace MonoDevelop.PackageManagement Action<MessageHandler> guiDispatcher;
public PackageManagementProgressProvider (IPackageRepositoryFactoryEvents repositoryFactoryEvents)
- : this (repositoryFactoryEvents, DispatchService.GuiDispatch)
+ : this (repositoryFactoryEvents, h => DispatchService.GuiDispatch (h))
{
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProject.cs index d5a036502b..2aa0377574 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProject.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProject.cs @@ -253,5 +253,15 @@ namespace ICSharpCode.PackageManagement {
return projectManager.LocalRepository.Exists (packageReference.Id, packageReference.Version);
}
+
+ public IPackageConstraintProvider ConstraintProvider {
+ get {
+ var constraintProvider = projectManager.LocalRepository as IPackageConstraintProvider;
+ if (constraintProvider != null) {
+ return constraintProvider;
+ }
+ return NullConstraintProvider.Instance;
+ }
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProjectOperations.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProjectOperations.cs new file mode 100644 index 0000000000..b550cf2910 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementProjectOperations.cs @@ -0,0 +1,151 @@ +//
+// PackageManagementProjectOperations.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using ICSharpCode.PackageManagement;
+using MonoDevelop.Ide;
+using MonoDevelop.Projects;
+using NuGet;
+
+namespace MonoDevelop.PackageManagement
+{
+ public class PackageManagementProjectOperations : IPackageManagementProjectOperations
+ {
+ IPackageManagementSolution solution;
+ IRegisteredPackageRepositories registeredPackageRepositories;
+ BackgroundPackageActionRunner backgroundActionRunner;
+ IPackageManagementEvents packageManagementEvents;
+
+ public PackageManagementProjectOperations (
+ IPackageManagementSolution solution,
+ IRegisteredPackageRepositories registeredPackageRepositories,
+ BackgroundPackageActionRunner backgroundActionRunner,
+ IPackageManagementEvents packageManagementEvents)
+ {
+ this.solution = solution;
+ this.registeredPackageRepositories = registeredPackageRepositories;
+ this.backgroundActionRunner = backgroundActionRunner;
+ this.packageManagementEvents = packageManagementEvents;
+
+ packageManagementEvents.ParentPackageInstalled += PackageInstalled;
+ packageManagementEvents.ParentPackageUninstalled += PackageUninstalled;
+ }
+
+ public event EventHandler<PackageManagementPackageReferenceEventArgs> PackageReferenceAdded;
+ public event EventHandler<PackageManagementPackageReferenceEventArgs> PackageReferenceRemoved;
+
+ public void InstallPackages (
+ string packageSourceUrl,
+ Project project,
+ IEnumerable<PackageManagementPackageReference> packages)
+ {
+ List<IPackageAction> actions = null;
+
+ DispatchService.GuiSyncDispatch (() => {
+ IPackageRepository repository = CreatePackageRepository (packageSourceUrl);
+ IPackageManagementProject packageManagementProject = solution.GetProject (repository, new DotNetProjectProxy ((DotNetProject)project));
+ actions = packages.Select (packageReference => {
+ InstallPackageAction action = packageManagementProject.CreateInstallPackageAction ();
+ action.PackageId = packageReference.Id;
+ action.PackageVersion = new SemanticVersion (packageReference.Version);
+ return (IPackageAction)action;
+ }).ToList ();
+ });
+
+ ProgressMonitorStatusMessage progressMessage = GetProgressMonitorStatusMessages (actions);
+ backgroundActionRunner.RunAndWait (progressMessage, actions);
+ }
+
+ IPackageRepository CreatePackageRepository (string packageSourceUrl)
+ {
+ IPackageRepository repository = registeredPackageRepositories.CreateRepository (new PackageSource (packageSourceUrl));
+ return new PriorityPackageRepository (MachineCache.Default, repository);
+ }
+
+ ProgressMonitorStatusMessage GetProgressMonitorStatusMessages (List<IPackageAction> packageActions)
+ {
+ if (packageActions.Count == 1) {
+ string packageId = packageActions.OfType<ProcessPackageAction> ().First ().PackageId;
+ return ProgressMonitorStatusMessageFactory.CreateInstallingSinglePackageMessage (packageId);
+ }
+ return ProgressMonitorStatusMessageFactory.CreateInstallingMultiplePackagesMessage (packageActions.Count);
+ }
+
+ public IEnumerable<PackageManagementPackageReference> GetInstalledPackages (Project project)
+ {
+ List<PackageManagementPackageReference> packageReferences = null;
+
+ DispatchService.GuiSyncDispatch (() => {
+ string url = RegisteredPackageSources.DefaultPackageSourceUrl;
+ var repository = registeredPackageRepositories.CreateRepository (new PackageSource (url));
+ IPackageManagementProject packageManagementProject = solution.GetProject (repository, new DotNetProjectProxy ((DotNetProject)project));
+ packageReferences = packageManagementProject
+ .GetPackageReferences ()
+ .Select (packageReference => new PackageManagementPackageReference (packageReference.Id, packageReference.Version.ToString ()))
+ .ToList ();
+ });
+
+ return packageReferences;
+ }
+
+ void PackageUninstalled (object sender, ParentPackageOperationEventArgs e)
+ {
+ OnPackageReferencedRemoved (e);
+ }
+
+ void PackageInstalled (object sender, ParentPackageOperationEventArgs e)
+ {
+ OnPackageReferenceAdded (e);
+ }
+
+ void OnPackageReferencedRemoved (ParentPackageOperationEventArgs e)
+ {
+ var handler = PackageReferenceRemoved;
+ if (handler != null) {
+ handler (this, CreateEventArgs (e));
+ }
+ }
+
+ void OnPackageReferenceAdded (ParentPackageOperationEventArgs e)
+ {
+ var handler = PackageReferenceAdded;
+ if (handler != null) {
+ handler (this, CreateEventArgs (e));
+ }
+ }
+
+ PackageManagementPackageReferenceEventArgs CreateEventArgs (ParentPackageOperationEventArgs e)
+ {
+ return new PackageManagementPackageReferenceEventArgs (
+ e.Project.DotNetProject,
+ e.Package.Id,
+ e.Package.Version.ToString ());
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementServices.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementServices.cs index 30670dbd14..ccf2cb438c 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementServices.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementServices.cs @@ -29,6 +29,7 @@ using System;
using NuGet;
using MonoDevelop.PackageManagement;
+using MonoDevelop.Core;
namespace ICSharpCode.PackageManagement
{
@@ -49,8 +50,9 @@ namespace ICSharpCode.PackageManagement static readonly IPackageManagementProgressMonitorFactory progressMonitorFactory;
static readonly PackageManagementProgressProvider progressProvider;
static readonly ProjectTargetFrameworkMonitor projectTargetFrameworkMonitor;
- static readonly PackageCompatibilityHandler packageCompatibilityHander;
+ static readonly PackageCompatibilityHandler packageCompatibilityHandler;
static readonly UpdatedPackagesInSolution updatedPackagesInSolution;
+ static readonly PackageManagementProjectOperations projectOperations;
static PackageManagementServices()
{
@@ -71,10 +73,13 @@ namespace ICSharpCode.PackageManagement backgroundPackageActionRunner = new BackgroundPackageActionRunner (progressMonitorFactory, packageManagementEvents, progressProvider);
projectTargetFrameworkMonitor = new ProjectTargetFrameworkMonitor (projectService);
- packageCompatibilityHander = new PackageCompatibilityHandler (projectTargetFrameworkMonitor);
+ packageCompatibilityHandler = new PackageCompatibilityHandler ();
+ packageCompatibilityHandler.MonitorTargetFrameworkChanges (projectTargetFrameworkMonitor);
updatedPackagesInSolution = new UpdatedPackagesInSolution (solution, registeredPackageRepositories, packageManagementEvents);
+ projectOperations = new PackageManagementProjectOperations (solution, registeredPackageRepositories, backgroundPackageActionRunner, packageManagementEvents);
+
InitializeCredentialProvider();
}
@@ -85,11 +90,21 @@ namespace ICSharpCode.PackageManagement static SettingsCredentialProvider CreateSettingsCredentialProvider (ICredentialProvider credentialProvider)
{
- ISettings settings = Settings.LoadDefaultSettings (null, null, null);
+ ISettings settings = LoadSettings ();
var packageSourceProvider = new PackageSourceProvider (settings);
return new SettingsCredentialProvider(credentialProvider, packageSourceProvider);
}
+ static ISettings LoadSettings ()
+ {
+ try {
+ return Settings.LoadDefaultSettings (null, null, null);
+ } catch (Exception ex) {
+ LoggingService.LogInternalError ("Unable to load NuGet.Config.", ex);
+ }
+ return NullSettings.Instance;
+ }
+
public static PackageManagementOptions Options {
get { return options; }
}
@@ -149,5 +164,9 @@ namespace ICSharpCode.PackageManagement public static IUpdatedPackagesInSolution UpdatedPackagesInSolution {
get { return updatedPackagesInSolution; }
}
+
+ public static IPackageManagementProjectOperations ProjectOperations {
+ get { return projectOperations; }
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementSolution.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementSolution.cs index eaed7d4ed3..f732ecd211 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementSolution.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementSolution.cs @@ -214,5 +214,10 @@ namespace ICSharpCode.PackageManagement yield return CreateProject (sourceRepository, dotNetProject);
}
}
+
+ public ISolutionPackageRepository GetRepository ()
+ {
+ return CreateSolutionPackageRepository ();
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRepositoryCache.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRepositoryCache.cs index 0315f4530a..ca1ae8b41d 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRepositoryCache.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRepositoryCache.cs @@ -29,6 +29,7 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using MonoDevelop.PackageManagement;
using NuGet;
namespace ICSharpCode.PackageManagement
@@ -40,17 +41,30 @@ namespace ICSharpCode.PackageManagement PackageManagementOptions options;
IList<RecentPackageInfo> recentPackages;
IRecentPackageRepository recentPackageRepository;
+ IPackageRepository machineCache;
ConcurrentDictionary<string, IPackageRepository> repositories =
new ConcurrentDictionary<string, IPackageRepository>();
public PackageRepositoryCache (
PackageManagementOptions options,
+ IPackageRepository machineCache,
ISharpDevelopPackageRepositoryFactory factory)
{
this.options = options;
+ this.machineCache = machineCache;
this.factory = factory;
this.recentPackages = options.RecentPackages;
}
+
+ public PackageRepositoryCache (
+ PackageManagementOptions options,
+ ISharpDevelopPackageRepositoryFactory factory)
+ : this (
+ options,
+ MachineCache.Default,
+ factory)
+ {
+ }
public PackageRepositoryCache (PackageManagementOptions options)
: this(
@@ -119,7 +133,7 @@ namespace ICSharpCode.PackageManagement IEnumerable<IPackageRepository> CreateAllEnabledRepositories()
{
foreach (PackageSource source in PackageSources.GetEnabledPackageSources ()) {
- yield return CreateRepository(source.Source);
+ yield return CreateRepositoryIgnoringFailures (source.Source);
}
}
@@ -160,5 +174,23 @@ namespace ICSharpCode.PackageManagement }
return recentPackageRepository;
}
+
+ public IPackageRepository CreateAggregateWithPriorityMachineCacheRepository ()
+ {
+ return new PriorityPackageRepository (machineCache, CreateAggregateRepository ());
+ }
+
+ IPackageRepository CreateRepositoryIgnoringFailures (string packageSource)
+ {
+ try {
+ return CreateRepository (packageSource);
+ } catch (Exception ex) {
+ // Deliberately caching the failing package source so the
+ // AggregateRepository only reports its failure once.
+ var repository = new FailingPackageRepository (packageSource, ex);
+ repositories.TryAdd(packageSource, repository);
+ return repository;
+ }
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestoreRunner.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestoreRunner.cs index dbf9d5af71..eb919868c7 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestoreRunner.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestoreRunner.cs @@ -1,4 +1,4 @@ -//
+//
// PackageRestoreRunner.cs
//
// Author:
@@ -33,6 +33,7 @@ using MonoDevelop.Ide; using MonoDevelop.Ide.Gui;
using MonoDevelop.Core.ProgressMonitoring;
using MonoDevelop.Projects;
+using NuGet;
namespace MonoDevelop.PackageManagement
{
@@ -41,23 +42,28 @@ namespace MonoDevelop.PackageManagement IPackageManagementSolution solution;
IPackageManagementProgressMonitorFactory progressMonitorFactory;
IPackageManagementEvents packageManagementEvents;
+ IProgressProvider progressProvider;
+ IDotNetProject project;
public PackageRestoreRunner()
: this(
PackageManagementServices.Solution,
PackageManagementServices.ProgressMonitorFactory,
- PackageManagementServices.PackageManagementEvents)
+ PackageManagementServices.PackageManagementEvents,
+ PackageManagementServices.ProgressProvider)
{
}
public PackageRestoreRunner(
IPackageManagementSolution solution,
IPackageManagementProgressMonitorFactory progressMonitorFactory,
- IPackageManagementEvents packageManagementEvents)
+ IPackageManagementEvents packageManagementEvents,
+ IProgressProvider progressProvider)
{
this.solution = solution;
this.progressMonitorFactory = progressMonitorFactory;
this.packageManagementEvents = packageManagementEvents;
+ this.progressProvider = progressProvider;
}
public void Run ()
@@ -65,72 +71,55 @@ namespace MonoDevelop.PackageManagement Run (ProgressMonitorStatusMessageFactory.CreateRestoringPackagesInSolutionMessage ());
}
+ public void Run (IDotNetProject project, ProgressMonitorStatusMessage progressMessage)
+ {
+ this.project = project;
+ Run (progressMessage);
+ }
+
public void Run (ProgressMonitorStatusMessage progressMessage)
{
- IProgressMonitor progressMonitor = CreateProgressMonitor (progressMessage);
-
- try {
- RestorePackages(progressMonitor, progressMessage);
- } catch (Exception ex) {
- LoggingService.LogInternalError (ex);
- progressMonitor.Log.WriteLine(ex.Message);
- progressMonitor.ReportError (progressMessage.Error, null);
- progressMonitor.ShowPackageConsole ();
- progressMonitor.Dispose();
- RestoreFailed = true;
+ using (ProgressMonitor progressMonitor = CreateProgressMonitor (progressMessage)) {
+ using (PackageManagementEventsMonitor eventMonitor = CreateEventMonitor (progressMonitor)) {
+ try {
+ RestorePackages (progressMonitor, progressMessage);
+ } catch (Exception ex) {
+ LoggingService.LogInternalError (ex);
+ progressMonitor.Log.WriteLine (ex.Message);
+ progressMonitor.ReportError (progressMessage.Error, null);
+ progressMonitor.ShowPackageConsole ();
+ progressMonitor.Dispose ();
+ RestoreFailed = true;
+ }
+ }
}
}
public bool RestoreFailed { get; private set; }
- IProgressMonitor CreateProgressMonitor (ProgressMonitorStatusMessage progressMessage)
+ ProgressMonitor CreateProgressMonitor (ProgressMonitorStatusMessage progressMessage)
{
return progressMonitorFactory.CreateProgressMonitor (progressMessage.Status);
}
- void RestorePackages(IProgressMonitor progressMonitor, ProgressMonitorStatusMessage progressMessage)
+ PackageManagementEventsMonitor CreateEventMonitor (ProgressMonitor monitor)
{
- var commandLine = new NuGetPackageRestoreCommandLine(solution);
-
- progressMonitor.Log.WriteLine(commandLine.ToString());
-
- RestorePackages(progressMonitor, progressMessage, commandLine);
+ return new PackageManagementEventsMonitor (monitor, packageManagementEvents, progressProvider);
}
- void RestorePackages(
- IProgressMonitor progressMonitor,
- ProgressMonitorStatusMessage progressMessage,
- NuGetPackageRestoreCommandLine commandLine)
+ void RestorePackages (ProgressMonitor progressMonitor, ProgressMonitorStatusMessage progressMessage)
{
- var aggregatedMonitor = (PackageManagementProgressMonitor)progressMonitor;
-
- IProcessAsyncOperation operation = Runtime.ProcessService.StartConsoleProcess (
- commandLine.Command,
- commandLine.Arguments,
- commandLine.WorkingDirectory,
- aggregatedMonitor.Console,
- (sender, e) => {
- using (progressMonitor) {
- OnPackageRestoreCompleted ((IAsyncOperation)sender, progressMonitor, progressMessage);
- }
- }
- );
+ var action = new RestorePackagesAction (solution, packageManagementEvents);
+ if (project != null) {
+ action.Project = project;
+ }
+ action.Execute ();
- // Wait for console to finish just so check for updates does not run until
- // all packages are restored.
- operation.WaitForCompleted ();
- }
+ RefreshProjectReferences ();
+ ForceCreationOfSharedRepositoriesConfigFile ();
- void OnPackageRestoreCompleted (
- IAsyncOperation operation,
- IProgressMonitor progressMonitor,
- ProgressMonitorStatusMessage progressMessage)
- {
- if (operation.Success) {
- RefreshProjectReferences ();
- ForceCreationOfSharedRepositoriesConfigFile ();
- }
- ReportOutcome (operation, progressMonitor, progressMessage);
+ progressMonitor.ReportSuccess (progressMessage.Success);
+ packageManagementEvents.OnPackagesRestored ();
}
/// <summary>
@@ -143,32 +132,18 @@ namespace MonoDevelop.PackageManagement solution.GetProjects (repository).ToList ();
}
+ /// <summary>
+ /// Refresh all projects even though we may have only restored packages for one project since
+ /// the packages may be used in other projects.
+ /// </summary>
void RefreshProjectReferences ()
{
DispatchService.GuiDispatch (() => {
- Solution solution = IdeApp.ProjectOperations.CurrentSelectedSolution;
- if (solution != null) {
- foreach (DotNetProject project in solution.GetAllDotNetProjects ()) {
- project.RefreshReferenceStatus ();
- }
+ foreach (IDotNetProject projectInSolution in solution.GetDotNetProjects ()) {
+ projectInSolution.DotNetProject.RefreshReferenceStatus ();
}
});
}
-
- void ReportOutcome (
- IAsyncOperation operation,
- IProgressMonitor progressMonitor,
- ProgressMonitorStatusMessage progressMessage)
- {
- if (operation.Success) {
- progressMonitor.ReportSuccess (progressMessage.Success);
- packageManagementEvents.OnPackagesRestored ();
- } else {
- progressMonitor.ReportError (progressMessage.Error, null);
- progressMonitor.ShowPackageConsole ();
- RestoreFailed = true;
- }
- }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestorer.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestorer.cs index da8eba3d32..912e981ecc 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestorer.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestorer.cs @@ -38,6 +38,7 @@ namespace MonoDevelop.PackageManagement public class PackageRestorer
{
List<ProjectPackageReferenceFile> packageReferenceFiles;
+ IDotNetProject singleProject;
public PackageRestorer (Solution solution)
: this (solution.GetAllDotNetProjects ())
@@ -47,6 +48,7 @@ namespace MonoDevelop.PackageManagement public PackageRestorer (DotNetProject project)
: this (new [] { project })
{
+ singleProject = new DotNetProjectProxy (project);
}
public PackageRestorer (IEnumerable<DotNetProject> projects)
@@ -88,7 +90,11 @@ namespace MonoDevelop.PackageManagement void RestoreWithProgressMonitor (ProgressMonitorStatusMessage progressMessage)
{
var runner = new PackageRestoreRunner ();
- runner.Run (progressMessage);
+ if (singleProject != null) {
+ runner.Run (singleProject, progressMessage);
+ } else {
+ runner.Run (progressMessage);
+ }
RestoreFailed = runner.RestoreFailed;
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageUpdateChecker.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageUpdateChecker.cs index 78c67ca0bb..8850375e3e 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageUpdateChecker.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageUpdateChecker.cs @@ -62,10 +62,10 @@ namespace MonoDevelop.PackageManagement void CheckForPackageUpdatesWithProgressMonitor ()
{
ProgressMonitorStatusMessage progressMessage = ProgressMonitorStatusMessageFactory.CreateCheckingForPackageUpdatesMessage ();
- using (IProgressMonitor progressMonitor = CreateProgressMonitor (progressMessage)) {
+ using (ProgressMonitor progressMonitor = CreateProgressMonitor (progressMessage)) {
try {
- using (IDisposable eventMonitor = new PackageUpdatesEventMonitor (progressMonitor)) {
- CheckForPackageUpdates (progressMonitor, progressMessage);
+ using (var eventMonitor = new PackageUpdatesEventMonitor (progressMonitor)) {
+ CheckForPackageUpdates (progressMonitor, progressMessage, eventMonitor);
}
} catch (Exception ex) {
LoggingService.LogInternalError (ex);
@@ -76,16 +76,21 @@ namespace MonoDevelop.PackageManagement }
}
- IProgressMonitor CreateProgressMonitor (ProgressMonitorStatusMessage progressMessage)
+ ProgressMonitor CreateProgressMonitor (ProgressMonitorStatusMessage progressMessage)
{
return progressMonitorFactory.CreateProgressMonitor (progressMessage.Status);
}
- void CheckForPackageUpdates (IProgressMonitor progressMonitor, ProgressMonitorStatusMessage progressMessage)
+ void CheckForPackageUpdates (
+ ProgressMonitor progressMonitor,
+ ProgressMonitorStatusMessage progressMessage,
+ PackageUpdatesEventMonitor eventMonitor)
{
updatedPackagesInSolution.CheckForUpdates ();
if (updatedPackagesInSolution.AnyUpdates ()) {
progressMonitor.ReportSuccess (GettextCatalog.GetString ("Package updates are available."));
+ } else if (eventMonitor.WarningReported) {
+ progressMonitor.ReportWarning (progressMessage.Warning);
} else {
progressMonitor.ReportSuccess (progressMessage.Success);
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageUpdatesEventMonitor.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageUpdatesEventMonitor.cs index 472aacdcef..4957c8b673 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageUpdatesEventMonitor.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageUpdatesEventMonitor.cs @@ -27,15 +27,16 @@ using System;
using ICSharpCode.PackageManagement;
using MonoDevelop.Core;
+using NuGet;
namespace MonoDevelop.PackageManagement
{
public class PackageUpdatesEventMonitor : IDisposable
{
IPackageManagementEvents packageEvents;
- IProgressMonitor progressMonitor;
+ ProgressMonitor progressMonitor;
- public PackageUpdatesEventMonitor (IProgressMonitor progressMonitor)
+ public PackageUpdatesEventMonitor (ProgressMonitor progressMonitor)
: this (
progressMonitor,
PackageManagementServices.PackageManagementEvents)
@@ -43,7 +44,7 @@ namespace MonoDevelop.PackageManagement }
public PackageUpdatesEventMonitor (
- IProgressMonitor progressMonitor,
+ ProgressMonitor progressMonitor,
IPackageManagementEvents packageEvents)
{
this.progressMonitor = progressMonitor;
@@ -55,13 +56,18 @@ namespace MonoDevelop.PackageManagement void PackageOperationMessageLogged (object sender, PackageOperationMessageLoggedEventArgs e)
{
progressMonitor.Log.WriteLine (e.Message.ToString ());
+
+ if (e.Message.Level == MessageLevel.Warning) {
+ WarningReported = true;
+ }
}
public void Dispose ()
{
packageEvents.PackageOperationMessageLogged -= PackageOperationMessageLogged;
}
- }
+ public bool WarningReported { get; private set; }
+ }
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackagesViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackagesViewModel.cs index 3c2934d1d8..86b2ed48c8 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackagesViewModel.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackagesViewModel.cs @@ -124,7 +124,7 @@ namespace ICSharpCode.PackageManagement void StartReadPackagesTask(bool clearPackages = true)
{
IsReadingPackages = true;
- HasError = false;
+ ClearError ();
if (clearPackages) {
ClearPackages ();
}
@@ -132,6 +132,12 @@ namespace ICSharpCode.PackageManagement CreateReadPackagesTask();
task.Start();
}
+
+ void ClearError ()
+ {
+ HasError = false;
+ ErrorMessage = String.Empty;
+ }
protected virtual void UpdateRepositoryBeforeReadPackagesTaskStarts()
{
@@ -170,6 +176,7 @@ namespace ICSharpCode.PackageManagement // Ignore.
return;
} else {
+ SaveAnyWarnings ();
UpdatePackagesForSelectedPage(task.Result);
}
base.OnPropertyChanged(null);
@@ -193,6 +200,20 @@ namespace ICSharpCode.PackageManagement return errorMessage.ToString();
}
+ void SaveAnyWarnings ()
+ {
+ string warning = GetWarningMessage ();
+ if (!String.IsNullOrEmpty (warning)) {
+ HasError = true;
+ ErrorMessage = warning;
+ }
+ }
+
+ protected virtual string GetWarningMessage ()
+ {
+ return String.Empty;
+ }
+
void UpdatePackagesForSelectedPage(PackagesForSelectedPageResult result)
{
pages.TotalItems = result.TotalPackages;
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackagesViewModels.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackagesViewModels.cs index 2bf7ad3e67..f93581a5ab 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackagesViewModels.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackagesViewModels.cs @@ -44,7 +44,7 @@ namespace ICSharpCode.PackageManagement //var installedPackageViewModelFactory = new InstalledPackageViewModelFactory(packageViewModelFactory);
IRecentPackageRepository recentPackageRepository = PackageManagementServices.RecentPackageRepository;
- AvailablePackagesViewModel = new AvailablePackagesViewModel(registeredPackageRepositories, recentPackageRepository, packageViewModelFactory, taskFactory);
+ AvailablePackagesViewModel = new AvailablePackagesViewModel (solution, registeredPackageRepositories, recentPackageRepository, packageViewModelFactory, taskFactory);
//InstalledPackagesViewModel = new InstalledPackagesViewModel(solution, packageManagementEvents, registeredPackageRepositories, installedPackageViewModelFactory, taskFactory);
//UpdatedPackagesViewModel = new UpdatedPackagesViewModel(solution, registeredPackageRepositories, updatedPackageViewModelFactory, taskFactory);
//RecentPackagesViewModel = new RecentPackagesViewModel(packageManagementEvents, registeredPackageRepositories, packageViewModelFactory, taskFactory);
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PreventPackagesConfigFileBeingRemovedOnUpdateMonitor.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PreventPackagesConfigFileBeingRemovedOnUpdateMonitor.cs new file mode 100644 index 0000000000..07345ba0a2 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PreventPackagesConfigFileBeingRemovedOnUpdateMonitor.cs @@ -0,0 +1,71 @@ +//
+// PreventPackagesConfigFileBeingRemovedOnUpdateMonitor.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using ICSharpCode.PackageManagement;
+using System.IO;
+using MonoDevelop.Core;
+
+namespace MonoDevelop.PackageManagement
+{
+ /// <summary>
+ /// When updating a package the packages.config file may be removed, if all packages are
+ /// uninstalled during the update, which causes the version control system to mark the file as
+ /// deleted. During an update the packages.config file will be recreated so the version control
+ /// system should not mark it as deleted. This monitor class looks for the packages.config file
+ /// being removed, cancels the standard file deletion call to FileService.RemoveFile, and
+ /// removes the file itself.
+ /// </summary>
+ public class PreventPackagesConfigFileBeingRemovedOnUpdateMonitor : IDisposable
+ {
+ IPackageManagementEvents packageManagementEvents;
+ IFileRemover fileRemover;
+
+ public PreventPackagesConfigFileBeingRemovedOnUpdateMonitor (
+ IPackageManagementEvents packageManagementEvents,
+ IFileRemover fileRemover)
+ {
+ this.packageManagementEvents = packageManagementEvents;
+ this.fileRemover = fileRemover;
+
+ packageManagementEvents.FileRemoving += FileRemoving;
+ }
+
+ void FileRemoving (object sender, FileRemovingEventArgs e)
+ {
+ if (e.FileName.IsPackagesConfigFileName ()) {
+ e.IsCancelled = true;
+ fileRemover.RemoveFile (e.FileName);
+ }
+ }
+
+ public void Dispose ()
+ {
+ packageManagementEvents.FileRemoving -= FileRemoving;
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageAction.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageAction.cs index 53d3b33c81..a17603c744 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageAction.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageAction.cs @@ -218,7 +218,12 @@ namespace ICSharpCode.PackageManagement {
Package = Project
.SourceRepository
- .FindPackage(PackageId, PackageVersion, AllowPrereleaseVersions, allowUnlisted: false);
+ .FindPackage (
+ PackageId,
+ PackageVersion,
+ Project.ConstraintProvider,
+ AllowPrereleaseVersions,
+ allowUnlisted: false);
}
void ThrowPackageNotFoundError(string packageId)
@@ -233,12 +238,20 @@ namespace ICSharpCode.PackageManagement return Project.IsPackageInstalled(id);
}
- string GetPackageId()
+ public string GetPackageId ()
{
if (Package != null) {
return Package.Id;
}
return PackageId;
}
+
+ public SemanticVersion GetPackageVersion ()
+ {
+ if (Package != null) {
+ return Package.Version;
+ }
+ return PackageVersion;
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProgressMonitorExtensions.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProgressMonitorExtensions.cs index 6054ce7cf4..6474b90952 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProgressMonitorExtensions.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProgressMonitorExtensions.cs @@ -34,7 +34,7 @@ namespace MonoDevelop.PackageManagement {
public static class ProgressMonitorExtensions
{
- public static void ShowPackageConsole (this IProgressMonitor monitor)
+ public static void ShowPackageConsole (this ProgressMonitor monitor)
{
DispatchService.GuiDispatch (() => {
var aggregatedMonitor = (PackageManagementProgressMonitor)monitor;
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProgressMonitorStatusMessageFactory.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProgressMonitorStatusMessageFactory.cs index 7de966f3a8..ae73cdb840 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProgressMonitorStatusMessageFactory.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProgressMonitorStatusMessageFactory.cs @@ -163,6 +163,16 @@ namespace MonoDevelop.PackageManagement );
}
+ public static ProgressMonitorStatusMessage CreateRestoringPackagesInProjectMessage ()
+ {
+ return new ProgressMonitorStatusMessage (
+ GetString ("Restoring packages for project..."),
+ GetString ("Packages successfully restored."),
+ GetString ("Could not restore packages. Please see Package Console for details."),
+ GetString ("Packages restored with warnings. Please see Package Console for details.")
+ );
+ }
+
public static ProgressMonitorStatusMessage CreateCheckingPackageCompatibilityMessage ()
{
return new ProgressMonitorStatusMessage (
@@ -209,7 +219,7 @@ namespace MonoDevelop.PackageManagement GetString ("Checking for package updates..."),
GetString ("Packages are up to date."),
GetString ("Could not check for package updates. Please see Package Console for details."),
- String.Empty);
+ GetString ("No updates found but warnings were reported. Please see Package Console for details."));
}
static string GetString (string phrase)
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectExtensions.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectExtensions.cs index d04a5b35f4..a75fe987ca 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectExtensions.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectExtensions.cs @@ -38,7 +38,7 @@ namespace ICSharpCode.PackageManagement public static void Save(this Project project)
{
DispatchService.GuiSyncDispatch(() => {
- IdeApp.ProjectOperations.Save(project);
+ IdeApp.ProjectOperations.SaveAsync(project);
});
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectProxy.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectProxy.cs index 7aef3277df..763b683343 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectProxy.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectProxy.cs @@ -29,6 +29,7 @@ using System.Collections; using ICSharpCode.PackageManagement;
using MonoDevelop.Core;
using MonoDevelop.Projects;
+using System.Collections.Generic;
namespace MonoDevelop.PackageManagement
{
@@ -61,6 +62,10 @@ namespace MonoDevelop.PackageManagement get { return project.ExtendedProperties; }
}
+ public IEnumerable<string> FlavorGuids {
+ get { return project.FlavorGuids; }
+ }
+
public void Save ()
{
project.Save ();
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectTemplateNuGetPackageInstaller.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectTemplateNuGetPackageInstaller.cs index 5197bcba90..03884b65c7 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectTemplateNuGetPackageInstaller.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectTemplateNuGetPackageInstaller.cs @@ -61,6 +61,9 @@ namespace MonoDevelop.PackageManagement public override void Run (Solution solution, IList<PackageReferencesForCreatedProject> packageReferencesForCreatedProjects)
{
List<IPackageAction> installPackageActions = CreatePackageActions (solution, packageReferencesForCreatedProjects);
+ if (!installPackageActions.Any ())
+ return;
+
ProgressMonitorStatusMessage progressMessage = ProgressMonitorStatusMessageFactory.CreateInstallingProjectTemplatePackagesMessage ();
backgroundPackageActionRunner.Run (progressMessage, installPackageActions);
}
@@ -79,7 +82,7 @@ namespace MonoDevelop.PackageManagement var installPackageActions = new List<IPackageAction> ();
foreach (PackageReferencesForCreatedProject packageReferences in packageReferencesForCreatedProjects) {
- var project = solution.GetAllProjects ().First (p => p.Name == packageReferences.ProjectName) as DotNetProject;
+ var project = solution.GetAllProjects ().FirstOrDefault (p => p.Name == packageReferences.ProjectName) as DotNetProject;
if (project != null) {
installPackageActions.AddRange (CreateInstallPackageActions (project, packageReferences));
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectTemplatePackageRepositoryCache.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectTemplatePackageRepositoryCache.cs index 5b546e5d09..d6e695b431 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectTemplatePackageRepositoryCache.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectTemplatePackageRepositoryCache.cs @@ -86,5 +86,10 @@ namespace ICSharpCode.PackageManagement {
return packageRepositoryCache.CreateRepository(packageSource);
}
+
+ public IPackageRepository CreateAggregateWithPriorityMachineCacheRepository ()
+ {
+ throw new NotImplementedException ();
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentPackageRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentPackageRepository.cs index f2e8b14cc8..b8c869ebc1 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentPackageRepository.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentPackageRepository.cs @@ -117,6 +117,7 @@ namespace ICSharpCode.PackageManagement public IQueryable<IPackage> GetPackages()
{
//UpdatePackages();
+ RemoveInvalidPackages ();
return packages.AsQueryable();
}
@@ -127,6 +128,17 @@ namespace ICSharpCode.PackageManagement packages.AddRange(recentPackages);
}
}
+
+ void RemoveInvalidPackages ()
+ {
+ packages.RemoveAll (package => !IsValidPackage (package));
+ }
+
+ static bool IsValidPackage (IPackage package)
+ {
+ var packageFromRepository = package as IPackageFromRepository;
+ return (packageFromRepository != null) && packageFromRepository.IsValid;
+ }
bool HasRecentPackagesBeenRead()
{
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RegisteredPackageRepositories.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RegisteredPackageRepositories.cs index c326c47d1b..fcc7f64264 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RegisteredPackageRepositories.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RegisteredPackageRepositories.cs @@ -37,7 +37,6 @@ namespace ICSharpCode.PackageManagement {
IPackageRepositoryCache repositoryCache;
PackageManagementOptions options;
- RegisteredPackageSources registeredPackageSources;
PackageSource activePackageSource;
IPackageRepository activePackageRepository;
@@ -47,7 +46,6 @@ namespace ICSharpCode.PackageManagement {
this.repositoryCache = repositoryCache;
this.options = options;
- registeredPackageSources = options.PackageSources;
}
public IRecentPackageRepository RecentPackageRepository {
@@ -69,7 +67,7 @@ namespace ICSharpCode.PackageManagement }
public bool HasMultiplePackageSources {
- get { return registeredPackageSources.HasMultipleEnabledPackageSources; }
+ get { return PackageSources.HasMultipleEnabledPackageSources; }
}
public PackageSource ActivePackageSource {
@@ -122,6 +120,7 @@ namespace ICSharpCode.PackageManagement }
UpdateActivePackageSource ();
+ UpdateActivePackageRepository ();
} catch (Exception) {
PackageSources.AddRange (packageSourcesBackup);
UpdateActivePackageSource ();
@@ -149,5 +148,17 @@ namespace ICSharpCode.PackageManagement }
}
}
+
+ void UpdateActivePackageRepository ()
+ {
+ if (activePackageSource == null)
+ return;
+
+ if (activePackageSource.IsAggregate ()) {
+ // Force recreation of AggregateRepository to reset any
+ // failing package repositories.
+ activePackageRepository = null;
+ }
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RestoreBeforeUpdateAction.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RestoreBeforeUpdateAction.cs index 154e67ee5f..3d3c5ce64c 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RestoreBeforeUpdateAction.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RestoreBeforeUpdateAction.cs @@ -57,7 +57,8 @@ namespace MonoDevelop.PackageManagement IPackageManagementProject project,
Action afterRestore)
{
- Restore (new [] { project }, afterRestore);
+ var runner = new RestoreBeforeUpdateAction ();
+ runner.RestoreProjectPackages (project.DotNetProject, afterRestore);
}
public static void Restore (
@@ -65,18 +66,23 @@ namespace MonoDevelop.PackageManagement Action afterRestore)
{
var runner = new RestoreBeforeUpdateAction ();
- runner.RestoreProjectPackages (
+ runner.RestoreAllPackagesInSolution (
projects.Select (project => project.DotNetProject),
afterRestore);
}
- public void RestoreProjectPackages (
+ public void RestoreAllPackagesInSolution (
IEnumerable<DotNetProject> projects,
Action afterRestore)
{
+ var restorer = new PackageRestorer (projects);
+ Restore (restorer, afterRestore);
+ }
+
+ void Restore (PackageRestorer restorer, Action afterRestore)
+ {
ProgressMonitorStatusMessage progressMessage = ProgressMonitorStatusMessageFactory.CreateRestoringPackagesBeforeUpdateMessage ();
- var restorer = new PackageRestorer (projects);
DispatchService.BackgroundDispatch (() => {
restorer.Restore (progressMessage);
if (!restorer.RestoreFailed) {
@@ -84,6 +90,12 @@ namespace MonoDevelop.PackageManagement }
});
}
+
+ public void RestoreProjectPackages (DotNetProject project, Action afterRestore)
+ {
+ var restorer = new PackageRestorer (project);
+ Restore (restorer, afterRestore);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RestorePackagesAction.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RestorePackagesAction.cs new file mode 100644 index 0000000000..17e844d4da --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RestorePackagesAction.cs @@ -0,0 +1,192 @@ +//
+// RestorePackagesAction.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using ICSharpCode.PackageManagement;
+using NuGet;
+using MonoDevelop.Core;
+
+namespace MonoDevelop.PackageManagement
+{
+ public class RestorePackagesAction : IPackageAction
+ {
+ IPackageManagementSolution solution;
+ ISolutionPackageRepository solutionPackageRepository;
+ IPackageRepositoryCache repositoryCache;
+ IPackageManagerFactory packageManagerFactory;
+ ILogger logger;
+
+ public RestorePackagesAction ()
+ : this (
+ PackageManagementServices.Solution,
+ PackageManagementServices.PackageManagementEvents)
+ {
+ }
+
+ public RestorePackagesAction (
+ IPackageManagementSolution solution,
+ IPackageManagementEvents packageManagementEvents)
+ : this (
+ solution,
+ packageManagementEvents,
+ PackageManagementServices.PackageRepositoryCache,
+ new SharpDevelopPackageManagerFactory ())
+ {
+ }
+
+ public RestorePackagesAction (
+ IPackageManagementSolution solution,
+ IPackageManagementEvents packageManagementEvents,
+ IPackageRepositoryCache repositoryCache,
+ IPackageManagerFactory packageManagerFactory)
+ {
+ this.solution = solution;
+ this.repositoryCache = repositoryCache;
+ this.packageManagerFactory = packageManagerFactory;
+
+ logger = new PackageManagementLogger (packageManagementEvents);
+ }
+
+ public IDotNetProject Project { get; set; }
+
+ public void Execute ()
+ {
+ Log ("Restoring packages...");
+
+ int packagesRestored = 0;
+ List<PackageReference> packageReferences = GetPackageReferences ().ToList ();
+ foreach (PackageReference packageReference in packageReferences) {
+ if (IsPackageRestored (packageReference)) {
+ LogPackageAlreadyRestored (packageReference);
+ } else {
+ packagesRestored++;
+ RestorePackage (packageReference.Id, packageReference.Version);
+ }
+ }
+
+ LogResult (packageReferences.Count, packagesRestored);
+ }
+
+ void Log (string message)
+ {
+ logger.Log (MessageLevel.Info, message);
+ }
+
+ void LogPackageAlreadyRestored (PackageReference packageReference)
+ {
+ logger.Log (MessageLevel.Debug, GettextCatalog.GetString ("Skipping '{0}' because it is already restored.", packageReference));
+ }
+
+ void LogResult (int totalPackageReferences, int packagesRestored)
+ {
+ if (packagesRestored == 0) {
+ Log ("All packages are already restored.");
+ } else if (packagesRestored == 1) {
+ Log (GettextCatalog.GetString ("1 package restored successfully."));
+ } else if (packagesRestored > 0) {
+ Log (GettextCatalog.GetString ("{0} packages restored successfully.", packagesRestored));
+ }
+ }
+
+ IEnumerable<PackageReference> GetPackageReferences ()
+ {
+ if (Project != null) {
+ return GetPackageReferencesForSingleProject ();
+ }
+ return GetPackageReferencesForSolution ()
+ .Concat (GetPackageReferencesForAllProjects ());
+ }
+
+ IEnumerable<PackageReference> GetPackageReferencesForSingleProject ()
+ {
+ IPackageRepository repository = repositoryCache.CreateAggregateRepository ();
+ IPackageManagementProject project = solution.GetProject (repository, Project);
+ return project.GetPackageReferences ();
+ }
+
+ IEnumerable<PackageReference> GetPackageReferencesForSolution ()
+ {
+ return SolutionPackageRepository.GetPackageReferences ();
+ }
+
+ IEnumerable<PackageReference> GetPackageReferencesForAllProjects ()
+ {
+ return solution
+ .GetProjects (repositoryCache.CreateAggregateRepository ())
+ .SelectMany (project => project.GetPackageReferences ())
+ .Distinct ();
+ }
+
+ bool IsPackageRestored (PackageReference packageReference)
+ {
+ return SolutionPackageRepository.IsRestored (packageReference);
+ }
+
+ ISolutionPackageRepository SolutionPackageRepository {
+ get {
+ if (solutionPackageRepository == null) {
+ solutionPackageRepository = solution.GetRepository ();
+ }
+ return solutionPackageRepository;
+ }
+ }
+
+ void RestorePackage (string packageId, SemanticVersion version)
+ {
+ IPackageRepository sourceRepository = CreateSourceRepository ();
+ using (IDisposable operation = sourceRepository.StartRestoreOperation (packageId, version.ToString ())) {
+ IPackage package = PackageHelper.ResolvePackage (sourceRepository, packageId, version);
+ IPackageManager packageManager = CreatePackageManager (sourceRepository);
+
+ packageManager.InstallPackage (
+ package,
+ ignoreDependencies: true,
+ allowPrereleaseVersions: true,
+ ignoreWalkInfo: true);
+ }
+ }
+
+ IPackageRepository CreateSourceRepository ()
+ {
+ return repositoryCache.CreateAggregateWithPriorityMachineCacheRepository ();
+ }
+
+ IPackageManager CreatePackageManager (IPackageRepository sourceRepository)
+ {
+ IPackageManager packageManager = packageManagerFactory.CreatePackageManager (sourceRepository, SolutionPackageRepository);
+ packageManager.Logger = logger;
+ return packageManager;
+ }
+
+ public bool HasPackageScriptsToRun ()
+ {
+ return false;
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SettingsProvider.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SettingsProvider.cs index 8d277b8f69..2488c558da 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SettingsProvider.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SettingsProvider.cs @@ -28,6 +28,7 @@ using System; using System.IO;
using ICSharpCode.PackageManagement;
using NuGet;
+using MonoDevelop.Core;
namespace MonoDevelop.PackageManagement
{
@@ -62,7 +63,12 @@ namespace MonoDevelop.PackageManagement public ISettings LoadSettings ()
{
- return LoadSettings (GetSolutionDirectory ());
+ try {
+ return LoadSettings (GetSolutionDirectory ());
+ } catch (Exception ex) {
+ LoggingService.LogInternalError ("Unable to load NuGet.Config file.", ex);
+ }
+ return NullSettings.Instance;
}
string GetSolutionDirectory ()
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SharpDevelopPackageManagerFactory.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SharpDevelopPackageManagerFactory.cs index b73f1a0b20..02626127aa 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SharpDevelopPackageManagerFactory.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SharpDevelopPackageManagerFactory.cs @@ -80,5 +80,16 @@ namespace ICSharpCode.PackageManagement {
return projectSystemFactory.CreateProjectSystem(project);
}
+
+ public IPackageManager CreatePackageManager (
+ IPackageRepository sourceRepository,
+ ISolutionPackageRepository solutionPackageRepository)
+ {
+ return new PackageManager (
+ sourceRepository,
+ solutionPackageRepository.PackagePathResolver,
+ solutionPackageRepository.FileSystem,
+ solutionPackageRepository.Repository);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SharpDevelopPackageRepositoryFactory.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SharpDevelopPackageRepositoryFactory.cs index 938cf529a5..afcd7dffb4 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SharpDevelopPackageRepositoryFactory.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SharpDevelopPackageRepositoryFactory.cs @@ -28,6 +28,7 @@ using System;
using System.Collections.Generic;
+using MonoDevelop.PackageManagement;
using NuGet;
namespace ICSharpCode.PackageManagement
@@ -51,7 +52,7 @@ namespace ICSharpCode.PackageManagement public IPackageRepository CreateAggregateRepository(IEnumerable<IPackageRepository> repositories)
{
- return new AggregateRepository(repositories);
+ return new MonoDevelopAggregateRepository (repositories);
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SolutionExtensions.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SolutionExtensions.cs index c77db7ebe2..2ed0ee5e66 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SolutionExtensions.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SolutionExtensions.cs @@ -29,7 +29,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
-using MonoDevelop.Core.ProgressMonitoring;
+using MonoDevelop.Core;
using MonoDevelop.Projects;
namespace ICSharpCode.PackageManagement
@@ -38,7 +38,7 @@ namespace ICSharpCode.PackageManagement {
public static void Save(this Solution solution)
{
- solution.Save(new NullProgressMonitor());
+ solution.Save(new ProgressMonitor());
}
public static IEnumerable<DotNetProject> GetAllDotNetProjects (this Solution solution)
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SolutionPackageRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SolutionPackageRepository.cs index 47600b40a3..da361f1f20 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SolutionPackageRepository.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SolutionPackageRepository.cs @@ -115,5 +115,30 @@ namespace ICSharpCode.PackageManagement {
return repository.GetPackages();
}
+
+ public bool IsRestored (PackageReference packageReference)
+ {
+ if (packageReference.Version == null) {
+ return false;
+ }
+
+ return CreateLocalPackageRepository ()
+ .GetPackageLookupPaths (packageReference.Id, packageReference.Version)
+ .Any ();
+ }
+
+ protected virtual LocalPackageRepository CreateLocalPackageRepository ()
+ {
+ return new LocalPackageRepository (packagePathResolver, fileSystem);
+ }
+
+ public IEnumerable<PackageReference> GetPackageReferences ()
+ {
+ var sharedRepository = Repository as SharedPackageRepository;
+ if (sharedRepository != null) {
+ return sharedRepository.PackageReferenceFile.GetPackageReferences ();
+ }
+ return Enumerable.Empty <PackageReference> ();
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ThreadSafePackageManagementEvents.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ThreadSafePackageManagementEvents.cs index 394a4089a3..f4a3eaf390 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ThreadSafePackageManagementEvents.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ThreadSafePackageManagementEvents.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using MonoDevelop.Core;
using MonoDevelop.Ide;
using NuGet;
+using MonoDevelop.PackageManagement;
namespace ICSharpCode.PackageManagement
{
@@ -272,5 +273,15 @@ namespace ICSharpCode.PackageManagement {
unsafeEvents.OnUpdatedPackagesAvailable ();
}
+
+ public event EventHandler<FileRemovingEventArgs> FileRemoving {
+ add { unsafeEvents.FileRemoving += value; }
+ remove { unsafeEvents.FileRemoving -= value; }
+ }
+
+ public bool OnFileRemoving (string path)
+ {
+ return unsafeEvents.OnFileRemoving (path);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/UpdatePackageAction.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/UpdatePackageAction.cs index 5ece2f0a90..888c0a861e 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/UpdatePackageAction.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/UpdatePackageAction.cs @@ -29,16 +29,33 @@ using System;
using System.Collections.Generic;
using NuGet;
+using MonoDevelop.PackageManagement;
namespace ICSharpCode.PackageManagement
{
public class UpdatePackageAction : ProcessPackageOperationsAction, IUpdatePackageSettings
{
- public UpdatePackageAction(
+ IPackageManagementEvents packageManagementEvents;
+ IFileRemover fileRemover;
+
+ public UpdatePackageAction (
IPackageManagementProject project,
IPackageManagementEvents packageManagementEvents)
- : base(project, packageManagementEvents)
+ : this (
+ project,
+ packageManagementEvents,
+ new FileRemover ())
+ {
+ }
+
+ public UpdatePackageAction (
+ IPackageManagementProject project,
+ IPackageManagementEvents packageManagementEvents,
+ IFileRemover fileRemover)
+ : base (project, packageManagementEvents)
{
+ this.packageManagementEvents = packageManagementEvents;
+ this.fileRemover = fileRemover;
UpdateDependencies = true;
UpdateIfPackageDoesNotExistInProject = true;
}
@@ -57,7 +74,9 @@ namespace ICSharpCode.PackageManagement protected override void ExecuteCore()
{
if (ShouldUpdatePackage()) {
- Project.UpdatePackage(Package, this);
+ using (IDisposable monitor = CreateFileMonitor ()) {
+ Project.UpdatePackage(Package, this);
+ }
OnParentPackageInstalled();
}
}
@@ -70,6 +89,13 @@ namespace ICSharpCode.PackageManagement return true;
}
+ IDisposable CreateFileMonitor ()
+ {
+ return new PreventPackagesConfigFileBeingRemovedOnUpdateMonitor (
+ packageManagementEvents,
+ fileRemover);
+ }
+
protected override string StartingMessageFormat {
get { return "Updating {0}..."; }
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/UpdatedPackages.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/UpdatedPackages.cs index 7e01c69ed0..3d2984e654 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/UpdatedPackages.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/UpdatedPackages.cs @@ -38,19 +38,22 @@ namespace ICSharpCode.PackageManagement {
IPackageRepository sourceRepository;
List<IPackageName> installedPackages;
+ IPackageConstraintProvider constraintProvider;
public UpdatedPackages (
IPackageManagementProject project,
IPackageRepository aggregateRepository)
: this (
project.GetPackageReferences (),
- aggregateRepository)
+ aggregateRepository,
+ project.ConstraintProvider)
{
}
public UpdatedPackages (
IEnumerable<PackageReference> packageReferences,
- IPackageRepository aggregrateRepository)
+ IPackageRepository aggregrateRepository,
+ IPackageConstraintProvider constraintProvider)
{
installedPackages = packageReferences
.Select (packageReference => new PackageName (packageReference.Id, packageReference.Version))
@@ -58,6 +61,7 @@ namespace ICSharpCode.PackageManagement .ToList ();
this.sourceRepository = aggregrateRepository;
+ this.constraintProvider = constraintProvider;
}
public UpdatedPackages(
@@ -71,14 +75,14 @@ namespace ICSharpCode.PackageManagement public IEnumerable<IPackage> GetUpdatedPackages (bool includePrerelease = false)
{
List<IPackageName> localPackages = installedPackages;
- IEnumerable<IPackageName> distinctLocalPackages = DistinctPackages2 (localPackages);
- return GetUpdatedPackages (sourceRepository, distinctLocalPackages, includePrerelease);
+ IEnumerable<IPackageName> distinctLocalPackages = DistinctPackages (localPackages);
+ return GetUpdatedPackages (distinctLocalPackages, includePrerelease);
}
/// <summary>
/// If we have jQuery 1.6 and 1.7 then return just jquery 1.6
/// </summary>
- IEnumerable<IPackageName> DistinctPackages2 (List<IPackageName> packages)
+ IEnumerable<IPackageName> DistinctPackages (List<IPackageName> packages)
{
if (packages.Any ()) {
packages.Sort ((x, y) => x.Version.CompareTo (y.Version));
@@ -88,11 +92,18 @@ namespace ICSharpCode.PackageManagement }
IEnumerable<IPackage> GetUpdatedPackages (
- IPackageRepository sourceRepository,
IEnumerable<IPackageName> localPackages,
bool includePrelease)
{
- return sourceRepository.GetUpdates (localPackages, includePrelease, false);
+ IEnumerable<IVersionSpec> constraints = localPackages
+ .Select (package => constraintProvider.GetConstraint (package.Id));
+
+ return sourceRepository.GetUpdates (
+ localPackages,
+ includePrelease,
+ false,
+ null,
+ constraints);
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/UpdatedPackagesInSolution.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/UpdatedPackagesInSolution.cs index 1ed3238092..696a33cde0 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/UpdatedPackagesInSolution.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/UpdatedPackagesInSolution.cs @@ -111,6 +111,7 @@ namespace MonoDevelop.PackageManagement {
LogCheckingForUpdates (project.Name);
+ project.Logger = new PackageManagementLogger (packageManagementEvents);
var updatedPackages = new UpdatedPackages (project, project.SourceRepository);
List<IPackage> packages = updatedPackages.GetUpdatedPackages ().ToList ();
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisCommands.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisCommands.cs index 4fe2c5f86f..392aacd522 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisCommands.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisCommands.cs @@ -59,10 +59,18 @@ namespace MonoDevelop.AnalysisCore { protected override void Update (CommandInfo info) { - MonoDevelop.Ide.Gui.Document document; - IList<FixableResult> results; - info.Enabled = FixOperationsHandler.GetFixes (out document, out results) - && results.Any (r => FixOperationsHandler.GetActions (document, r).Any ()); + var doc = MonoDevelop.Ide.IdeApp.Workbench.ActiveDocument; + if (doc == null || doc.Editor == null) { + info.Enabled = false; + return; + } + var codeActionExtension = doc.GetContent <CodeActionEditorExtension> (); + if (codeActionExtension == null) { + info.Enabled = false; + return; + } + var fixes = codeActionExtension.GetCurrentFixes (); + info.Enabled = fixes.Any (); } protected override void Run () diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs index 9c3b135e75..ea74e0f17b 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs @@ -607,12 +607,12 @@ namespace MonoDevelop.CodeActions currentSmartTag.Popup (); } + static readonly List<CodeAction> emptyList = new List<CodeAction> (); internal List<CodeAction> GetCurrentFixes () { - if (currentSmartTag == null) + if (QuickTaskStrip.EnableFancyFeatures && currentSmartTag == null) return RefactoringService.GetValidActions (document, document.Editor.Caret.Location).Result.ToList (); - return currentSmartTag.fixes; + return currentSmartTag == null ? emptyList : currentSmartTag.fixes; } } -} - +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/BatchFixer.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/BatchFixer.cs index 783b45ff03..a0d4cf4cde 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/BatchFixer.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/BatchFixer.cs @@ -46,9 +46,9 @@ namespace MonoDevelop.CodeIssues { readonly IActionMatcher matcher; - readonly IProgressMonitor monitor; + readonly ProgressMonitor monitor; - public BatchFixer (IActionMatcher matcher, IProgressMonitor monitor) + public BatchFixer (IActionMatcher matcher, ProgressMonitor monitor) { this.matcher = matcher; this.monitor = monitor; diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/ProgressMonitorWrapperJob.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/ProgressMonitorWrapperJob.cs index 6557a3c04e..b1eea307cf 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/ProgressMonitorWrapperJob.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/ProgressMonitorWrapperJob.cs @@ -36,7 +36,7 @@ namespace MonoDevelop.CodeIssues { readonly IAnalysisJob wrappedJob; - IProgressMonitor monitor;
+ ProgressMonitor monitor;
int reportingThinningFactor = 100;
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameItemDialog.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameItemDialog.cs index c39249dc12..cb6bf8acef 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameItemDialog.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameItemDialog.cs @@ -113,6 +113,10 @@ namespace MonoDevelop.Refactoring.Rename entry.Text = member.Name; } // fileName = member.Region.FileName; + } else if (options.SelectedItem is IType) { + var lvar = (IType)options.SelectedItem; + entry.Text = lvar.Name; + // this.fileName = lvar.Region.FileName; } else if (options.SelectedItem is ITypeParameter) { var lvar = (ITypeParameter)options.SelectedItem; entry.Text = lvar.Name; @@ -183,7 +187,7 @@ namespace MonoDevelop.Refactoring.Rename var properties = Properties; ((Widget)this).Destroy (); List<Change> changes = rename.PerformChanges (options, properties); - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor (this.Title, null); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor (this.Title, null); RefactoringService.AcceptChanges (monitor, changes); } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameRefactoring.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameRefactoring.cs index 7a3cf5a6c3..2faf66fb59 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameRefactoring.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameRefactoring.cs @@ -89,7 +89,7 @@ namespace MonoDevelop.Refactoring.Rename new RenameRefactoring ().Run (options); return; } - using (var monitor = new NullProgressMonitor ()) { + using (var monitor = new ProgressMonitor ()) { var col = ReferenceFinder.FindReferences (entity, true, monitor); List<Change> result = new List<Change> (); @@ -110,7 +110,7 @@ namespace MonoDevelop.Refactoring.Rename public static void RenameVariable (IVariable variable, string newName) { - using (var monitor = new NullProgressMonitor ()) { + using (var monitor = new ProgressMonitor ()) { var col = ReferenceFinder.FindReferences (variable, true, monitor); List<Change> result = new List<Change> (); @@ -139,7 +139,7 @@ namespace MonoDevelop.Refactoring.Rename return; } - using (var monitor = new NullProgressMonitor ()) { + using (var monitor = new ProgressMonitor ()) { var col = ReferenceFinder.FindReferences (typeParameter, true, monitor); List<Change> result = new List<Change> (); @@ -160,7 +160,7 @@ namespace MonoDevelop.Refactoring.Rename public static void RenameNamespace (INamespace ns, string newName) { - using (var monitor = new NullProgressMonitor ()) { + using (var monitor = new ProgressMonitor ()) { var col = ReferenceFinder.FindReferences (ns, true, monitor); List<Change> result = new List<Change> (); diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/Change.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/Change.cs index 0f3805e639..3b09f630f7 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/Change.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/Change.cs @@ -47,7 +47,7 @@ namespace MonoDevelop.Refactoring { } - public abstract void PerformChange (IProgressMonitor monitor, RefactoringOptions rctx); + public abstract void PerformChange (ProgressMonitor monitor, RefactoringOptions rctx); } public class TextReplaceChange : Change @@ -118,7 +118,7 @@ namespace MonoDevelop.Refactoring return GetTextEditorData (FileName); } } - public override void PerformChange (IProgressMonitor monitor, RefactoringOptions rctx) + public override void PerformChange (ProgressMonitor monitor, RefactoringOptions rctx) { if (rctx == null) throw new InvalidOperationException ("Refactory context not available."); @@ -177,11 +177,11 @@ namespace MonoDevelop.Refactoring this.Description = string.Format (GettextCatalog.GetString ("Create file '{0}'"), Path.GetFileName (fileName)); } - public override void PerformChange (IProgressMonitor monitor, RefactoringOptions rctx) + public override void PerformChange (ProgressMonitor monitor, RefactoringOptions rctx) { File.WriteAllText (FileName, Content); rctx.Document.Project.AddFile (FileName); - IdeApp.ProjectOperations.Save (rctx.Document.Project); + IdeApp.ProjectOperations.SaveAsync (rctx.Document.Project); } } @@ -198,7 +198,7 @@ namespace MonoDevelop.Refactoring this.Description = string.Format (GettextCatalog.GetString ("Open file '{0}'"), Path.GetFileName (fileName)); } - public override void PerformChange (IProgressMonitor monitor, RefactoringOptions rctx) + public override void PerformChange (ProgressMonitor monitor, RefactoringOptions rctx) { IdeApp.Workbench.OpenDocument (FileName); } @@ -227,7 +227,7 @@ namespace MonoDevelop.Refactoring this.Description = string.Format (GettextCatalog.GetString ("Rename file '{0}' to '{1}'"), Path.GetFileName (oldName), Path.GetFileName (newName)); } - public override void PerformChange (IProgressMonitor monitor, RefactoringOptions rctx) + public override void PerformChange (ProgressMonitor monitor, RefactoringOptions rctx) { if (rctx == null) throw new ArgumentNullException ("rctx"); @@ -235,7 +235,7 @@ namespace MonoDevelop.Refactoring if (IdeApp.ProjectOperations.CurrentSelectedSolution != null) { foreach (var p in IdeApp.ProjectOperations.CurrentSelectedSolution.GetAllProjects ()) { if (p.GetProjectFile (NewName) != null) - IdeApp.ProjectOperations.Save (p); + IdeApp.ProjectOperations.SaveAsync (p); } } } @@ -254,9 +254,9 @@ namespace MonoDevelop.Refactoring this.Description = string.Format (GettextCatalog.GetString ("Save project {0}"), project.Name); } - public override void PerformChange (IProgressMonitor monitor, RefactoringOptions rctx) + public override void PerformChange (ProgressMonitor monitor, RefactoringOptions rctx) { - IdeApp.ProjectOperations.Save (this.Project); + IdeApp.ProjectOperations.SaveAsync (this.Project); } } } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewDialog.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewDialog.cs index ecfbf2e593..0f98ee8010 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewDialog.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewDialog.cs @@ -87,7 +87,7 @@ namespace MonoDevelop.Refactoring }; buttonOk.Clicked += delegate { - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor (this.Title, null); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor (this.Title, null); RefactoringService.AcceptChanges (monitor, changes); Destroy (); diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs index d91b6f9a6d..1d9353ba5e 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs @@ -156,12 +156,12 @@ namespace MonoDevelop.Refactoring } } - public static void AcceptChanges (IProgressMonitor monitor, List<Change> changes) + public static void AcceptChanges (ProgressMonitor monitor, List<Change> changes) { AcceptChanges (monitor, changes, MonoDevelop.Ide.TextFileProvider.Instance); } - public static void AcceptChanges (IProgressMonitor monitor, List<Change> changes, MonoDevelop.Projects.Text.ITextFileProvider fileProvider) + public static void AcceptChanges (ProgressMonitor monitor, List<Change> changes, MonoDevelop.Projects.Text.ITextFileProvider fileProvider) { var rctx = new RefactoringOptions (null); var handler = new RenameHandler (changes); @@ -199,6 +199,9 @@ namespace MonoDevelop.Refactoring return inspectors.Where (i => i.MimeType == mimeType); } + static Stopwatch validActionsWatch = new Stopwatch (); + static Stopwatch actionWatch = new Stopwatch (); + public static Task<IEnumerable<CodeAction>> GetValidActions (Document doc, TextLocation loc, CancellationToken cancellationToken = default (CancellationToken)) { var editor = doc.Editor; @@ -207,6 +210,8 @@ namespace MonoDevelop.Refactoring var result = new List<CodeAction> (); var timer = InstrumentationService.CreateTimerCounter ("Source analysis background task", "Source analysis"); timer.BeginTiming (); + validActionsWatch.Restart (); + var timeTable = new Dictionary<CodeActionProvider, long> (); try { var parsedDocument = doc.ParsedDocument; if (editor != null && parsedDocument != null && parsedDocument.CreateRefactoringContext != null) { @@ -217,7 +222,10 @@ namespace MonoDevelop.Refactoring disabledNodes.IndexOf (fix.IdString, StringComparison.Ordinal) < 0)) { try { + actionWatch.Restart (); result.AddRange (provider.GetActions (doc, ctx, loc, cancellationToken)); + actionWatch.Stop (); + timeTable[provider] = actionWatch.ElapsedMilliseconds; } catch (Exception ex) { LoggingService.LogError ("Error in context action provider " + provider.Title, ex); } @@ -228,6 +236,14 @@ namespace MonoDevelop.Refactoring LoggingService.LogError ("Error in analysis service", ex); } finally { timer.EndTiming (); + validActionsWatch.Stop (); + if (validActionsWatch.ElapsedMilliseconds > 1000) { + LoggingService.LogWarning ("Warning slow edit action update."); + foreach (var pair in timeTable) { + if (pair.Value > 50) + LoggingService.LogInfo ("ACTION '" + pair.Key.Title + "' took " + pair.Value +"ms"); + } + } } return (IEnumerable<CodeAction>)result; }, cancellationToken); diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/ResolveCommandHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/ResolveCommandHandler.cs index bb4555eb46..97ab500655 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/ResolveCommandHandler.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/ResolveCommandHandler.cs @@ -202,9 +202,12 @@ namespace MonoDevelop.Refactoring var unit = SyntaxTree.Parse (CreateStub (doc, offset), doc.FileName); + var parsedDocument = doc.ParsedDocument; + if (parsedDocument == null) + return null; return ResolveAtLocation.Resolve ( doc.Compilation, - doc.ParsedDocument.ParsedFile as CSharpUnresolvedFile, + parsedDocument.ParsedFile as CSharpUnresolvedFile, unit, location, out node); @@ -276,14 +279,14 @@ namespace MonoDevelop.Refactoring if (OnlyAddReference) return GettextCatalog.GetString ( "Reference '{0}'", - GetLibraryName ()); + GetLibraryName ().Replace ("_", "__")); if (Reference != null) return GettextCatalog.GetString ( "Reference '{0}' and use '{1}'", GetLibraryName (), - string.Format ("using {0};", Namespace)); + string.Format ("using {0};", Namespace.Replace ("_", "__"))); - return string.Format ("using {0};", Namespace); + return string.Format ("using {0};", Namespace.Replace ("_", "__")); } public string GetInsertNamespaceText (string member) @@ -291,10 +294,10 @@ namespace MonoDevelop.Refactoring if (Reference != null) return GettextCatalog.GetString ( "Reference '{0}' and use '{1}'", - GetLibraryName (), - Namespace + "." + member + GetLibraryName ().Replace ("_", "__"), + (Namespace + "." + member).Replace ("_", "__") ); - return Namespace + "." + member; + return (Namespace + "." + member).Replace ("_", "__"); } } @@ -338,14 +341,14 @@ namespace MonoDevelop.Refactoring var compilations = new List<Tuple<ICompilation, MonoDevelop.Projects.ProjectReference>> (); compilations.Add (Tuple.Create (doc.Compilation, (MonoDevelop.Projects.ProjectReference)null)); - var referencedItems = IdeApp.Workspace != null ? project.GetReferencedItems (IdeApp.Workspace.ActiveConfiguration).ToList () : (IEnumerable<SolutionItem>) new SolutionItem[0]; + var referencedItems = IdeApp.Workspace != null ? project.GetReferencedItems (IdeApp.Workspace.ActiveConfiguration).ToList () : (IEnumerable<SolutionFolderItem>) new SolutionFolderItem[0]; var solution = project != null ? project.ParentSolution : null; if (solution != null) { foreach (var curProject in solution.GetAllProjects ()) { if (curProject == project || referencedItems.Contains (curProject)) continue; - var otherRefes = IdeApp.Workspace != null ? curProject.GetReferencedItems (IdeApp.Workspace.ActiveConfiguration).ToList () : (IEnumerable<SolutionItem>) new SolutionItem[0]; + var otherRefes = IdeApp.Workspace != null ? curProject.GetReferencedItems (IdeApp.Workspace.ActiveConfiguration).ToList () : (IEnumerable<SolutionFolderItem>) new SolutionFolderItem[0]; if (otherRefes.Contains (project)) continue; @@ -540,7 +543,7 @@ namespace MonoDevelop.Refactoring if (reference != null) { var project = doc.Project; project.Items.Add (reference); - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); } if (string.IsNullOrEmpty (ns)) diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.OptionPanels/BehaviorPanel.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.OptionPanels/BehaviorPanel.cs index e916b46e87..ccf1be8f63 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.OptionPanels/BehaviorPanel.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.OptionPanels/BehaviorPanel.cs @@ -40,9 +40,8 @@ namespace MonoDevelop.SourceEditor.OptionPanels indentationCombobox.InsertText (2, GettextCatalog.GetString ("Smart")); // indentationCombobox.InsertText (3, GettextCatalog.GetString ("Virtual")); - controlLeftRightCombobox.InsertText (0, GettextCatalog.GetString ("MonoDevelop")); - controlLeftRightCombobox.InsertText (1, GettextCatalog.GetString ("Emacs")); - controlLeftRightCombobox.InsertText (2, GettextCatalog.GetString ("SharpDevelop")); + controlLeftRightCombobox.InsertText (0, GettextCatalog.GetString ("Unix")); + controlLeftRightCombobox.InsertText (1, GettextCatalog.GetString ("Windows")); autoInsertBraceCheckbutton.Toggled += HandleAutoInsertBraceCheckbuttonToggled; } @@ -55,7 +54,7 @@ namespace MonoDevelop.SourceEditor.OptionPanels tabAsReindentCheckbutton.Active = DefaultSourceEditorOptions.Instance.TabIsReindent; indentationCombobox.Active = (int)DefaultSourceEditorOptions.Instance.IndentStyle; - controlLeftRightCombobox.Active = (int)DefaultSourceEditorOptions.Instance.ControlLeftRightMode; + controlLeftRightCombobox.Active = (int)DefaultSourceEditorOptions.Instance.WordNavigationStyle; useViModesCheck.Active = DefaultSourceEditorOptions.Instance.UseViModes; checkbuttonOnTheFlyFormatting.Active = DefaultSourceEditorOptions.Instance.OnTheFlyFormatting; checkbuttonGenerateFormattingUndoStep.Active = DefaultSourceEditorOptions.Instance.GenerateFormattingUndoStep; @@ -79,7 +78,7 @@ namespace MonoDevelop.SourceEditor.OptionPanels DefaultSourceEditorOptions.Instance.SmartSemicolonPlacement = smartSemicolonPlaceCheckbutton.Active; DefaultSourceEditorOptions.Instance.IndentStyle = (IndentStyle)indentationCombobox.Active; DefaultSourceEditorOptions.Instance.TabIsReindent = tabAsReindentCheckbutton.Active; - DefaultSourceEditorOptions.Instance.ControlLeftRightMode = (ControlLeftRightMode)controlLeftRightCombobox.Active; + DefaultSourceEditorOptions.Instance.WordNavigationStyle = (WordNavigationStyle)controlLeftRightCombobox.Active; DefaultSourceEditorOptions.Instance.UseViModes = useViModesCheck.Active; DefaultSourceEditorOptions.Instance.OnTheFlyFormatting = checkbuttonOnTheFlyFormatting.Active; DefaultSourceEditorOptions.Instance.GenerateFormattingUndoStep = checkbuttonGenerateFormattingUndoStep.Active; diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/AbstractUsagesExtension.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/AbstractUsagesExtension.cs index 102de5bf0a..a88335d795 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/AbstractUsagesExtension.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/AbstractUsagesExtension.cs @@ -71,7 +71,8 @@ namespace MonoDevelop.SourceEditor void HandleTextEditorDataSelectionChanged (object sender, EventArgs e) { - RemoveMarkers (); + if (TextEditorData.IsSomethingSelected) + RemoveMarkers (); } void HandleTextEditorDataDocumentTextReplaced (object sender, DocumentChangeEventArgs e) diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ErrorText.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ErrorText.cs index dadd156bd5..1f09e62575 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ErrorText.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ErrorText.cs @@ -40,11 +40,11 @@ namespace MonoDevelop.SourceEditor { public class ErrorText { - public Task Task { get; set; } + public UserTask Task { get; set; } public bool IsError { get; set; } public string ErrorMessage { get; set; } - public ErrorText (Task task, bool isError, string errorMessage) + public ErrorText (UserTask task, bool isError, string errorMessage) { this.Task = task; this.IsError = isError; diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/MessageBubbleTextMarker.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/MessageBubbleTextMarker.cs index 7484634970..c80f55b283 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/MessageBubbleTextMarker.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/MessageBubbleTextMarker.cs @@ -61,7 +61,7 @@ namespace MonoDevelop.SourceEditor get { return errors; } } - Task task; + UserTask task; DocumentLine lineSegment; // int editorAllocHeight = -1; // int lastLineLength = -1; @@ -143,7 +143,7 @@ namespace MonoDevelop.SourceEditor string initialText; bool isError; - internal MessageBubbleTextMarker (MessageBubbleCache cache, Task task, DocumentLine lineSegment, bool isError, string errorMessage) + internal MessageBubbleTextMarker (MessageBubbleCache cache, UserTask task, DocumentLine lineSegment, bool isError, string errorMessage) { if (cache == null) throw new ArgumentNullException ("cache"); @@ -158,7 +158,7 @@ namespace MonoDevelop.SourceEditor } static System.Text.RegularExpressions.Regex mcsErrorFormat = new System.Text.RegularExpressions.Regex ("(.+)\\(CS\\d+\\)\\Z"); - public void AddError (Task task, bool isError, string errorMessage) + public void AddError (UserTask task, bool isError, string errorMessage) { var match = mcsErrorFormat.Match (errorMessage); if (match.Success) diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorOptions.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorOptions.cs index 1aff7ad2ae..349021bdef 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorOptions.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorOptions.cs @@ -33,11 +33,18 @@ using MonoDevelop.Ide.Fonts; namespace MonoDevelop.SourceEditor { - public enum ControlLeftRightMode { + [Obsolete ("Use WordNavigationStyle")] + public enum ControlLeftRightMode + { MonoDevelop, Emacs, SharpDevelop - + } + + public enum WordNavigationStyle + { + Unix, + Windows } public enum LineEndingConversion { @@ -180,8 +187,8 @@ namespace MonoDevelop.SourceEditor case "OnTheFlyFormatting": this.OnTheFlyFormatting = (bool)args.NewValue; break; - case "ControlLeftRightMode": - this.ControlLeftRightMode = (ControlLeftRightMode)args.NewValue; + case "WordNavigationStyle": + this.WordNavigationStyle = (WordNavigationStyle)args.NewValue; break; case "EnableAnimations": base.EnableAnimations = (bool)args.NewValue; @@ -223,8 +230,13 @@ namespace MonoDevelop.SourceEditor this.defaultCommentFolding = PropertyService.Get ("DefaultCommentFolding", true); this.useViModes = PropertyService.Get ("UseViModes", false); this.onTheFlyFormatting = PropertyService.Get ("OnTheFlyFormatting", true); - var defaultControlMode = (ControlLeftRightMode)Enum.Parse (typeof(ControlLeftRightMode), DesktopService.DefaultControlLeftRightBehavior); - this.ControlLeftRightMode = PropertyService.Get ("ControlLeftRightMode", defaultControlMode); + + WordNavigationStyle defaultWordNavigation = WordNavigationStyle.Unix; + if (Platform.IsWindows || PropertyService.Get ("ControlLeftRightMode", (string)null) == "SharpDevelop") { + defaultWordNavigation = WordNavigationStyle.Windows; + } + this.WordNavigationStyle = PropertyService.Get ("WordNavigationStyle", defaultWordNavigation); + base.EnableAnimations = PropertyService.Get ("EnableAnimations", true); this.EnableHighlightUsages = PropertyService.Get ("EnableHighlightUsages", false); base.DrawIndentationMarkers = PropertyService.Get ("DrawIndentationMarkers", false); @@ -448,18 +460,38 @@ namespace MonoDevelop.SourceEditor get { return defaultEolMarker; } } - ControlLeftRightMode controlLeftRightMode = Platform.IsWindows - ? ControlLeftRightMode.SharpDevelop - : ControlLeftRightMode.MonoDevelop; - + WordNavigationStyle wordNavigationStyle = Platform.IsWindows + ? WordNavigationStyle.Windows + : WordNavigationStyle.Unix; + + [Obsolete("Use WordNavigationStyle")] public ControlLeftRightMode ControlLeftRightMode { get { - return controlLeftRightMode; + return WordNavigationStyle == WordNavigationStyle.Unix + ? ControlLeftRightMode.MonoDevelop + : ControlLeftRightMode.SharpDevelop; } set { - if (controlLeftRightMode != value) { - controlLeftRightMode = value; - PropertyService.Set ("ControlLeftRightMode", value); + switch (value) { + case ControlLeftRightMode.Emacs: + case ControlLeftRightMode.MonoDevelop: + WordNavigationStyle = WordNavigationStyle.Unix; + return; + default: + WordNavigationStyle = WordNavigationStyle.Windows; + return; + } + } + } + + public WordNavigationStyle WordNavigationStyle { + get { + return wordNavigationStyle; + } + set { + if (wordNavigationStyle != value) { + wordNavigationStyle = value; + PropertyService.Set ("WordNavigationStyle", value); SetWordFindStrategy (); OnChanged (EventArgs.Empty); } @@ -481,19 +513,16 @@ namespace MonoDevelop.SourceEditor void SetWordFindStrategy () { if (useViModes) { - this.wordFindStrategy = new Mono.TextEditor.Vi.ViWordFindStrategy (); + wordFindStrategy = new Mono.TextEditor.Vi.ViWordFindStrategy (); return; } - switch (ControlLeftRightMode) { - case ControlLeftRightMode.MonoDevelop: - this.wordFindStrategy = new EmacsWordFindStrategy (true); - break; - case ControlLeftRightMode.Emacs: - this.wordFindStrategy = new EmacsWordFindStrategy (false); + switch (WordNavigationStyle) { + case WordNavigationStyle.Windows: + wordFindStrategy = new SharpDevelopWordFindStrategy (); break; - case ControlLeftRightMode.SharpDevelop: - this.wordFindStrategy = new SharpDevelopWordFindStrategy (); + default: + wordFindStrategy = new EmacsWordFindStrategy (); break; } } diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs index d301d929f5..97788a8b15 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs @@ -562,7 +562,7 @@ namespace MonoDevelop.SourceEditor void UpdateTasks (object sender, TaskEventArgs e) { - Task[] tasks = TaskService.Errors.GetFileTasks (ContentName); + UserTask[] tasks = TaskService.Errors.GetFileTasks (ContentName); if (tasks == null) return; DisposeErrorMarkers (); // disposes messageBubbleCache as well. @@ -573,7 +573,7 @@ namespace MonoDevelop.SourceEditor messageBubbleCache.Dispose (); messageBubbleCache = new MessageBubbleCache (widget.TextEditor); - foreach (Task task in tasks) { + foreach (UserTask task in tasks) { if (task.Severity == TaskSeverity.Error || task.Severity == TaskSeverity.Warning) { if (IdeApp.Preferences.ShowMessageBubbles == ShowMessageBubbles.ForErrors && task.Severity == TaskSeverity.Warning) continue; diff --git a/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Commands/WebReferenceCommandHandler.cs b/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Commands/WebReferenceCommandHandler.cs index 6a50df42ec..fcf9d390cf 100644 --- a/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Commands/WebReferenceCommandHandler.cs +++ b/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Commands/WebReferenceCommandHandler.cs @@ -47,7 +47,7 @@ namespace MonoDevelop.WebReferences.Commands return; dialog.SelectedService.GenerateFiles (project, dialog.Namespace, dialog.ReferenceName); - IdeApp.ProjectOperations.Save(project); + IdeApp.ProjectOperations.SaveAsync(project); } catch (Exception exception) { MessageService.ShowException (exception); } finally { @@ -105,7 +105,7 @@ namespace MonoDevelop.WebReferences.Commands DispatchService.GuiDispatch (() => { // Make sure that we save all relevant projects, there should only be 1 though foreach (var project in items.Select (i =>i.Project).Distinct ()) - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); IdeApp.Workbench.StatusBar.ShowMessage(GettextCatalog.GetPluralString ("Updated Web Reference {0}", "Updated Web References", items.Count, items[0].Name)); DisposeUpdateContext (); @@ -133,7 +133,7 @@ namespace MonoDevelop.WebReferences.Commands if (!MessageService.Confirm (GettextCatalog.GetString ("Are you sure you want to delete the web service reference '{0}'?", item.Name), AlertButton.Delete)) return; item.Delete(); - IdeApp.ProjectOperations.Save (item.Project); + IdeApp.ProjectOperations.SaveAsync (item.Project); IdeApp.Workbench.StatusBar.ShowMessage("Deleted Web Reference " + item.Name); } @@ -153,7 +153,7 @@ namespace MonoDevelop.WebReferences.Commands foreach (var item in items.ToList ()) item.Delete(); - IdeApp.ProjectOperations.Save(project); + IdeApp.ProjectOperations.SaveAsync(project); IdeApp.Workbench.StatusBar.ShowMessage("Deleted all Web References"); } diff --git a/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Dialogs/WCFConfigWidget.cs b/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Dialogs/WCFConfigWidget.cs index d69ba80256..cfbea29412 100644 --- a/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Dialogs/WCFConfigWidget.cs +++ b/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Dialogs/WCFConfigWidget.cs @@ -53,7 +53,7 @@ namespace MonoDevelop.WebReferences.Dialogs listAccess.Active = options.GenerateInternalTypes ? 1 : 0; listAsync.Active = AsyncOptionToIndex; - if (project is PortableDotNetProject) { + if (project.IsPortableLibrary) { listAccess.Sensitive = false; listAsync.Sensitive = false; } diff --git a/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Dialogs/WebReferenceDialog.cs b/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Dialogs/WebReferenceDialog.cs index e5873989a4..9feda476cf 100644 --- a/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Dialogs/WebReferenceDialog.cs +++ b/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Dialogs/WebReferenceDialog.cs @@ -169,7 +169,7 @@ namespace MonoDevelop.WebReferences.Dialogs tbxReferenceURL.Text = homeUrl; wcfOptions = WebReferencesService.WcfEngine.DefaultClientOptions; - if (project is PortableDotNetProject) { + if (project.IsPortableLibrary) { wcfOptions.GenerateAsynchronousMethods = false; wcfOptions.GenerateEventBasedAsynchronousMethods = true; } @@ -491,7 +491,7 @@ namespace MonoDevelop.WebReferences.Dialogs btnOK.Sensitive = isWebService; tlbNavigate.Visible = WebBrowserService.CanGetWebBrowser; tbxReferenceName.Sensitive = isWebService; - comboModel.Sensitive = !(project is PortableDotNetProject); + comboModel.Sensitive = !project.IsPortableLibrary; break; case DialogState.CreateConfig: diff --git a/main/src/addins/MonoDevelop.WebReferences/gtk-gui/MonoDevelop.WebReferences.Dialogs.WCFConfigWidget.cs b/main/src/addins/MonoDevelop.WebReferences/gtk-gui/MonoDevelop.WebReferences.Dialogs.WCFConfigWidget.cs index 26c8b48195..3788b1590a 100644 --- a/main/src/addins/MonoDevelop.WebReferences/gtk-gui/MonoDevelop.WebReferences.Dialogs.WCFConfigWidget.cs +++ b/main/src/addins/MonoDevelop.WebReferences/gtk-gui/MonoDevelop.WebReferences.Dialogs.WCFConfigWidget.cs @@ -5,14 +5,23 @@ namespace MonoDevelop.WebReferences.Dialogs public partial class WCFConfigWidget { private global::Gtk.VBox dialog1_VBox; + private global::Gtk.Table wcfOptions; + private global::Gtk.ComboBox dictionaryCollection; + private global::Gtk.Label label1; + private global::Gtk.Label label2; + private global::Gtk.Label label3; + private global::Gtk.Label label4; + private global::Gtk.ComboBox listAccess; + private global::Gtk.ComboBox listAsync; + private global::Gtk.ComboBox listCollection; protected virtual void Build () diff --git a/main/src/addins/MonoDevelop.WebReferences/gtk-gui/MonoDevelop.WebReferences.Dialogs.WebReferenceDialog.cs b/main/src/addins/MonoDevelop.WebReferences/gtk-gui/MonoDevelop.WebReferences.Dialogs.WebReferenceDialog.cs index 9a240c227b..b103b95f2a 100644 --- a/main/src/addins/MonoDevelop.WebReferences/gtk-gui/MonoDevelop.WebReferences.Dialogs.WebReferenceDialog.cs +++ b/main/src/addins/MonoDevelop.WebReferences/gtk-gui/MonoDevelop.WebReferences.Dialogs.WebReferenceDialog.cs @@ -5,29 +5,53 @@ namespace MonoDevelop.WebReferences.Dialogs internal partial class WebReferenceDialog { private global::Gtk.UIManager UIManager; + private global::Gtk.Action btnNavBack; + private global::Gtk.Action btnNavNext; + private global::Gtk.Action btnRefresh; + private global::Gtk.Action btnStop; + private global::Gtk.Action btnHome; + private global::Gtk.VBox vbxContainer; + private global::Gtk.Toolbar tlbNavigate; + private global::Gtk.Table tblWebReferenceUrl; + private global::Gtk.Button btnGO; + private global::Gtk.Label lblWebServiceUrl; + private global::Gtk.Entry tbxReferenceURL; + private global::Gtk.Frame frmBrowser; + private global::Gtk.Table tblReferenceName; + private global::Gtk.HBox hbox1; + private global::Gtk.ComboBox comboModel; + private global::Gtk.Label label1; + private global::Gtk.Label lblNamespace; + private global::Gtk.Label lblReference; + private global::Gtk.Entry tbxNamespace; + private global::Gtk.Entry tbxReferenceName; + private global::Gtk.Button btnCancel; + private global::Gtk.Button btnBack; + private global::Gtk.Button btnOK; + private global::Gtk.Button btnConfig; protected virtual void Build () @@ -61,7 +85,7 @@ namespace MonoDevelop.WebReferences.Dialogs this.vbxContainer = new global::Gtk.VBox (); this.vbxContainer.Name = "vbxContainer"; // Container child vbxContainer.Gtk.Box+BoxChild - this.UIManager.AddUiFromString (@"<ui><toolbar name='tlbNavigate'><toolitem name='btnNavBack' action='btnNavBack'/><toolitem name='btnNavNext' action='btnNavNext'/><toolitem name='btnRefresh' action='btnRefresh'/><toolitem name='btnStop' action='btnStop'/><toolitem name='btnHome' action='btnHome'/></toolbar></ui>"); + this.UIManager.AddUiFromString ("<ui><toolbar name='tlbNavigate'><toolitem name='btnNavBack' action='btnNavBack'/><toolitem name='btnNavNext' action='btnNavNext'/><toolitem name='btnRefresh' action='btnRefresh'/><toolitem name='btnStop' action='btnStop'/><toolitem name='btnHome' action='btnHome'/></toolbar></ui>"); this.tlbNavigate = ((global::Gtk.Toolbar)(this.UIManager.GetWidget ("/tlbNavigate"))); this.tlbNavigate.Name = "tlbNavigate"; this.tlbNavigate.ShowArrow = false; diff --git a/main/src/addins/MonoDeveloperExtensions/Commands.cs b/main/src/addins/MonoDeveloperExtensions/Commands.cs index 9c0477378e..8cab36b704 100644 --- a/main/src/addins/MonoDeveloperExtensions/Commands.cs +++ b/main/src/addins/MonoDeveloperExtensions/Commands.cs @@ -50,13 +50,13 @@ namespace MonoDeveloper protected override void Update (CommandInfo info) { - info.Visible = MonoMakefileFormat.IsMonoProject (IdeApp.ProjectOperations.CurrentSelectedProject); + info.Visible = IdeApp.ProjectOperations.CurrentSelectedItem is MakefileProject; } void Install (object prj) { DotNetProject p = prj as DotNetProject; - using (IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBuildProgressMonitor ()) { + using (ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBuildProgressMonitor ()) { p.RunTarget (monitor, "install", IdeApp.Workspace.ActiveConfiguration); } } diff --git a/main/src/addins/MonoDeveloperExtensions/MakefileProject.cs b/main/src/addins/MonoDeveloperExtensions/MakefileProject.cs new file mode 100644 index 0000000000..d48001bfad --- /dev/null +++ b/main/src/addins/MonoDeveloperExtensions/MakefileProject.cs @@ -0,0 +1,405 @@ +// +// MakefileProject.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using MonoDevelop.Projects; +using MonoDevelop.Core; +using System.Collections; +using System.Threading.Tasks; +using System.IO; +using System.Text.RegularExpressions; +using MonoDevelop.Ide; +using MonoDevelop.Core.ProgressMonitoring; +using MonoDevelop.Core.Execution; +using System.CodeDom.Compiler; + +namespace MonoDeveloper +{ + public class MakefileProject: WorkspaceObject + { + string name; + FilePath file; + + public MakefileProject (string lang) + { + } + + public new string Name { + get { return name; } + set { name = value; } + } + + public FilePath FileName { + get { return file; } + set { file = value; } + } + + #region implemented abstract members of WorkspaceObject + + protected override string OnGetName () + { + return name; + } + + protected override string OnGetItemDirectory () + { + return file.ParentDirectory; + } + + protected override string OnGetBaseDirectory () + { + return file.ParentDirectory; + } + + #endregion + + + DotNetProject project; + string outFile; + ArrayList refNames = new ArrayList (); + bool loading; + string testFileBase; + object unitTest; + + public MakefileProject (DotNetProject project) + { + this.project = project; + project.FileAddedToProject += OnFileAddedToProject; + project.FileRemovedFromProject += OnFileRemovedFromProject; + project.FileRenamedInProject += OnFileRenamedInProject; + } + + public string SourcesFile { + get { return outFile + ".sources"; } + } + + public bool SyncFileName { + get { return false; } + } + + public string ItemId { + get { + if (project.ParentSolution != null) + return project.ParentSolution.GetRelativeChildPath (project.FileName); + else + return project.Name; + } + } + + public Task Save (MonoDevelop.Core.ProgressMonitor monitor) + { + return Task.FromResult (0); + } + + internal void Read (MonoMakefile mkfile) + { + loading = true; + + string basePath = Path.GetDirectoryName (mkfile.FileName); + string aname; + + string targetAssembly = mkfile.GetVariable ("LIBRARY"); + if (targetAssembly == null) { + targetAssembly = mkfile.GetVariable ("PROGRAM"); + if (Path.GetDirectoryName (targetAssembly) == "") + targetAssembly = Path.Combine (basePath, targetAssembly); + aname = Path.GetFileName (targetAssembly); + } else { + aname = Path.GetFileName (targetAssembly); + string targetName = mkfile.GetVariable ("LIBRARY_NAME"); + if (targetName != null) targetAssembly = targetName; + targetAssembly = "$(topdir)/class/lib/$(PROFILE)/" + targetAssembly; + } + + outFile = Path.Combine (basePath, aname); + project.FileName = mkfile.FileName; + + ArrayList checkedFolders = new ArrayList (); + + // Parse projects + string sources = outFile + ".sources"; + StreamReader sr = new StreamReader (sources); + string line; + while ((line = sr.ReadLine ()) != null) { + line = line.Trim (' ','\t'); + if (line != "") { + string fname = Path.Combine (basePath, line); + project.Files.Add (new ProjectFile (fname)); + + string dir = Path.GetDirectoryName (fname); + if (!checkedFolders.Contains (dir)) { + checkedFolders.Add (dir); + fname = Path.Combine (dir, "ChangeLog"); + if (File.Exists (fname)) + project.Files.Add (new ProjectFile (fname, BuildAction.Content)); + } + } + } + + sr.Close (); + + // Project references + string refs = mkfile.GetVariable ("LIB_MCS_FLAGS"); + if (refs == null || refs == "") refs = mkfile.GetVariable ("LOCAL_MCS_FLAGS"); + + if (refs != null && refs != "") { + Regex var = new Regex(@"(.*?/r:(?<ref>.*?)(( |\t)|$).*?)*"); + Match match = var.Match (refs); + if (match.Success) { + foreach (Capture c in match.Groups["ref"].Captures) + refNames.Add (Path.GetFileNameWithoutExtension (c.Value)); + } + } + + int i = basePath.LastIndexOf ("/mcs/", basePath.Length - 2); + string topdir = basePath.Substring (0, i + 4); + targetAssembly = targetAssembly.Replace ("$(topdir)", topdir); + + if (mkfile.GetVariable ("NO_TEST") != "yes") { + string tname = Path.GetFileNameWithoutExtension (aname) + "_test_"; + testFileBase = Path.Combine (basePath, tname); + } + + foreach (string sconf in MonoMakefileFormat.Configurations) { + DotNetProjectConfiguration conf = new DotNetProjectConfiguration (sconf); + conf.CompilationParameters = project.LanguageBinding.CreateCompilationParameters (null); + conf.OutputDirectory = basePath; + conf.OutputAssembly = Path.GetFileName (targetAssembly); + project.Configurations.Add (conf); + } + + loading = false; + IdeApp.Workspace.SolutionLoaded += CombineOpened; + } + + public void CombineOpened (object sender, SolutionEventArgs args) + { + if (args.Solution == project.ParentSolution) { + foreach (string pref in refNames) { + Project p = project.ParentSolution.FindProjectByName (pref); + if (p != null) project.References.Add (new ProjectReference (p)); + } + } + } + + static Regex regexError = new Regex (@"^(\s*(?<file>.*)\((?<line>\d*)(,(?<column>\d*[\+]*))?\)(:|)\s+)*(?<level>\w+)\s*(?<number>.*):\s(?<message>.*)", + RegexOptions.Compiled | RegexOptions.ExplicitCapture); + + public Task<BuildResult> RunTarget (MonoDevelop.Core.ProgressMonitor monitor, string target, ConfigurationSelector configuration) + { + if (target == ProjectService.BuildTarget) + target = "all"; + else if (target == ProjectService.CleanTarget) + target = "clean"; + + DotNetProjectConfiguration conf = (DotNetProjectConfiguration) project.GetConfiguration (configuration); + + return Task<BuildResult>.Factory.StartNew (delegate { + using (var output = new StringWriter ()) { + using (var tw = new LogTextWriter ()) { + tw.ChainWriter (output); + tw.ChainWriter (monitor.Log); + + using (ProcessWrapper proc = Runtime.ProcessService.StartProcess ("make", "PROFILE=" + conf.Id + " " + target, conf.OutputDirectory, monitor.Log, tw, null)) + proc.WaitForOutput (); + + tw.UnchainWriter (output); + tw.UnchainWriter (monitor.Log); + + CompilerResults cr = new CompilerResults (null); + string[] lines = output.ToString ().Split ('\n'); + foreach (string line in lines) { + CompilerError err = CreateErrorFromString (line); + if (err != null) + cr.Errors.Add (err); + } + + return new BuildResult (cr, output.ToString ()); + } + } + }); + } + + private CompilerError CreateErrorFromString (string error_string) + { + // When IncludeDebugInformation is true, prevents the debug symbols stats from braeking this. + if (error_string.StartsWith ("WROTE SYMFILE") || + error_string.StartsWith ("make[") || + error_string.StartsWith ("OffsetTable") || + error_string.StartsWith ("Compilation succeeded") || + error_string.StartsWith ("Compilation failed")) + return null; + + CompilerError error = new CompilerError(); + + Match match=regexError.Match(error_string); + if (!match.Success) + return null; + + string level = match.Result("${level}"); + if (level == "warning") + error.IsWarning = true; + else if (level != "error") + return null; + + if (String.Empty != match.Result("${file}")) + error.FileName = Path.Combine (project.BaseDirectory, match.Result("${file}")); + if (String.Empty != match.Result("${line}")) + error.Line=Int32.Parse(match.Result("${line}")); + if (String.Empty != match.Result("${column}")) + error.Column = Int32.Parse(match.Result("${column}")); + error.ErrorNumber = match.Result ("${number}"); + error.ErrorText = match.Result ("${message}"); + return error; + } + + void OnFileAddedToProject (object s, ProjectFileEventArgs args) + { + if (loading) return; + + foreach (ProjectFileEventInfo e in args) { + if (e.ProjectFile.BuildAction != BuildAction.Compile) + continue; + AddSourceFile (e.ProjectFile.Name); + } + } + + void OnFileRemovedFromProject (object s, ProjectFileEventArgs args) + { + if (loading) return; + + foreach (ProjectFileEventInfo e in args) { + if (e.ProjectFile.BuildAction != BuildAction.Compile) + continue; + + RemoveSourceFile (e.ProjectFile.Name); + } + } + + void OnFileRenamedInProject (object s, ProjectFileRenamedEventArgs args) + { + if (loading) return; + + foreach (ProjectFileRenamedEventInfo e in args) { + if (e.ProjectFile.BuildAction != BuildAction.Compile) + continue; + + if (RemoveSourceFile (e.OldName)) + AddSourceFile (e.NewName); + } + } + + void AddSourceFile (string sourceFile) + { + StreamReader sr = null; + StreamWriter sw = null; + + try { + sr = new StreamReader (outFile + ".sources"); + sw = new StreamWriter (outFile + ".sources.new"); + + string newFile = project.GetRelativeChildPath (sourceFile); + if (newFile.StartsWith ("./")) newFile = newFile.Substring (2); + + string line; + while ((line = sr.ReadLine ()) != null) { + string file = line.Trim (' ','\t'); + if (newFile != null && (file == "" || string.Compare (file, newFile) > 0)) { + sw.WriteLine (newFile); + newFile = null; + } + sw.WriteLine (line); + } + if (newFile != null) + sw.WriteLine (newFile); + } finally { + if (sr != null) sr.Close (); + if (sw != null) sw.Close (); + } + File.Delete (outFile + ".sources"); + File.Move (outFile + ".sources.new", outFile + ".sources"); + } + + bool RemoveSourceFile (string sourceFile) + { + StreamReader sr = null; + StreamWriter sw = null; + bool found = false; + + try { + sr = new StreamReader (outFile + ".sources"); + sw = new StreamWriter (outFile + ".sources.new"); + + string oldFile = project.GetRelativeChildPath (sourceFile); + if (oldFile.StartsWith ("./")) oldFile = oldFile.Substring (2); + + string line; + while ((line = sr.ReadLine ()) != null) { + string file = line.Trim (' ','\t'); + if (oldFile != file) + sw.WriteLine (line); + else + found = true; + } + } finally { + if (sr != null) sr.Close (); + if (sw != null) sw.Close (); + } + if (found) { + File.Delete (outFile + ".sources"); + File.Move (outFile + ".sources.new", outFile + ".sources"); + } + return found; + } + + public void Dispose () + { + project.FileAddedToProject -= OnFileAddedToProject; + project.FileRemovedFromProject -= OnFileRemovedFromProject; + project.FileRenamedInProject -= OnFileRenamedInProject; + IdeApp.Workspace.SolutionLoaded -= CombineOpened; + } + + public void OnModified (string hint) + { + } + + public string GetTestFileBase () + { + return testFileBase; + } + + public object UnitTest { + get { return unitTest; } + set { unitTest = value; } + } + + public object GetService (Type t) + { + return null; + } + } +} + diff --git a/main/src/addins/MonoDeveloperExtensions/MonoDeveloperExtensions.csproj b/main/src/addins/MonoDeveloperExtensions/MonoDeveloperExtensions.csproj index a994b138b5..17c7f36e9b 100644 --- a/main/src/addins/MonoDeveloperExtensions/MonoDeveloperExtensions.csproj +++ b/main/src/addins/MonoDeveloperExtensions/MonoDeveloperExtensions.csproj @@ -79,6 +79,7 @@ <Compile Include="Commands.cs" /> <Compile Include="MonoSolutionItemHandler.cs" /> <Compile Include="AddinInfo.cs" /> + <Compile Include="MakefileProject.cs" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="MonoDeveloperExtensions.addin.xml"> diff --git a/main/src/addins/MonoDeveloperExtensions/MonoMakefileFormat.cs b/main/src/addins/MonoDeveloperExtensions/MonoMakefileFormat.cs index ce6dd41f4a..45376b3d8b 100644 --- a/main/src/addins/MonoDeveloperExtensions/MonoMakefileFormat.cs +++ b/main/src/addins/MonoDeveloperExtensions/MonoMakefileFormat.cs @@ -35,6 +35,7 @@ using MonoDevelop.Core; using System.Text.RegularExpressions; using MonoDevelop.Projects; using MonoDevelop.Projects.Extensions; +using System.Threading.Tasks; namespace MonoDeveloper { @@ -70,121 +71,118 @@ namespace MonoDeveloper public bool CanWriteFile (object obj) { - return (obj is SolutionFolder) || IsMonoProject (obj); + return (obj is SolutionFolder) || (obj is MakefileProject); }
- public void WriteFile (FilePath file, object node, IProgressMonitor monitor) + public Task WriteFile (FilePath file, object node, ProgressMonitor monitor) { + return Task.FromResult (0); }
public List<FilePath> GetItemFiles (object obj) {
List<FilePath> col = new List<FilePath> (); - DotNetProject mp = obj as DotNetProject; + var mp = obj as MakefileProject; if (mp != null) { - MonoSolutionItemHandler handler = ProjectExtensionUtil.GetItemHandler (mp) as MonoSolutionItemHandler; - if (handler != null && File.Exists (handler.SourcesFile)) { + if (File.Exists (mp.SourcesFile)) { col.Add (mp.FileName); - col.Add (handler.SourcesFile); + col.Add (mp.SourcesFile); } } return col; }
- public object ReadFile (FilePath fileName, Type expectedType, IProgressMonitor monitor) + public Task<object> ReadFile (FilePath fileName, Type expectedType, ProgressMonitor monitor) { return ReadFile (fileName, false, monitor); }
- public object ReadFile (FilePath fileName, bool hasParentSolution, IProgressMonitor monitor) - {
- FilePath basePath = fileName.ParentDirectory; - MonoMakefile mkfile = new MonoMakefile (fileName); - string aname = mkfile.GetVariable ("LIBRARY"); - if (aname == null) aname = mkfile.GetVariable ("PROGRAM"); + public Task<object> ReadFile (FilePath fileName, bool hasParentSolution, ProgressMonitor monitor) + { + return Task<object>.Factory.StartNew (delegate { + FilePath basePath = fileName.ParentDirectory; + MonoMakefile mkfile = new MonoMakefile (fileName); + string aname = mkfile.GetVariable ("LIBRARY"); + if (aname == null) + aname = mkfile.GetVariable ("PROGRAM"); - try { - ProjectExtensionUtil.BeginLoadOperation (); - if (aname != null) { - // It is a project - monitor.BeginTask ("Loading '" + fileName + "'", 0); - DotNetAssemblyProject project = new DotNetAssemblyProject ("C#"); - MonoSolutionItemHandler handler = new MonoSolutionItemHandler (project); - ProjectExtensionUtil.InstallHandler (handler, project); - project.Name = Path.GetFileName (basePath); - handler.Read (mkfile); - monitor.EndTask (); - return project; - } else { - string subdirs; - StringBuilder subdirsBuilder = new StringBuilder (); - subdirsBuilder.Append (mkfile.GetVariable ("common_dirs")); - if (subdirsBuilder.Length != 0) { - subdirsBuilder.Append ("\t"); - subdirsBuilder.Append (mkfile.GetVariable ("net_2_0_dirs")); - } - if (subdirsBuilder.Length == 0) - subdirsBuilder.Append (mkfile.GetVariable ("SUBDIRS")); + try { + ProjectExtensionUtil.BeginLoadOperation (); + if (aname != null) { + // It is a project + monitor.BeginTask ("Loading '" + fileName + "'", 0); + MakefileProject project = new MakefileProject ("C#"); + project.Name = Path.GetFileName (basePath); + project.Read (mkfile); + monitor.EndTask (); + return project; + } else { + string subdirs; + StringBuilder subdirsBuilder = new StringBuilder (); + subdirsBuilder.Append (mkfile.GetVariable ("common_dirs")); + if (subdirsBuilder.Length != 0) { + subdirsBuilder.Append ("\t"); + subdirsBuilder.Append (mkfile.GetVariable ("net_2_0_dirs")); + } + if (subdirsBuilder.Length == 0) + subdirsBuilder.Append (mkfile.GetVariable ("SUBDIRS")); - subdirs = subdirsBuilder.ToString (); - if (subdirs != null && (subdirs = subdirs.Trim (' ','\t')) != "") - { - object retObject; - SolutionFolder folder; - if (!hasParentSolution) { - Solution sol = new Solution (); - sol.ConvertToFormat (Services.ProjectService.FileFormats.GetFileFormat ("MonoMakefile"), false); - sol.FileName = fileName; - folder = sol.RootFolder; - retObject = sol; + subdirs = subdirsBuilder.ToString (); + if (subdirs != null && (subdirs = subdirs.Trim (' ', '\t')) != "") { + object retObject; + SolutionFolder folder; + if (!hasParentSolution) { + Solution sol = new Solution (); + sol.ConvertToFormat (Services.ProjectService.FileFormats.GetFileFormat ("MonoMakefile"), false); + sol.FileName = fileName; + folder = sol.RootFolder; + retObject = sol; - foreach (string conf in MonoMakefileFormat.Configurations) { - SolutionConfiguration sc = new SolutionConfiguration (conf); - sol.Configurations.Add (sc); + foreach (string conf in MonoMakefileFormat.Configurations) { + SolutionConfiguration sc = new SolutionConfiguration (conf); + sol.Configurations.Add (sc); + } + } else { + folder = new SolutionFolder (); + folder.Name = Path.GetFileName (Path.GetDirectoryName (fileName)); + retObject = folder; } - } else { - folder = new SolutionFolder (); - folder.Name = Path.GetFileName (Path.GetDirectoryName (fileName)); - retObject = folder; - } - subdirs = subdirs.Replace ('\t',' '); - string[] dirs = subdirs.Split (' '); + subdirs = subdirs.Replace ('\t', ' '); + string[] dirs = subdirs.Split (' '); - monitor.BeginTask ("Loading '" + fileName + "'", dirs.Length); - Hashtable added = new Hashtable (); - foreach (string dir in dirs) { - if (added.Contains (dir)) continue; - added.Add (dir, dir); - monitor.Step (1); - if (dir == null) continue; - string tdir = dir.Trim (); - if (tdir == "") continue; - string mfile = Path.Combine (Path.Combine (basePath, tdir), "Makefile"); - if (File.Exists (mfile) && CanReadFile (mfile, typeof(SolutionItem))) { - SolutionItem it = (SolutionItem) ReadFile (mfile, true, monitor); - folder.Items.Add (it); + monitor.BeginTask ("Loading '" + fileName + "'", dirs.Length); + Hashtable added = new Hashtable (); + foreach (string dir in dirs) { + if (added.Contains (dir)) + continue; + added.Add (dir, dir); + monitor.Step (1); + if (dir == null) + continue; + string tdir = dir.Trim (); + if (tdir == "") + continue; + string mfile = Path.Combine (Path.Combine (basePath, tdir), "Makefile"); + if (File.Exists (mfile) && CanReadFile (mfile, typeof(SolutionFolderItem))) { + SolutionFolderItem it = (SolutionFolderItem)ReadFile (mfile, true, monitor).Result; + folder.Items.Add (it); + } } + monitor.EndTask (); + return retObject; } - monitor.EndTask (); - return retObject; } + } finally { + ProjectExtensionUtil.EndLoadOperation (); } - } finally { - ProjectExtensionUtil.EndLoadOperation (); - } - return null; + return null; + }); } - public static bool IsMonoProject (object obj) - { - DotNetProject p = obj as DotNetProject; - return p != null && (ProjectExtensionUtil.GetItemHandler (p) is MonoSolutionItemHandler); - } - - public void ConvertToFormat (object obj) + public Task ConvertToFormat (object obj) { - // Nothing can be converted to this format. + return Task.FromResult (0); } public bool SupportsMixedFormats { diff --git a/main/src/addins/MonoDeveloperExtensions/MonoSolutionItemHandler.cs b/main/src/addins/MonoDeveloperExtensions/MonoSolutionItemHandler.cs index d43e15eb86..9636ac7e1c 100644 --- a/main/src/addins/MonoDeveloperExtensions/MonoSolutionItemHandler.cs +++ b/main/src/addins/MonoDeveloperExtensions/MonoSolutionItemHandler.cs @@ -36,6 +36,7 @@ using MonoDevelop.Core.ProgressMonitoring; using MonoDevelop.Ide; using MonoDevelop.Projects; using MonoDevelop.Projects.Extensions; +using System.Threading.Tasks; namespace MonoDeveloper { @@ -73,8 +74,9 @@ namespace MonoDeveloper } } - public void Save (MonoDevelop.Core.IProgressMonitor monitor) + public Task Save (MonoDevelop.Core.ProgressMonitor monitor) { + return Task.FromResult (0); } internal void Read (MonoMakefile mkfile) @@ -171,7 +173,7 @@ namespace MonoDeveloper static Regex regexError = new Regex (@"^(\s*(?<file>.*)\((?<line>\d*)(,(?<column>\d*[\+]*))?\)(:|)\s+)*(?<level>\w+)\s*(?<number>.*):\s(?<message>.*)", RegexOptions.Compiled | RegexOptions.ExplicitCapture); - public BuildResult RunTarget (MonoDevelop.Core.IProgressMonitor monitor, string target, ConfigurationSelector configuration) + public Task<BuildResult> RunTarget (MonoDevelop.Core.ProgressMonitor monitor, string target, ConfigurationSelector configuration) { if (target == ProjectService.BuildTarget) target = "all"; @@ -180,28 +182,30 @@ namespace MonoDeveloper DotNetProjectConfiguration conf = (DotNetProjectConfiguration) project.GetConfiguration (configuration); - using (var output = new StringWriter ()) { - using (var tw = new LogTextWriter ()) { - tw.ChainWriter (output); - tw.ChainWriter (monitor.Log); + return Task<BuildResult>.Factory.StartNew (delegate { + using (var output = new StringWriter ()) { + using (var tw = new LogTextWriter ()) { + tw.ChainWriter (output); + tw.ChainWriter (monitor.Log); - using (ProcessWrapper proc = Runtime.ProcessService.StartProcess ("make", "PROFILE=" + conf.Id + " " + target, conf.OutputDirectory, monitor.Log, tw, null)) - proc.WaitForOutput (); + using (ProcessWrapper proc = Runtime.ProcessService.StartProcess ("make", "PROFILE=" + conf.Id + " " + target, conf.OutputDirectory, monitor.Log, tw, null)) + proc.WaitForOutput (); - tw.UnchainWriter (output); - tw.UnchainWriter (monitor.Log); + tw.UnchainWriter (output); + tw.UnchainWriter (monitor.Log); - CompilerResults cr = new CompilerResults (null); - string[] lines = output.ToString().Split ('\n'); - foreach (string line in lines) { - CompilerError err = CreateErrorFromString (line); - if (err != null) cr.Errors.Add (err); - } + CompilerResults cr = new CompilerResults (null); + string[] lines = output.ToString ().Split ('\n'); + foreach (string line in lines) { + CompilerError err = CreateErrorFromString (line); + if (err != null) + cr.Errors.Add (err); + } - return new BuildResult (cr, output.ToString()); + return new BuildResult (cr, output.ToString ()); + } } - } - + }); } private CompilerError CreateErrorFromString (string error_string) diff --git a/main/src/addins/MonoDeveloperExtensions/NUnit/MonoTestProvider.cs b/main/src/addins/MonoDeveloperExtensions/NUnit/MonoTestProvider.cs index 026631b786..8d38969172 100644 --- a/main/src/addins/MonoDeveloperExtensions/NUnit/MonoTestProvider.cs +++ b/main/src/addins/MonoDeveloperExtensions/NUnit/MonoTestProvider.cs @@ -36,19 +36,16 @@ namespace MonoDeveloper { class MonoTestProvider: ITestProvider { - public UnitTest CreateUnitTest (IWorkspaceObject entry) + public UnitTest CreateUnitTest (WorkspaceObject entry) { - if (entry is DotNetProject) { - DotNetProject project = (DotNetProject) entry; - MonoSolutionItemHandler handler = ProjectExtensionUtil.GetItemHandler (project) as MonoSolutionItemHandler; - if (handler != null) { - if (handler.UnitTest != null) - return (UnitTest) handler.UnitTest; - string testFileBase = handler.GetTestFileBase (); - UnitTest testSuite = new MonoTestSuite (project, project.Name, testFileBase); - handler.UnitTest = testSuite; - return testSuite; - } + if (entry is MakefileProject) { + var project = (MakefileProject) entry; + if (project.UnitTest != null) + return (UnitTest) project.UnitTest; + string testFileBase = project.GetTestFileBase (); + UnitTest testSuite = new MonoTestSuite (project, project.Name, testFileBase); + project.UnitTest = testSuite; + return testSuite; } return null; } @@ -63,7 +60,7 @@ namespace MonoDeveloper { string basePath; - public MonoTestSuite (Project p, string name, string basePath): base (name, p) + public MonoTestSuite (MakefileProject p, string name, string basePath): base (name, p) { this.basePath = basePath; } diff --git a/main/src/addins/NUnit/Commands/NUnitCommands.cs b/main/src/addins/NUnit/Commands/NUnitCommands.cs index f0d9322df4..22f6ebb2d3 100644 --- a/main/src/addins/NUnit/Commands/NUnitCommands.cs +++ b/main/src/addins/NUnit/Commands/NUnitCommands.cs @@ -64,7 +64,7 @@ namespace MonoDevelop.NUnit.Commands { protected override void Run () { - IWorkspaceObject ob = IdeApp.ProjectOperations.CurrentSelectedBuildTarget; + WorkspaceObject ob = IdeApp.ProjectOperations.CurrentSelectedObject; if (ob != null) { UnitTest test = NUnitService.Instance.FindRootTest (ob); if (test != null) @@ -74,7 +74,7 @@ namespace MonoDevelop.NUnit.Commands protected override void Update (CommandInfo info) { - IWorkspaceObject ob = IdeApp.ProjectOperations.CurrentSelectedBuildTarget; + WorkspaceObject ob = IdeApp.ProjectOperations.CurrentSelectedObject; if (ob != null) { UnitTest test = NUnitService.Instance.FindRootTest (ob); info.Enabled = (test != null); diff --git a/main/src/addins/NUnit/Gui/NUnitAssemblyGroupConfigurationNodeBuilder.cs b/main/src/addins/NUnit/Gui/NUnitAssemblyGroupConfigurationNodeBuilder.cs index 1d7c6e5a4e..bea7c43faa 100644 --- a/main/src/addins/NUnit/Gui/NUnitAssemblyGroupConfigurationNodeBuilder.cs +++ b/main/src/addins/NUnit/Gui/NUnitAssemblyGroupConfigurationNodeBuilder.cs @@ -122,7 +122,7 @@ namespace MonoDevelop.NUnit foreach (string file in dlg.SelectedFiles) config.Assemblies.Add (new TestAssembly (file)); - IdeApp.Workspace.Save(); + IdeApp.Workspace.SaveAsync(); } } } diff --git a/main/src/addins/NUnit/Gui/NUnitAssemblyGroupNodeBuilder.cs b/main/src/addins/NUnit/Gui/NUnitAssemblyGroupNodeBuilder.cs index 490a355404..2cc8a48c5e 100644 --- a/main/src/addins/NUnit/Gui/NUnitAssemblyGroupNodeBuilder.cs +++ b/main/src/addins/NUnit/Gui/NUnitAssemblyGroupNodeBuilder.cs @@ -117,7 +117,7 @@ namespace MonoDevelop.NUnit NUnitAssemblyGroupProject project = CurrentNode.DataItem as NUnitAssemblyGroupProject; project.ParentFolder.Items.Remove (project); project.Dispose (); - IdeApp.Workspace.Save (); + IdeApp.Workspace.SaveAsync (); } } } diff --git a/main/src/addins/NUnit/Gui/TestPad.cs b/main/src/addins/NUnit/Gui/TestPad.cs index 9b2c1fc7c3..15ece94e07 100644 --- a/main/src/addins/NUnit/Gui/TestPad.cs +++ b/main/src/addins/NUnit/Gui/TestPad.cs @@ -44,6 +44,7 @@ using MonoDevelop.Projects; using Mono.TextEditor; using System.Linq; using MonoDevelop.Components; +using MonoDevelop.Ide.Commands; namespace MonoDevelop.NUnit { @@ -51,7 +52,7 @@ namespace MonoDevelop.NUnit { NUnitService testService = NUnitService.Instance; - IAsyncOperation runningTestOperation; + AsyncOperation runningTestOperation; VPaned paned; TreeView detailsTree; ListStore detailsStore; @@ -411,7 +412,7 @@ namespace MonoDevelop.NUnit { UnitTest test = GetSelectedTest (); if (test != null) { - SolutionEntityItem item = test.OwnerObject as SolutionEntityItem; + SolutionItem item = test.OwnerObject as SolutionItem; ExecutionModeCommandService.GenerateExecutionModeCommands ( item, test.CanRun, @@ -467,12 +468,12 @@ namespace MonoDevelop.NUnit return nav.DataItem as UnitTest; } - public IAsyncOperation RunTest (UnitTest test, IExecutionHandler mode) + public AsyncOperation RunTest (UnitTest test, IExecutionHandler mode) { return RunTest (FindTestNode (test), mode, false); } - IAsyncOperation RunTest (ITreeNavigator nav, IExecutionHandler mode, bool bringToFront = true) + AsyncOperation RunTest (ITreeNavigator nav, IExecutionHandler mode, bool bringToFront = true) { if (nav == null) return null; @@ -487,7 +488,7 @@ namespace MonoDevelop.NUnit if (bringToFront) IdeApp.Workbench.GetPad<TestPad> ().BringToFront (); runningTestOperation = testService.RunTest (test, mode); - runningTestOperation.Completed += (OperationHandler) DispatchService.GuiDispatch (new OperationHandler (OnTestSessionCompleted)); + runningTestOperation.Task.ContinueWith (t => OnTestSessionCompleted ()); return runningTestOperation; } @@ -501,10 +502,9 @@ namespace MonoDevelop.NUnit RunTest (TreeView.GetSelectedNode (), mode); } - void OnTestSessionCompleted (IAsyncOperation op) + void OnTestSessionCompleted () { - if (op.Success) - RefreshDetails (); + RefreshDetails (); runningTestOperation = null; this.buttonRunAll.Sensitive = true; this.buttonStop.Sensitive = false; diff --git a/main/src/addins/NUnit/Gui/TestResultsPad.cs b/main/src/addins/NUnit/Gui/TestResultsPad.cs index 1baf8b81e5..00c4fa75ea 100644 --- a/main/src/addins/NUnit/Gui/TestResultsPad.cs +++ b/main/src/addins/NUnit/Gui/TestResultsPad.cs @@ -42,6 +42,8 @@ using MonoDevelop.Components.Docking; using MonoDevelop.Ide; using System.Text.RegularExpressions; using MonoDevelop.Components; +using System.Threading; +using MonoDevelop.Ide.Commands; namespace MonoDevelop.NUnit { @@ -475,7 +477,34 @@ namespace MonoDevelop.NUnit } } } - + + [CommandHandler (EditCommands.Copy)] + protected void OnCopy () + { + UnitTest test = GetSelectedTest (); + if (test != null) { + var last = test.GetLastResult (); + if (last == null) + return; + var clipboard = Clipboard.Get (Gdk.Atom.Intern ("CLIPBOARD", false)); + clipboard.Text = last.StackTrace; + } + } + + [CommandUpdateHandler (EditCommands.Copy)] + protected void OnUpdateCopy (CommandInfo info) + { + UnitTest test = GetSelectedTest (); + if (test != null) { + var result = test.GetLastResult (); + if (result != null) { + info.Enabled = !string.IsNullOrEmpty (result.StackTrace); + return; + } + } + info.Enabled = false; + } + [CommandHandler (TestCommands.SelectTestInTree)] protected void OnSelectTestInTree () { @@ -704,11 +733,14 @@ namespace MonoDevelop.NUnit { ITestProgressMonitor monitor; TestResultsPad pad; + CancellationTokenSource cs; - public TestMonitor (TestResultsPad pad) + public TestMonitor (TestResultsPad pad, CancellationTokenSource cs) { this.pad = pad; this.monitor = pad; + this.cs = cs; + cs.Token.Register (Cancel); } public void InitializeTestRun (UnitTest test) { diff --git a/main/src/addins/NUnit/Makefile.am b/main/src/addins/NUnit/Makefile.am index 4b4491f083..3ae131ae68 100644 --- a/main/src/addins/NUnit/Makefile.am +++ b/main/src/addins/NUnit/Makefile.am @@ -1,4 +1,3 @@ SUBDIRS = NUnitRunner . include $(top_srcdir)/xbuild.include -EXTRA_DIST += lib/nunit.core.dll lib/nunit.core.interfaces.dll lib/nunit.framework.dll lib/nunit.util.dll diff --git a/main/src/addins/NUnit/MonoDevelop.NUnit.csproj b/main/src/addins/NUnit/MonoDevelop.NUnit.csproj index ae8af1922d..2a2aa548c8 100644 --- a/main/src/addins/NUnit/MonoDevelop.NUnit.csproj +++ b/main/src/addins/NUnit/MonoDevelop.NUnit.csproj @@ -39,12 +39,6 @@ <DocumentationFile>..\..\..\build\AddIns\NUnit\MonoDevelop.NUnit.xml</DocumentationFile> </PropertyGroup> <ItemGroup> - <Reference Include="nunit.core"> - <HintPath>lib\nunit.core.dll</HintPath> - </Reference> - <Reference Include="nunit.framework"> - <HintPath>lib\nunit.framework.dll</HintPath> - </Reference> <Reference Include="System" /> <Reference Include="System.Xml" /> <Reference Include="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> @@ -67,14 +61,20 @@ </Reference> <Reference Include="Mono.Posix" /> <Reference Include="Mono.Cairo" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Core" /> + <Reference Include="nunit.framework"> + <HintPath>..\..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath> + </Reference> + <Reference Include="nunit.core"> + <HintPath>..\..\..\packages\NUnit.Runners.2.6.3\tools\lib\nunit.core.dll</HintPath> + </Reference> <Reference Include="nunit.core.interfaces"> - <HintPath>lib\nunit.core.interfaces.dll</HintPath> + <HintPath>..\..\..\packages\NUnit.Runners.2.6.3\tools\lib\nunit.core.interfaces.dll</HintPath> </Reference> <Reference Include="nunit.util"> - <HintPath>lib\nunit.util.dll</HintPath> + <HintPath>..\..\..\packages\NUnit.Runners.2.6.3\tools\lib\nunit.util.dll</HintPath> </Reference> - <Reference Include="System.Xml.Linq" /> - <Reference Include="System.Core" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj"> @@ -247,6 +247,14 @@ </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> + <None Include="packages.config" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <Target Name="BeforeBuild"> + <PropertyGroup> + <NuGet>$(SolutionDir)\external\nuget-binary\NuGet.exe</NuGet> + <NuGet Condition="$(OS)=='Unix'">mono $(NuGet)</NuGet> + </PropertyGroup> + <Exec Condition="Exists('$(SolutionDir)\..\.git')" Command="$(NuGet) restore -SolutionDirectory $(SolutionDir)" /> + </Target> </Project> diff --git a/main/src/addins/NUnit/MonoDevelopNUnit.addin.xml b/main/src/addins/NUnit/MonoDevelopNUnit.addin.xml index f2af6ec39c..d0e267a3d7 100644 --- a/main/src/addins/NUnit/MonoDevelopNUnit.addin.xml +++ b/main/src/addins/NUnit/MonoDevelopNUnit.addin.xml @@ -50,16 +50,6 @@ <!-- Extensions --> - <Extension path="/MonoDevelop/Core/SupportPackages"> - <Condition id="PackageNotInstalled" name="mono-nunit" version="2.7"> - <Package name="nunit" version="2.4" clrVersion="Default"> - <Assembly file="nunit.core.dll" /> - <Assembly file="nunit.core.interfaces.dll" /> - <Assembly file="nunit.framework.dll" /> - </Package> - </Condition> - </Extension> - <Extension path = "/MonoDevelop/Ide/Pads"> <SolutionPad id = "MonoDevelop.NUnit.TestPad" defaultLayout="*" defaultPlacement = "Right" defaultStatus="AutoHide" _label = "Unit Tests" icon = "nunit-pad-icon" class = "MonoDevelop.NUnit.TestPad"> <PadOption id = "ShowTestTime" _label = "Show Test Time" defaultValue = "False" /> @@ -146,6 +136,8 @@ <CommandItem id = "MonoDevelop.NUnit.Commands.TestCommands.GoToFailure" /> <CommandItem id = "MonoDevelop.NUnit.Commands.TestCommands.ShowTestCode" /> <CommandItem id = "MonoDevelop.NUnit.Commands.TestCommands.SelectTestInTree" /> + <SeparatorItem id = "s1" /> + <CommandItem id = "MonoDevelop.Ide.Commands.EditCommands.Copy" /> </Extension> <Extension path = "/MonoDevelop/NUnit/ContextMenu/TestChart"> @@ -190,8 +182,8 @@ <StockIcon stockid = "nunit-run" resource = "unit-run-light-16.png" size="Menu" /> </Extension> - <Extension path = "/MonoDevelop/ProjectModel/ProjectServiceExtensions"> - <Class class = "MonoDevelop.NUnit.NUnitProjectServiceExtension" /> + <Extension path = "/MonoDevelop/ProjectModel/ProjectModelExtensions"> + <ProjectExtension class = "MonoDevelop.NUnit.NUnitProjectServiceExtension" /> </Extension> <Extension path = "/MonoDevelop/ProjectModel/SerializableClasses"> diff --git a/main/src/addins/NUnit/NUnitRunner/NUnitRunner.csproj b/main/src/addins/NUnit/NUnitRunner/NUnitRunner.csproj index 68153a46ba..2248340e29 100644 --- a/main/src/addins/NUnit/NUnitRunner/NUnitRunner.csproj +++ b/main/src/addins/NUnit/NUnitRunner/NUnitRunner.csproj @@ -37,18 +37,28 @@ <ItemGroup> <Reference Include="System" /> <Reference Include="System.Xml" /> - <Reference Include="nunit.core"> - <HintPath>..\lib\nunit.core.dll</HintPath> - </Reference> <Reference Include="nunit.framework"> - <HintPath>..\lib\nunit.framework.dll</HintPath> + <HintPath>..\..\..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath> + </Reference> + <Reference Include="nunit.core"> + <HintPath>..\..\..\..\packages\NUnit.Runners.2.6.3\tools\lib\nunit.core.dll</HintPath> </Reference> <Reference Include="nunit.core.interfaces"> - <HintPath>..\lib\nunit.core.interfaces.dll</HintPath> + <HintPath>..\..\..\..\packages\NUnit.Runners.2.6.3\tools\lib\nunit.core.interfaces.dll</HintPath> </Reference> </ItemGroup> <ItemGroup> <Compile Include="NUnitTestRunner.cs" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> -</Project>
\ No newline at end of file + <ItemGroup> + <None Include="packages.config" /> + </ItemGroup> + <Target Name="BeforeBuild"> + <PropertyGroup> + <NuGet>$(SolutionDir)\external\nuget-binary\NuGet.exe</NuGet> + <NuGet Condition="$(OS)=='Unix'">mono $(NuGet)</NuGet> + </PropertyGroup> + <Exec Condition="Exists('$(SolutionDir)\..\.git')" Command="$(NuGet) restore -SolutionDirectory $(SolutionDir)" /> + </Target> +</Project> diff --git a/main/src/addins/NUnit/NUnitRunner/packages.config b/main/src/addins/NUnit/NUnitRunner/packages.config new file mode 100644 index 0000000000..3ca92b52ea --- /dev/null +++ b/main/src/addins/NUnit/NUnitRunner/packages.config @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="2.6.3" targetFramework="net40" />
+ <package id="NUnit.Runners" version="2.6.3" targetFramework="net40" />
+</packages>
\ No newline at end of file diff --git a/main/src/addins/NUnit/Project/NUnitAssemblyGroupProject.cs b/main/src/addins/NUnit/Project/NUnitAssemblyGroupProject.cs index 0a67aac29d..561ede1a8a 100644 --- a/main/src/addins/NUnit/Project/NUnitAssemblyGroupProject.cs +++ b/main/src/addins/NUnit/Project/NUnitAssemblyGroupProject.cs @@ -38,7 +38,7 @@ using MonoDevelop.Ide.TypeSystem; namespace MonoDevelop.NUnit { [DataInclude (typeof(NUnitAssemblyGroupProjectConfiguration))] - public class NUnitAssemblyGroupProject: SolutionEntityItem + public class NUnitAssemblyGroupProject: SolutionItem { RootTest rootTest; @@ -53,7 +53,7 @@ namespace MonoDevelop.NUnit Configurations.Add (CreateConfiguration ("Default")); } - public override void InitializeFromTemplate (XmlElement element) + protected override void OnInitializeFromTemplate (XmlElement element) { Configurations.Add (CreateConfiguration ("Default")); } @@ -73,28 +73,6 @@ namespace MonoDevelop.NUnit conf.Name = name; return conf; } - - protected override void OnClean (IProgressMonitor monitor, ConfigurationSelector configuration) - { - } - - protected override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration) - { - return null; - } - - protected override void OnExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) - { - } - - protected override bool OnGetNeedsBuilding (ConfigurationSelector configuration) - { - return false; - } - - protected override void OnSetNeedsBuilding (bool value, ConfigurationSelector configuration) - { - } } public class NUnitAssemblyGroupProjectConfiguration: SolutionItemConfiguration diff --git a/main/src/addins/NUnit/Services/ITestProvider.cs b/main/src/addins/NUnit/Services/ITestProvider.cs index b9cd72530d..c2bea5f998 100644 --- a/main/src/addins/NUnit/Services/ITestProvider.cs +++ b/main/src/addins/NUnit/Services/ITestProvider.cs @@ -35,7 +35,7 @@ namespace MonoDevelop.NUnit { public interface ITestProvider { - UnitTest CreateUnitTest (IWorkspaceObject entry); + UnitTest CreateUnitTest (WorkspaceObject entry); Type[] GetOptionTypes (); } } diff --git a/main/src/addins/NUnit/Services/NUnitAssemblyTestSuite.cs b/main/src/addins/NUnit/Services/NUnitAssemblyTestSuite.cs index 3e55a824be..895b07674d 100644 --- a/main/src/addins/NUnit/Services/NUnitAssemblyTestSuite.cs +++ b/main/src/addins/NUnit/Services/NUnitAssemblyTestSuite.cs @@ -45,6 +45,7 @@ using MonoDevelop.Ide; using System.Xml.Linq; using System.Linq; using System.Globalization; +using System.Threading.Tasks; namespace MonoDevelop.NUnit { @@ -69,7 +70,7 @@ namespace MonoDevelop.NUnit { } - public NUnitAssemblyTestSuite (string name, SolutionItem ownerSolutionItem): base (name, ownerSolutionItem) + public NUnitAssemblyTestSuite (string name, WorkspaceObject ownerSolutionItem): base (name, ownerSolutionItem) { } @@ -145,10 +146,9 @@ namespace MonoDevelop.NUnit } } - public override IAsyncOperation Refresh () + public override Task Refresh (CancellationToken ct) { - AsyncOperation oper = new AsyncOperation (); - System.Threading.ThreadPool.QueueUserWorkItem (delegate { + return Task.Factory.StartNew (delegate { lock (locker) { try { while (Status == TestStatus.Loading) { @@ -162,13 +162,10 @@ namespace MonoDevelop.NUnit Monitor.Wait (locker); } } - oper.SetCompleted (true); } catch { - oper.SetCompleted (false); } } }); - return oper; } DateTime GetAssemblyTime () diff --git a/main/src/addins/NUnit/Services/NUnitProjectServiceExtension.cs b/main/src/addins/NUnit/Services/NUnitProjectServiceExtension.cs index 0ecd719fd8..ff59f13226 100644 --- a/main/src/addins/NUnit/Services/NUnitProjectServiceExtension.cs +++ b/main/src/addins/NUnit/Services/NUnitProjectServiceExtension.cs @@ -28,44 +28,32 @@ using MonoDevelop.Core; using MonoDevelop.Projects; using MonoDevelop.Ide; +using System.Threading.Tasks; namespace MonoDevelop.NUnit { - public class NUnitProjectServiceExtension: ProjectServiceExtension + public class NUnitProjectServiceExtension: ProjectExtension { - public override void Execute (MonoDevelop.Core.IProgressMonitor monitor, IBuildTarget item, ExecutionContext context, ConfigurationSelector configuration) + protected override Task OnExecute (MonoDevelop.Core.ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { - if (base.CanExecute (item, context, configuration)) { + if (base.OnGetCanExecute (context, configuration)) { // It is executable by default - base.Execute(monitor, item, context, configuration); - return; - } else if (item is IWorkspaceObject) { - UnitTest test = NUnitService.Instance.FindRootTest ((IWorkspaceObject)item); - if (test != null) { - IAsyncOperation oper = null; - DispatchService.GuiSyncDispatch (delegate { - oper = NUnitService.Instance.RunTest (test, context.ExecutionHandler, false); - }); -// if (oper != null) { -// monitor.CancelRequested += delegate { -// oper.Cancel (); -// }; -// oper.WaitForCompleted (); -// } - } + return base.OnExecute (monitor, context, configuration); } + UnitTest test = NUnitService.Instance.FindRootTest (Project); + if (test != null) + return NUnitService.Instance.RunTest (test, context.ExecutionHandler, false).Task; + else + return Task.FromResult (0); } - public override bool CanExecute (IBuildTarget item, ExecutionContext context, ConfigurationSelector configuration) + protected override bool OnGetCanExecute (ExecutionContext context, ConfigurationSelector configuration) { // We check for DefaultExecutionHandlerFactory because the tests can't run using any other execution mode - bool res = base.CanExecute (item, context, configuration); - if (!res && (item is IWorkspaceObject)) { - UnitTest test = NUnitService.Instance.FindRootTest ((IWorkspaceObject)item); - return (test != null) && test.CanRun (context.ExecutionHandler); - } else - return res; + bool res = base.OnGetCanExecute (context, configuration); + UnitTest test = NUnitService.Instance.FindRootTest (Project); + return (test != null) && test.CanRun (context.ExecutionHandler); } } } diff --git a/main/src/addins/NUnit/Services/NUnitService.cs b/main/src/addins/NUnit/Services/NUnitService.cs index c5a2407532..79877e0fc4 100644 --- a/main/src/addins/NUnit/Services/NUnitService.cs +++ b/main/src/addins/NUnit/Services/NUnitService.cs @@ -38,6 +38,8 @@ using MonoDevelop.Projects; using NUnit.Core; using MonoDevelop.Ide.Gui; using MonoDevelop.Ide; +using System.Threading.Tasks; +using System.Linq; namespace MonoDevelop.NUnit { @@ -99,14 +101,20 @@ namespace MonoDevelop.NUnit } } - public IAsyncOperation RunTest (UnitTest test, IExecutionHandler context) + public AsyncOperation RunTest (UnitTest test, IExecutionHandler context) { var result = RunTest (test, context, IdeApp.Preferences.BuildBeforeRunningTests); - result.Completed += (OperationHandler) DispatchService.GuiDispatch (new OperationHandler (OnTestSessionCompleted)); + result.Task.ContinueWith (t => OnTestSessionCompleted ()); return result; } - public IAsyncOperation RunTest (UnitTest test, IExecutionHandler context, bool buildOwnerObject) + public AsyncOperation RunTest (UnitTest test, IExecutionHandler context, bool buildOwnerObject) + { + var cs = new CancellationTokenSource (); + return new AsyncOperation (RunTestAsync (test, context, buildOwnerObject, cs), cs); + } + + async Task RunTestAsync (UnitTest test, IExecutionHandler context, bool buildOwnerObject, CancellationTokenSource cs) { string testName = test.FullName; @@ -115,39 +123,23 @@ namespace MonoDevelop.NUnit if (bt != null && bt.NeedsBuilding (IdeApp.Workspace.ActiveConfiguration)) { if (!IdeApp.ProjectOperations.CurrentRunOperation.IsCompleted) { MonoDevelop.Ide.Commands.StopHandler.StopBuildOperations (); - IdeApp.ProjectOperations.CurrentRunOperation.WaitForCompleted (); + await IdeApp.ProjectOperations.CurrentRunOperation.Task; } - AsyncOperation retOper = new AsyncOperation (); - - IAsyncOperation op = IdeApp.ProjectOperations.Build (bt); - retOper.TrackOperation (op, false); - - op.Completed += delegate { - // The completed event of the build operation is run in the gui thread, - // so we need a new thread, because refreshing must be async - System.Threading.ThreadPool.QueueUserWorkItem (delegate { - if (op.Success) { - RefreshTests (); - test = SearchTest (testName); - if (test != null) { - Gtk.Application.Invoke (delegate { - // RunTest must run in the gui thread - retOper.TrackOperation (RunTest (test, context, false), true); - }); - } - else - retOper.SetCompleted (false); - } - }); - }; - - return retOper; + var res = await IdeApp.ProjectOperations.Build (bt, cs.Token).Task; + if (res.HasErrors) + return; + + await RefreshTests (cs.Token); + test = SearchTest (testName); + if (test != null) + await RunTestAsync (test, context, false, cs); + return; } } if (!IdeApp.ProjectOperations.ConfirmExecutionOperation ()) - return NullProcessAsyncOperation.Failure; + return; Pad resultsPad = IdeApp.Workbench.GetPad <TestResultsPad>(); if (resultsPad == null) { @@ -160,25 +152,17 @@ namespace MonoDevelop.NUnit resultsPad.Sticky = true; resultsPad.BringToFront (); - TestSession session = new TestSession (test, context, (TestResultsPad) resultsPad.Content); - - session.Completed += delegate { - Gtk.Application.Invoke (delegate { - resultsPad.Sticky = false; - }); - }; - - session.Start (); - + TestSession session = new TestSession (test, context, (TestResultsPad) resultsPad.Content, cs); IdeApp.ProjectOperations.CurrentRunOperation = session; - - return session; + + await session.Start (); + + resultsPad.Sticky = false; } - public void RefreshTests () + public Task RefreshTests (CancellationToken ct) { - foreach (UnitTest t in RootTests) - t.Refresh ().WaitForCompleted (); + return Task.WhenAll (RootTests.Select (t => t.Refresh (ct))); } public UnitTest SearchTest (string fullName) @@ -238,12 +222,12 @@ namespace MonoDevelop.NUnit return null; } - public UnitTest FindRootTest (IWorkspaceObject item) + public UnitTest FindRootTest (WorkspaceObject item) { return FindRootTest (RootTests, item); } - public UnitTest FindRootTest (IEnumerable<UnitTest> tests, IWorkspaceObject item) + public UnitTest FindRootTest (IEnumerable<UnitTest> tests, WorkspaceObject item) { foreach (UnitTest t in tests) { if (t.OwnerObject == item) @@ -281,7 +265,7 @@ namespace MonoDevelop.NUnit NotifyTestSuiteChanged (); } - public UnitTest BuildTest (IWorkspaceObject entry) + public UnitTest BuildTest (WorkspaceObject entry) { foreach (ITestProvider p in providers) { try { @@ -325,7 +309,7 @@ namespace MonoDevelop.NUnit public event EventHandler TestSuiteChanged; - void OnTestSessionCompleted (IAsyncOperation op) + void OnTestSessionCompleted () { var handler = TestSessionCompleted; if (handler != null) @@ -337,31 +321,28 @@ namespace MonoDevelop.NUnit - class TestSession: IAsyncOperation, ITestProgressMonitor + class TestSession: AsyncOperation, ITestProgressMonitor { UnitTest test; TestMonitor monitor; Thread runThread; bool success; - ManualResetEvent waitEvent; IExecutionHandler context; TestResultsPad resultsPad; - public TestSession (UnitTest test, IExecutionHandler context, TestResultsPad resultsPad) + public TestSession (UnitTest test, IExecutionHandler context, TestResultsPad resultsPad, CancellationTokenSource cs) { this.test = test; this.context = context; - this.monitor = new TestMonitor (resultsPad); + CancellationTokenSource = cs; + this.monitor = new TestMonitor (resultsPad, CancellationTokenSource); this.resultsPad = resultsPad; resultsPad.InitializeTestRun (test); } - public void Start () + public Task Start () { - runThread = new Thread (new ThreadStart (RunTests)); - runThread.Name = "NUnit test runner"; - runThread.IsBackground = true; - runThread.Start (); + return Task = Task.Factory.StartNew (RunTests); } void RunTests () @@ -381,12 +362,6 @@ namespace MonoDevelop.NUnit monitor.FinishTestRun (); runThread = null; } - lock (this) { - if (waitEvent != null) - waitEvent.Set (); - } - if (Completed != null) - Completed (this); } void ITestProgressMonitor.BeginTest (UnitTest test) @@ -412,45 +387,7 @@ namespace MonoDevelop.NUnit bool ITestProgressMonitor.IsCancelRequested { get { return monitor.IsCancelRequested; } } - - void IAsyncOperation.Cancel () - { - monitor.Cancel (); - } - - public void WaitForCompleted () - { - if (IsCompleted) return; - - if (DispatchService.IsGuiThread) { - while (!IsCompleted) { - while (Gtk.Application.EventsPending ()) - Gtk.Application.RunIteration (); - Thread.Sleep (100); - } - } else { - lock (this) { - if (waitEvent == null) - waitEvent = new ManualResetEvent (false); - } - waitEvent.WaitOne (); - } - } - - public bool IsCompleted { - get { return runThread == null; } - } - - public bool Success { - get { return success; } - } - public bool SuccessWithWarnings { - get { return false; } - } - - public event OperationHandler Completed; - public event TestHandler CancelRequested { add { monitor.CancelRequested += value; } remove { monitor.CancelRequested -= value; } diff --git a/main/src/addins/NUnit/Services/SolutionFolderTestGroup.cs b/main/src/addins/NUnit/Services/SolutionFolderTestGroup.cs index c961b9c7e8..384598bc45 100644 --- a/main/src/addins/NUnit/Services/SolutionFolderTestGroup.cs +++ b/main/src/addins/NUnit/Services/SolutionFolderTestGroup.cs @@ -81,7 +81,7 @@ namespace MonoDevelop.NUnit protected override void OnCreateTests () { NUnitService testService = NUnitService.Instance; - foreach (SolutionItem e in combine.Items) { + foreach (SolutionFolderItem e in combine.Items) { UnitTest t = testService.BuildTest (e); if (t != null) Tests.Add (t); diff --git a/main/src/addins/NUnit/Services/SystemTestProvider.cs b/main/src/addins/NUnit/Services/SystemTestProvider.cs index 9e60f7767a..4090e3fff2 100644 --- a/main/src/addins/NUnit/Services/SystemTestProvider.cs +++ b/main/src/addins/NUnit/Services/SystemTestProvider.cs @@ -34,7 +34,7 @@ namespace MonoDevelop.NUnit { public class SystemTestProvider: ITestProvider { - public UnitTest CreateUnitTest (IWorkspaceObject entry) + public UnitTest CreateUnitTest (WorkspaceObject entry) { UnitTest test = null; diff --git a/main/src/addins/NUnit/Services/UnitTest.cs b/main/src/addins/NUnit/Services/UnitTest.cs index f8e9816015..a0044ac0c7 100644 --- a/main/src/addins/NUnit/Services/UnitTest.cs +++ b/main/src/addins/NUnit/Services/UnitTest.cs @@ -34,6 +34,9 @@ using MonoDevelop.Core.ProgressMonitoring; using MonoDevelop.Projects; using MonoDevelop.Core.Serialization; using MonoDevelop.Core.Execution; +using MonoDevelop.Ide; +using System.Threading.Tasks; +using System.Threading; namespace MonoDevelop.NUnit { @@ -45,8 +48,8 @@ namespace MonoDevelop.NUnit UnitTest parent; TestStatus status; Hashtable options; - IWorkspaceObject ownerSolutionItem; - SolutionEntityItem ownerSolutionEntityItem; + WorkspaceObject ownerSolutionItem; + SolutionItem ownerSolutionEntityItem; UnitTestResultsStore results; bool historicResult; bool resultLoaded; @@ -71,11 +74,11 @@ namespace MonoDevelop.NUnit this.name = name; } - protected UnitTest (string name, IWorkspaceObject ownerSolutionItem) + protected UnitTest (string name, WorkspaceObject ownerSolutionItem) { this.name = name; this.ownerSolutionItem = ownerSolutionItem; - ownerSolutionEntityItem = ownerSolutionItem as SolutionEntityItem; + ownerSolutionEntityItem = ownerSolutionItem as SolutionItem; if (ownerSolutionEntityItem != null) ownerSolutionEntityItem.DefaultConfigurationChanged += OnConfugurationChanged; } @@ -363,11 +366,11 @@ namespace MonoDevelop.NUnit } } - protected IWorkspaceObject OwnerSolutionItem { + protected WorkspaceObject OwnerSolutionItem { get { return ownerSolutionItem; } } - public IWorkspaceObject OwnerObject { + public WorkspaceObject OwnerObject { get { if (ownerSolutionItem != null) return ownerSolutionItem; @@ -390,11 +393,9 @@ namespace MonoDevelop.NUnit } // Forces the reloading of tests, if they have changed - public virtual IAsyncOperation Refresh () + public virtual Task Refresh (CancellationToken ct) { - AsyncOperation op = new AsyncOperation (); - op.SetCompleted (true); - return op; + return Task.FromResult (0); } public UnitTestResult Run (TestContext testContext) @@ -521,8 +522,8 @@ namespace MonoDevelop.NUnit oset.Tests.Remove (te); } } - - ce.Save (new NullProgressMonitor ()); + + IdeApp.ProjectOperations.SaveAsync ((WorkspaceObject)ce); } protected virtual ICollection OnLoadOptions (string configuration) @@ -552,8 +553,8 @@ namespace MonoDevelop.NUnit void GetOwnerSolutionItem (UnitTest t, out IConfigurationTarget c, out string path) { - if (OwnerSolutionItem is SolutionEntityItem) { - c = OwnerSolutionItem as SolutionEntityItem; + if (OwnerSolutionItem is SolutionItem) { + c = OwnerSolutionItem as SolutionItem; path = ""; } else if (parent != null) { parent.GetOwnerSolutionItem (t, out c, out path); diff --git a/main/src/addins/NUnit/Services/UnitTestGroup.cs b/main/src/addins/NUnit/Services/UnitTestGroup.cs index f478e1f00b..eaa541f83a 100644 --- a/main/src/addins/NUnit/Services/UnitTestGroup.cs +++ b/main/src/addins/NUnit/Services/UnitTestGroup.cs @@ -31,6 +31,8 @@ using MonoDevelop.Core; using MonoDevelop.Core.ProgressMonitoring; using System.Collections; using MonoDevelop.Projects; +using System.Threading.Tasks; +using System.Threading; namespace MonoDevelop.NUnit { @@ -42,7 +44,7 @@ namespace MonoDevelop.NUnit { } - protected UnitTestGroup (string name, IWorkspaceObject ownerSolutionItem): base (name, ownerSolutionItem) + protected UnitTestGroup (string name, WorkspaceObject ownerSolutionItem): base (name, ownerSolutionItem) { } @@ -121,13 +123,10 @@ namespace MonoDevelop.NUnit { } - public override IAsyncOperation Refresh () + public async override Task Refresh (CancellationToken ct) { - AggregatedAsyncOperation oper = new AggregatedAsyncOperation (); foreach (UnitTest t in Tests) - oper.Add (t.Refresh ()); - oper.StartMonitoring (); - return oper; + await t.Refresh (ct); } protected override UnitTestResult OnRun (TestContext testContext) diff --git a/main/src/addins/NUnit/lib/nunit.core.dll b/main/src/addins/NUnit/lib/nunit.core.dll Binary files differdeleted file mode 100644 index 5f748becd1..0000000000 --- a/main/src/addins/NUnit/lib/nunit.core.dll +++ /dev/null diff --git a/main/src/addins/NUnit/lib/nunit.core.interfaces.dll b/main/src/addins/NUnit/lib/nunit.core.interfaces.dll Binary files differdeleted file mode 100644 index 72b9486d74..0000000000 --- a/main/src/addins/NUnit/lib/nunit.core.interfaces.dll +++ /dev/null diff --git a/main/src/addins/NUnit/lib/nunit.framework.dll b/main/src/addins/NUnit/lib/nunit.framework.dll Binary files differdeleted file mode 100644 index eaea9eedf7..0000000000 --- a/main/src/addins/NUnit/lib/nunit.framework.dll +++ /dev/null diff --git a/main/src/addins/NUnit/lib/nunit.util.dll b/main/src/addins/NUnit/lib/nunit.util.dll Binary files differdeleted file mode 100644 index 28d603c662..0000000000 --- a/main/src/addins/NUnit/lib/nunit.util.dll +++ /dev/null diff --git a/main/src/addins/NUnit/packages.config b/main/src/addins/NUnit/packages.config new file mode 100644 index 0000000000..3ca92b52ea --- /dev/null +++ b/main/src/addins/NUnit/packages.config @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="2.6.3" targetFramework="net40" />
+ <package id="NUnit.Runners" version="2.6.3" targetFramework="net40" />
+</packages>
\ No newline at end of file diff --git a/main/src/addins/NUnit/templates/NUnitProject.xpt.xml b/main/src/addins/NUnit/templates/NUnitProject.xpt.xml index 9a83ac6b23..4a42bb84fb 100644 --- a/main/src/addins/NUnit/templates/NUnitProject.xpt.xml +++ b/main/src/addins/NUnit/templates/NUnitProject.xpt.xml @@ -27,9 +27,12 @@ <References> <Reference type="Package" refto="System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> - <Reference type="Package" refto="nunit.framework" SpecificVersion = "false" LocalCopy = "false" /> </References> - + + <Packages> + <Package ID="NUnit" Version="2.6.3" /> + </Packages> + <Files> <CodeDomFile name="Test"> <CompileUnit> diff --git a/main/src/addins/TextTemplating/Mono.TextTemplating.Tests/TemplateEnginePreprocessTemplateTests.cs b/main/src/addins/TextTemplating/Mono.TextTemplating.Tests/TemplateEnginePreprocessTemplateTests.cs index 824a06ed1a..c904caacf7 100644 --- a/main/src/addins/TextTemplating/Mono.TextTemplating.Tests/TemplateEnginePreprocessTemplateTests.cs +++ b/main/src/addins/TextTemplating/Mono.TextTemplating.Tests/TemplateEnginePreprocessTemplateTests.cs @@ -60,6 +60,16 @@ namespace Mono.TextTemplating.Tests Assert.AreEqual (expectedOutput, output, output); } + + [Test] + public void CaptureEncodingAndExtension () + { + string input = InputTemplate_CaptureEncodingAndExtension; + string output = Preprocess (input); + string expectedOutput = TemplatingEngineHelper.CleanCodeDom (Output_CaptureEncodingAndExtension, "\n"); + + Assert.AreEqual (expectedOutput, output, output); + } #region Helpers @@ -145,6 +155,12 @@ Included Method Body Text Block #> "; + public static string InputTemplate_CaptureEncodingAndExtension = + @" +<#@ template debug=""false"" language=""C#"" inherits=""Foo"" hostspecific=""trueFromBase"" #> +<#@ output extension="".cs"" encoding=""utf-8"" #> +"; + #endregion #region Expected output strings @@ -589,6 +605,34 @@ namespace Templating { } } "; + + public static string Output_CaptureEncodingAndExtension = + + @"namespace Templating { + + + public partial class PreprocessedTemplate : Foo { + + public override string TransformText() { + this.GenerationEnvironment = null; + + #line 1 """" + this.Write(""\n""); + + #line default + #line hidden + return this.GenerationEnvironment.ToString(); + } + + protected override void Initialize() { + if ((this.Host != null)) { + this.Host.SetFileExtension("".cs""); + this.Host.SetOutputEncoding(System.Text.Encoding.GetEncoding(65001, true)); + } + base.Initialize(); + } + } +}"; #endregion } } diff --git a/main/src/addins/TextTemplating/Mono.TextTemplating/Microsoft.VisualStudio.TextTemplating/TextTransformation.cs b/main/src/addins/TextTemplating/Mono.TextTemplating/Microsoft.VisualStudio.TextTemplating/TextTransformation.cs index 409a36a9a6..f6a597752d 100644 --- a/main/src/addins/TextTemplating/Mono.TextTemplating/Microsoft.VisualStudio.TextTemplating/TextTransformation.cs +++ b/main/src/addins/TextTemplating/Mono.TextTemplating/Microsoft.VisualStudio.TextTemplating/TextTransformation.cs @@ -43,7 +43,7 @@ namespace Microsoft.VisualStudio.TextTemplating { } - protected internal virtual void Initialize () + public virtual void Initialize () { } @@ -55,15 +55,12 @@ namespace Microsoft.VisualStudio.TextTemplating public void Error (string message) { - Errors.Add (new CompilerError (null, -1, -1, null, message)); + Errors.Add (new CompilerError ("", 0, 0, "", message)); } public void Warning (string message) { - var err = new CompilerError (null, -1, -1, null, message) { - IsWarning = true, - }; - Errors.Add (err); + Errors.Add (new CompilerError ("", 0, 0, "", message) { IsWarning = true }); } protected internal CompilerErrorCollection Errors { diff --git a/main/src/addins/TextTemplating/Mono.TextTemplating/Mono.TextTemplating/RecyclableAppDomain.cs b/main/src/addins/TextTemplating/Mono.TextTemplating/Mono.TextTemplating/RecyclableAppDomain.cs index 51934e42e3..8ef80cddc1 100644 --- a/main/src/addins/TextTemplating/Mono.TextTemplating/Mono.TextTemplating/RecyclableAppDomain.cs +++ b/main/src/addins/TextTemplating/Mono.TextTemplating/Mono.TextTemplating/RecyclableAppDomain.cs @@ -201,6 +201,12 @@ namespace Mono.TextTemplating {
map[name] = location;
}
+
+ //keep this alive as long as the app domain is alive
+ public override object InitializeLifetimeService ()
+ {
+ return null;
+ }
}
}
}
\ No newline at end of file diff --git a/main/src/addins/TextTemplating/Mono.TextTemplating/Mono.TextTemplating/TemplatingEngine.cs b/main/src/addins/TextTemplating/Mono.TextTemplating/Mono.TextTemplating/TemplatingEngine.cs index 24394ff826..bdecf05e34 100644 --- a/main/src/addins/TextTemplating/Mono.TextTemplating/Mono.TextTemplating/TemplatingEngine.cs +++ b/main/src/addins/TextTemplating/Mono.TextTemplating/Mono.TextTemplating/TemplatingEngine.cs @@ -500,7 +500,7 @@ namespace Mono.TextTemplating case SegmentType.Block: if (helperMode) //TODO: are blocks permitted after helpers? - throw new ParserException ("Blocks are not permitted after helpers", seg.StartLocation); + pt.LogError ("Blocks are not permitted after helpers", seg.TagStartLocation); st = new CodeSnippetStatement (seg.Text); break; case SegmentType.Expression: @@ -512,7 +512,8 @@ namespace Mono.TextTemplating st = new CodeExpressionStatement (new CodeMethodInvokeExpression (writeMeth, new CodePrimitiveExpression (seg.Text))); break; case SegmentType.Helper: - type.Members.Add (CreateSnippetMember (seg.Text, location)); + if (!string.IsNullOrEmpty (seg.Text)) + type.Members.Add (CreateSnippetMember (seg.Text, location)); helperMode = true; break; default: @@ -524,7 +525,9 @@ namespace Mono.TextTemplating //TODO: is there a way to do this for languages that use indentation for blocks, e.g. python? using (var writer = new StringWriter ()) { settings.Provider.GenerateCodeFromStatement (st, writer, null); - type.Members.Add (CreateSnippetMember (writer.ToString (), location )); + var text = writer.ToString (); + if (!string.IsNullOrEmpty (text)) + type.Members.Add (CreateSnippetMember (text, location)); } } else { st.LinePragma = location; @@ -546,7 +549,7 @@ namespace Mono.TextTemplating //class code and attributes from processors foreach (var processor in settings.DirectiveProcessors.Values) { string classCode = processor.GetClassCodeForProcessingRun (); - if (classCode != null) + if (!string.IsNullOrEmpty (classCode)) type.Members.Add (CreateSnippetMember (classCode)); var atts = processor.GetTemplateClassCustomAttributes (); if (atts != null) { @@ -605,6 +608,44 @@ namespace Mono.TextTemplating }; if (!settings.IncludePreprocessingHelpers) initializeMeth.Attributes |= MemberAttributes.Override; + + //if preprocessed, pass the extension and encoding to the host + if (settings.IsPreprocessed && settings.HostSpecific) { + var hostProp = new CodePropertyReferenceExpression (new CodeThisReferenceExpression (), "Host"); + var statements = new List<CodeStatement> (); + + if (!string.IsNullOrEmpty (settings.Extension)) { + statements.Add (new CodeExpressionStatement (new CodeMethodInvokeExpression ( + hostProp, + "SetFileExtension", + new CodePrimitiveExpression (settings.Extension) + ))); + } + + if (settings.Encoding != null) { + statements.Add (new CodeExpressionStatement (new CodeMethodInvokeExpression ( + hostProp, + "SetOutputEncoding", + new CodeMethodInvokeExpression( + new CodeTypeReferenceExpression (typeof(Encoding)), + "GetEncoding", + new CodePrimitiveExpression (settings.Encoding.CodePage), + new CodePrimitiveExpression(true) + ) + ))); + } + + if (statements.Count > 0) { + initializeMeth.Statements.Add (new CodeConditionStatement ( + new CodeBinaryOperatorExpression ( + hostProp, + CodeBinaryOperatorType.IdentityInequality, + new CodePrimitiveExpression (null) + ), + statements.ToArray() + )); + } + } //pre-init code from processors foreach (var processor in settings.DirectiveProcessors.Values) { diff --git a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/TextTemplatingFileGenerator.cs b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/TextTemplatingFileGenerator.cs index ce0582208c..5b37d5c0b2 100644 --- a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/TextTemplatingFileGenerator.cs +++ b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/TextTemplatingFileGenerator.cs @@ -28,14 +28,15 @@ using System; using MonoDevelop.Ide.CustomTools; using MonoDevelop.Projects; using MonoDevelop.Core; +using System.Threading.Tasks; namespace MonoDevelop.TextTemplating { public class TextTemplatingFileGenerator : ISingleFileCustomTool { - public IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) + public Task Generate (ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { - return new ThreadAsyncOperation (delegate { + return Task.Factory.StartNew (delegate { using (var host = new ProjectFileTemplatingHost (file)) { host.AddMonoDevelopHostImport (); var defaultOutputName = file.FilePath.ChangeExtension (".cs"); //cs extension for VS compat @@ -50,7 +51,7 @@ namespace MonoDevelop.TextTemplating foreach (var err in host.Errors) monitor.Log.WriteLine (err); } - }, result); + }); } } } diff --git a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/TextTemplatingFilePreprocessor.cs b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/TextTemplatingFilePreprocessor.cs index bf08fb5dff..e1887f35b2 100644 --- a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/TextTemplatingFilePreprocessor.cs +++ b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/TextTemplatingFilePreprocessor.cs @@ -33,14 +33,15 @@ using MonoDevelop.Ide; using MonoDevelop.Ide.CustomTools; using MonoDevelop.Projects; using MonoDevelop.Projects.Policies; +using System.Threading.Tasks; namespace MonoDevelop.TextTemplating { public class TextTemplatingFilePreprocessor : ISingleFileCustomTool { - public IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) + public Task Generate (ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { - return new ThreadAsyncOperation (delegate { + return Task.Factory.StartNew (delegate { var host = new ProjectFileTemplatingHost (file); var dnp = file.Project as DotNetProject; @@ -74,7 +75,7 @@ namespace MonoDevelop.TextTemplating result.Errors.AddRange (host.Errors); foreach (var err in host.Errors) monitor.Log.WriteLine (err); - }, result); + }); } static bool warningLogged; diff --git a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/TextTemplatingService.cs b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/TextTemplatingService.cs index e434450482..34892038ad 100644 --- a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/TextTemplatingService.cs +++ b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/TextTemplatingService.cs @@ -39,7 +39,7 @@ namespace MonoDevelop.TextTemplating TaskService.Errors.Clear (); foreach (CompilerError err in errors) { - TaskService.Errors.Add (new Task (err.FileName, err.ErrorText, err.Column, err.Line, + TaskService.Errors.Add (new UserTask (err.FileName, err.ErrorText, err.Column, err.Line, err.IsWarning? TaskSeverity.Warning : TaskSeverity.Error)); } TaskService.ShowErrors (); diff --git a/main/src/addins/VBNetBinding/Gui/ProjectOptionsPanelWidget.cs b/main/src/addins/VBNetBinding/Gui/ProjectOptionsPanelWidget.cs index 211b6a8f7a..b72279305b 100644 --- a/main/src/addins/VBNetBinding/Gui/ProjectOptionsPanelWidget.cs +++ b/main/src/addins/VBNetBinding/Gui/ProjectOptionsPanelWidget.cs @@ -39,7 +39,7 @@ namespace MonoDevelop.VBNetBinding public partial class ProjectOptionsPanelWidget : Gtk.Bin { DotNetProject project; - VBProjectParameters parameters; + VBProjectExtension parameters; public ProjectOptionsPanelWidget (MonoDevelop.Projects.Project project) { @@ -49,7 +49,7 @@ namespace MonoDevelop.VBNetBinding this.Build(); this.project = (DotNetProject) project; - parameters = (VBProjectParameters) this.project.LanguageParameters; + parameters = this.project.GetService<VBProjectExtension> (); cr = new Gtk.CellRendererText (); store = new Gtk.ListStore (typeof (string)); diff --git a/main/src/addins/VBNetBinding/Project/Import.cs b/main/src/addins/VBNetBinding/Project/Import.cs index f8685402fa..227b7a27a1 100644 --- a/main/src/addins/VBNetBinding/Project/Import.cs +++ b/main/src/addins/VBNetBinding/Project/Import.cs @@ -30,14 +30,14 @@ using MonoDevelop.Projects; namespace MonoDevelop.VBNetBinding { - [DataItem ("Import")] - public class Import: SimpleProjectItem + public class Import: ProjectItem { public Import () { + ItemName = "Import"; } - public Import (string include) + public Import (string include): this () { Include = include; } diff --git a/main/src/addins/VBNetBinding/Project/VBCompilerParameters.cs b/main/src/addins/VBNetBinding/Project/VBCompilerParameters.cs index 386f8cab79..1dc141c777 100644 --- a/main/src/addins/VBNetBinding/Project/VBCompilerParameters.cs +++ b/main/src/addins/VBNetBinding/Project/VBCompilerParameters.cs @@ -36,7 +36,7 @@ using MonoDevelop.Core.Serialization; namespace MonoDevelop.VBNetBinding {
- public class VBCompilerParameters: ConfigurationParameters
+ public class VBCompilerParameters: DotNetCompilerParameters
{ // // Project level properties: diff --git a/main/src/addins/VBNetBinding/Project/VBProjectParameters.cs b/main/src/addins/VBNetBinding/Project/VBProjectExtension.cs index f3e8dd95ff..b10b0d0300 100644 --- a/main/src/addins/VBNetBinding/Project/VBProjectParameters.cs +++ b/main/src/addins/VBNetBinding/Project/VBProjectExtension.cs @@ -1,21 +1,21 @@ -// -// VBProjectParameters.cs -// +// +// VBProjectExtension.cs +// // Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,54 +23,44 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - using System; -using MonoDevelop.Core.Serialization; using MonoDevelop.Projects; +using MonoDevelop.Projects.Formats.MSBuild; +using MonoDevelop.Core.Serialization; namespace MonoDevelop.VBNetBinding { - public class VBProjectParameters: DotNetProjectParameters + public class VBProjectExtension: DotNetProjectExtension { - public override bool DefaultNamespaceIsImplicit { - get { - return true; - } - } - [ItemProperty ("OptionInfer", DefaultValue="Off")] string optionInfer = "Off"; - + [ItemProperty ("OptionExplicit", DefaultValue="On")] string optionExplicit = "On"; - + [ItemProperty ("OptionCompare", DefaultValue="Binary")] string optionCompare = "Binary"; - + [ItemProperty ("OptionStrict", DefaultValue="Off")] string optionStrict = "Off"; - + [ItemProperty ("MyType", DefaultValue="")] string myType = string.Empty; - + [ItemProperty ("StartupObject", DefaultValue="")] string startupObject = string.Empty; - + [ProjectPathItemProperty ("ApplicationIcon", DefaultValue="")] string applicationIcon = string.Empty; - + [ItemProperty ("CodePage", DefaultValue="")] string codePage = string.Empty; - - public VBProjectParameters() - { - } - + public bool OptionInfer { get { return optionInfer == "On"; } set { optionInfer = value ? "On" : "Off"; } } - + public bool OptionExplicit { get { return optionExplicit == "On"; } set { optionExplicit = value ? "On" : "Off"; } @@ -85,25 +75,44 @@ namespace MonoDevelop.VBNetBinding get { return optionStrict == "On"; } set { optionStrict = value ? "On" : "Off"; } } - + public string MyType { get { return myType; } set { myType = value ?? string.Empty; } } - + public string StartupObject { get { return startupObject; } set { startupObject = value ?? string.Empty; } } - + public string ApplicationIcon { get { return applicationIcon; } set { applicationIcon = value ?? string.Empty; } } - + public string CodePage { get { return codePage; } set { codePage = value ?? string.Empty; } } + + protected override void Initialize () + { + base.Initialize (); + Project.DefaultNamespaceIsImplicit = true; + } + + protected override void OnReadProject (MonoDevelop.Core.ProgressMonitor monitor, MSBuildProject msproject) + { + base.OnReadProject (monitor, msproject); + msproject.GetGlobalPropertyGroup ().ReadObjectProperties (this, typeof(VBProjectExtension)); + } + + protected override void OnWriteProject (MonoDevelop.Core.ProgressMonitor monitor, MSBuildProject msproject) + { + base.OnWriteProject (monitor, msproject); + msproject.GetGlobalPropertyGroup ().WriteObjectProperties (this, typeof(VBProjectExtension)); + } } } + diff --git a/main/src/addins/VBNetBinding/VBBindingCompilerServices.cs b/main/src/addins/VBNetBinding/VBBindingCompilerServices.cs index a5eb348271..8ef14e9669 100644 --- a/main/src/addins/VBNetBinding/VBBindingCompilerServices.cs +++ b/main/src/addins/VBNetBinding/VBBindingCompilerServices.cs @@ -55,7 +55,7 @@ namespace MonoDevelop.VBNetBinding { static Regex regexError = new Regex (@"^\s*((?<file>.*)\s?\((?<line>\d*)(,(?<column>\d*))?\) : )?(?<level>\w+) :? ?(?<number>[^:]*): (?<message>.*)$", RegexOptions.Compiled | RegexOptions.ExplicitCapture); - string GenerateOptions (DotNetProjectConfiguration configuration, VBCompilerParameters compilerparameters, VBProjectParameters projectparameters, string outputFileName) + string GenerateOptions (DotNetProjectConfiguration configuration, VBCompilerParameters compilerparameters, VBProjectExtension projectparameters, string outputFileName) { DotNetProject project = (DotNetProject) configuration.ParentItem; StringBuilder sb = new StringBuilder (); @@ -189,16 +189,14 @@ namespace MonoDevelop.VBNetBinding { return sb.ToString(); } - public BuildResult Compile (ProjectItemCollection items, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, IProgressMonitor monitor) + public BuildResult Compile (ProjectItemCollection items, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, ProgressMonitor monitor) { VBCompilerParameters compilerparameters = (VBCompilerParameters) configuration.CompilationParameters; if (compilerparameters == null) compilerparameters = new VBCompilerParameters (); - VBProjectParameters projectparameters = (VBProjectParameters) configuration.ProjectParameters; - if (projectparameters == null) - projectparameters = new VBProjectParameters (); - + var projectparameters = configuration.ParentItem.GetService<VBProjectExtension> (); + string exe = configuration.CompiledOutputName; string responseFileName = Path.GetTempFileName(); StreamWriter writer = new StreamWriter (responseFileName); diff --git a/main/src/addins/VBNetBinding/VBLanguageBinding.cs b/main/src/addins/VBNetBinding/VBLanguageBinding.cs index 0fbca6123c..8ddde46aaa 100644 --- a/main/src/addins/VBNetBinding/VBLanguageBinding.cs +++ b/main/src/addins/VBNetBinding/VBLanguageBinding.cs @@ -62,13 +62,13 @@ namespace MonoDevelop.VBNetBinding return Path.GetExtension(fileName) == ".vb"; } - public BuildResult Compile (ProjectItemCollection items, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, IProgressMonitor monitor) + public BuildResult Compile (ProjectItemCollection items, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, ProgressMonitor monitor) { Debug.Assert(compilerServices != null); return compilerServices.Compile (items, configuration, configSelector, monitor); } - public ConfigurationParameters CreateCompilationParameters (XmlElement projectOptions) + public DotNetCompilerParameters CreateCompilationParameters (XmlElement projectOptions) { return new VBCompilerParameters (); } @@ -94,11 +94,6 @@ namespace MonoDevelop.VBNetBinding return new ClrVersion[] { ClrVersion.Net_2_0, ClrVersion.Net_4_0 }; } - public ProjectParameters CreateProjectParameters (XmlElement projectOptions) - { - return new VBProjectParameters (); - } - class ImprovedCodeDomProvider : Microsoft.VisualBasic.VBCodeProvider { [Obsolete ("Use CodeDomProvider class")] diff --git a/main/src/addins/VBNetBinding/VBNetBinding.csproj b/main/src/addins/VBNetBinding/VBNetBinding.csproj index d730d2a3f5..7591c7b96c 100644 --- a/main/src/addins/VBNetBinding/VBNetBinding.csproj +++ b/main/src/addins/VBNetBinding/VBNetBinding.csproj @@ -95,8 +95,8 @@ <Compile Include="Gui\ImportsOptionsPanelWidget.cs" /> <Compile Include="Gui\ImportsOptionsPanel.cs" /> <Compile Include="gtk-gui\MonoDevelop.VBNetBinding.ImportsOptionsPanelWidget.cs" /> - <Compile Include="Project\VBProjectParameters.cs" /> <Compile Include="AddinInfo.cs" /> + <Compile Include="Project\VBProjectExtension.cs" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="templates\EmptyVBFile.xft.xml"> diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs index 8841f269d3..a87f73024f 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs @@ -155,7 +155,7 @@ namespace MonoDevelop.VersionControl.Git.Tests protected override void PostCommit (Repository repo)
{
var repo2 = (GitRepository)repo;
- repo2.Push (new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor (), repo2.GetCurrentRemote (), repo2.GetCurrentBranch ());
+ repo2.Push (new MonoDevelop.Core.ProgressMonitor (), repo2.GetCurrentRemote (), repo2.GetCurrentBranch ());
}
protected override void BlameExtraInternals (Annotation [] annotations)
@@ -193,19 +193,19 @@ namespace MonoDevelop.VersionControl.Git.Tests AddFile ("file1", "text", true, true);
repo2.CreateBranch ("branch1", null);
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor (), "branch1");
+ repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "branch1");
Assert.AreEqual ("branch1", repo2.GetCurrentBranch ());
Assert.IsTrue (File.Exists (LocalPath + "file1"), "Branch not inheriting from current.");
AddFile ("file2", "text", true, false);
repo2.CreateBranch ("branch2", null);
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor (), "branch2");
+ repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "branch2");
Assert.IsTrue (!File.Exists (LocalPath + "file2"), "Uncommitted changes were not stashed");
repo2.GetStashes ().Pop (new NullProgressMonitor ());
Assert.IsTrue (File.Exists (LocalPath + "file2"), "Uncommitted changes were not stashed correctly");
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor (), "master");
+ repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "master");
repo2.RemoveBranch ("branch1");
Assert.IsFalse (repo2.GetBranches ().Any (b => b.Name == "branch1"), "Failed to delete branch");
@@ -224,14 +224,14 @@ namespace MonoDevelop.VersionControl.Git.Tests PostCommit (repo2);
repo2.CreateBranch ("branch3", null);
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor (), "branch3");
+ repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "branch3");
AddFile ("file2", "asdf", true, true);
- repo2.Push (new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor (), "origin", "branch3");
+ repo2.Push (new MonoDevelop.Core.ProgressMonitor (), "origin", "branch3");
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor (), "master");
+ repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "master");
repo2.CreateBranch ("branch4", "origin/branch3");
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor (), "branch4");
+ repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "branch4");
Assert.IsTrue (File.Exists (LocalPath + "file2"), "Tracking remote is not grabbing correct commits");
}
@@ -306,7 +306,7 @@ namespace MonoDevelop.VersionControl.Git.Tests AddFile ("file1", "text", true, true);
PostCommit (repo2);
repo2.CreateBranch ("branch1", null);
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor (), "branch1");
+ repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "branch1");
AddFile ("file2", "text", true, true);
PostCommit (repo2);
Assert.AreEqual (2, repo2.GetBranches ().Count ());
@@ -329,12 +329,12 @@ namespace MonoDevelop.VersionControl.Git.Tests Assert.IsTrue (repo2.IsBranchMerged ("master"));
repo2.CreateBranch ("branch1", null);
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor (), "branch1");
+ repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "branch1");
AddFile ("file2", "text", true, true);
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor (), "master");
+ repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "master");
Assert.IsFalse (repo2.IsBranchMerged ("branch1"));
- repo2.Merge ("branch1", GitUpdateOptions.NormalUpdate, new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor ());
+ repo2.Merge ("branch1", GitUpdateOptions.NormalUpdate, new MonoDevelop.Core.ProgressMonitor ());
Assert.IsTrue (repo2.IsBranchMerged ("branch1"));
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseRepositoryTests.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseRepositoryTests.cs index ba74fd3e0e..648cc45fdb 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseRepositoryTests.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseRepositoryTests.cs @@ -242,15 +242,15 @@ namespace MonoDevelop.VersionControl.Tests Repo2 = GetRepo (second, RemoteUrl); string added = second + "testfile2"; File.Create (added).Close (); - Repo2.Add (added, false, new NullProgressMonitor ()); + Repo2.Add (added, false, new ProgressMonitor ()); ChangeSet changes = Repo.CreateChangeSet (Repo.RootPath); changes.AddFile (Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache)); changes.GlobalComment = "test2"; - Repo2.Commit (changes, new NullProgressMonitor ()); + Repo2.Commit (changes, new ProgressMonitor ()); PostCommit (Repo2); - Repo.Update (Repo.RootPath, true, new NullProgressMonitor ()); + Repo.Update (Repo.RootPath, true, new ProgressMonitor ()); Assert.True (File.Exists (LocalPath + "testfile2")); DeleteDirectory (second); @@ -290,7 +290,7 @@ namespace MonoDevelop.VersionControl.Tests // Revert to head. File.WriteAllText (added, content); - Repo.Revert (added, false, new NullProgressMonitor ()); + Repo.Revert (added, false, new ProgressMonitor ()); Assert.AreEqual (Repo.GetBaseText (added), File.ReadAllText (added)); } @@ -317,7 +317,7 @@ namespace MonoDevelop.VersionControl.Tests string added = LocalPath + "testfile2"; AddFile ("testfile", "text", true, true); AddFile ("testfile2", "text2", true, true); - Repo.RevertRevision (added, GetHeadRevision (), new NullProgressMonitor ()); + Repo.RevertRevision (added, GetHeadRevision (), new ProgressMonitor ()); Assert.IsFalse (File.Exists (added)); } @@ -334,7 +334,7 @@ namespace MonoDevelop.VersionControl.Tests AddFile ("testfile", null, true, true); src = LocalPath + "testfile"; dst = src + "2"; - Repo.MoveFile (src, dst, false, new NullProgressMonitor ()); + Repo.MoveFile (src, dst, false, new ProgressMonitor ()); srcVi = Repo.GetVersionInfo (src, VersionInfoQueryFlags.IgnoreCache); dstVi = Repo.GetVersionInfo (dst, VersionInfoQueryFlags.IgnoreCache); const VersionStatus versionedStatus = VersionStatus.ScheduledDelete | VersionStatus.ScheduledReplace; @@ -345,7 +345,7 @@ namespace MonoDevelop.VersionControl.Tests AddFile ("addedfile", null, true, false); src = LocalPath + "addedfile"; dst = src + "2"; - Repo.MoveFile (src, dst, false, new NullProgressMonitor ()); + Repo.MoveFile (src, dst, false, new ProgressMonitor ()); srcVi = Repo.GetVersionInfo (src, VersionInfoQueryFlags.IgnoreCache); dstVi = Repo.GetVersionInfo (dst, VersionInfoQueryFlags.IgnoreCache); Assert.AreEqual (VersionStatus.Unversioned, srcVi.Status); @@ -355,7 +355,7 @@ namespace MonoDevelop.VersionControl.Tests AddFile ("unversionedfile", null, false, false); src = LocalPath + "unversionedfile"; dst = src + "2"; - Repo.MoveFile (src, dst, false, new NullProgressMonitor ()); + Repo.MoveFile (src, dst, false, new ProgressMonitor ()); srcVi = Repo.GetVersionInfo (src, VersionInfoQueryFlags.IgnoreCache); dstVi = Repo.GetVersionInfo (dst, VersionInfoQueryFlags.IgnoreCache); Assert.AreEqual (VersionStatus.Unversioned, srcVi.Status); @@ -374,7 +374,7 @@ namespace MonoDevelop.VersionControl.Tests AddDirectory ("test", true, false); AddFile ("test" + Path.DirectorySeparatorChar + "testfile", null, true, true); - Repo.MoveDirectory (srcDir, dstDir, false, new NullProgressMonitor ()); + Repo.MoveDirectory (srcDir, dstDir, false, new ProgressMonitor ()); VersionInfo srcVi = Repo.GetVersionInfo (src, VersionInfoQueryFlags.IgnoreCache); VersionInfo dstVi = Repo.GetVersionInfo (dst, VersionInfoQueryFlags.IgnoreCache); const VersionStatus expectedStatus = VersionStatus.ScheduledDelete | VersionStatus.ScheduledReplace; @@ -390,7 +390,7 @@ namespace MonoDevelop.VersionControl.Tests // Versioned file. added = LocalPath + "testfile1" + postFix; AddFile ("testfile1" + postFix, null, true, true); - Repo.DeleteFile (added, true, new NullProgressMonitor (), keepLocal); + Repo.DeleteFile (added, true, new ProgressMonitor (), keepLocal); vi = Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache); Assert.AreEqual (VersionStatus.ScheduledDelete, vi.Status & VersionStatus.ScheduledDelete); Assert.AreEqual (keepLocal, File.Exists (added)); @@ -398,7 +398,7 @@ namespace MonoDevelop.VersionControl.Tests // Just added file. added = LocalPath + "testfile2" + postFix; AddFile ("testfile2" + postFix, null, true, false); - Repo.DeleteFile (added, true, new NullProgressMonitor (), keepLocal); + Repo.DeleteFile (added, true, new ProgressMonitor (), keepLocal); vi = Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache); Assert.AreEqual (VersionStatus.Unversioned, vi.Status); Assert.AreEqual (keepLocal, File.Exists (added)); @@ -406,7 +406,7 @@ namespace MonoDevelop.VersionControl.Tests // Non versioned file. added = LocalPath + "testfile3" + postFix; AddFile ("testfile3" + postFix, null, false, false); - Repo.DeleteFile (added, true, new NullProgressMonitor (), keepLocal); + Repo.DeleteFile (added, true, new ProgressMonitor (), keepLocal); vi = Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache); Assert.AreEqual (VersionStatus.Unversioned, vi.Status); Assert.AreEqual (keepLocal, File.Exists (added)); @@ -433,7 +433,7 @@ namespace MonoDevelop.VersionControl.Tests AddDirectory ("test1" + postFix, true, false); AddFile ("test1" + postFix + Path.DirectorySeparatorChar + "testfile", null, true, true); - Repo.DeleteDirectory (addedDir, true, new NullProgressMonitor (), keepLocal); + Repo.DeleteDirectory (addedDir, true, new ProgressMonitor (), keepLocal); vi = Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache); Assert.AreEqual (VersionStatus.ScheduledDelete, vi.Status & VersionStatus.ScheduledDelete); Assert.AreEqual (keepLocal, File.Exists (added)); @@ -444,7 +444,7 @@ namespace MonoDevelop.VersionControl.Tests AddDirectory ("test2" + postFix, true, false); AddFile ("test2" + postFix + Path.DirectorySeparatorChar + "testfile", null, true, false); - Repo.DeleteDirectory (addedDir, true, new NullProgressMonitor (), keepLocal); + Repo.DeleteDirectory (addedDir, true, new ProgressMonitor (), keepLocal); vi = Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache); Assert.AreEqual (VersionStatus.Unversioned, vi.Status); Assert.AreEqual (keepLocal, File.Exists (added)); @@ -455,7 +455,7 @@ namespace MonoDevelop.VersionControl.Tests AddDirectory ("test3" + postFix, true, false); AddFile ("test3" + postFix + Path.DirectorySeparatorChar + "testfile", null, false, false); - Repo.DeleteDirectory (addedDir, true, new NullProgressMonitor (), keepLocal); + Repo.DeleteDirectory (addedDir, true, new ProgressMonitor (), keepLocal); vi = Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache); Assert.AreEqual (VersionStatus.Unversioned, vi.Status); Assert.AreEqual (keepLocal, File.Exists (added)); @@ -475,7 +475,7 @@ namespace MonoDevelop.VersionControl.Tests { string added = LocalPath + "testfile"; AddFile ("testfile", null, true, true); - Repo.Lock (new NullProgressMonitor (), added); + Repo.Lock (new ProgressMonitor (), added); PostLock (); } @@ -490,8 +490,8 @@ namespace MonoDevelop.VersionControl.Tests { string added = LocalPath + "testfile"; AddFile ("testfile", null, true, true); - Repo.Lock (new NullProgressMonitor (), "testfile"); - Repo.Unlock (new NullProgressMonitor (), added); + Repo.Lock (new ProgressMonitor (), "testfile"); + Repo.Unlock (new ProgressMonitor (), added); PostLock (); } @@ -575,7 +575,7 @@ namespace MonoDevelop.VersionControl.Tests protected void Checkout (string path, string url) { Repository _repo = GetRepo (path, url); - _repo.Checkout (path, true, new NullProgressMonitor ()); + _repo.Checkout (path, true, new ProgressMonitor ()); if (Repo == null) Repo = _repo; else @@ -589,7 +589,7 @@ namespace MonoDevelop.VersionControl.Tests changes.AddFile (Repo.GetVersionInfo (item, VersionInfoQueryFlags.IgnoreCache)); } changes.GlobalComment = String.Format ("Commit #{0}", CommitNumber); - Repo.Commit (changes, new NullProgressMonitor ()); + Repo.Commit (changes, new ProgressMonitor ()); CommitNumber++; } @@ -603,7 +603,7 @@ namespace MonoDevelop.VersionControl.Tests changes.AddFile (Repo.GetVersionInfo (path, VersionInfoQueryFlags.IgnoreCache)); changes.GlobalComment = String.Format ("Commit #{0}", CommitNumber); - Repo.Commit (changes, new NullProgressMonitor ()); + Repo.Commit (changes, new ProgressMonitor ()); CommitNumber++; } @@ -626,7 +626,7 @@ namespace MonoDevelop.VersionControl.Tests File.WriteAllText (added, contents); if (toVcs) - Repo.Add (added, false, new NullProgressMonitor ()); + Repo.Add (added, false, new ProgressMonitor ()); if (commit) CommitFile (added); diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Commands.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Commands.cs index b624b70f0e..72d67d950a 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Commands.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Commands.cs @@ -50,7 +50,7 @@ namespace MonoDevelop.VersionControl.Git { public GitRepository Repository { get { - IWorkspaceObject wob = IdeApp.ProjectOperations.CurrentSelectedSolutionItem; + WorkspaceObject wob = IdeApp.ProjectOperations.CurrentSelectedSolutionItem; if (wob == null) wob = IdeApp.ProjectOperations.CurrentSelectedWorkspaceItem; if (wob != null) @@ -86,7 +86,7 @@ namespace MonoDevelop.VersionControl.Git if (repo == null) return; - IWorkspaceObject wob = IdeApp.ProjectOperations.CurrentSelectedItem as IWorkspaceObject; + WorkspaceObject wob = IdeApp.ProjectOperations.CurrentSelectedItem as WorkspaceObject; if (wob == null) return; if (((wob is WorkspaceItem) && ((WorkspaceItem)wob).ParentWorkspace == null) || diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitNodeBuilderExtension.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitNodeBuilderExtension.cs index 6f008faa03..03561045fe 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitNodeBuilderExtension.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitNodeBuilderExtension.cs @@ -35,7 +35,7 @@ namespace MonoDevelop.VersionControl.Git { sealed class GitNodeBuilderExtension: NodeBuilderExtension { - readonly Dictionary<FilePath,IWorkspaceObject> repos = new Dictionary<FilePath, IWorkspaceObject> (); + readonly Dictionary<FilePath,WorkspaceObject> repos = new Dictionary<FilePath, WorkspaceObject> (); protected override void Initialize () { @@ -53,15 +53,15 @@ namespace MonoDevelop.VersionControl.Git public override bool CanBuildNode (Type dataType) { - return typeof(IWorkspaceObject).IsAssignableFrom (dataType); + return typeof(WorkspaceObject).IsAssignableFrom (dataType); } public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, NodeInfo nodeInfo) { - IWorkspaceObject ob = (IWorkspaceObject) dataObject; + WorkspaceObject ob = (WorkspaceObject) dataObject; GitRepository rep = VersionControlService.GetRepository (ob) as GitRepository; if (rep != null) { - IWorkspaceObject rob; + WorkspaceObject rob; if (repos.TryGetValue (rep.RootPath.CanonicalPath, out rob)) { if (ob == rob) nodeInfo.Label += " (" + rep.GetCurrentBranch () + ")"; @@ -71,7 +71,7 @@ namespace MonoDevelop.VersionControl.Git public override void OnNodeAdded (object dataObject) { - IWorkspaceObject ob = (IWorkspaceObject) dataObject; + WorkspaceObject ob = (WorkspaceObject) dataObject; GitRepository rep = VersionControlService.GetRepository (ob) as GitRepository; if (rep != null && !repos.ContainsKey (rep.RootPath.CanonicalPath)) { repos [rep.RootPath] = ob; @@ -80,9 +80,9 @@ namespace MonoDevelop.VersionControl.Git public override void OnNodeRemoved (object dataObject) { - IWorkspaceObject ob = (IWorkspaceObject) dataObject; + WorkspaceObject ob = (WorkspaceObject) dataObject; GitRepository rep = VersionControlService.GetRepository (ob) as GitRepository; - IWorkspaceObject rob; + WorkspaceObject rob; if (rep != null && repos.TryGetValue (rep.RootPath.CanonicalPath, out rob)) { if (ob == rob) repos.Remove (rep.RootPath.CanonicalPath); diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs index 144e81b7ce..83725fb1d1 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs @@ -44,6 +44,7 @@ using NGit.Transport; using NGit.Diff; using NGit.Merge; using NGit.Submodule; +using ProgressMonitor = MonoDevelop.Core.ProgressMonitor; namespace MonoDevelop.VersionControl.Git { @@ -409,7 +410,7 @@ namespace MonoDevelop.VersionControl.Git .Select (f => new FilePath (f).CanonicalPath)); } - protected override Repository OnPublish (string serverPath, FilePath localPath, FilePath[] files, string message, IProgressMonitor monitor) + protected override Repository OnPublish (string serverPath, FilePath localPath, FilePath[] files, string message, ProgressMonitor monitor) { // Initialize the repository RootRepository = GitUtil.Init (localPath, Url); @@ -451,7 +452,7 @@ namespace MonoDevelop.VersionControl.Git return this; } - protected override void OnUpdate (FilePath[] localPaths, bool recurse, IProgressMonitor monitor) + protected override void OnUpdate (FilePath[] localPaths, bool recurse, ProgressMonitor monitor) { IEnumerable<DiffEntry> statusList = null; @@ -478,7 +479,7 @@ namespace MonoDevelop.VersionControl.Git monitor.EndTask (); } - public void Fetch (IProgressMonitor monitor) + public void Fetch (ProgressMonitor monitor) { string remote = GetCurrentRemote (); if (remote == null) @@ -536,7 +537,7 @@ namespace MonoDevelop.VersionControl.Git return true; } - public void Rebase (string upstreamRef, GitUpdateOptions options, IProgressMonitor monitor) + public void Rebase (string upstreamRef, GitUpdateOptions options, ProgressMonitor monitor) { StashCollection stashes = GitUtil.GetStashes (RootRepository); Stash stash = null; @@ -660,7 +661,7 @@ namespace MonoDevelop.VersionControl.Git } } - public void Merge (string branch, GitUpdateOptions options, IProgressMonitor monitor) + public void Merge (string branch, GitUpdateOptions options, ProgressMonitor monitor) { IEnumerable<DiffEntry> statusList = null; Stash stash = null; @@ -798,7 +799,7 @@ namespace MonoDevelop.VersionControl.Git return res; } - protected override void OnCommit (ChangeSet changeSet, IProgressMonitor monitor) + protected override void OnCommit (ChangeSet changeSet, ProgressMonitor monitor) { string message = changeSet.GlobalComment; if (string.IsNullOrEmpty (message)) @@ -864,7 +865,7 @@ namespace MonoDevelop.VersionControl.Git config.Save (); } - protected override void OnCheckout (FilePath targetLocalPath, Revision rev, bool recurse, IProgressMonitor monitor) + protected override void OnCheckout (FilePath targetLocalPath, Revision rev, bool recurse, ProgressMonitor monitor) { CloneCommand cmd = NGit.Api.Git.CloneRepository (); cmd.SetURI (Url); @@ -889,108 +890,109 @@ namespace MonoDevelop.VersionControl.Git } } - protected override void OnRevert (FilePath[] localPaths, bool recurse, IProgressMonitor monitor) + protected override void OnRevert (FilePath[] localPaths, bool recurse, ProgressMonitor monitor) { // Replace with NGit.Api.Git.Reset () + // FIXME: we lack info about what happened to files - foreach (var group in GroupByRepository (localPaths)) { + + var groups = GroupByRepository (localPaths).ToArray (); + monitor.BeginTask (GettextCatalog.GetString ("Reverting files"), groups.Length); + + foreach (var group in groups) { + monitor.BeginStep (1); var repository = group.Key; var files = group.ToArray (); - var c = GetHeadCommit (repository); - RevTree tree = c != null ? c.Tree : null; - - List<FilePath> changedFiles = new List<FilePath> (); - List<FilePath> removedFiles = new List<FilePath> (); - - monitor.BeginTask (GettextCatalog.GetString ("Reverting files"), 3); - monitor.BeginStepTask (GettextCatalog.GetString ("Reverting files"), files.Length, 2); - - DirCache dc = repository.LockDirCache (); - DirCacheBuilder builder = dc.Builder (); - - try { - HashSet<string> entriesToRemove = new HashSet<string> (); - HashSet<string> foldersToRemove = new HashSet<string> (); + var c = GetHeadCommit (repository); + RevTree tree = c != null ? c.Tree : null; - // Add the new entries - foreach (FilePath fp in files) { - string p = repository.ToGitPath (fp); - - // Register entries to be removed from the index - if (Directory.Exists (fp)) - foldersToRemove.Add (p); - else - entriesToRemove.Add (p); + List<FilePath> changedFiles = new List<FilePath> (); + List<FilePath> removedFiles = new List<FilePath> (); + + monitor.BeginTask (files.Length); + + DirCache dc = repository.LockDirCache (); + DirCacheBuilder builder = dc.Builder (); + + try { + HashSet<string> entriesToRemove = new HashSet<string> (); + HashSet<string> foldersToRemove = new HashSet<string> (); - TreeWalk tw = tree != null ? TreeWalk.ForPath (repository, p, tree) : null; - if (tw == null) { - // Removed from the index - } - else { - // Add new entries + // Add the new entries + foreach (FilePath fp in files) { + string p = repository.ToGitPath (fp); - TreeWalk r; - if (tw.IsSubtree) { - // It's a directory. Make sure we remove existing index entries of this directory + // Register entries to be removed from the index + if (Directory.Exists (fp)) foldersToRemove.Add (p); + else + entriesToRemove.Add (p); + + TreeWalk tw = tree != null ? TreeWalk.ForPath (repository, p, tree) : null; + if (tw == null) { + // Removed from the index + } + else { + // Add new entries - // We have to iterate through all folder files. We need a new iterator since the - // existing rw is not recursive - r = new TreeWalk(repository); - r.Reset (tree); - r.Filter = PathFilterGroup.CreateFromStrings(new string[]{p}); - r.Recursive = true; - r.Next (); - } else { - r = tw; + TreeWalk r; + if (tw.IsSubtree) { + // It's a directory. Make sure we remove existing index entries of this directory + foldersToRemove.Add (p); + + // We have to iterate through all folder files. We need a new iterator since the + // existing rw is not recursive + r = new TreeWalk(repository); + r.Reset (tree); + r.Filter = PathFilterGroup.CreateFromStrings(new string[]{p}); + r.Recursive = true; + r.Next (); + } else { + r = tw; + } + + do { + // There can be more than one entry if reverting a whole directory + string rpath = repository.FromGitPath (r.PathString); + DirCacheEntry e = new DirCacheEntry (r.PathString); + e.SetObjectId (r.GetObjectId (0)); + e.FileMode = r.GetFileMode (0); + if (!Directory.Exists (Path.GetDirectoryName (rpath))) + Directory.CreateDirectory (rpath); + DirCacheCheckout.CheckoutEntry (repository, rpath, e); + builder.Add (e); + changedFiles.Add (rpath); + } while (r.Next ()); } - - do { - // There can be more than one entry if reverting a whole directory - string rpath = repository.FromGitPath (r.PathString); - DirCacheEntry e = new DirCacheEntry (r.PathString); - e.SetObjectId (r.GetObjectId (0)); - e.FileMode = r.GetFileMode (0); - if (!Directory.Exists (Path.GetDirectoryName (rpath))) - Directory.CreateDirectory (rpath); - DirCacheCheckout.CheckoutEntry (repository, rpath, e); + } + + // Add entries we want to keep + int count = dc.GetEntryCount (); + for (int n=0; n<count; n++) { + DirCacheEntry e = dc.GetEntry (n); + string path = e.PathString; + if (!entriesToRemove.Contains (path) && !foldersToRemove.Any (f => IsSubpath (f,path))) builder.Add (e); - changedFiles.Add (rpath); - } while (r.Next ()); } + + builder.Commit (); monitor.Step (1); } - - // Add entries we want to keep - int count = dc.GetEntryCount (); - for (int n=0; n<count; n++) { - DirCacheEntry e = dc.GetEntry (n); - string path = e.PathString; - if (!entriesToRemove.Contains (path) && !foldersToRemove.Any (f => IsSubpath (f,path))) - builder.Add (e); + catch { + dc.Unlock (); + throw; } - builder.Commit (); - } - catch { - dc.Unlock (); - throw; - } - - monitor.EndTask (); - monitor.BeginTask (null, files.Length); + foreach (FilePath p in changedFiles) + FileService.NotifyFileChanged (p, true); - foreach (FilePath p in changedFiles) { - FileService.NotifyFileChanged (p, true); - monitor.Step (1); - } - foreach (FilePath p in removedFiles) { - FileService.NotifyFileRemoved (p); - monitor.Step (1); + foreach (FilePath p in removedFiles) + FileService.NotifyFileRemoved (p); + + monitor.EndTask (); } monitor.EndTask (); - } } static bool IsSubpath (string basePath, string childPath) @@ -1001,12 +1003,12 @@ namespace MonoDevelop.VersionControl.Git return childPath.StartsWith (basePath + "/", StringComparison.InvariantCulture); } - protected override void OnRevertRevision (FilePath localPath, Revision revision, IProgressMonitor monitor) + protected override void OnRevertRevision (FilePath localPath, Revision revision, ProgressMonitor monitor) { throw new NotSupportedException (); } - protected override void OnRevertToRevision (FilePath localPath, Revision revision, IProgressMonitor monitor) + protected override void OnRevertToRevision (FilePath localPath, Revision revision, ProgressMonitor monitor) { NGit.Repository repo = GetRepository (localPath); NGit.Api.Git git = new NGit.Api.Git (repo); @@ -1020,7 +1022,7 @@ namespace MonoDevelop.VersionControl.Git } - protected override void OnAdd (FilePath[] localPaths, bool recurse, IProgressMonitor monitor) + protected override void OnAdd (FilePath[] localPaths, bool recurse, ProgressMonitor monitor) { foreach (var group in GroupByRepository (localPaths)) { var repository = group.Key; @@ -1034,7 +1036,7 @@ namespace MonoDevelop.VersionControl.Git } } - protected override void OnDeleteFiles (FilePath[] localPaths, bool force, IProgressMonitor monitor, bool keepLocal) + protected override void OnDeleteFiles (FilePath[] localPaths, bool force, ProgressMonitor monitor, bool keepLocal) { DeleteCore (localPaths, force, monitor, keepLocal); @@ -1054,7 +1056,7 @@ namespace MonoDevelop.VersionControl.Git } } - protected override void OnDeleteDirectories (FilePath[] localPaths, bool force, IProgressMonitor monitor, bool keepLocal) + protected override void OnDeleteDirectories (FilePath[] localPaths, bool force, ProgressMonitor monitor, bool keepLocal) { DeleteCore (localPaths, force, monitor, keepLocal); @@ -1076,7 +1078,7 @@ namespace MonoDevelop.VersionControl.Git } } - void DeleteCore (FilePath[] localPaths, bool force, IProgressMonitor monitor, bool keepLocal) + void DeleteCore (FilePath[] localPaths, bool force, ProgressMonitor monitor, bool keepLocal) { foreach (var group in GroupByRepository (localPaths)) { List<FilePath> backupFiles = new List<FilePath> (); @@ -1220,7 +1222,7 @@ namespace MonoDevelop.VersionControl.Git return remotes[0]; } - public void Push (IProgressMonitor monitor, string remote, string remoteBranch) + public void Push (ProgressMonitor monitor, string remote, string remoteBranch) { string remoteRef = "refs/heads/" + remoteBranch; IEnumerable<PushResult> res; @@ -1422,7 +1424,7 @@ namespace MonoDevelop.VersionControl.Git return RootRepository.GetBranch (); } - public void SwitchToBranch (IProgressMonitor monitor, string branch) + public void SwitchToBranch (ProgressMonitor monitor, string branch) { monitor.BeginTask (GettextCatalog.GetString ("Switching to branch {0}", branch), GitService.StashUnstashWhenSwitchingBranches ? 4 : 2); @@ -1477,7 +1479,7 @@ namespace MonoDevelop.VersionControl.Git monitor.EndTask (); } - void NotifyFileChanges (IProgressMonitor monitor, IEnumerable<DiffEntry> statusList) + void NotifyFileChanges (ProgressMonitor monitor, IEnumerable<DiffEntry> statusList) { List<DiffEntry> changes = new List<DiffEntry> (statusList); @@ -1575,7 +1577,7 @@ namespace MonoDevelop.VersionControl.Git return diffs.ToArray (); } - protected override void OnMoveFile (FilePath localSrcPath, FilePath localDestPath, bool force, IProgressMonitor monitor) + protected override void OnMoveFile (FilePath localSrcPath, FilePath localDestPath, bool force, ProgressMonitor monitor) { VersionInfo vi = GetVersionInfo (localSrcPath, VersionInfoQueryFlags.IgnoreCache); if (vi == null || !vi.IsVersioned) { @@ -1589,7 +1591,7 @@ namespace MonoDevelop.VersionControl.Git Revert (localSrcPath, false, monitor); } - protected override void OnMoveDirectory (FilePath localSrcPath, FilePath localDestPath, bool force, IProgressMonitor monitor) + protected override void OnMoveDirectory (FilePath localSrcPath, FilePath localDestPath, bool force, ProgressMonitor monitor) { VersionInfo[] versionedFiles = GetDirectoryVersionInfo (localSrcPath, false, true); base.OnMoveDirectory (localSrcPath, localDestPath, force, monitor); @@ -1767,21 +1769,21 @@ namespace MonoDevelop.VersionControl.Git public string PushUrl { get; internal set; } } - class GitMonitor: ProgressMonitor, IDisposable + class GitMonitor: NGit.ProgressMonitor, IDisposable { - readonly IProgressMonitor monitor; + readonly MonoDevelop.Core.ProgressMonitor monitor; int currentWork; int currentStep; bool taskStarted; int totalTasksOverride = -1; bool monitorStarted; - public GitMonitor (IProgressMonitor monitor) + public GitMonitor (MonoDevelop.Core.ProgressMonitor monitor) { this.monitor = monitor; } - public GitMonitor (IProgressMonitor monitor, int totalTasksOverride) + public GitMonitor (MonoDevelop.Core.ProgressMonitor monitor, int totalTasksOverride) { this.monitor = monitor; this.totalTasksOverride = totalTasksOverride; @@ -1829,7 +1831,7 @@ namespace MonoDevelop.VersionControl.Git public override bool IsCancelled () { - return monitor.IsCancelRequested; + return monitor.CancellationToken.IsCancellationRequested; } public void Dispose () diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitService.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitService.cs index 41ffac25fd..6b7d86cf14 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitService.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitService.cs @@ -30,6 +30,7 @@ using MonoDevelop.Ide; using MonoDevelop.Ide.ProgressMonitoring; using NGit.Api; using System.Threading; +using System.Threading.Tasks; namespace MonoDevelop.VersionControl.Git { @@ -63,7 +64,7 @@ namespace MonoDevelop.VersionControl.Git string remote = dlg.SelectedRemote; string branch = dlg.SelectedRemoteBranch ?? repo.GetCurrentBranch (); - IProgressMonitor monitor = VersionControlService.GetProgressMonitor (GettextCatalog.GetString ("Pushing changes..."), VersionControlOperationType.Push); + ProgressMonitor monitor = VersionControlService.GetProgressMonitor (GettextCatalog.GetString ("Pushing changes..."), VersionControlOperationType.Push); ThreadPool.QueueUserWorkItem (delegate { try { repo.Push (monitor, remote, branch); @@ -91,13 +92,13 @@ namespace MonoDevelop.VersionControl.Git if (MessageService.RunCustomDialog (dlg) == (int) Gtk.ResponseType.Ok) { dlg.Hide (); if (rebasing) { - using (IProgressMonitor monitor = VersionControlService.GetProgressMonitor (GettextCatalog.GetString ("Rebasing branch '{0}'...", dlg.SelectedBranch))) { + using (ProgressMonitor monitor = VersionControlService.GetProgressMonitor (GettextCatalog.GetString ("Rebasing branch '{0}'...", dlg.SelectedBranch))) { if (dlg.IsRemote) repo.Fetch (monitor); repo.Rebase (dlg.SelectedBranch, dlg.StageChanges ? GitUpdateOptions.SaveLocalChanges : GitUpdateOptions.None, monitor); } } else { - using (IProgressMonitor monitor = VersionControlService.GetProgressMonitor (GettextCatalog.GetString ("Merging branch '{0}'...", dlg.SelectedBranch))) { + using (ProgressMonitor monitor = VersionControlService.GetProgressMonitor (GettextCatalog.GetString ("Merging branch '{0}'...", dlg.SelectedBranch))) { if (dlg.IsRemote) repo.Fetch (monitor); repo.Merge (dlg.SelectedBranch, dlg.StageChanges ? GitUpdateOptions.SaveLocalChanges : GitUpdateOptions.None, monitor); @@ -115,13 +116,13 @@ namespace MonoDevelop.VersionControl.Git MessageService.ShowCustomDialog (dlg); } - public static void SwitchToBranch (GitRepository repo, string branch) + public async static void SwitchToBranch (GitRepository repo, string branch) { MessageDialogProgressMonitor monitor = new MessageDialogProgressMonitor (true, false, false, true); try { IdeApp.Workbench.AutoReloadDocuments = true; IdeApp.Workbench.LockGui (); - ThreadPool.QueueUserWorkItem (delegate { + await Task.Factory.StartNew (delegate { try { repo.SwitchToBranch (monitor, branch); } catch (Exception ex) { @@ -130,18 +131,17 @@ namespace MonoDevelop.VersionControl.Git monitor.Dispose (); } }); - monitor.AsyncOperation.WaitForCompleted (); } finally { IdeApp.Workbench.AutoReloadDocuments = false; IdeApp.Workbench.UnlockGui (); } } - public static IAsyncOperation ApplyStash (Stash s) + public static Task ApplyStash (Stash s) { MessageDialogProgressMonitor monitor = new MessageDialogProgressMonitor (true, false, false, true); var statusTracker = IdeApp.Workspace.GetFileStatusTracker (); - ThreadPool.QueueUserWorkItem (delegate { + var t = Task.Factory.StartNew (delegate { try { MergeCommandResult result; using (var gm = new GitMonitor (monitor)) @@ -156,10 +156,10 @@ namespace MonoDevelop.VersionControl.Git statusTracker.NotifyChanges (); } }); - return monitor.AsyncOperation; + return t; } - public static void ReportStashResult (IProgressMonitor monitor, MergeCommandResult result) + public static void ReportStashResult (ProgressMonitor monitor, MergeCommandResult result) { if (result.GetMergeStatus () == MergeStatus.FAILED) { string msg = GettextCatalog.GetString ("Stash operation failed."); diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitSupportFeature.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitSupportFeature.cs index 437c28627f..9ee17b62cb 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitSupportFeature.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitSupportFeature.cs @@ -27,31 +27,32 @@ using System; using MonoDevelop.Ide.Templates; using MonoDevelop.Core; using MonoDevelop.Projects; +using System.Linq; namespace MonoDevelop.VersionControl.Git { sealed class GitSupportFeature: ISolutionItemFeature { - public FeatureSupportLevel GetSupportLevel (SolutionFolder parentFolder, SolutionItem entry) + public FeatureSupportLevel GetSupportLevel (SolutionFolder parentFolder, SolutionFolderItem entry) { if (parentFolder != null && !parentFolder.ParentSolution.FileName.IsNullOrEmpty && System.IO.File.Exists (parentFolder.ParentSolution.FileName)) return FeatureSupportLevel.NotSupported; return FeatureSupportLevel.SupportedByDefault; } - public Gtk.Widget CreateFeatureEditor (SolutionFolder parentCombine, SolutionItem entry) + public Gtk.Widget CreateFeatureEditor (SolutionFolder parentCombine, SolutionFolderItem entry) { Gtk.Label label = new Gtk.Label (GettextCatalog.GetString ("A new local Git Repository for the solution will be created")); label.Show (); return label; } - public string Validate (SolutionFolder parentCombine, SolutionItem entry, Gtk.Widget editor) + public string Validate (SolutionFolder parentCombine, SolutionFolderItem entry, Gtk.Widget editor) { return null; } - public void ApplyFeature (SolutionFolder parentFolder, SolutionItem entry, Gtk.Widget editor) + public void ApplyFeature (SolutionFolder parentFolder, SolutionFolderItem entry, Gtk.Widget editor) { // The solution may not be saved yet if (parentFolder.ParentSolution.FileName.IsNullOrEmpty || !System.IO.File.Exists (parentFolder.ParentSolution.FileName)) @@ -67,7 +68,7 @@ namespace MonoDevelop.VersionControl.Git GitUtil.Init (sol.BaseDirectory, null); GitRepository gitRepo = new GitRepository (sol.BaseDirectory, null); - gitRepo.Add (sol.GetItemFiles (true).ToArray (), false, new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor ()); + gitRepo.Add (sol.GetItemFiles (true).ToArray (), false, new MonoDevelop.Core.ProgressMonitor ()); } public string Title { diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs index 2b56ef3e51..5ec0df4cbf 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs @@ -38,6 +38,7 @@ using NGit.Transport; using NGit.Diff; using NGit.Internal; using System; +using ProgressMonitor = MonoDevelop.Core.ProgressMonitor; namespace MonoDevelop.VersionControl.Git { @@ -287,7 +288,7 @@ namespace MonoDevelop.VersionControl.Git return repo; } - public static MergeCommandResult MergeTrees (ProgressMonitor monitor, NGit.Repository repo, RevCommit srcBase, RevCommit srcCommit, string sourceDisplayName, bool commitResult) + public static MergeCommandResult MergeTrees (NGit.ProgressMonitor monitor, NGit.Repository repo, RevCommit srcBase, RevCommit srcCommit, string sourceDisplayName, bool commitResult) { RevCommit newHead; RevWalk revWalk = new RevWalk(repo); diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Stash.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Stash.cs index ccf2f2e338..be5d4fd6d1 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Stash.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Stash.cs @@ -300,7 +300,7 @@ namespace MonoDevelop.VersionControl.Git } } - internal MergeCommandResult Apply (ProgressMonitor monitor, Stash stash) + internal MergeCommandResult Apply (NGit.ProgressMonitor monitor, Stash stash) { monitor.Start (1); monitor.BeginTask ("Applying stash", 100); diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/StashManagerDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/StashManagerDialog.cs index b546e803fc..284522c521 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/StashManagerDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/StashManagerDialog.cs @@ -93,13 +93,11 @@ namespace MonoDevelop.VersionControl.Git return (Stash) store.GetValue (it, 0); } - void ApplyStashAndRemove(Stash s) + async void ApplyStashAndRemove (Stash s) { using (IdeApp.Workspace.GetFileStatusTracker ()) { - GitService.ApplyStash (s).Completed += delegate(IAsyncOperation op) { - if (op.Success) - stashes.Remove (s); - }; + await GitService.ApplyStash (s); + stashes.Remove (s); } } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Unix/MonoDevelop.VersionControl.Subversion.Unix/LibSvnClient.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Unix/MonoDevelop.VersionControl.Subversion.Unix/LibSvnClient.cs index fe6ecd5e69..c331c3b3da 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Unix/MonoDevelop.VersionControl.Subversion.Unix/LibSvnClient.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Unix/MonoDevelop.VersionControl.Subversion.Unix/LibSvnClient.cs @@ -146,7 +146,6 @@ namespace MonoDevelop.VersionControl.Subversion.Unix { public abstract IntPtr client_get_wc_root (out IntPtr wcroot_abspath, string local_abspath, IntPtr ctx, IntPtr result_pool, IntPtr scratch_pool); - // TODO: Check if intptr public abstract IntPtr strerror (int statcode, byte[] buf, int bufsize); public abstract IntPtr path_internal_style (string path, IntPtr pool); @@ -617,8 +616,56 @@ namespace MonoDevelop.VersionControl.Subversion.Unix { Locked, Unlocked, FailedLock, - FailedUnlock - // TODO: Add more enum data + FailedUnlock, + Exists, + ChangelistSet, + ChangelistClear, + ChangelistMoved, + MergeBegin, + ForeignMergeBegin, + UpdateReplace, + PropertyAdded, + PropertyDeleted, + PropertyDeletedNonexistent, + RevpropSet, + RevpropDeleted, + MergeCompleted, + TreeConflict, + FailedExternal, + UpdateStarted, + UpdateSkipObstruction, + UpdateSkipWorkingOnly, + UpdateSkipAccessDenied, + UpdateExternalRemoved, + UpdateShadowedAdd, + UpdateShadowedDelete, + MergeRecordInfo, + UpgradedPath, + MergeRecordInfoBegin, + MergeElideInfo, + Patch, + PatchAppliedHunk, + PatchRejectedHunk, + PatchHunkAlreadyApplied, + CommitCopied, + CommitCopiedReplaced, + UrlRedirect, + PathNonexistent, + Exclude, + FailedConflict, + FailedMissing, + FailedOutOfDate, + FailedNoParent, + FailedLocked, + FailedForbiddenByServer, + SkipConflicted, + UpdateBrokenLock, + FailedObstruction, + ConflictResolverStarting, + ConflictResolverDone, + LeftLocalModifications, + ForeignCopyBegin, + MoveBroken, } public enum NotifyState { diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Unix/MonoDevelop.VersionControl.Subversion.Unix/SvnClient.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Unix/MonoDevelop.VersionControl.Subversion.Unix/SvnClient.cs index b94c055d25..a27a322a82 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Unix/MonoDevelop.VersionControl.Subversion.Unix/SvnClient.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Unix/MonoDevelop.VersionControl.Subversion.Unix/SvnClient.cs @@ -11,6 +11,8 @@ using svn_revnum_t = System.IntPtr; using size_t = System.Int32; using off_t = System.Int64; using MonoDevelop.Projects.Text; +using System.Threading; +using System.Linq; namespace MonoDevelop.VersionControl.Subversion.Unix { @@ -77,6 +79,7 @@ namespace MonoDevelop.VersionControl.Subversion.Unix return error.message; else { byte[] buf = new byte [300]; + // Caller will handle the lock. Svn.strerror (error.apr_err, buf, buf.Length); return Encoding.UTF8.GetString (buf); } @@ -86,16 +89,25 @@ namespace MonoDevelop.VersionControl.Subversion.Unix { IntPtr p; + // Caller will handle the lock. Apr.pool_create_ex (out p, parent, IntPtr.Zero, IntPtr.Zero); if (p == IntPtr.Zero) throw new InvalidOperationException ("Could not create an APR pool."); return p; } + + internal static void destroypool (IntPtr pool) + { + // Caller will handle lock. + if (pool != IntPtr.Zero) + Apr.pool_destroy (pool); + } public static string NormalizePath (string pathOrUrl, IntPtr localpool) { if (pathOrUrl == null) return null; + // Caller will handle the lock. IntPtr res = Svn.path_internal_style (pathOrUrl, localpool); return Marshal.PtrToStringAnsi (res); } @@ -129,7 +141,9 @@ namespace MonoDevelop.VersionControl.Subversion.Unix public static string GetVersion () { - IntPtr ptr = Svn.client_version (); + IntPtr ptr; + lock (Svn) + ptr = Svn.client_version (); LibSvnClient.svn_version_t ver = (LibSvnClient.svn_version_t)Marshal.PtrToStructure (ptr, typeof(LibSvnClient.svn_version_t)); return ver.major + "." + ver.minor + "." + ver.patch; } @@ -173,26 +187,6 @@ namespace MonoDevelop.VersionControl.Subversion.Unix return new UnixSvnBackend (); } - public override string GetPathUrl (FilePath path) - { - if (path == FilePath.Null) - throw new ArgumentNullException(); - - IntPtr ret = IntPtr.Zero; - IntPtr localpool = newpool (IntPtr.Zero); - try { - string npath = NormalizePath (path, localpool); - CheckError (Svn.client_url_from_path (ref ret, npath, localpool)); - } finally { - Apr.pool_destroy (localpool); - } - - if (ret == IntPtr.Zero) - return null; - - return Marshal.PtrToStringAnsi (ret); - } - public override string GetDirectoryDotSvn (FilePath path) { if (Pre_1_7) @@ -240,15 +234,17 @@ namespace MonoDevelop.VersionControl.Subversion.Unix return SvnClient.newpool (parent); } + static void destroypool (IntPtr pool) + { + SvnClient.destroypool (pool); + } + bool disposed; readonly IntPtr auth_baton; readonly IntPtr pool; readonly IntPtr ctx; - readonly object sync = new object(); - bool inProgress; - - IProgressMonitor updatemonitor; + ProgressMonitor updatemonitor; ArrayList updateFileList; string commitmessage; @@ -274,109 +270,113 @@ namespace MonoDevelop.VersionControl.Subversion.Unix public UnixSvnBackend () { - // Allocate the APR pool and the SVN client context. - pool = newpool (IntPtr.Zero); + lock (svn) { + // Allocate the APR pool and the SVN client context. + pool = newpool (IntPtr.Zero); - // Make sure the config directory is properly created. - // If the config directory and specifically the subdirectories - // for the authentication providers don't exist, authentication - // data won't be saved and no error is given. - svn.config_ensure (null, pool); + // Make sure the config directory is properly created. + // If the config directory and specifically the subdirectories + // for the authentication providers don't exist, authentication + // data won't be saved and no error is given. + svn.config_ensure (null, pool); - // Load user and system configuration - svn.config_get_config (ref config_hash, null, pool); + // Load user and system configuration + svn.config_get_config (ref config_hash, null, pool); - if (svn.client_create_context (out ctx, pool) != IntPtr.Zero) - throw new InvalidOperationException ("Could not create a Subversion client context."); + if (svn.client_create_context (out ctx, pool) != IntPtr.Zero) + throw new InvalidOperationException ("Could not create a Subversion client context."); - // Set the callbacks on the client context structure. - notify_func = new LibSvnClient.svn_wc_notify_func2_t (svn_wc_notify_func_t_impl); - Marshal.WriteIntPtr (ctx, - (int) Marshal.OffsetOf (typeof (LibSvnClient.svn_client_ctx_t), "NotifyFunc2"), - Marshal.GetFunctionPointerForDelegate (notify_func)); - log_func = new LibSvnClient.svn_client_get_commit_log_t (svn_client_get_commit_log_impl); - Marshal.WriteIntPtr (ctx, - (int) Marshal.OffsetOf (typeof (LibSvnClient.svn_client_ctx_t), "LogMsgFunc"), - Marshal.GetFunctionPointerForDelegate (log_func)); - progress_func = new LibSvnClient.svn_ra_progress_notify_func_t (svn_ra_progress_notify_func_t_impl); - Marshal.WriteIntPtr (ctx, - (int) Marshal.OffsetOf (typeof (LibSvnClient.svn_client_ctx_t), "progress_func"), - Marshal.GetFunctionPointerForDelegate (progress_func)); - cancel_func = new LibSvnClient.svn_cancel_func_t (svn_cancel_func_t_impl); - Marshal.WriteIntPtr (ctx, - (int) Marshal.OffsetOf (typeof (LibSvnClient.svn_client_ctx_t), "cancel_func"), - Marshal.GetFunctionPointerForDelegate (cancel_func)); - - Marshal.WriteIntPtr (ctx, - (int) Marshal.OffsetOf (typeof (LibSvnClient.svn_client_ctx_t), "config"), - config_hash); - - if (!SvnClient.Pre_1_7) { - IntPtr scratch = newpool (IntPtr.Zero); - svn.wc_context_create (out wc_ctx, IntPtr.Zero, pool, scratch); + // Set the callbacks on the client context structure. + notify_func = new LibSvnClient.svn_wc_notify_func2_t (svn_wc_notify_func_t_impl); Marshal.WriteIntPtr (ctx, - (int) Marshal.OffsetOf (typeof (LibSvnClient.svn_client_ctx_t), "wc_ctx"), - wc_ctx); - apr.pool_destroy (scratch); - } + (int)Marshal.OffsetOf (typeof(LibSvnClient.svn_client_ctx_t), "NotifyFunc2"), + Marshal.GetFunctionPointerForDelegate (notify_func)); + log_func = new LibSvnClient.svn_client_get_commit_log_t (svn_client_get_commit_log_impl); + Marshal.WriteIntPtr (ctx, + (int)Marshal.OffsetOf (typeof(LibSvnClient.svn_client_ctx_t), "LogMsgFunc"), + Marshal.GetFunctionPointerForDelegate (log_func)); + progress_func = new LibSvnClient.svn_ra_progress_notify_func_t (svn_ra_progress_notify_func_t_impl); + Marshal.WriteIntPtr (ctx, + (int)Marshal.OffsetOf (typeof(LibSvnClient.svn_client_ctx_t), "progress_func"), + Marshal.GetFunctionPointerForDelegate (progress_func)); + cancel_func = new LibSvnClient.svn_cancel_func_t (svn_cancel_func_t_impl); + Marshal.WriteIntPtr (ctx, + (int)Marshal.OffsetOf (typeof(LibSvnClient.svn_client_ctx_t), "cancel_func"), + Marshal.GetFunctionPointerForDelegate (cancel_func)); - IntPtr providers = apr.array_make (pool, 16, IntPtr.Size); - IntPtr item; + Marshal.WriteIntPtr (ctx, + (int)Marshal.OffsetOf (typeof(LibSvnClient.svn_client_ctx_t), "config"), + config_hash); + + if (!SvnClient.Pre_1_7) { + IntPtr scratch = newpool (IntPtr.Zero); + svn.wc_context_create (out wc_ctx, IntPtr.Zero, pool, scratch); + Marshal.WriteIntPtr (ctx, + (int)Marshal.OffsetOf (typeof(LibSvnClient.svn_client_ctx_t), "wc_ctx"), + wc_ctx); + apr.pool_destroy (scratch); + } + + IntPtr providers = apr.array_make (pool, 16, IntPtr.Size); + IntPtr item; - // The main disk-caching auth providers, for both - // 'username/password' creds and 'username' creds. + // The main disk-caching auth providers, for both + // 'username/password' creds and 'username' creds. - item = apr.array_push (providers); - svn.client_get_simple_provider (item, pool); + item = apr.array_push (providers); + svn.client_get_simple_provider (item, pool); - item = apr.array_push (providers); - svn.client_get_username_provider (item, pool); + item = apr.array_push (providers); + svn.client_get_username_provider (item, pool); - // The server-cert, client-cert, and client-cert-password providers + // The server-cert, client-cert, and client-cert-password providers - item = apr.array_push (providers); - svn.client_get_ssl_server_trust_file_provider (item, pool); + item = apr.array_push (providers); + svn.client_get_ssl_server_trust_file_provider (item, pool); - item = apr.array_push (providers); - svn.client_get_ssl_client_cert_file_provider (item, pool); + item = apr.array_push (providers); + svn.client_get_ssl_client_cert_file_provider (item, pool); - item = apr.array_push (providers); - svn.client_get_ssl_client_cert_pw_file_provider (item, pool); + item = apr.array_push (providers); + svn.client_get_ssl_client_cert_pw_file_provider (item, pool); - // Two basic prompt providers: username/password, and just username. + // Two basic prompt providers: username/password, and just username. - item = apr.array_push (providers); - svn.client_get_simple_prompt_provider (item, OnAuthSimplePromptCallback, IntPtr.Zero, 2, pool); + item = apr.array_push (providers); + svn.client_get_simple_prompt_provider (item, OnAuthSimplePromptCallback, IntPtr.Zero, 2, pool); - item = apr.array_push (providers); - svn.client_get_username_prompt_provider (item, OnAuthUsernamePromptCallback, IntPtr.Zero, 2, pool); + item = apr.array_push (providers); + svn.client_get_username_prompt_provider (item, OnAuthUsernamePromptCallback, IntPtr.Zero, 2, pool); - // Three ssl prompt providers, for server-certs, client-certs, - // and client-cert-passphrases. + // Three ssl prompt providers, for server-certs, client-certs, + // and client-cert-passphrases. - item = apr.array_push (providers); - svn.client_get_ssl_server_trust_prompt_provider (item, OnAuthSslServerTrustPromptCallback, IntPtr.Zero, pool); + item = apr.array_push (providers); + svn.client_get_ssl_server_trust_prompt_provider (item, OnAuthSslServerTrustPromptCallback, IntPtr.Zero, pool); - item = apr.array_push (providers); - svn.client_get_ssl_client_cert_prompt_provider (item, OnAuthSslClientCertPromptCallback, IntPtr.Zero, 2, pool); + item = apr.array_push (providers); + svn.client_get_ssl_client_cert_prompt_provider (item, OnAuthSslClientCertPromptCallback, IntPtr.Zero, 2, pool); - item = apr.array_push (providers); - svn.client_get_ssl_client_cert_pw_prompt_provider (item, OnAuthSslClientCertPwPromptCallback, IntPtr.Zero, 2, pool); + item = apr.array_push (providers); + svn.client_get_ssl_client_cert_pw_prompt_provider (item, OnAuthSslClientCertPwPromptCallback, IntPtr.Zero, 2, pool); - // Create the authentication baton - svn.auth_open (out auth_baton, providers, pool); + // Create the authentication baton + svn.auth_open (out auth_baton, providers, pool); - Marshal.WriteIntPtr (ctx, - (int) Marshal.OffsetOf (typeof(LibSvnClient.svn_client_ctx_t), "auth_baton"), - auth_baton); + Marshal.WriteIntPtr (ctx, + (int)Marshal.OffsetOf (typeof(LibSvnClient.svn_client_ctx_t), "auth_baton"), + auth_baton); + } } public void Dispose () { - if (!disposed) { - if (apr != null) - apr.pool_destroy(pool); - disposed = true; + lock (svn) { + if (!disposed) { + if (apr != null) + apr.pool_destroy (pool); + disposed = true; + } } } @@ -387,14 +387,15 @@ namespace MonoDevelop.VersionControl.Subversion.Unix static IntPtr GetCancelError () { - LibSvnClient.svn_error_t error = new LibSvnClient.svn_error_t (); - error.apr_err = LibApr.APR_OS_START_USEERR; - error.message = "Operation cancelled."; - // Subversion destroys the error pool to dispose the error object, // so we need to use a non-shared pool. IntPtr localpool = newpool (IntPtr.Zero); - error.pool = localpool; + var error = new LibSvnClient.svn_error_t { + apr_err = LibApr.APR_OS_START_USEERR, + message = "Operation cancelled.", + pool = localpool, + }; + return apr.pcalloc (localpool, error); } @@ -420,8 +421,9 @@ namespace MonoDevelop.VersionControl.Subversion.Unix static readonly LibSvnClient.svn_auth_username_prompt_func_t OnAuthUsernamePromptCallback = OnAuthUsernamePrompt; static IntPtr OnAuthUsernamePrompt (ref IntPtr cred, IntPtr baton, string realm, bool may_save, IntPtr pool) { - LibSvnClient.svn_auth_cred_username_t data = new LibSvnClient.svn_auth_cred_username_t (); - data.username = "";
+ LibSvnClient.svn_auth_cred_username_t data = new LibSvnClient.svn_auth_cred_username_t { + username = "", + };
bool ms; if (UserNameAuthenticationPrompt (realm, may_save, ref data.username, out ms)) {
data.may_save = ms; @@ -438,15 +440,16 @@ namespace MonoDevelop.VersionControl.Subversion.Unix static readonly LibSvnClient.svn_auth_ssl_server_trust_prompt_func_t OnAuthSslServerTrustPromptCallback = OnAuthSslServerTrustPrompt; static IntPtr OnAuthSslServerTrustPrompt (ref IntPtr cred, IntPtr baton, string realm, UInt32 failures, ref LibSvnClient.svn_auth_ssl_server_cert_info_t cert_info, bool may_save, IntPtr pool) { - LibSvnClient.svn_auth_cred_ssl_server_trust_t data = new LibSvnClient.svn_auth_cred_ssl_server_trust_t (); - - CertficateInfo ci = new CertficateInfo (); - ci.AsciiCert = cert_info.ascii_cert; - ci.Fingerprint = cert_info.fingerprint; - ci.HostName = cert_info.hostname; - ci.IssuerName = cert_info.issuer_dname; - ci.ValidFrom = cert_info.valid_from; - ci.ValidUntil = cert_info.valid_until; + var data = new LibSvnClient.svn_auth_cred_ssl_server_trust_t (); + + var ci = new CertficateInfo { + AsciiCert = cert_info.ascii_cert, + Fingerprint = cert_info.fingerprint, + HostName = cert_info.hostname, + IssuerName = cert_info.issuer_dname, + ValidFrom = cert_info.valid_from, + ValidUntil = cert_info.valid_until, + }; SslFailure accepted_failures;
bool ms; @@ -466,7 +469,7 @@ namespace MonoDevelop.VersionControl.Subversion.Unix static readonly LibSvnClient.svn_auth_ssl_client_cert_prompt_func_t OnAuthSslClientCertPromptCallback = OnAuthSslClientCertPrompt; static IntPtr OnAuthSslClientCertPrompt (ref IntPtr cred, IntPtr baton, string realm, bool may_save, IntPtr pool) { - LibSvnClient.svn_auth_cred_ssl_client_cert_t data = new LibSvnClient.svn_auth_cred_ssl_client_cert_t ();
+ var data = new LibSvnClient.svn_auth_cred_ssl_client_cert_t ();
bool ms; if (SslClientCertAuthenticationPrompt (realm, may_save, out data.cert_file, out ms)) {
data.may_save = ms; @@ -483,7 +486,7 @@ namespace MonoDevelop.VersionControl.Subversion.Unix static readonly LibSvnClient.svn_auth_ssl_client_cert_pw_prompt_func_t OnAuthSslClientCertPwPromptCallback = OnAuthSslClientCertPwPrompt; static IntPtr OnAuthSslClientCertPwPrompt (ref IntPtr cred, IntPtr baton, string realm, bool may_save, IntPtr pool) { - LibSvnClient.svn_auth_cred_ssl_client_cert_pw_t data;
+ var data = new LibSvnClient.svn_auth_cred_ssl_client_cert_pw_t ();
bool ms; if (SslClientCertPwAuthenticationPrompt (realm, may_save, out data.password, out ms)) {
data.may_save = ms; @@ -513,6 +516,17 @@ namespace MonoDevelop.VersionControl.Subversion.Unix { return SvnClient.NormalizePath (pathOrUrl, localpool); } + + static IntPtr NormalizePaths (IntPtr pool, params FilePath[] paths) + { + IntPtr array = apr.array_make (pool, 0, IntPtr.Size); + foreach (string path in paths) { + string pathorurl = NormalizePath (path, pool); + IntPtr item = apr.array_push (array); + Marshal.WriteIntPtr (item, apr.pstrdup (pool, pathorurl)); + } + return array; + } public override IEnumerable<DirectoryEntry> ListUrl (string url, bool recurse, SvnRevision rev) { @@ -520,12 +534,13 @@ namespace MonoDevelop.VersionControl.Subversion.Unix throw new ArgumentNullException (); LibSvnClient.Rev revision = (LibSvnClient.Rev) rev; - IntPtr localpool = TryStartOperation (null); + IntPtr localpool = IntPtr.Zero; List<DirectoryEntry> items = new List<DirectoryEntry> (); try { IntPtr hash; - + + localpool = TryStartOperation (null); url = NormalizePath (url, localpool); CheckError (svn.client_ls (out hash, url, ref revision, @@ -538,22 +553,22 @@ namespace MonoDevelop.VersionControl.Subversion.Unix apr.hash_this (item, out nameptr, out namelen, out val); string name = Marshal.PtrToStringAnsi (nameptr); - LibSvnClient.svn_dirent_t ent = (LibSvnClient.svn_dirent_t) Marshal.PtrToStructure (val, typeof (LibSvnClient.svn_dirent_t)); + var ent = (LibSvnClient.svn_dirent_t) Marshal.PtrToStructure (val, typeof (LibSvnClient.svn_dirent_t)); item = apr.hash_next (item); - DirectoryEntry dent = new DirectoryEntry (); - dent.Name = name; - dent.IsDirectory = ent.kind == LibSvnClient.svn_node_kind_t.Dir; - dent.Size = ent.size; - dent.HasProps = ent.has_props; - dent.CreatedRevision = (int) ent.created_rev; - dent.Time = new DateTime (1970, 1, 1).AddTicks(ent.time * 10); - dent.LastAuthor = ent.last_author; + var dent = new DirectoryEntry { + Name = name, + IsDirectory = ent.kind == LibSvnClient.svn_node_kind_t.Dir, + Size = ent.size, + HasProps = ent.has_props, + CreatedRevision = (int) ent.created_rev, + Time = new DateTime (1970, 1, 1).AddTicks(ent.time * 10), + LastAuthor = ent.last_author, + }; items.Add (dent); } } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } return items; @@ -568,8 +583,9 @@ namespace MonoDevelop.VersionControl.Subversion.Unix ArrayList ret = new ArrayList (); StatusCollector collector = new StatusCollector (ret); - var localpool = TryStartOperation (null); + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (null); string pathorurl = NormalizePath (path, localpool); CheckError (svn.client_status (IntPtr.Zero, pathorurl, ref revision, collector.Func, @@ -584,8 +600,7 @@ namespace MonoDevelop.VersionControl.Subversion.Unix if (e.ErrorCode != 155007 && e.ErrorCode != 155008) throw; } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } List<VersionInfo> nodes = new List<VersionInfo>(); @@ -605,8 +620,9 @@ namespace MonoDevelop.VersionControl.Subversion.Unix List<SvnRevision> ret = new List<SvnRevision> (); IntPtr strptr = IntPtr.Zero; - var localpool = TryStartOperation (null); + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (null); IntPtr array = apr.array_make (localpool, 0, IntPtr.Size); IntPtr first = apr.array_push (array); string pathorurl = NormalizePath (path, localpool); @@ -621,8 +637,7 @@ namespace MonoDevelop.VersionControl.Subversion.Unix } finally { if (strptr != IntPtr.Zero) Marshal.FreeHGlobal (strptr); - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } return ret; @@ -649,13 +664,13 @@ namespace MonoDevelop.VersionControl.Subversion.Unix Annotation[] annotations = new Annotation [numAnnotations]; AnnotationCollector collector = new AnnotationCollector (annotations); - var localpool = TryStartOperation (null); + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (null); string path = NormalizePath (file.FullPath, localpool); CheckError (svn.client_blame (path, ref revisionStart, ref revisionEnd, collector.Func, IntPtr.Zero, ctx, localpool)); } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } return annotations; @@ -695,8 +710,9 @@ namespace MonoDevelop.VersionControl.Subversion.Unix LibSvnClient.Rev revision = (LibSvnClient.Rev) rev; - var localpool = TryStartOperation (null); + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (null); pathorurl = NormalizePath (pathorurl, localpool); StreamCollector collector = new StreamCollector (stream); IntPtr svnstream = svn.stream_create (IntPtr.Zero, localpool); @@ -705,12 +721,11 @@ namespace MonoDevelop.VersionControl.Subversion.Unix // Otherwise, it will use Head as peg and it will throw exceptions. CheckError (svn.client_cat2 (svnstream, pathorurl, ref revision, ref revision, ctx, localpool), 195007); } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } }
- public override void Update (FilePath path, bool recurse, IProgressMonitor monitor) + public override void Update (FilePath path, bool recurse, ProgressMonitor monitor) { if (path == FilePath.Null || monitor == null) throw new ArgumentNullException(); @@ -718,15 +733,15 @@ namespace MonoDevelop.VersionControl.Subversion.Unix updateFileList = new ArrayList (); LibSvnClient.Rev rev = LibSvnClient.Rev.Head; - var localpool = TryStartOperation (monitor); + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (monitor); string pathorurl = NormalizePath (path, localpool); IntPtr result = Marshal.AllocHGlobal (IntPtr.Size); CheckError (svn.client_update (result, pathorurl, ref rev, recurse, ctx, localpool)); Marshal.FreeHGlobal (result); } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); foreach (string file in updateFileList) FileService.NotifyFileChanged (file, true); @@ -735,56 +750,50 @@ namespace MonoDevelop.VersionControl.Subversion.Unix } }
- public override void Revert (FilePath[] paths, bool recurse, IProgressMonitor monitor) + public override void Revert (FilePath[] paths, bool recurse, ProgressMonitor monitor) { if (paths == null || monitor == null) throw new ArgumentNullException(); - var localpool = TryStartOperation (monitor); + IntPtr localpool = IntPtr.Zero; try { - // Put each item into an APR array. - IntPtr array = apr.array_make (localpool, 0, IntPtr.Size); - foreach (string path in paths) { - string pathorurl = NormalizePath (path, localpool); - IntPtr item = apr.array_push (array); - Marshal.WriteIntPtr (item, apr.pstrdup (localpool, pathorurl)); - } - + localpool = TryStartOperation (monitor); + IntPtr array = NormalizePaths (localpool, paths); CheckError (svn.client_revert (array, recurse, ctx, localpool)); } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } }
- public override void Add (FilePath path, bool recurse, IProgressMonitor monitor) + public override void Add (FilePath path, bool recurse, ProgressMonitor monitor) { if (path == FilePath.Null || monitor == null) throw new ArgumentNullException (); nb = new notify_baton (); - var localpool = TryStartOperation (monitor); + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (monitor); string pathorurl = NormalizePath (path, localpool); CheckError (svn.client_add3 (pathorurl, recurse, true, false, ctx, localpool)); } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } }
- public override void Checkout (string url, FilePath path, Revision revision, bool recurse, IProgressMonitor monitor) + public override void Checkout (string url, FilePath path, Revision revision, bool recurse, ProgressMonitor monitor) { if (url == null || monitor == null) throw new ArgumentNullException (); if (revision == null) revision = SvnRevision.Head; - LibSvnClient.Rev rev = (LibSvnClient.Rev) revision; + var rev = (LibSvnClient.Rev) revision; nb = new notify_baton (); - var localpool = TryStartOperation (monitor); + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (monitor); // Using Uri here because the normalization method doesn't remove the redundant port number when using https url = NormalizePath (new Uri(url).ToString(), localpool); string npath = NormalizePath (path, localpool); @@ -796,27 +805,20 @@ namespace MonoDevelop.VersionControl.Subversion.Unix if (Directory.Exists (path.ParentDirectory)) FileService.DeleteDirectory (path.ParentDirectory); } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } }
- public override void Commit (FilePath[] paths, string message, IProgressMonitor monitor) + public override void Commit (FilePath[] paths, string message, ProgressMonitor monitor) { if (paths == null || message == null || monitor == null) throw new ArgumentNullException(); nb = new notify_baton (); - var localpool = TryStartOperation (monitor); + IntPtr localpool = IntPtr.Zero; try { - // Put each item into an APR array. - IntPtr array = apr.array_make (localpool, 0, IntPtr.Size); - foreach (string path in paths) { - string npath = NormalizePath (path, localpool); - IntPtr item = apr.array_push (array); - Marshal.WriteIntPtr (item, apr.pstrdup (localpool, npath)); - } - + localpool = TryStartOperation (monitor); + IntPtr array = NormalizePaths (localpool, paths); IntPtr commit_info = IntPtr.Zero; commitmessage = message; @@ -829,26 +831,20 @@ namespace MonoDevelop.VersionControl.Subversion.Unix } } finally { commitmessage = null; - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } }
- public override void Mkdir (string[] paths, string message, IProgressMonitor monitor) + public override void Mkdir (string[] paths, string message, ProgressMonitor monitor) { if (paths == null || monitor == null) throw new ArgumentNullException (); nb = new notify_baton (); - var localpool = TryStartOperation (monitor); + IntPtr localpool = IntPtr.Zero; try { - // Put each item into an APR array. - IntPtr array = apr.array_make (localpool, paths.Length, IntPtr.Size); - foreach (string path in paths) { - string npath = NormalizePath (path, localpool); - IntPtr item = apr.array_push (array); - Marshal.WriteIntPtr (item, apr.pstrdup (localpool, npath)); - } + localpool = TryStartOperation (monitor); + IntPtr array = NormalizePaths (localpool, paths.Select (p => (FilePath)p).ToArray ()); commitmessage = message; @@ -856,36 +852,29 @@ namespace MonoDevelop.VersionControl.Subversion.Unix CheckError (svn.client_mkdir2 (ref commit_info, array, ctx, localpool)); } finally { commitmessage = null; - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } }
- public override void Delete (FilePath path, bool force, IProgressMonitor monitor) + public override void Delete (FilePath path, bool force, ProgressMonitor monitor) { if (path == FilePath.Null || monitor == null) throw new ArgumentNullException (); nb = new notify_baton (); - var localpool = TryStartOperation (monitor); + IntPtr localpool = IntPtr.Zero; try { - // Put each item into an APR array. - IntPtr array = apr.array_make (localpool, 0, IntPtr.Size); - //foreach (string path in paths) { - string npath = NormalizePath (path, localpool); - IntPtr item = apr.array_push (array); - Marshal.WriteIntPtr (item, apr.pstrdup (localpool, npath)); - //} + localpool = TryStartOperation (monitor); + IntPtr array = NormalizePaths (localpool, path); IntPtr commit_info = IntPtr.Zero; CheckError (svn.client_delete (ref commit_info, array, force, ctx, localpool)); } finally { commitmessage = null; - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } }
- public override void Move (FilePath srcPath, FilePath destPath, SvnRevision rev, bool force, IProgressMonitor monitor) + public override void Move (FilePath srcPath, FilePath destPath, SvnRevision rev, bool force, ProgressMonitor monitor) { if (srcPath == FilePath.Null || destPath == FilePath.Null || monitor == null) throw new ArgumentNullException (); @@ -894,29 +883,25 @@ namespace MonoDevelop.VersionControl.Subversion.Unix nb = new notify_baton (); IntPtr commit_info = IntPtr.Zero; - var localpool = TryStartOperation (monitor); + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (monitor); string nsrcPath = NormalizePath (srcPath, localpool); string ndestPath = NormalizePath (destPath, localpool); CheckError (svn.client_move (ref commit_info, nsrcPath, ref revision, ndestPath, force, ctx, localpool)); } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } }
- public override void Lock (IProgressMonitor monitor, string comment, bool stealLock, params FilePath[] paths) + public override void Lock (ProgressMonitor monitor, string comment, bool stealLock, params FilePath[] paths) { nb = new notify_baton (); - var localpool = TryStartOperation (monitor); + IntPtr localpool = IntPtr.Zero; try { - IntPtr array = apr.array_make (localpool, 0, IntPtr.Size); - foreach (string path in paths) { - string npath = NormalizePath (path, localpool); - IntPtr item = apr.array_push (array); - Marshal.WriteIntPtr (item, apr.pstrdup (localpool, npath)); - } + localpool = TryStartOperation (monitor); + IntPtr array = NormalizePaths (localpool, paths); lockFileList = new ArrayList (); requiredLockState = LibSvnClient.NotifyLockState.Locked; @@ -924,23 +909,18 @@ namespace MonoDevelop.VersionControl.Subversion.Unix if (paths.Length != lockFileList.Count) throw new SubversionException ("Lock operation failed."); } finally { - apr.pool_destroy (localpool); lockFileList = null; - TryEndOperation (); + TryEndOperation (localpool); } } - public override void Unlock (IProgressMonitor monitor, bool breakLock, params FilePath[] paths) + public override void Unlock (ProgressMonitor monitor, bool breakLock, params FilePath[] paths) { nb = new notify_baton (); - var localpool = TryStartOperation (monitor); + IntPtr localpool = IntPtr.Zero; try { - IntPtr array = apr.array_make (localpool, 0, IntPtr.Size); - foreach (string path in paths) { - string npath = NormalizePath (path, localpool); - IntPtr item = apr.array_push (array); - Marshal.WriteIntPtr (item, apr.pstrdup (localpool, npath)); - } + localpool = TryStartOperation (monitor); + IntPtr array = NormalizePaths (localpool, paths); lockFileList = new ArrayList (); requiredLockState = LibSvnClient.NotifyLockState.Unlocked; @@ -948,9 +928,8 @@ namespace MonoDevelop.VersionControl.Subversion.Unix if (paths.Length != lockFileList.Count) throw new SubversionException ("Lock operation failed."); } finally { - apr.pool_destroy (localpool); lockFileList = null; - TryEndOperation (); + TryEndOperation (localpool); } }
@@ -964,8 +943,9 @@ namespace MonoDevelop.VersionControl.Subversion.Unix LibSvnClient.Rev revision1 = (LibSvnClient.Rev) rev1; LibSvnClient.Rev revision2 = (LibSvnClient.Rev) rev2; - var localpool = TryStartOperation (null); + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (null); IntPtr options = apr.array_make (localpool, 0, IntPtr.Size); fout = Path.GetTempFileName (); @@ -1001,18 +981,17 @@ namespace MonoDevelop.VersionControl.Subversion.Unix FileService.DeleteFile (fout); } catch { } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } } }
- public override void RevertToRevision (FilePath path, Revision revision, IProgressMonitor monitor) + public override void RevertToRevision (FilePath path, Revision revision, ProgressMonitor monitor) { Merge (path, LibSvnClient.Rev.Head, (LibSvnClient.Rev) revision); }
- public override void RevertRevision (FilePath path, Revision revision, IProgressMonitor monitor) + public override void RevertRevision (FilePath path, Revision revision, ProgressMonitor monitor) { SvnRevision srev = (SvnRevision) revision; Merge (path, (LibSvnClient.Rev) srev, LibSvnClient.Rev.Number (srev.Rev - 1)); @@ -1020,8 +999,9 @@ namespace MonoDevelop.VersionControl.Subversion.Unix private void Merge (string path, LibSvnClient.Rev revision1, LibSvnClient.Rev revision2) { - var localpool = TryStartOperation (null); + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (null); path = NormalizePath (path, localpool); LibSvnClient.Rev working = LibSvnClient.Rev.Working; CheckError (svn.client_merge_peg2 (path, @@ -1034,117 +1014,110 @@ namespace MonoDevelop.VersionControl.Subversion.Unix ctx, localpool)); } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } } - public override void Ignore (FilePath[] paths) + static void GetProps (StringBuilder props, IntPtr pool, IntPtr result) { - IntPtr hash_item, hash_name, hash_val; + LibSvnClient.svn_string_t new_props; + IntPtr hash_name, hash_val; + IntPtr hash_item = apr.hash_first (pool, result); int length; + + while (hash_item != IntPtr.Zero) { + apr.hash_this (hash_item, out hash_name, out length, out hash_val); + new_props = (LibSvnClient.svn_string_t) Marshal.PtrToStructure (hash_val, typeof (LibSvnClient.svn_string_t)); + props.Append (Marshal.PtrToStringAnsi (new_props.data)); + hash_item = apr.hash_next (hash_item); + } + } + + public override void Ignore (FilePath[] paths) + { IntPtr result; - IntPtr props_ptr = IntPtr.Zero; - StringBuilder props = new StringBuilder (); + IntPtr props_ptr; + var props = new StringBuilder (); string new_path; LibSvnClient.svn_string_t new_props; LibSvnClient.Rev rev = LibSvnClient.Rev.Working; - var localpool = TryStartOperation (null); + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (null); foreach (var path in paths) { new_path = NormalizePath (path, localpool); CheckError (svn.client_propget (out result, "svn:ignore", Path.GetDirectoryName (new_path), ref rev, false, ctx, localpool)); - hash_item = apr.hash_first (localpool, result); - while (hash_item != IntPtr.Zero) { - apr.hash_this (hash_item, out hash_name, out length, out hash_val); - new_props = (LibSvnClient.svn_string_t) Marshal.PtrToStructure (hash_val, typeof (LibSvnClient.svn_string_t)); - props.Append (Marshal.PtrToStringAnsi (new_props.data)); - hash_item = apr.hash_next (hash_item); - } + GetProps (props, localpool, result); + props.AppendLine (Path.GetFileName (new_path)); - new_props = new LibSvnClient.svn_string_t (); - new_props.data = Marshal.StringToHGlobalAnsi (props.ToString ()); - new_props.len = props.Length; + new_props = new LibSvnClient.svn_string_t { + data = Marshal.StringToHGlobalAnsi (props.ToString ()), + len = props.Length, + }; props_ptr = apr.pcalloc (localpool, new_props); CheckError (svn.client_propset ("svn:ignore", props_ptr, Path.GetDirectoryName (new_path), false, localpool)); } } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } } public override void Unignore (FilePath[] paths) { - IntPtr hash_item, hash_name, hash_val; - int length; IntPtr result; - IntPtr props_ptr = IntPtr.Zero; - StringBuilder props = new StringBuilder (); + IntPtr props_ptr; + var props = new StringBuilder (); string new_path; LibSvnClient.svn_string_t new_props; LibSvnClient.Rev rev = LibSvnClient.Rev.Working; int index; string props_str; - var localpool = TryStartOperation (null); + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (null); foreach (var path in paths) { new_path = NormalizePath (path, localpool); CheckError (svn.client_propget (out result, "svn:ignore", Path.GetDirectoryName (new_path), ref rev, false, ctx, localpool)); - hash_item = apr.hash_first (localpool, result); - while (hash_item != IntPtr.Zero) { - apr.hash_this (hash_item, out hash_name, out length, out hash_val); - new_props = (LibSvnClient.svn_string_t) Marshal.PtrToStructure (hash_val, typeof (LibSvnClient.svn_string_t)); - props.Append (Marshal.PtrToStringAnsi (new_props.data)); - hash_item = apr.hash_next (hash_item); - } + GetProps (props, localpool, result); + props_str = props.ToString (); index = props_str.IndexOf (Path.GetFileName (new_path) + Environment.NewLine, StringComparison.Ordinal); props_str = (index < 0) ? props_str : props_str.Remove (index, Path.GetFileName(new_path).Length+1); - new_props = new LibSvnClient.svn_string_t (); - new_props.data = Marshal.StringToHGlobalAnsi (props_str); - new_props.len = props_str.Length; + new_props = new LibSvnClient.svn_string_t { + data = Marshal.StringToHGlobalAnsi (props_str), + len = props_str.Length, + }; props_ptr = apr.pcalloc (localpool, new_props); CheckError (svn.client_propset ("svn:ignore", props_ptr, Path.GetDirectoryName (new_path), false, localpool)); } } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } } public override bool HasNeedLock (FilePath file) { - IntPtr hash_item, hash_name, hash_val; - int length; IntPtr result; - IntPtr props_ptr = IntPtr.Zero; - StringBuilder props = new StringBuilder (); + var props = new StringBuilder (); string new_path; - LibSvnClient.svn_string_t new_props; LibSvnClient.Rev rev = LibSvnClient.Rev.Working; - var localpool = TryStartOperation (null); + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (null); new_path = NormalizePath (file, localpool); CheckError (svn.client_propget (out result, "svn:needs-lock", new_path, ref rev, false, ctx, localpool)); - hash_item = apr.hash_first (localpool, result); - while (hash_item != IntPtr.Zero) { - apr.hash_this (hash_item, out hash_name, out length, out hash_val); - new_props = (LibSvnClient.svn_string_t) Marshal.PtrToStructure (hash_val, typeof (LibSvnClient.svn_string_t)); - props.Append (Marshal.PtrToStringAnsi (new_props.data)); - hash_item = apr.hash_next (hash_item); - } + GetProps (props, localpool, result); + return props.Length != 0; } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } } @@ -1172,32 +1145,19 @@ namespace MonoDevelop.VersionControl.Subversion.Unix return IntPtr.Zero; } - string oldStacktrace = String.Empty; - IntPtr TryStartOperation (IProgressMonitor monitor) + IntPtr TryStartOperation (ProgressMonitor monitor) { - lock (sync) { - if (inProgress) { - var se = new SubversionException ("Another Subversion operation is already in progress."); - se.Data.Add ("OldStacktrace", oldStacktrace); - se.Data.Add ("CurrentStackTrace", Environment.StackTrace); - throw se; - } - oldStacktrace = Environment.StackTrace; - inProgress = true; - updatemonitor = monitor; - progressData = new ProgressData (); - return newpool (pool); - } + Monitor.Enter (svn); + updatemonitor = monitor; + progressData = new ProgressData (); + return newpool (pool); } - void TryEndOperation () + void TryEndOperation (IntPtr pool) { - lock (sync) { - if (!inProgress) - throw new SubversionException ("No Subversion operation is in progress."); - inProgress = false; - updatemonitor = null; - } + destroypool (pool); + updatemonitor = null; + Monitor.Exit (svn); } static VersionInfo CreateNode (LibSvnClient.StatusEnt ent, Repository repo) @@ -1266,15 +1226,16 @@ namespace MonoDevelop.VersionControl.Subversion.Unix IntPtr svn_cancel_func_t_impl (IntPtr baton) { - if (updatemonitor == null || !updatemonitor.IsCancelRequested) + if (updatemonitor == null || !updatemonitor.CancellationToken.IsCancellationRequested) return IntPtr.Zero; - LibSvnClient.svn_error_t err = new LibSvnClient.svn_error_t (); - err.apr_err = 200015; - err.message = "The operation was interrupted"; - IntPtr localpool = newpool (IntPtr.Zero); - err.pool = localpool; + var err = new LibSvnClient.svn_error_t { + apr_err = 200015, + message = "The operation was interrupted", + pool = localpool + }; + return apr.pcalloc (localpool, err); } @@ -1525,9 +1486,11 @@ namespace MonoDevelop.VersionControl.Subversion.Unix return String.Empty; IntPtr result; - IntPtr scratch = newpool (pool); - var localpool = TryStartOperation (null); + IntPtr scratch = IntPtr.Zero; + IntPtr localpool = IntPtr.Zero; try { + localpool = TryStartOperation (null); + scratch = newpool (pool); string new_path = NormalizePath (path.FullPath, localpool); SubversionException e = CheckErrorNoThrow (svn.client_get_wc_root (out result, new_path, ctx, localpool, scratch), null); if (e != null) { @@ -1553,9 +1516,8 @@ namespace MonoDevelop.VersionControl.Subversion.Unix } return Marshal.PtrToStringAnsi (result); } finally { - apr.pool_destroy (localpool); - apr.pool_destroy (scratch); - TryEndOperation (); + destroypool (scratch); + TryEndOperation (localpool); if (TooOld) WorkingCopyFormatPrompt (false, null); @@ -1572,15 +1534,15 @@ namespace MonoDevelop.VersionControl.Subversion.Unix if (!Upgrading || path.IsNullOrEmpty) return; - var localpool = TryStartOperation (null); + IntPtr localpool = IntPtr.Zero; bool tryParent = false; try { + localpool = TryStartOperation (null); CheckError (svn.client_upgrade (path, ctx, localpool)); } catch (Exception e) { tryParent = true; } finally { - apr.pool_destroy (localpool); - TryEndOperation (); + TryEndOperation (localpool); } if (tryParent) @@ -1653,7 +1615,7 @@ namespace MonoDevelop.VersionControl.Subversion.Unix apr.hash_this (item, out nameptr, out namelen, out val); string name = Marshal.PtrToStringAnsi (nameptr); - LibSvnClient.svn_log_changed_path_t ch = (LibSvnClient.svn_log_changed_path_t) Marshal.PtrToStructure (val, typeof (LibSvnClient.svn_log_changed_path_t)); + LibSvnClient.svn_log_changed_path_t ch = (LibSvnClient.svn_log_changed_path_t) Marshal.PtrToStructure (val, typeof(LibSvnClient.svn_log_changed_path_t)); item = apr.hash_next (item); RevisionAction ac; diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionRepository.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionRepository.cs index 1172cb4bdf..c373e0564a 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionRepository.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionRepository.cs @@ -144,17 +144,17 @@ namespace MonoDevelop.VersionControl.Subversion return true;
}
- protected override void OnLock (IProgressMonitor monitor, params FilePath[] localPaths)
+ protected override void OnLock (ProgressMonitor monitor, params FilePath[] localPaths)
{
Svn.Lock (monitor, "", false, localPaths);
}
- protected override void OnUnlock (IProgressMonitor monitor, params FilePath[] localPaths)
+ protected override void OnUnlock (ProgressMonitor monitor, params FilePath[] localPaths)
{
Svn.Unlock (monitor, false, localPaths);
}
- protected override Repository OnPublish (string serverPath, FilePath localPath, FilePath[] files, string message, IProgressMonitor monitor)
+ protected override Repository OnPublish (string serverPath, FilePath localPath, FilePath[] files, string message, ProgressMonitor monitor)
{
string url = Url;
if (!serverPath.StartsWith ("/", StringComparison.Ordinal) && !url.EndsWith ("/", StringComparison.Ordinal))
@@ -180,7 +180,7 @@ namespace MonoDevelop.VersionControl.Subversion return new SubversionRepository (VersionControlSystem, paths[0], localPath);
}
- void PublishDir (Set<FilePath> dirs, FilePath dir, bool rec, IProgressMonitor monitor)
+ void PublishDir (Set<FilePath> dirs, FilePath dir, bool rec, ProgressMonitor monitor)
{
if (dirs.Add (dir.CanonicalPath)) {
if (rec) {
@@ -190,31 +190,28 @@ namespace MonoDevelop.VersionControl.Subversion }
}
- protected override void OnUpdate (FilePath[] localPaths, bool recurse, IProgressMonitor monitor)
+ protected override void OnUpdate (FilePath[] localPaths, bool recurse, ProgressMonitor monitor)
{
foreach (string path in localPaths)
Svn.Update (path, recurse, monitor);
}
- protected override void OnCommit (ChangeSet changeSet, IProgressMonitor monitor)
+ protected override void OnCommit (ChangeSet changeSet, ProgressMonitor monitor)
{
- List<FilePath> list = new List<FilePath> ();
- foreach (ChangeSetItem it in changeSet.Items)
- list.Add (it.LocalPath);
- Svn.Commit (list.ToArray (), changeSet.GlobalComment, monitor);
+ Svn.Commit (changeSet.Items.Select (it => it.LocalPath).ToArray (), changeSet.GlobalComment, monitor);
}
- void CreateDirectory (string[] paths, string message, IProgressMonitor monitor)
+ void CreateDirectory (string[] paths, string message, ProgressMonitor monitor)
{
Svn.Mkdir (paths, message, monitor);
}
- protected override void OnCheckout (FilePath targetLocalPath, Revision rev, bool recurse, IProgressMonitor monitor)
+ protected override void OnCheckout (FilePath targetLocalPath, Revision rev, bool recurse, ProgressMonitor monitor)
{
Svn.Checkout (this.Url, targetLocalPath, rev, recurse, monitor);
}
- protected override void OnRevert (FilePath[] localPaths, bool recurse, IProgressMonitor monitor)
+ protected override void OnRevert (FilePath[] localPaths, bool recurse, ProgressMonitor monitor)
{
// If we have an array of paths such as: new [] { "/Foo/Directory", "/Foo/Directory/File1", "/Foo/Directory/File2" }
// svn will successfully revert the first entry (the directory) and then throw an error when trying to revert the
@@ -225,17 +222,17 @@ namespace MonoDevelop.VersionControl.Subversion Svn.Revert (localPaths, recurse, monitor);
}
- protected override void OnRevertRevision (FilePath localPath, Revision revision, IProgressMonitor monitor)
+ protected override void OnRevertRevision (FilePath localPath, Revision revision, ProgressMonitor monitor)
{
Svn.RevertRevision (localPath, revision, monitor);
}
- protected override void OnRevertToRevision (FilePath localPath, Revision revision, IProgressMonitor monitor)
+ protected override void OnRevertToRevision (FilePath localPath, Revision revision, ProgressMonitor monitor)
{
Svn.RevertToRevision (localPath, revision, monitor);
}
- protected override void OnAdd (FilePath[] localPaths, bool recurse, IProgressMonitor monitor)
+ protected override void OnAdd (FilePath[] localPaths, bool recurse, ProgressMonitor monitor)
{
foreach (FilePath path in localPaths) {
if (IsVersioned (path) && File.Exists (path) && !Directory.Exists (path)) {
@@ -293,10 +290,10 @@ namespace MonoDevelop.VersionControl.Subversion public string Root {
get {
try {
- UriBuilder ub = new UriBuilder (Url);
- ub.Path = string.Empty;
- ub.Query = string.Empty;
- return ub.ToString ();
+ return new UriBuilder (Url) {
+ Path = string.Empty,
+ Query = string.Empty
+ }.ToString ();
} catch {
return string.Empty;
}
@@ -308,7 +305,7 @@ namespace MonoDevelop.VersionControl.Subversion return (srcRepository is SubversionRepository) && ((SubversionRepository)srcRepository).Root == Root;
}
- protected override void OnMoveFile (FilePath localSrcPath, FilePath localDestPath, bool force, IProgressMonitor monitor)
+ protected override void OnMoveFile (FilePath localSrcPath, FilePath localDestPath, bool force, ProgressMonitor monitor)
{
bool destIsVersioned = false;
@@ -343,7 +340,7 @@ namespace MonoDevelop.VersionControl.Subversion }
}
- protected override void OnMoveDirectory (FilePath localSrcPath, FilePath localDestPath, bool force, IProgressMonitor monitor)
+ protected override void OnMoveDirectory (FilePath localSrcPath, FilePath localDestPath, bool force, ProgressMonitor monitor)
{
if (IsVersioned (localDestPath))
{
@@ -434,7 +431,7 @@ namespace MonoDevelop.VersionControl.Subversion }
}
- void MakeDirVersioned (string dir, IProgressMonitor monitor)
+ void MakeDirVersioned (string dir, ProgressMonitor monitor)
{
if (Directory.Exists (SubversionBackend.GetDirectoryDotSvn (VersionControlSystem, dir)))
return;
@@ -461,7 +458,7 @@ namespace MonoDevelop.VersionControl.Subversion collection.Add(f);
}
- protected override void OnDeleteFiles (FilePath[] localPaths, bool force, IProgressMonitor monitor, bool keepLocal)
+ protected override void OnDeleteFiles (FilePath[] localPaths, bool force, ProgressMonitor monitor, bool keepLocal)
{
foreach (string path in localPaths) {
if (IsVersioned (path)) {
@@ -489,7 +486,7 @@ namespace MonoDevelop.VersionControl.Subversion }
}
- protected override void OnDeleteDirectories (FilePath[] localPaths, bool force, IProgressMonitor monitor, bool keepLocal)
+ protected override void OnDeleteDirectories (FilePath[] localPaths, bool force, ProgressMonitor monitor, bool keepLocal)
{
foreach (string path in localPaths) {
if (IsVersioned (path)) {
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionVersionControl.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionVersionControl.cs index 0ee35899fe..3ffd857b6f 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionVersionControl.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionVersionControl.cs @@ -4,6 +4,7 @@ using System.IO; using MonoDevelop.Core; using MonoDevelop.VersionControl.Subversion.Gui; +using System.Linq; namespace MonoDevelop.VersionControl.Subversion { @@ -23,8 +24,6 @@ namespace MonoDevelop.VersionControl.Subversion } public abstract SubversionBackend CreateBackend (); - - public abstract string GetPathUrl (FilePath path); public override Repository GetRepositoryReference (FilePath path, string id) { @@ -57,17 +56,12 @@ namespace MonoDevelop.VersionControl.Subversion public Revision[] GetHistory (Repository repo, FilePath sourcefile, Revision since) { - List<Revision> revs = new List<Revision>(); - SvnRevision startrev = SvnRevision.Working; SvnRevision sincerev = SvnRevision.First; if (since != null) sincerev = (SvnRevision) since; - - foreach (SvnRevision rev in Log (repo, sourcefile, startrev, sincerev)) - revs.Add (rev); - - return revs.ToArray (); + + return Log (repo, sourcefile, startrev, sincerev).ToArray (); }
public abstract IEnumerable<SvnRevision> Log (Repository repo, FilePath path, SvnRevision revisionStart, SvnRevision revisionEnd); @@ -110,9 +104,8 @@ namespace MonoDevelop.VersionControl.Subversion return VersionInfo.CreateUnversioned (sourcefile, false); if (!sourcefile.IsChildPathOf (srepo.RootPath)) return VersionInfo.CreateUnversioned (sourcefile, false); - - List<VersionInfo> statuses = new List<VersionInfo> (); - statuses.AddRange (Status (repo, sourcefile, SvnRevision.Head, false, false, getRemoteStatus)); + + var statuses = new List<VersionInfo> (Status (repo, sourcefile, SvnRevision.Head, false, false, getRemoteStatus)); if (statuses.Count == 0) return VersionInfo.CreateUnversioned (sourcefile, false); @@ -120,7 +113,7 @@ namespace MonoDevelop.VersionControl.Subversion if (statuses.Count != 1) return VersionInfo.CreateUnversioned (sourcefile, false); - VersionInfo ent = (VersionInfo) statuses[0]; + VersionInfo ent = statuses [0]; if (ent.IsDirectory) return VersionInfo.CreateUnversioned (sourcefile, false); @@ -143,30 +136,28 @@ namespace MonoDevelop.VersionControl.Subversion public VersionInfo[] GetDirectoryVersionInfo (Repository repo, FilePath sourcepath, bool getRemoteStatus, bool recursive) { - List<VersionInfo> list = new List<VersionInfo> (); - list.AddRange (Status (repo, sourcepath, SvnRevision.Head, recursive, true, getRemoteStatus)); - return list.ToArray (); + return Status (repo, sourcepath, SvnRevision.Head, recursive, true, getRemoteStatus).ToArray (); }
public abstract IEnumerable<VersionInfo> Status (Repository repo, FilePath path, SvnRevision revision, bool descendDirs, bool changedItemsOnly, bool remoteStatus);
- public abstract void Update (FilePath path, bool recurse, IProgressMonitor monitor);
+ public abstract void Update (FilePath path, bool recurse, ProgressMonitor monitor);
- public abstract void Commit (FilePath[] paths, string message, IProgressMonitor monitor);
+ public abstract void Commit (FilePath[] paths, string message, ProgressMonitor monitor);
- public abstract void Mkdir (string[] paths, string message, IProgressMonitor monitor);
+ public abstract void Mkdir (string[] paths, string message, ProgressMonitor monitor);
- public abstract void Checkout (string url, FilePath path, Revision rev, bool recurse, IProgressMonitor monitor);
+ public abstract void Checkout (string url, FilePath path, Revision rev, bool recurse, ProgressMonitor monitor);
- public abstract void Revert (FilePath[] paths, bool recurse, IProgressMonitor monitor);
+ public abstract void Revert (FilePath[] paths, bool recurse, ProgressMonitor monitor);
- public abstract void RevertRevision (FilePath path, Revision revision, IProgressMonitor monitor);
+ public abstract void RevertRevision (FilePath path, Revision revision, ProgressMonitor monitor);
- public abstract void RevertToRevision (FilePath path, Revision revision, IProgressMonitor monitor);
+ public abstract void RevertToRevision (FilePath path, Revision revision, ProgressMonitor monitor);
- public abstract void Add (FilePath path, bool recurse, IProgressMonitor monitor); + public abstract void Add (FilePath path, bool recurse, ProgressMonitor monitor); - public abstract void Delete (FilePath path, bool force, IProgressMonitor monitor); + public abstract void Delete (FilePath path, bool force, ProgressMonitor monitor); public abstract void Ignore (FilePath[] paths); @@ -186,16 +177,16 @@ namespace MonoDevelop.VersionControl.Subversion public abstract IEnumerable<DirectoryEntry> ListUrl (string url, bool recurse, SvnRevision rev); - public void Move (FilePath srcPath, FilePath destPath, bool force, IProgressMonitor monitor) + public void Move (FilePath srcPath, FilePath destPath, bool force, ProgressMonitor monitor) { Move (srcPath, destPath, SvnRevision.Head, force, monitor); }
- public abstract void Move (FilePath srcPath, FilePath destPath, SvnRevision rev, bool force, IProgressMonitor monitor);
+ public abstract void Move (FilePath srcPath, FilePath destPath, SvnRevision rev, bool force, ProgressMonitor monitor);
- public abstract void Lock (IProgressMonitor monitor, string comment, bool stealLock, params FilePath[] paths);
+ public abstract void Lock (ProgressMonitor monitor, string comment, bool stealLock, params FilePath[] paths);
- public abstract void Unlock (IProgressMonitor monitor, bool breakLock, params FilePath[] paths);
+ public abstract void Unlock (ProgressMonitor monitor, bool breakLock, params FilePath[] paths);
public string GetUnifiedDiff (FilePath path, bool recursive, bool remoteDiff) { diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/StatusView.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/StatusView.cs index b9496598a4..95f58746ed 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/StatusView.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/StatusView.cs @@ -162,9 +162,10 @@ namespace MonoDevelop.VersionControl.Views scroller.VscrollbarPolicy = PolicyType.Automatic; filelist.RowActivated += OnRowActivated; filelist.DiffLineActivated += OnDiffLineActivated; + filelist.CommitSelectionToggled += OnCommitSelectionToggled; cellToggle = new CellRendererToggle(); - cellToggle.Toggled += new ToggledHandler(OnCommitToggledHandler); + cellToggle.Toggled += new ToggledHandler(OnCommitCellToggled); var crc = new CellRendererImage (); crc.StockId = "vc-comment"; colCommit = new TreeViewColumn (); @@ -409,13 +410,14 @@ namespace MonoDevelop.VersionControl.Views filelist.DoPopupMenu = null; filelist.RowActivated -= OnRowActivated; filelist.DiffLineActivated -= OnDiffLineActivated; + filelist.CommitSelectionToggled -= OnCommitSelectionToggled; filelist.TestExpandRow -= OnTestExpandRow; filelist.Selection.Changed -= OnCursorChanged; filelist.Destroy (); filelist = null; } if (cellToggle != null) { - cellToggle.Toggled -= OnCommitToggledHandler; + cellToggle.Toggled -= OnCommitCellToggled; cellToggle.Destroy (); cellToggle = null; } @@ -455,7 +457,7 @@ namespace MonoDevelop.VersionControl.Views ThreadPool.QueueUserWorkItem (delegate { if (fileList != null) { - var group = fileList.GroupBy (v => v.IsDirectory || v.WorkspaceObject is SolutionItem); + var group = fileList.GroupBy (v => v.IsDirectory || v.WorkspaceObject is SolutionFolderItem); foreach (var item in group) { // Is directory. if (item.Key) { @@ -710,11 +712,8 @@ namespace MonoDevelop.VersionControl.Views OnOpen (null, null); } - void OnCommitToggledHandler(object o, ToggledArgs args) { - TreeIter pos; - if (!filestore.GetIterFromString (out pos, args.Path)) - return; - + void ToggleCommitStatus(TreeIter pos) + { string localpath = (string) filestore.GetValue (pos, ColFullPath); if (changeSet.ContainsFile (localpath)) { @@ -728,6 +727,20 @@ namespace MonoDevelop.VersionControl.Views UpdateSelectionStatus (); } + void OnCommitSelectionToggled (object sender, EventArgs e) + { + filelist.Selection.SelectedForeach((model, path, iter) => ToggleCommitStatus(iter)); + } + + void OnCommitCellToggled(object o, ToggledArgs args) + { + TreeIter pos; + if (!filestore.GetIterFromString (out pos, args.Path)) + return; + + ToggleCommitStatus (pos); + } + VersionInfo GetVersionInfo (string file) { foreach (VersionInfo vi in statuses) @@ -1134,6 +1147,32 @@ namespace MonoDevelop.VersionControl.Views { const Gdk.ModifierType selectionModifiers = Gdk.ModifierType.ShiftMask | Gdk.ModifierType.ControlMask; + protected override bool OnKeyPressEvent (Gdk.EventKey evnt) + { + if (evnt.Key == Gdk.Key.Right || evnt.Key == Gdk.Key.KP_Right) { + Selection.SelectedForeach ((model, path, iter) => ExpandRow (path, true)); + return true; + } + + if (evnt.Key == Gdk.Key.Left || evnt.Key == Gdk.Key.KP_Left) { + Selection.SelectedForeach ((model, path, iter) => CollapseRow (path)); + return true; + } + + if (evnt.Key == Gdk.Key.space && CommitSelectionToggled != null) { + CommitSelectionToggled (this, EventArgs.Empty); + return true; + } + + if (evnt.Key == Gdk.Key.Return || evnt.Key == Gdk.Key.KP_Enter) { + if (DiffLineActivated != null) + DiffLineActivated (this, EventArgs.Empty); + return true; + } + + return base.OnKeyPressEvent (evnt); + } + protected override bool OnButtonPressEvent (Gdk.EventButton evnt) { bool keepPos = false; @@ -1228,5 +1267,6 @@ namespace MonoDevelop.VersionControl.Views public Action<Gdk.EventButton> DoPopupMenu; public event EventHandler DiffLineActivated; + public event EventHandler CommitSelectionToggled; } } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/SubviewAttachmentHandler.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/SubviewAttachmentHandler.cs index 9808922e3d..b95b373dea 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/SubviewAttachmentHandler.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/SubviewAttachmentHandler.cs @@ -48,10 +48,10 @@ namespace MonoDevelop.VersionControl.Views if (document == null || !document.IsFile || document.Window.FindView<IDiffView> () >= 0) return; - IWorkspaceObject project = document.Project; + WorkspaceObject project = document.Project; if (project == null) { // Fix for broken .csproj and .sln files not being seen as having a project. - foreach (var projItem in Ide.IdeApp.Workspace.GetAllSolutionItems<UnknownSolutionItem> ()) { + foreach (var projItem in Ide.IdeApp.Workspace.GetAllItems<UnknownSolutionItem> ()) { if (projItem.FileName == document.FileName) { project = projItem; } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.csproj b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.csproj index 937b7abc9f..f4bf6413df 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.csproj +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.csproj @@ -330,7 +330,6 @@ <Compile Include="MonoDevelop.VersionControl\Repository.cs" /> <Compile Include="MonoDevelop.VersionControl\RevertCommand.cs" /> <Compile Include="MonoDevelop.VersionControl\Revision.cs" /> - <Compile Include="MonoDevelop.VersionControl\Task.cs" /> <Compile Include="MonoDevelop.VersionControl\UnknownRepository.cs" /> <Compile Include="MonoDevelop.VersionControl\UpdateCommand.cs" /> <Compile Include="MonoDevelop.VersionControl\UrlBasedRepository.cs" /> @@ -396,6 +395,7 @@ <Compile Include="MonoDevelop.VersionControl.Dialogs\VersionControlSolutionOptionsPanel.cs" /> <Compile Include="AddinInfo.cs" /> <Compile Include="MonoDevelop.VersionControl\VersionControlException.cs" /> + <Compile Include="MonoDevelop.VersionControl\VersionControlTask.cs" /> </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/AddRemoveMoveCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/AddRemoveMoveCommand.cs index 70766591ea..60850e1c15 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/AddRemoveMoveCommand.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/AddRemoveMoveCommand.cs @@ -17,7 +17,7 @@ namespace MonoDevelop.VersionControl return true; } - private class AddWorker : Task { + private class AddWorker : VersionControlTask { VersionControlItemList items; public AddWorker (VersionControlItemList items) @@ -32,7 +32,7 @@ namespace MonoDevelop.VersionControl protected override void Run () { - IProgressMonitor monitor = Monitor; + ProgressMonitor monitor = Monitor; foreach (VersionControlItemList list in items.SplitByRepository ()) list[0].Repository.Add (list.Paths, true, monitor); @@ -108,7 +108,7 @@ namespace MonoDevelop.VersionControl return true; } - private class RemoveWorker : Task { + private class RemoveWorker : VersionControlTask { VersionControlItemList items; public RemoveWorker (VersionControlItemList items) { diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CheckoutCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CheckoutCommand.cs index 7ecd9340ed..7e03982d5a 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CheckoutCommand.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CheckoutCommand.cs @@ -28,7 +28,7 @@ namespace MonoDevelop.VersionControl } } - class CheckoutWorker : Task + class CheckoutWorker : VersionControlTask { Repository vc; string path; @@ -45,7 +45,7 @@ namespace MonoDevelop.VersionControl return GettextCatalog.GetString ("Checking out {0}...", path); } - protected override IProgressMonitor CreateProgressMonitor () + protected override ProgressMonitor CreateProgressMonitor () { return new MonoDevelop.Core.ProgressMonitoring.AggregatedProgressMonitor ( base.CreateProgressMonitor (), @@ -73,7 +73,7 @@ namespace MonoDevelop.VersionControl return; } - if (Monitor.IsCancelRequested) { + if (Monitor.CancellationToken.IsCancellationRequested) { Monitor.ReportSuccess (GettextCatalog.GetString ("Checkout operation cancelled")); return; } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Commands.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Commands.cs index 6c8d5abea3..5462cd8978 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Commands.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Commands.cs @@ -37,7 +37,7 @@ namespace MonoDevelop.VersionControl VersionControlItemList list = new VersionControlItemList (); WorkspaceItem wob; - SolutionItem sol; + SolutionFolderItem sol; Repository repo = null; wob = IdeApp.ProjectOperations.CurrentSelectedWorkspaceItem; if (wob != null) diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CommitCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CommitCommand.cs index f5257c5979..c3e6e4979c 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CommitCommand.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CommitCommand.cs @@ -32,7 +32,7 @@ namespace MonoDevelop.VersionControl } } - private class CommitWorker : Task + private class CommitWorker : VersionControlTask { Repository vc; ChangeSet changeSet; diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/IgnoreCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/IgnoreCommand.cs index d9f74988ca..48297e4b43 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/IgnoreCommand.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/IgnoreCommand.cs @@ -62,7 +62,7 @@ namespace MonoDevelop.VersionControl }
}
- private class IgnoreWorker : Task
+ private class IgnoreWorker : VersionControlTask
{
VersionControlItemList items;
@@ -125,7 +125,7 @@ namespace MonoDevelop.VersionControl }
}
- private class UnignoreWorker : Task
+ private class UnignoreWorker : VersionControlTask
{
VersionControlItemList items;
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/LockCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/LockCommand.cs index 66507132e4..46cb65a80c 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/LockCommand.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/LockCommand.cs @@ -43,7 +43,7 @@ namespace MonoDevelop.VersionControl return true; } - private class LockWorker : Task + private class LockWorker : VersionControlTask { VersionControlItemList items; diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/PublishCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/PublishCommand.cs index b636e7e3db..5dee5c58c9 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/PublishCommand.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/PublishCommand.cs @@ -10,7 +10,7 @@ namespace MonoDevelop.VersionControl { internal class PublishCommand {
- public static bool Publish (IWorkspaceObject entry, FilePath localPath, bool test) + public static bool Publish (WorkspaceObject entry, FilePath localPath, bool test) { if (test) return VersionControlService.CheckVersionControlInstalled () && VersionControlService.GetRepository (entry) == null; @@ -52,7 +52,7 @@ namespace MonoDevelop.VersionControl return true; }
- static void GetFiles (List<FilePath> files, IWorkspaceObject entry) + static void GetFiles (List<FilePath> files, WorkspaceObject entry) { // Ensure that we strip out all linked files from outside of the solution/projects path. if (entry is IWorkspaceFileObject) @@ -69,7 +69,7 @@ namespace MonoDevelop.VersionControl } } - internal class PublishWorker : Task { + internal class PublishWorker : VersionControlTask { Repository vc;
FilePath path; string moduleName;
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs index aef5e0dd2d..aca8706d1d 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs @@ -372,6 +372,25 @@ namespace MonoDevelop.VersionControl } catch (Exception ex) { LoggingService.LogError ("Version control status query failed", ex); + //Release all items in current batch + foreach (var item in recursiveDirectoryQueryQueueClone) + item.ResetEvent.Set (); + + lock (queryLock) { + queryRunning = false; + + fileQueryQueue.Clear (); + filesInQueryQueue.Clear (); + + directoriesInQueryQueue.Clear (); + directoryQueryQueue.Clear (); + + recursiveDirectoryQueryQueueClone = recursiveDirectoryQueryQueue.ToArray (); + recursiveDirectoriesInQueryQueue.Clear (); + recursiveDirectoryQueryQueue.Clear (); + } + + //Release newly pending foreach (var item in recursiveDirectoryQueryQueueClone) item.ResetEvent.Set (); } @@ -421,29 +440,29 @@ namespace MonoDevelop.VersionControl // Imports a directory into the repository. 'serverPath' is the relative path in the repository. // 'localPath' is the local directory to publish. 'files' is the list of files to add to the new // repository directory (must use absolute local paths). - public Repository Publish (string serverPath, FilePath localPath, FilePath[] files, string message, IProgressMonitor monitor) + public Repository Publish (string serverPath, FilePath localPath, FilePath[] files, string message, ProgressMonitor monitor) { var res = OnPublish (serverPath, localPath, files, message, monitor); ClearCachedVersionInfo (localPath); return res; } - protected abstract Repository OnPublish (string serverPath, FilePath localPath, FilePath[] files, string message, IProgressMonitor monitor); + protected abstract Repository OnPublish (string serverPath, FilePath localPath, FilePath[] files, string message, ProgressMonitor monitor); // Updates a local file or directory from the repository // Returns a list of updated files - public void Update (FilePath localPath, bool recurse, IProgressMonitor monitor) + public void Update (FilePath localPath, bool recurse, ProgressMonitor monitor) { Update (new FilePath[] { localPath }, recurse, monitor); } - public void Update (FilePath[] localPaths, bool recurse, IProgressMonitor monitor) + public void Update (FilePath[] localPaths, bool recurse, ProgressMonitor monitor) { OnUpdate (localPaths, recurse, monitor); ClearCachedVersionInfo (localPaths); } - protected abstract void OnUpdate (FilePath[] localPaths, bool recurse, IProgressMonitor monitor); + protected abstract void OnUpdate (FilePath[] localPaths, bool recurse, ProgressMonitor monitor); // Called to create a ChangeSet to be used for a commit operation public virtual ChangeSet CreateChangeSet (FilePath basePath) @@ -468,70 +487,70 @@ namespace MonoDevelop.VersionControl } // Commits changes in a set of files or directories into the repository - public void Commit (ChangeSet changeSet, IProgressMonitor monitor) + public void Commit (ChangeSet changeSet, ProgressMonitor monitor) { ClearCachedVersionInfo (changeSet.BaseLocalPath); OnCommit (changeSet, monitor); } - protected abstract void OnCommit (ChangeSet changeSet, IProgressMonitor monitor); + protected abstract void OnCommit (ChangeSet changeSet, ProgressMonitor monitor); // Gets the contents of this repositories into the specified local path - public void Checkout (FilePath targetLocalPath, bool recurse, IProgressMonitor monitor) + public void Checkout (FilePath targetLocalPath, bool recurse, ProgressMonitor monitor) { Checkout (targetLocalPath, null, recurse, monitor); } - public void Checkout (FilePath targetLocalPath, Revision rev, bool recurse, IProgressMonitor monitor) + public void Checkout (FilePath targetLocalPath, Revision rev, bool recurse, ProgressMonitor monitor) { ClearCachedVersionInfo (targetLocalPath); OnCheckout (targetLocalPath, rev, recurse, monitor); } - protected abstract void OnCheckout (FilePath targetLocalPath, Revision rev, bool recurse, IProgressMonitor monitor); + protected abstract void OnCheckout (FilePath targetLocalPath, Revision rev, bool recurse, ProgressMonitor monitor); - public void Revert (FilePath[] localPaths, bool recurse, IProgressMonitor monitor) + public void Revert (FilePath[] localPaths, bool recurse, ProgressMonitor monitor) { ClearCachedVersionInfo (localPaths); OnRevert (localPaths, recurse, monitor); } - public void Revert (FilePath localPath, bool recurse, IProgressMonitor monitor) + public void Revert (FilePath localPath, bool recurse, ProgressMonitor monitor) { Revert (new FilePath[] { localPath }, recurse, monitor); } - protected abstract void OnRevert (FilePath[] localPaths, bool recurse, IProgressMonitor monitor); + protected abstract void OnRevert (FilePath[] localPaths, bool recurse, ProgressMonitor monitor); - public void RevertRevision (FilePath localPath, Revision revision, IProgressMonitor monitor) + public void RevertRevision (FilePath localPath, Revision revision, ProgressMonitor monitor) { ClearCachedVersionInfo (localPath); OnRevertRevision (localPath, revision, monitor); } - protected abstract void OnRevertRevision (FilePath localPath, Revision revision, IProgressMonitor monitor); + protected abstract void OnRevertRevision (FilePath localPath, Revision revision, ProgressMonitor monitor); - public void RevertToRevision (FilePath localPath, Revision revision, IProgressMonitor monitor) + public void RevertToRevision (FilePath localPath, Revision revision, ProgressMonitor monitor) { ClearCachedVersionInfo (localPath); OnRevertToRevision (localPath, revision, monitor); } - protected abstract void OnRevertToRevision (FilePath localPath, Revision revision, IProgressMonitor monitor); + protected abstract void OnRevertToRevision (FilePath localPath, Revision revision, ProgressMonitor monitor); // Adds a file or directory to the repository - public void Add (FilePath localPath, bool recurse, IProgressMonitor monitor) + public void Add (FilePath localPath, bool recurse, ProgressMonitor monitor) { Add (new FilePath[] { localPath }, recurse, monitor); } - public void Add (FilePath[] localPaths, bool recurse, IProgressMonitor monitor) + public void Add (FilePath[] localPaths, bool recurse, ProgressMonitor monitor) { OnAdd (localPaths, recurse, monitor); ClearCachedVersionInfo (localPaths); } - protected abstract void OnAdd (FilePath[] localPaths, bool recurse, IProgressMonitor monitor); + protected abstract void OnAdd (FilePath[] localPaths, bool recurse, ProgressMonitor monitor); // Returns true if the file can be moved from source location (and repository) to this repository public virtual bool CanMoveFilesFrom (Repository srcRepository, FilePath localSrcPath, FilePath localDestPath) @@ -545,57 +564,57 @@ namespace MonoDevelop.VersionControl // For example, when moving a file to an unversioned directory, the implementation // might just throw an exception, or it could version the directory, or it could // ask the user what to do. - public void MoveFile (FilePath localSrcPath, FilePath localDestPath, bool force, IProgressMonitor monitor) + public void MoveFile (FilePath localSrcPath, FilePath localDestPath, bool force, ProgressMonitor monitor) { ClearCachedVersionInfo (localSrcPath, localDestPath); OnMoveFile (localSrcPath, localDestPath, force, monitor); } - protected virtual void OnMoveFile (FilePath localSrcPath, FilePath localDestPath, bool force, IProgressMonitor monitor) + protected virtual void OnMoveFile (FilePath localSrcPath, FilePath localDestPath, bool force, ProgressMonitor monitor) { File.Move (localSrcPath, localDestPath); } // Moves a directory. This method may be called for versioned and unversioned // files. The default implementetions performs a system file move. - public void MoveDirectory (FilePath localSrcPath, FilePath localDestPath, bool force, IProgressMonitor monitor) + public void MoveDirectory (FilePath localSrcPath, FilePath localDestPath, bool force, ProgressMonitor monitor) { ClearCachedVersionInfo (localSrcPath, localDestPath); OnMoveDirectory (localSrcPath, localDestPath, force, monitor); } - protected virtual void OnMoveDirectory (FilePath localSrcPath, FilePath localDestPath, bool force, IProgressMonitor monitor) + protected virtual void OnMoveDirectory (FilePath localSrcPath, FilePath localDestPath, bool force, ProgressMonitor monitor) { - Directory.Move (localSrcPath, localDestPath); + FileService.SystemDirectoryRename (localSrcPath, localDestPath); } // Deletes a file or directory. This method may be called for versioned and unversioned // files. The default implementetions performs a system file delete. - public void DeleteFile (FilePath localPath, bool force, IProgressMonitor monitor, bool keepLocal = true) + public void DeleteFile (FilePath localPath, bool force, ProgressMonitor monitor, bool keepLocal = true) { DeleteFiles (new FilePath[] { localPath }, force, monitor, keepLocal); } - public void DeleteFiles (FilePath[] localPaths, bool force, IProgressMonitor monitor, bool keepLocal = true) + public void DeleteFiles (FilePath[] localPaths, bool force, ProgressMonitor monitor, bool keepLocal = true) { OnDeleteFiles (localPaths, force, monitor, keepLocal); ClearCachedVersionInfo (localPaths); } - protected abstract void OnDeleteFiles (FilePath[] localPaths, bool force, IProgressMonitor monitor, bool keepLocal); + protected abstract void OnDeleteFiles (FilePath[] localPaths, bool force, ProgressMonitor monitor, bool keepLocal); - public void DeleteDirectory (FilePath localPath, bool force, IProgressMonitor monitor, bool keepLocal = true) + public void DeleteDirectory (FilePath localPath, bool force, ProgressMonitor monitor, bool keepLocal = true) { DeleteDirectories (new FilePath[] { localPath }, force, monitor, keepLocal); } - public void DeleteDirectories (FilePath[] localPaths, bool force, IProgressMonitor monitor, bool keepLocal = true) + public void DeleteDirectories (FilePath[] localPaths, bool force, ProgressMonitor monitor, bool keepLocal = true) { OnDeleteDirectories (localPaths, force, monitor, keepLocal); ClearCachedVersionInfo (localPaths); } - protected abstract void OnDeleteDirectories (FilePath[] localPaths, bool force, IProgressMonitor monitor, bool keepLocal); + protected abstract void OnDeleteDirectories (FilePath[] localPaths, bool force, ProgressMonitor monitor, bool keepLocal); // Called to request write permission for a file. The file may not yet exist. // After the file is modified or created, NotifyFileChanged is called. @@ -620,26 +639,26 @@ namespace MonoDevelop.VersionControl } // Locks a file in the repository so no other users can change it - public void Lock (IProgressMonitor monitor, params FilePath[] localPaths) + public void Lock (ProgressMonitor monitor, params FilePath[] localPaths) { ClearCachedVersionInfo (localPaths); OnLock (monitor, localPaths); } // Locks a file in the repository so no other users can change it - protected virtual void OnLock (IProgressMonitor monitor, params FilePath[] localPaths) + protected virtual void OnLock (ProgressMonitor monitor, params FilePath[] localPaths) { throw new System.NotSupportedException (); } // Unlocks a file in the repository so other users can change it - public void Unlock (IProgressMonitor monitor, params FilePath[] localPaths) + public void Unlock (ProgressMonitor monitor, params FilePath[] localPaths) { ClearCachedVersionInfo (localPaths); OnUnlock (monitor, localPaths); } - protected virtual void OnUnlock (IProgressMonitor monitor, params FilePath[] localPaths) + protected virtual void OnUnlock (ProgressMonitor monitor, params FilePath[] localPaths) { throw new System.NotSupportedException (); } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertCommand.cs index b69500f639..f49c902b47 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertCommand.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertCommand.cs @@ -43,7 +43,7 @@ namespace MonoDevelop.VersionControl } } - private class RevertWorker : Task { + private class RevertWorker : VersionControlTask { VersionControlItemList items; public RevertWorker (VersionControlItemList items) { diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertRevisionsCommands.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertRevisionsCommands.cs index e0be0ad697..bf4fa3cf85 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertRevisionsCommands.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertRevisionsCommands.cs @@ -75,7 +75,7 @@ namespace MonoDevelop.VersionControl } } - private class RevertWorker : Task { + private class RevertWorker : VersionControlTask { Repository vc; string path; Revision revision; diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UnknownRepository.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UnknownRepository.cs index 030583d3ce..7735cab3f2 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UnknownRepository.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UnknownRepository.cs @@ -45,52 +45,52 @@ namespace MonoDevelop.VersionControl }
- protected override Repository OnPublish (string serverPath, FilePath localPath, FilePath[] FilePath, string message, IProgressMonitor monitor) + protected override Repository OnPublish (string serverPath, FilePath localPath, FilePath[] FilePath, string message, ProgressMonitor monitor) { return null; }
- protected override void OnUpdate (FilePath[] paths, bool recurse, IProgressMonitor monitor) + protected override void OnUpdate (FilePath[] paths, bool recurse, ProgressMonitor monitor) { } - protected override void OnCommit (ChangeSet changeSet, IProgressMonitor monitor) + protected override void OnCommit (ChangeSet changeSet, ProgressMonitor monitor) { }
- protected override void OnCheckout (FilePath path, Revision rev, bool recurse, IProgressMonitor monitor) + protected override void OnCheckout (FilePath path, Revision rev, bool recurse, ProgressMonitor monitor) { }
- protected override void OnRevert (FilePath[] localPaths, bool recurse, IProgressMonitor monitor) + protected override void OnRevert (FilePath[] localPaths, bool recurse, ProgressMonitor monitor) { }
- protected override void OnRevertRevision (FilePath localPath, Revision revision, IProgressMonitor monitor) + protected override void OnRevertRevision (FilePath localPath, Revision revision, ProgressMonitor monitor) { }
- protected override void OnRevertToRevision (FilePath localPath, Revision revision, IProgressMonitor monitor) + protected override void OnRevertToRevision (FilePath localPath, Revision revision, ProgressMonitor monitor) { }
- protected override void OnAdd (FilePath[] paths, bool recurse, IProgressMonitor monitor) + protected override void OnAdd (FilePath[] paths, bool recurse, ProgressMonitor monitor) { }
- protected override void OnMoveFile (FilePath srcPath, FilePath destPath, bool force, IProgressMonitor monitor) + protected override void OnMoveFile (FilePath srcPath, FilePath destPath, bool force, ProgressMonitor monitor) { }
- protected override void OnMoveDirectory (FilePath srcPath, FilePath destPath, bool force, IProgressMonitor monitor) + protected override void OnMoveDirectory (FilePath srcPath, FilePath destPath, bool force, ProgressMonitor monitor) { } - protected override void OnDeleteFiles (FilePath[] path, bool force, IProgressMonitor monitor, bool keepLocal) + protected override void OnDeleteFiles (FilePath[] path, bool force, ProgressMonitor monitor, bool keepLocal) { }
- protected override void OnDeleteDirectories (FilePath[] path, bool force, IProgressMonitor monitor, bool keepLocal) + protected override void OnDeleteDirectories (FilePath[] path, bool force, ProgressMonitor monitor, bool keepLocal) { } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UnlockCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UnlockCommand.cs index 599e3d56f0..90b5cf4f79 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UnlockCommand.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UnlockCommand.cs @@ -45,7 +45,7 @@ namespace MonoDevelop.VersionControl return true; } - private class UnlockWorker : Task + private class UnlockWorker : VersionControlTask { VersionControlItemList items; diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UpdateCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UpdateCommand.cs index 6677562bb1..838884e603 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UpdateCommand.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UpdateCommand.cs @@ -16,7 +16,7 @@ namespace MonoDevelop.VersionControl return true; } - private class UpdateWorker : Task { + private class UpdateWorker : VersionControlTask { VersionControlItemList items; public UpdateWorker (VersionControlItemList items) { diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlCommandHandler.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlCommandHandler.cs index ba12420ea5..009cfe0c50 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlCommandHandler.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlCommandHandler.cs @@ -70,7 +70,7 @@ namespace MonoDevelop.VersionControl { string path; bool isDir; - IWorkspaceObject pentry; + WorkspaceObject pentry; Repository repo; VersionInfo versionInfo = null; @@ -105,8 +105,8 @@ namespace MonoDevelop.VersionControl path = item.FileName; isDir = false; pentry = item; - } else if (obj is IWorkspaceObject) { - pentry = ((IWorkspaceObject)obj); + } else if (obj is WorkspaceObject) { + pentry = ((WorkspaceObject)obj); path = pentry.BaseDirectory; isDir = true; } else diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlFileSystemExtension.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlFileSystemExtension.cs index 4f50281ce9..c77a27fdfc 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlFileSystemExtension.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlFileSystemExtension.cs @@ -52,7 +52,7 @@ namespace MonoDevelop.VersionControl public override void MoveFile (FilePath source, FilePath dest) { - IProgressMonitor monitor = new NullProgressMonitor (); + ProgressMonitor monitor = new ProgressMonitor (); Repository srcRepo = GetRepository (source); Repository dstRepo = GetRepository (dest); @@ -78,7 +78,7 @@ namespace MonoDevelop.VersionControl public override void DeleteFile (FilePath file) { Repository repo = GetRepository (file); - repo.DeleteFile (file, true, new NullProgressMonitor (), false); + repo.DeleteFile (file, true, new ProgressMonitor (), false); } public override void CreateDirectory (FilePath path) @@ -86,12 +86,12 @@ namespace MonoDevelop.VersionControl Repository repo = GetRepository (path); repo.ClearCachedVersionInfo (path); System.IO.Directory.CreateDirectory (path); - repo.Add (path, false, new NullProgressMonitor ()); + repo.Add (path, false, new ProgressMonitor ()); } public override void MoveDirectory (FilePath sourcePath, FilePath destPath) { - IProgressMonitor monitor = new NullProgressMonitor (); + ProgressMonitor monitor = new ProgressMonitor (); Repository srcRepo = GetRepository (sourcePath); Repository dstRepo = GetRepository (destPath); @@ -107,7 +107,7 @@ namespace MonoDevelop.VersionControl public override void DeleteDirectory (FilePath path) { Repository repo = GetRepository (path); - repo.DeleteDirectory (path, true, new NullProgressMonitor (), false); + repo.DeleteDirectory (path, true, new ProgressMonitor (), false); } public override void RequestFileEdit (IEnumerable<FilePath> files) diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlItem.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlItem.cs index c8f3011f0d..7aa84c36ea 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlItem.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlItem.cs @@ -35,11 +35,11 @@ namespace MonoDevelop.VersionControl {
FilePath path;
bool isDirectory;
- IWorkspaceObject workspaceObject;
+ WorkspaceObject workspaceObject;
Repository repository; VersionInfo versionInfo;
- public VersionControlItem (Repository repository, IWorkspaceObject workspaceObject, FilePath path, bool isDirectory, VersionInfo versionInfo)
+ public VersionControlItem (Repository repository, WorkspaceObject workspaceObject, FilePath path, bool isDirectory, VersionInfo versionInfo)
{
this.path = path;
this.repository = repository;
@@ -48,7 +48,7 @@ namespace MonoDevelop.VersionControl this.versionInfo = versionInfo;
}
- public IWorkspaceObject WorkspaceObject { + public WorkspaceObject WorkspaceObject { get { return workspaceObject; } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlNodeExtension.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlNodeExtension.cs index 848be5eba1..a2f9544638 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlNodeExtension.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlNodeExtension.cs @@ -24,7 +24,7 @@ namespace MonoDevelop.VersionControl return typeof(ProjectFile).IsAssignableFrom (dataType) || typeof(SystemFile).IsAssignableFrom (dataType) || typeof(ProjectFolder).IsAssignableFrom (dataType) - || typeof(IWorkspaceObject).IsAssignableFrom (dataType); + || typeof(WorkspaceObject).IsAssignableFrom (dataType); } protected override void Initialize ()
@@ -46,8 +46,8 @@ namespace MonoDevelop.VersionControl // Add status overlays - if (dataObject is IWorkspaceObject) { - IWorkspaceObject ce = (IWorkspaceObject) dataObject; + if (dataObject is WorkspaceObject) { + WorkspaceObject ce = (WorkspaceObject) dataObject; Repository rep = VersionControlService.GetRepository (ce); if (rep != null) {
rep.GetDirectoryVersionInfo (ce.BaseDirectory, false, false); @@ -66,7 +66,7 @@ namespace MonoDevelop.VersionControl return; } - IWorkspaceObject prj; + WorkspaceObject prj; FilePath file; if (dataObject is ProjectFile) { @@ -202,8 +202,8 @@ namespace MonoDevelop.VersionControl return ((ProjectFile) dataObject).FilePath; } else if (dataObject is SystemFile) { return ((SystemFile) dataObject).Path; - } else if (dataObject is IWorkspaceObject) { - return ((IWorkspaceObject)dataObject).BaseDirectory; + } else if (dataObject is WorkspaceObject) { + return ((WorkspaceObject)dataObject).BaseDirectory; } else if (dataObject is ProjectFolder) { return ((ProjectFolder)dataObject).Path; } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs index 9d204b4309..f994eb7cfd 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs @@ -185,7 +185,7 @@ namespace MonoDevelop.VersionControl } internal static Dictionary<Repository, InternalRepositoryReference> referenceCache = new Dictionary<Repository, InternalRepositoryReference> (); - public static Repository GetRepository (IWorkspaceObject entry) + public static Repository GetRepository (WorkspaceObject entry) { if (IsGloballyDisabled) return null; @@ -437,6 +437,12 @@ namespace MonoDevelop.VersionControl FileStatusChanged (null, args); } } + + static bool ShouldAddFile (ProjectFileEventInfo info) + { + const ProjectItemFlags ignoreFlags = ProjectItemFlags.DontPersist | ProjectItemFlags.Hidden; + return (info.ProjectFile.Flags & ignoreFlags) != ignoreFlags; + } //static void OnFileChanged (object s, ProjectFileEventArgs args) //{ @@ -448,13 +454,14 @@ namespace MonoDevelop.VersionControl static void OnFileAdded (object s, ProjectFileEventArgs e) { FileUpdateEventArgs vargs = new FileUpdateEventArgs (); - IProgressMonitor monitor = null; + ProgressMonitor monitor = null; try { foreach (var repoFiles in e.GroupBy (i => i.Project)) { Repository repo = GetRepository (repoFiles.Key); if (repo == null) continue; - var versionInfos = repo.GetVersionInfo (repoFiles.Select (f => f.ProjectFile.FilePath), VersionInfoQueryFlags.IgnoreCache); + var filePaths = repoFiles.Where (ShouldAddFile).Select (f => f.ProjectFile.FilePath); + var versionInfos = repo.GetVersionInfo (filePaths, VersionInfoQueryFlags.IgnoreCache); FilePath[] paths = versionInfos.Where (i => i.CanAdd).Select (i => i.LocalPath).ToArray (); if (paths.Length > 0) { if (monitor == null) @@ -494,10 +501,10 @@ namespace MonoDevelop.VersionControl } } */ - static void SolutionItemAddFiles (string rootPath, SolutionItem entry, HashSet<string> files) + static void SolutionItemAddFiles (string rootPath, SolutionFolderItem entry, HashSet<string> files) { - if (entry is SolutionEntityItem) { - foreach (var file in ((SolutionEntityItem)entry).GetItemFiles (false)) + if (entry is SolutionItem) { + foreach (var file in ((SolutionItem)entry).GetItemFiles (false)) SolutionItemAddFile (rootPath, files, file); } @@ -507,7 +514,7 @@ namespace MonoDevelop.VersionControl SolutionItemAddFile (rootPath, files, file.FilePath); } } else if (entry is SolutionFolder) { - foreach (SolutionItem ent in ((SolutionFolder) entry).Items) + foreach (SolutionFolderItem ent in ((SolutionFolder) entry).Items) SolutionItemAddFiles (rootPath, ent, files); } } @@ -531,7 +538,7 @@ namespace MonoDevelop.VersionControl return; // handles addition of solutions and projects - SolutionItem parent = (SolutionItem) args.SolutionItem.ParentFolder; + SolutionFolderItem parent = (SolutionFolderItem) args.SolutionItem.ParentFolder; if (parent == null) return; @@ -541,7 +548,7 @@ namespace MonoDevelop.VersionControl if (repo == null) return; - SolutionItem entry = args.SolutionItem; + SolutionFolderItem entry = args.SolutionItem; Repository currentRepo = GetRepository (entry); if (currentRepo != null && currentRepo.VersionControlSystem != repo.VersionControlSystem) { // If the item is already under version control using a different version control system @@ -558,7 +565,7 @@ namespace MonoDevelop.VersionControl var files = new HashSet<string> { path }; SolutionItemAddFiles (path, entry, files); - using (IProgressMonitor monitor = GetStatusMonitor ()) { + using (ProgressMonitor monitor = GetStatusMonitor ()) { var status = repo.GetDirectoryVersionInfo (path, false, true);
foreach (var v in status) {
if (!v.IsVersioned && files.Contains (v.LocalPath))
@@ -572,12 +579,12 @@ namespace MonoDevelop.VersionControl NotifyFileStatusChanged (new FileUpdateEventArgs (repo, parent.BaseDirectory, true)); } - public static IProgressMonitor GetProgressMonitor (string operation) + public static ProgressMonitor GetProgressMonitor (string operation) { return GetProgressMonitor (operation, VersionControlOperationType.Other); } - public static IProgressMonitor GetProgressMonitor (string operation, VersionControlOperationType op) + public static ProgressMonitor GetProgressMonitor (string operation, VersionControlOperationType op) { IconId icon; switch (op) { @@ -586,7 +593,7 @@ namespace MonoDevelop.VersionControl default: icon = "md-version-control"; break; } - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetOutputProgressMonitor ("MonoDevelop.VersionControlOutput", "Version Control", "md-version-control", false, true); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetOutputProgressMonitor ("MonoDevelop.VersionControlOutput", "Version Control", "md-version-control", false, true); Pad outPad = IdeApp.Workbench.ProgressMonitors.GetPadForMonitor (monitor); AggregatedProgressMonitor mon = new AggregatedProgressMonitor (monitor); @@ -594,7 +601,7 @@ namespace MonoDevelop.VersionControl return mon; } - static IProgressMonitor GetStatusMonitor () + static ProgressMonitor GetStatusMonitor () { return IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor (GettextCatalog.GetString ("Updating version control repository"), "vc-remote-status", true); } @@ -736,7 +743,7 @@ namespace MonoDevelop.VersionControl } } - public static CommitMessageFormat GetCommitMessageFormat (SolutionItem item) + public static CommitMessageFormat GetCommitMessageFormat (SolutionFolderItem item) { CommitMessageFormat format = new CommitMessageFormat (); format.Style = item.Policies.Get<VersionControlPolicy> ().CommitMessageStyle; diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Task.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlTask.cs index 92aaac31c3..3ca1b9e2a5 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Task.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlTask.cs @@ -6,9 +6,9 @@ using MonoDevelop.Core; namespace MonoDevelop.VersionControl { - internal abstract class Task + internal abstract class VersionControlTask { - IProgressMonitor tracker; + ProgressMonitor tracker; ThreadNotify threadnotify; protected VersionControlOperationType OperationType { get; set; } @@ -24,17 +24,17 @@ namespace MonoDevelop.VersionControl { } - protected Task() + protected VersionControlTask() { OperationType = VersionControlOperationType.Other; threadnotify = new ThreadNotify(new ReadyEvent(Wakeup)); } - protected IProgressMonitor Monitor { + protected ProgressMonitor Monitor { get { return tracker; } } - protected virtual IProgressMonitor CreateProgressMonitor () + protected virtual ProgressMonitor CreateProgressMonitor () { return VersionControlService.GetProgressMonitor (GetDescription (), OperationType); } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/VersionControl.addin.xml b/main/src/addins/VersionControl/MonoDevelop.VersionControl/VersionControl.addin.xml index 848fcc2200..18e0f0809b 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/VersionControl.addin.xml +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/VersionControl.addin.xml @@ -164,7 +164,7 @@ defaultHandler = "MonoDevelop.VersionControl.UnlockCommandHandler" description = "Unlock files in the repository, so that other user can change them."/> <Command id = "MonoDevelop.VersionControl.Commands.Annotate" - _label = "Show Annotations" + _label = "Blame" defaultHandler = "MonoDevelop.VersionControl.CurrentFileBlameHandler" description = "Show the origin of each line in a file."/> <Command id = "MonoDevelop.VersionControl.Commands.CreatePatch" diff --git a/main/src/addins/VersionControl/Subversion.Win32/SvnSharpClient.cs b/main/src/addins/VersionControl/Subversion.Win32/SvnSharpClient.cs index 667308fa8f..e7d8902ebc 100644 --- a/main/src/addins/VersionControl/Subversion.Win32/SvnSharpClient.cs +++ b/main/src/addins/VersionControl/Subversion.Win32/SvnSharpClient.cs @@ -41,14 +41,6 @@ namespace SubversionAddinWindows return new SvnSharpBackend ();
}
- public override string GetPathUrl (FilePath path)
- {
- lock (client) {
- Uri u = client.Value.GetUriFromWorkingCopy (path);
- return u != null ? u.ToString () : null;
- }
- }
-
public override bool IsInstalled
{
get
@@ -69,7 +61,8 @@ namespace SubversionAddinWindows {
string wc_path;
try {
- wc_path = client.Value.GetWorkingCopyRoot (path.FullPath);
+ lock (client.Value)
+ wc_path = client.Value.GetWorkingCopyRoot (path.FullPath);
return wc_path;
} catch (SvnException e) {
switch (e.SvnErrorCode) {
@@ -88,7 +81,7 @@ namespace SubversionAddinWindows get { return SvnSharpClient.client.Value; }
}
- IProgressMonitor updateMonitor;
+ ProgressMonitor updateMonitor;
NotifData notifyData;
ProgressData progressData;
@@ -98,7 +91,8 @@ namespace SubversionAddinWindows try {
// This outputs the contents of the base revision
// of a file to a stream.
- client.Write (new SvnPathTarget (sourcefile), data);
+ lock (client)
+ client.Write (new SvnPathTarget (sourcefile), data);
return TextFile.ReadFile (sourcefile, data).Text;
} catch (SvnIllegalTargetException e) {
// This occurs when we don't have a base file for
@@ -173,13 +167,14 @@ namespace SubversionAddinWindows SslFailure acceptedFailures;
bool save;
- var certInfo = new CertficateInfo ();
- certInfo.AsciiCert = e.CertificateValue;
- certInfo.Fingerprint = e.Fingerprint;
- certInfo.HostName = e.CommonName;
- certInfo.IssuerName = e.Issuer;
- certInfo.ValidFrom = e.ValidFrom;
- certInfo.ValidUntil = e.ValidUntil;
+ var certInfo = new CertficateInfo {
+ AsciiCert = e.CertificateValue,
+ Fingerprint = e.Fingerprint,
+ HostName = e.CommonName,
+ IssuerName = e.Issuer,
+ ValidFrom = e.ValidFrom,
+ ValidUntil = e.ValidUntil,
+ };
e.Cancel = !SslServerTrustAuthenticationPrompt (e.Realm, (SslFailure) (uint) e.Failures, e.MaySave, certInfo, out acceptedFailures, out save);
@@ -205,23 +200,25 @@ namespace SubversionAddinWindows e.CertificateFile = file;
}
- public override void Add (FilePath path, bool recurse, IProgressMonitor monitor)
+ public override void Add (FilePath path, bool recurse, ProgressMonitor monitor)
{
- var args = new SvnAddArgs ();
+ var args = new SvnAddArgs {
+ Depth = recurse ? SvnDepth.Infinity : SvnDepth.Empty,
+ };
BindMonitor (monitor);
- args.Depth = recurse ? SvnDepth.Infinity : SvnDepth.Empty;
lock (client)
client.Add (path, args);
}
- public override void Checkout (string url, FilePath path, Revision rev, bool recurse, IProgressMonitor monitor)
+ public override void Checkout (string url, FilePath path, Revision rev, bool recurse, ProgressMonitor monitor)
{
- var args = new SvnCheckOutArgs ();
+ var args = new SvnCheckOutArgs {
+ Depth = recurse ? SvnDepth.Infinity : SvnDepth.Empty,
+ };
BindMonitor (monitor);
- args.Depth = recurse ? SvnDepth.Infinity : SvnDepth.Empty;
lock (client) {
try {
- client.CheckOut (new SvnUriTarget (url, GetRevision (rev)), path);
+ client.CheckOut (new SvnUriTarget (url, GetRevision (rev)), path, args);
} catch (SvnOperationCanceledException) {
if (Directory.Exists (path.ParentDirectory))
FileService.DeleteDirectory (path.ParentDirectory);
@@ -229,20 +226,22 @@ namespace SubversionAddinWindows }
}
- public override void Commit (FilePath[] paths, string message, IProgressMonitor monitor)
+ public override void Commit (FilePath[] paths, string message, ProgressMonitor monitor)
{
- var args = new SvnCommitArgs ();
+ var args = new SvnCommitArgs {
+ LogMessage = message,
+ };
BindMonitor (monitor);
- args.LogMessage = message;
lock (client)
client.Commit (paths.ToStringArray (), args);
}
- public override void Delete (FilePath path, bool force, IProgressMonitor monitor)
+ public override void Delete (FilePath path, bool force, ProgressMonitor monitor)
{
- var args = new SvnDeleteArgs ();
+ var args = new SvnDeleteArgs {
+ Force = force,
+ };
BindMonitor (monitor);
- args.Force = force;
lock (client)
client.Delete (path, args);
}
@@ -250,7 +249,9 @@ namespace SubversionAddinWindows public override string GetTextAtRevision (string repositoryPath, Revision revision, string rootPath)
{
var ms = new MemoryStream ();
- SvnUriTarget target = client.GetUriFromWorkingCopy (rootPath);
+ SvnUriTarget target;
+ lock (client)
+ target = client.GetUriFromWorkingCopy (rootPath);
// Redo path link.
repositoryPath = repositoryPath.TrimStart (new [] { '/' });
foreach (var segment in target.Uri.Segments) {
@@ -279,7 +280,8 @@ namespace SubversionAddinWindows public override string GetVersion ()
{
- return SvnClient.Version.ToString ();
+ lock (client)
+ return SvnClient.Version.ToString ();
}
public override IEnumerable<DirectoryEntry> ListUrl (string url, bool recurse, SvnRevision rev)
@@ -292,41 +294,42 @@ namespace SubversionAddinWindows return List (new SvnPathTarget (path, GetRevision (rev)), recurse);
}
- IEnumerable<DirectoryEntry> List (SvnTarget target, bool recurse)
+ static IEnumerable<DirectoryEntry> List (SvnTarget target, bool recurse)
{
var list = new List<DirectoryEntry> ();
- var args = new SvnListArgs ();
- args.Depth = recurse ? SvnDepth.Infinity : SvnDepth.Children;
+ var args = new SvnListArgs {
+ Depth = recurse ? SvnDepth.Infinity : SvnDepth.Children,
+ };
lock (client)
client.List (target, args, delegate (object o, SvnListEventArgs a) {
- if (string.IsNullOrEmpty (a.Path))
- return;
- var de = new DirectoryEntry ();
- de.CreatedRevision = ToBaseRevision (a.Entry.Revision).Rev;
- de.HasProps = a.Entry.HasProperties;
- de.IsDirectory = a.Entry.NodeKind == SvnNodeKind.Directory;
- de.LastAuthor = a.Entry.Author;
- de.Name = a.Path;
- de.Size = a.Entry.FileSize;
- de.Time = a.Entry.Time;
- list.Add (de);
- });
+ if (string.IsNullOrEmpty (a.Path))
+ return;
+ list.Add (new DirectoryEntry {
+ CreatedRevision = ToBaseRevision (a.Entry.Revision).Rev,
+ HasProps = a.Entry.HasProperties,
+ IsDirectory = a.Entry.NodeKind == SvnNodeKind.Directory,
+ LastAuthor = a.Entry.Author,
+ Name = a.Path,
+ Size = a.Entry.FileSize,
+ Time = a.Entry.Time,
+ });
+ });
return list;
}
public override IEnumerable<SvnRevision> Log (Repository repo, FilePath path, SvnRevision revisionStart, SvnRevision revisionEnd)
{
var list = new List<SvnRevision> ();
- var args = new SvnLogArgs ();
- args.Range = new SvnRevisionRange (GetRevision (revisionStart), GetRevision (revisionEnd));
+ var args = new SvnLogArgs {
+ Range = new SvnRevisionRange (GetRevision (revisionStart), GetRevision (revisionEnd)),
+ };
lock (client)
client.Log (path, args, delegate (object o, SvnLogEventArgs a) {
var paths = new List<RevisionPath> ();
foreach (SvnChangeItem item in a.ChangedPaths) {
paths.Add (new RevisionPath (item.Path, ConvertRevisionAction (item.Action), ""));
}
- var r = new SvnRevision (repo, (int) a.Revision, a.Time, a.Author, a.LogMessage, paths.ToArray ());
- list.Add (r);
+ list.Add (new SvnRevision (repo, (int) a.Revision, a.Time, a.Author, a.LogMessage, paths.ToArray ()));
});
return list;
}
@@ -342,24 +345,26 @@ namespace SubversionAddinWindows return RevisionAction.Other;
}
- public override void Mkdir (string[] paths, string message, IProgressMonitor monitor)
+ public override void Mkdir (string[] paths, string message, ProgressMonitor monitor)
{
- var args = new SvnCreateDirectoryArgs ();
- args.CreateParents = true;
+ var args = new SvnCreateDirectoryArgs {
+ CreateParents = true,
+ LogMessage = message,
+ };
BindMonitor (monitor);
var uris = new List<Uri> ();
foreach (string path in paths)
uris.Add (new Uri (path));
- args.LogMessage = message;
lock (client)
client.RemoteCreateDirectories (uris, args);
}
- public override void Move (FilePath srcPath, FilePath destPath, SvnRevision rev, bool force, IProgressMonitor monitor)
+ public override void Move (FilePath srcPath, FilePath destPath, SvnRevision rev, bool force, ProgressMonitor monitor)
{
- var args = new SvnMoveArgs ();
+ var args = new SvnMoveArgs {
+ Force = force,
+ };
BindMonitor (monitor);
- args.Force = force;
lock (client)
client.Move (srcPath, destPath, args);
}
@@ -368,27 +373,30 @@ namespace SubversionAddinWindows {
var t1 = new SvnPathTarget (path1, GetRevision (revision1));
var t2 = new SvnPathTarget (path2, GetRevision (revision2));
- var args = new SvnDiffArgs ();
- args.Depth = recursive ? SvnDepth.Infinity : SvnDepth.Children;
- var ms = new MemoryStream ();
- lock (client)
- client.Diff (t1, t2, args, ms);
- ms.Position = 0;
- using (var sr = new StreamReader (ms)) {
- return sr.ReadToEnd ();
+ var args = new SvnDiffArgs {
+ Depth = recursive ? SvnDepth.Infinity : SvnDepth.Children,
+ };
+ using (var ms = new MemoryStream ()) {
+ lock (client)
+ client.Diff (t1, t2, args, ms);
+ ms.Position = 0;
+ using (var sr = new StreamReader (ms)) {
+ return sr.ReadToEnd ();
+ }
}
}
- public override void Revert (FilePath[] paths, bool recurse, IProgressMonitor monitor)
+ public override void Revert (FilePath[] paths, bool recurse, ProgressMonitor monitor)
{
- var args = new SvnRevertArgs ();
+ var args = new SvnRevertArgs {
+ Depth = recurse ? SvnDepth.Infinity : SvnDepth.Children,
+ };
BindMonitor (monitor);
- args.Depth = recurse ? SvnDepth.Infinity : SvnDepth.Children;
lock (client)
client.Revert (paths.ToStringArray (), args);
}
- public override void RevertRevision (FilePath path, Revision revision, IProgressMonitor monitor)
+ public override void RevertRevision (FilePath path, Revision revision, ProgressMonitor monitor)
{
var args = new SvnMergeArgs ();
BindMonitor (monitor);
@@ -398,7 +406,7 @@ namespace SubversionAddinWindows client.Merge (path, new SvnPathTarget (path), range, args);
}
- public override void RevertToRevision (FilePath path, Revision revision, IProgressMonitor monitor)
+ public override void RevertToRevision (FilePath path, Revision revision, ProgressMonitor monitor)
{
var args = new SvnMergeArgs ();
BindMonitor (monitor);
@@ -410,11 +418,12 @@ namespace SubversionAddinWindows public override IEnumerable<VersionInfo> Status (Repository repo, FilePath path, SvnRevision revision, bool descendDirs, bool changedItemsOnly, bool remoteStatus)
{
var list = new List<VersionInfo> ();
- var args = new SvnStatusArgs ();
- args.Revision = GetRevision (revision);
- args.Depth = descendDirs ? SvnDepth.Infinity : SvnDepth.Children;
- args.RetrieveAllEntries = !changedItemsOnly;
- args.RetrieveRemoteStatus = remoteStatus;
+ var args = new SvnStatusArgs {
+ Revision = GetRevision (revision),
+ Depth = descendDirs ? SvnDepth.Infinity : SvnDepth.Children,
+ RetrieveAllEntries = !changedItemsOnly,
+ RetrieveRemoteStatus = remoteStatus,
+ };
lock (client) {
try {
client.Status (path, args, (o, a) => list.Add (CreateVersionInfo (repo, a)));
@@ -497,31 +506,35 @@ namespace SubversionAddinWindows return VersionStatus.Unversioned;
}
- public override void Lock (IProgressMonitor monitor, string comment, bool stealLock, params FilePath[] paths)
+ public override void Lock (ProgressMonitor monitor, string comment, bool stealLock, params FilePath[] paths)
{
- var args = new SvnLockArgs ();
+ var args = new SvnLockArgs {
+ Comment = comment,
+ StealLock = stealLock,
+ };
BindMonitor (monitor);
- args.Comment = comment;
- args.StealLock = stealLock;
lock (client)
client.Lock (paths.ToStringArray (), args);
}
- public override void Unlock (IProgressMonitor monitor, bool breakLock, params FilePath[] paths)
+ public override void Unlock (ProgressMonitor monitor, bool breakLock, params FilePath[] paths)
{
- var args = new SvnUnlockArgs ();
+ var args = new SvnUnlockArgs {
+ BreakLock = breakLock,
+ };
BindMonitor (monitor);
- args.BreakLock = breakLock;
lock (client)
client.Unlock (paths.ToStringArray (), args);
}
- public override void Update (FilePath path, bool recurse, IProgressMonitor monitor)
+ public override void Update (FilePath path, bool recurse, ProgressMonitor monitor)
{
- var args = new SvnUpdateArgs ();
+ var args = new SvnUpdateArgs {
+ Depth = recurse ? SvnDepth.Infinity : SvnDepth.Children,
+ };
BindMonitor (monitor);
- args.Depth = recurse ? SvnDepth.Infinity : SvnDepth.Children;
- client.Update (path, args);
+ lock (client)
+ client.Update (path, args);
}
public override void Ignore (FilePath[] paths)
@@ -556,22 +569,29 @@ namespace SubversionAddinWindows throw new ArgumentNullException ();
var target = new SvnPathTarget (file, SharpSvn.SvnRevision.Base);
- var data = new MemoryStream ();
int numAnnotations = 0;
- client.Write (target, data);
-
- using (var reader = new StreamReader (data)) {
- reader.BaseStream.Seek (0, SeekOrigin.Begin);
- while (reader.ReadLine () != null)
- numAnnotations++;
+ using (var data = new MemoryStream ()) {
+ lock (client)
+ client.Write (target, data);
+
+ using (var reader = new StreamReader (data)) {
+ reader.BaseStream.Seek (0, SeekOrigin.Begin);
+ while (reader.ReadLine () != null)
+ numAnnotations++;
+ }
}
System.Collections.ObjectModel.Collection<SvnBlameEventArgs> list;
- var args = new SvnBlameArgs ();
- args.Start = GetRevision (revStart);
- args.End = GetRevision (revEnd);
+ var args = new SvnBlameArgs {
+ Start = GetRevision (revStart),
+ End = GetRevision (revEnd),
+ };
- if (client.GetBlame (target, args, out list)) {
+ bool success;
+ lock (client) {
+ success = client.GetBlame (target, args, out list);
+ }
+ if (success) {
var annotations = new Annotation [numAnnotations];
foreach (var annotation in list) {
if (annotation.LineNumber < annotations.Length)
@@ -633,7 +653,7 @@ namespace SubversionAddinWindows public int Seconds;
}
- void BindMonitor (IProgressMonitor monitor)
+ void BindMonitor (ProgressMonitor monitor)
{
notifyData = new NotifData ();
progressData = new ProgressData ();
@@ -648,7 +668,7 @@ namespace SubversionAddinWindows return String.Format ("{0:0.00} MBytes", kbytes / 1024.0);
}
- static void ProgressWork (SvnProgressEventArgs e, ProgressData data, IProgressMonitor monitor)
+ static void ProgressWork (SvnProgressEventArgs e, ProgressData data, ProgressMonitor monitor)
{
if (monitor == null)
return;
@@ -685,7 +705,7 @@ namespace SubversionAddinWindows data.LogTimer.Start ();
}
- static void Notify (SvnNotifyEventArgs e, NotifData notifData, IProgressMonitor monitor)
+ static void Notify (SvnNotifyEventArgs e, NotifData notifData, ProgressMonitor monitor)
{
string actiondesc;
string file = e.Path;
diff --git a/main/src/addins/VersionControl/Subversion.Win32/VersionControl.Subversion.Win32.csproj b/main/src/addins/VersionControl/Subversion.Win32/VersionControl.Subversion.Win32.csproj index d635660a89..5a78c6eb76 100644 --- a/main/src/addins/VersionControl/Subversion.Win32/VersionControl.Subversion.Win32.csproj +++ b/main/src/addins/VersionControl/Subversion.Win32/VersionControl.Subversion.Win32.csproj @@ -59,8 +59,11 @@ </PropertyGroup> <ItemGroup> <Reference Include="System" /> - <Reference Include="SharpSvn, Version=1.8005.2778.15501, Culture=neutral, PublicKeyToken=d729672594885a28"> - <HintPath>..\..\..\..\external\sharpsvn-binary\SharpSvn.dll</HintPath> + <Reference Include="SharpSvn"> + <HintPath>..\..\..\..\packages\SharpSvn.1.8-x86.1.8010.3345.53\lib\net40\SharpSvn.dll</HintPath> + </Reference> + <Reference Include="SharpSvn.UI"> + <HintPath>..\..\..\..\packages\SharpSvn.1.8-x86.1.8010.3345.53\lib\net40\SharpSvn.UI.dll</HintPath> </Reference> </ItemGroup> <ItemGroup> @@ -89,13 +92,13 @@ </BootstrapperPackage> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> + <PropertyGroup> + <NuGet>$(SolutionDir)\external\nuget-binary\NuGet.exe</NuGet> + <NuGet Condition="$(OS)=='Unix'">mono $(NuGet)</NuGet> + </PropertyGroup> + <Exec Command="$(NuGet) restore -SolutionDirectory $(SolutionDir)" /> </Target> - <Target Name="AfterBuild"> - </Target> - --> <ItemGroup> <ProjectReference Include="..\..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj"> <Project>{7525BB88-6142-4A26-93B9-A30C6983390A}</Project> @@ -124,13 +127,14 @@ </ProjectReference> </ItemGroup> <ItemGroup> - <None Include="..\..\..\..\external\sharpsvn-binary\SharpPlink-Win32.svnExe"> + <None Include="..\..\..\..\packages\SharpSvn.1.8-x86.1.8010.3345.53\lib\net40\SharpPlink-Win32.svnExe"> <Link>SharpPlink-Win32.svnExe</Link> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> - <None Include="..\..\..\..\external\sharpsvn-binary\SharpSvn-DB44-20-win32.svnDll"> + <None Include="..\..\..\..\packages\SharpSvn.1.8-x86.1.8010.3345.53\lib\net40\SharpSvn-DB44-20-win32.svnDll"> <Link>SharpSvn-DB44-20-win32.svnDll</Link> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> + <None Include="packages.config" /> </ItemGroup> </Project>
\ No newline at end of file diff --git a/main/src/addins/VersionControl/Subversion.Win32/packages.config b/main/src/addins/VersionControl/Subversion.Win32/packages.config new file mode 100644 index 0000000000..eead751a62 --- /dev/null +++ b/main/src/addins/VersionControl/Subversion.Win32/packages.config @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="SharpSvn.1.8-x86" version="1.8010.3345.53" targetFramework="net40" />
+</packages>
\ No newline at end of file diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs index 068c0f69e6..5c548b0128 100644 --- a/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs +++ b/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs @@ -47,8 +47,6 @@ namespace MonoDevelop.Platform {
public class OpenFileDialogHandler : IOpenFileDialogHandler
{
- static int[] encodings;
-
public bool Run (OpenFileDialogData data)
{
var parent = data.TransientFor ?? MessageService.RootWindow;
@@ -96,6 +94,7 @@ namespace MonoDevelop.Platform dialog.Controls.Add (group);
if (IdeApp.Workspace.IsOpen) {
+ viewerCombo.SelectedIndexChanged += (o, e) => closeSolution.Visible = ((ViewerComboItem)viewerCombo.Items[viewerCombo.SelectedIndex]).Viewer == null;
var group2 = new CommonFileDialogGroupBox ();
// "Close current workspace" is too long and splits the text on 2 lines.
@@ -130,7 +129,9 @@ namespace MonoDevelop.Platform if (viewerCombo != null) {
if (closeSolution != null)
data.CloseCurrentWorkspace = closeSolution.Visible && closeSolution.IsChecked;
- data.SelectedViewer = ((ViewerComboItem)viewerCombo.Items [viewerCombo.SelectedIndex]).Viewer;
+ int index = viewerCombo.SelectedIndex;
+ if (index != -1)
+ data.SelectedViewer = ((ViewerComboItem)viewerCombo.Items [index]).Viewer;
}
return true;
@@ -173,39 +174,35 @@ namespace MonoDevelop.Platform int i = 0;
if (showAutoDetected) {
- combo.Items.Add (new EncodingComboItem (-1, GettextCatalog.GetString ("Auto Detected")));
+ combo.Items.Add (new EncodingComboItem (null, GettextCatalog.GetString ("Auto Detected")));
combo.SelectedIndex = 0;
i = 1;
}
- encodings = SelectedEncodings.ConversionEncodings;
- if (encodings == null || encodings.Length == 0)
- encodings = SelectedEncodings.DefaultEncodings;
-
int j = 1;
foreach (var e in TextEncoding.ConversionEncodings) {
- combo.Items.Add (new EncodingComboItem (j++, string.Format ("{0} ({1})", e.Name, e.Id)));
+ combo.Items.Add (new EncodingComboItem (Encoding.GetEncoding (e.CodePage), string.Format ("{0} ({1})", e.Name, e.Id)));
if (selectedEncoding != null && e.CodePage == selectedEncoding.WindowsCodePage)
combo.SelectedIndex = i;
i++;
}
if (combo.SelectedIndex == -1)
combo.SelectedIndex = 0;
- combo.Items.Add (new EncodingComboItem (-1, GettextCatalog.GetString ("Add or Remove...")));
+ combo.Items.Add (new EncodingComboItem (null, GettextCatalog.GetString ("Add or Remove...")));
}
class EncodingComboItem : CommonFileDialogComboBoxItem
{
- int tag;
+ Encoding encoding;
- public EncodingComboItem (int tag, string label) : base (label)
+ public EncodingComboItem (Encoding encoding, string label) : base (label)
{
- this.tag = tag;
+ this.encoding = encoding;
}
public Encoding Encoding {
get {
- return tag <= 0 ? null : Encoding.GetEncoding (encodings [tag - 1]);
+ return encoding;
}
}
}
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/Enums.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/Enums.cs deleted file mode 100644 index 489c9def44..0000000000 --- a/main/src/addins/WindowsPlatform/WindowsPlatform/Enums.cs +++ /dev/null @@ -1,573 +0,0 @@ -// Copyright (c) 2006, Gustavo Franco
-// Email: gustavo_franco@hotmail.com
-// All rights reserved.
-
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-
-// Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-
-// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
-// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
-// PURPOSE. IT CAN BE DISTRIBUTED FREE OF CHARGE AS LONG AS THIS HEADER
-// REMAINS UNCHANGED.
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Runtime.InteropServices;
-
-namespace CustomControls.OS
-{
- #region SWP_Flags
- [Flags]
- public enum SWP_Flags
- {
- SWP_NOSIZE = 0x0001,
- SWP_NOMOVE = 0x0002,
- SWP_NOZORDER = 0x0004,
- SWP_NOACTIVATE = 0x0010,
- SWP_FRAMECHANGED = 0x0020, /* The frame changed: send WM_NCCALCSIZE */
- SWP_SHOWWINDOW = 0x0040,
- SWP_HIDEWINDOW = 0x0080,
- SWP_NOOWNERZORDER = 0x0200, /* Don't do owner Z ordering */
-
- SWP_DRAWFRAME = SWP_FRAMECHANGED,
- SWP_NOREPOSITION = SWP_NOOWNERZORDER
- }
- #endregion
-
- #region DialogChangeStatus
- public enum DialogChangeStatus : long
- {
- CDN_FIRST = 0xFFFFFDA7,
- CDN_INITDONE = (CDN_FIRST - 0x0000),
- CDN_SELCHANGE = (CDN_FIRST - 0x0001),
- CDN_FOLDERCHANGE = (CDN_FIRST - 0x0002),
- CDN_SHAREVIOLATION = (CDN_FIRST - 0x0003),
- CDN_HELP = (CDN_FIRST - 0x0004),
- CDN_FILEOK = (CDN_FIRST - 0x0005),
- CDN_TYPECHANGE = (CDN_FIRST - 0x0006),
- }
- #endregion
-
- #region DialogChangeProperties
- public enum DialogChangeProperties
- {
- CDM_FIRST = (0x400 + 100),
- CDM_GETSPEC = (CDM_FIRST + 0x0000),
- CDM_GETFILEPATH = (CDM_FIRST + 0x0001),
- CDM_GETFOLDERPATH = (CDM_FIRST + 0x0002),
- CDM_GETFOLDERIDLIST = (CDM_FIRST + 0x0003),
- CDM_SETCONTROLTEXT = (CDM_FIRST + 0x0004),
- CDM_HIDECONTROL = (CDM_FIRST + 0x0005),
- CDM_SETDEFEXT = (CDM_FIRST + 0x0006)
- }
- #endregion
-
- #region ImeNotify
- [Author("Franco, Gustavo")]
- public enum ImeNotify
- {
- IMN_CLOSESTATUSWINDOW = 0x0001,
- IMN_OPENSTATUSWINDOW = 0x0002,
- IMN_CHANGECANDIDATE = 0x0003,
- IMN_CLOSECANDIDATE = 0x0004,
- IMN_OPENCANDIDATE = 0x0005,
- IMN_SETCONVERSIONMODE = 0x0006,
- IMN_SETSENTENCEMODE = 0x0007,
- IMN_SETOPENSTATUS = 0x0008,
- IMN_SETCANDIDATEPOS = 0x0009,
- IMN_SETCOMPOSITIONFONT = 0x000A,
- IMN_SETCOMPOSITIONWINDOW = 0x000B,
- IMN_SETSTATUSWINDOWPOS = 0x000C,
- IMN_GUIDELINE = 0x000D,
- IMN_PRIVATE = 0x000E
- }
- #endregion
-
- #region FolderViewMode
- [Author("Franco, Gustavo")]
- public enum FolderViewMode
- {
- Default = 0x7028,
- Icon = Default + 1,
- SmallIcon = Default + 2,
- List = Default + 3,
- Details = Default + 4,
- Thumbnails = Default + 5,
- Title = Default + 6,
- Thumbstrip = Default + 7,
- }
- #endregion
-
- #region Enum DialogViewProperty
- [Author("Franco, Gustavo")]
- public enum DefaultViewType
- {
- Icons = 0x7029,
- List = 0x702b,
- Details = 0x702c,
- Thumbnails = 0x702d,
- Tiles = 0x702e,
- }
- #endregion
-
- #region ButtonStyle
- [Author("Franco, Gustavo")]
- public enum ButtonStyle : long
- {
- BS_PUSHBUTTON = 0x00000000,
- BS_DEFPUSHBUTTON = 0x00000001,
- BS_CHECKBOX = 0x00000002,
- BS_AUTOCHECKBOX = 0x00000003,
- BS_RADIOBUTTON = 0x00000004,
- BS_3STATE = 0x00000005,
- BS_AUTO3STATE = 0x00000006,
- BS_GROUPBOX = 0x00000007,
- BS_USERBUTTON = 0x00000008,
- BS_AUTORADIOBUTTON= 0x00000009,
- BS_PUSHBOX = 0x0000000A,
- BS_OWNERDRAW = 0x0000000B,
- BS_TYPEMASK = 0x0000000F,
- BS_LEFTTEXT = 0x00000020,
- BS_TEXT = 0x00000000,
- BS_ICON = 0x00000040,
- BS_BITMAP = 0x00000080,
- BS_LEFT = 0x00000100,
- BS_RIGHT = 0x00000200,
- BS_CENTER = 0x00000300,
- BS_TOP = 0x00000400,
- BS_BOTTOM = 0x00000800,
- BS_VCENTER = 0x00000C00,
- BS_PUSHLIKE = 0x00001000,
- BS_MULTILINE = 0x00002000,
- BS_NOTIFY = 0x00004000,
- BS_FLAT = 0x00008000,
- BS_RIGHTBUTTON = BS_LEFTTEXT
- }
- #endregion
-
- #region ZOrderPos
- [Author("Franco, Gustavo")]
- public enum ZOrderPos
- {
- HWND_TOP = 0,
- HWND_BOTTOM = 1,
- HWND_TOPMOST = -1,
- HWND_NOTOPMOST = -2
- }
- #endregion
-
- #region Static Control Styles
- [Author("Franco, Gustavo")]
- public enum StaticControlStyles : long
- {
- SS_LEFT = 0x00000000,
- SS_CENTER = 0x00000001,
- SS_RIGHT = 0x00000002,
- SS_ICON = 0x00000003,
- SS_BLACKRECT = 0x00000004,
- SS_GRAYRECT = 0x00000005,
- SS_WHITERECT = 0x00000006,
- SS_BLACKFRAME = 0x00000007,
- SS_GRAYFRAME = 0x00000008,
- SS_WHITEFRAME = 0x00000009,
- SS_USERITEM = 0x0000000A,
- SS_SIMPLE = 0x0000000B,
- SS_LEFTNOWORDWRAP = 0x0000000C,
- SS_OWNERDRAW = 0x0000000D,
- SS_BITMAP = 0x0000000E,
- SS_ENHMETAFILE = 0x0000000F,
- SS_ETCHEDHORZ = 0x00000010,
- SS_ETCHEDVERT = 0x00000011,
- SS_ETCHEDFRAME = 0x00000012,
- SS_TYPEMASK = 0x0000001F,
- SS_REALSIZECONTROL = 0x00000040,
- SS_NOPREFIX = 0x00000080, /* Don't do "&" character translation */
- SS_NOTIFY = 0x00000100,
- SS_CENTERIMAGE = 0x00000200,
- SS_RIGHTJUST = 0x00000400,
- SS_REALSIZEIMAGE = 0x00000800,
- SS_SUNKEN = 0x00001000,
- SS_EDITCONTROL = 0x00002000,
- SS_ENDELLIPSIS = 0x00004000,
- SS_PATHELLIPSIS = 0x00008000,
- SS_WORDELLIPSIS = 0x0000C000,
- SS_ELLIPSISMASK = 0x0000C000
- }
- #endregion
-
- #region Combo Box styles
- [Author("Franco, Gustavo")]
- public enum ComboBoxStyles : long
- {
- CBS_SIMPLE = 0x0001,
- CBS_DROPDOWN = 0x0002,
- CBS_DROPDOWNLIST = 0x0003,
- CBS_OWNERDRAWFIXED = 0x0010,
- CBS_OWNERDRAWVARIABLE = 0x0020,
- CBS_AUTOHSCROLL = 0x0040,
- CBS_OEMCONVERT = 0x0080,
- CBS_SORT = 0x0100,
- CBS_HASSTRINGS = 0x0200,
- CBS_NOINTEGRALHEIGHT = 0x0400,
- CBS_DISABLENOSCROLL = 0x0800,
- CBS_UPPERCASE = 0x2000,
- CBS_LOWERCASE = 0x4000
- }
- #endregion
-
- #region Window Styles
- [Author("Franco, Gustavo")]
- public enum WindowStyles : long
- {
- WS_OVERLAPPED = 0x00000000,
- WS_POPUP = 0x80000000,
- WS_CHILD = 0x40000000,
- WS_MINIMIZE = 0x20000000,
- WS_VISIBLE = 0x10000000,
- WS_DISABLED = 0x08000000,
- WS_CLIPSIBLINGS = 0x04000000,
- WS_CLIPCHILDREN = 0x02000000,
- WS_MAXIMIZE = 0x01000000,
- WS_CAPTION = 0x00C00000,
- WS_BORDER = 0x00800000,
- WS_DLGFRAME = 0x00400000,
- WS_VSCROLL = 0x00200000,
- WS_HSCROLL = 0x00100000,
- WS_SYSMENU = 0x00080000,
- WS_THICKFRAME = 0x00040000,
- WS_GROUP = 0x00020000,
- WS_TABSTOP = 0x00010000,
- WS_MINIMIZEBOX = 0x00020000,
- WS_MAXIMIZEBOX = 0x00010000,
- WS_TILED = 0x00000000,
- WS_ICONIC = 0x20000000,
- WS_SIZEBOX = 0x00040000,
- WS_POPUPWINDOW = 0x80880000,
- WS_OVERLAPPEDWINDOW = 0x00CF0000,
- WS_TILEDWINDOW = 0x00CF0000,
- WS_CHILDWINDOW = 0x40000000
- }
- #endregion
-
- #region Window Extended Styles
- [Author("Franco, Gustavo")]
- [Flags]
- public enum WindowExStyles
- {
- WS_EX_DLGMODALFRAME = 0x00000001,
- WS_EX_NOPARENTNOTIFY = 0x00000004,
- WS_EX_TOPMOST = 0x00000008,
- WS_EX_ACCEPTFILES = 0x00000010,
- WS_EX_TRANSPARENT = 0x00000020,
- WS_EX_MDICHILD = 0x00000040,
- WS_EX_TOOLWINDOW = 0x00000080,
- WS_EX_WINDOWEDGE = 0x00000100,
- WS_EX_CLIENTEDGE = 0x00000200,
- WS_EX_CONTEXTHELP = 0x00000400,
- WS_EX_RIGHT = 0x00001000,
- WS_EX_LEFT = 0x00000000,
- WS_EX_RTLREADING = 0x00002000,
- WS_EX_LTRREADING = 0x00000000,
- WS_EX_LEFTSCROLLBAR = 0x00004000,
- WS_EX_RIGHTSCROLLBAR = 0x00000000,
- WS_EX_CONTROLPARENT = 0x00010000,
- WS_EX_STATICEDGE = 0x00020000,
- WS_EX_APPWINDOW = 0x00040000,
- WS_EX_OVERLAPPEDWINDOW = 0x00000300,
- WS_EX_PALETTEWINDOW = 0x00000188,
- WS_EX_LAYERED = 0x00080000
- }
- #endregion
-
- #region ChildFromPointFlags
- [Author("Franco, Gustavo")]
- public enum ChildFromPointFlags
- {
- CWP_ALL = 0x0000,
- CWP_SKIPINVISIBLE = 0x0001,
- CWP_SKIPDISABLED = 0x0002,
- CWP_SKIPTRANSPARENT = 0x0004
- }
- #endregion
-
- #region HitTest
- [Author("Franco, Gustavo")]
- public enum HitTest
- {
- HTERROR = (-2),
- HTTRANSPARENT = (-1),
- HTNOWHERE = 0,
- HTCLIENT = 1,
- HTCAPTION = 2,
- HTSYSMENU = 3,
- HTGROWBOX = 4,
- HTSIZE = HTGROWBOX,
- HTMENU = 5,
- HTHSCROLL = 6,
- HTVSCROLL = 7,
- HTMINBUTTON = 8,
- HTMAXBUTTON = 9,
- HTLEFT = 10,
- HTRIGHT = 11,
- HTTOP = 12,
- HTTOPLEFT = 13,
- HTTOPRIGHT = 14,
- HTBOTTOM = 15,
- HTBOTTOMLEFT = 16,
- HTBOTTOMRIGHT = 17,
- HTBORDER = 18,
- HTREDUCE = HTMINBUTTON,
- HTZOOM = HTMAXBUTTON,
- HTSIZEFIRST = HTLEFT,
- HTSIZELAST = HTBOTTOMRIGHT,
- HTOBJECT = 19,
- HTCLOSE = 20,
- HTHELP = 21
- }
- #endregion
-
- #region Windows Messages
- [Author("Franco, Gustavo")]
- public enum Msg
- {
- WM_NULL = 0x0000,
- WM_CREATE = 0x0001,
- WM_DESTROY = 0x0002,
- WM_MOVE = 0x0003,
- WM_SIZE = 0x0005,
- WM_ACTIVATE = 0x0006,
- WM_SETFOCUS = 0x0007,
- WM_KILLFOCUS = 0x0008,
- WM_ENABLE = 0x000A,
- WM_SETREDRAW = 0x000B,
- WM_SETTEXT = 0x000C,
- WM_GETTEXT = 0x000D,
- WM_GETTEXTLENGTH = 0x000E,
- WM_PAINT = 0x000F,
- WM_CLOSE = 0x0010,
- WM_QUERYENDSESSION = 0x0011,
- WM_QUIT = 0x0012,
- WM_QUERYOPEN = 0x0013,
- WM_ERASEBKGND = 0x0014,
- WM_SYSCOLORCHANGE = 0x0015,
- WM_ENDSESSION = 0x0016,
- WM_SHOWWINDOW = 0x0018,
- WM_CTLCOLOR = 0x0019,
- WM_WININICHANGE = 0x001A,
- WM_SETTINGCHANGE = 0x001A,
- WM_DEVMODECHANGE = 0x001B,
- WM_ACTIVATEAPP = 0x001C,
- WM_FONTCHANGE = 0x001D,
- WM_TIMECHANGE = 0x001E,
- WM_CANCELMODE = 0x001F,
- WM_SETCURSOR = 0x0020,
- WM_MOUSEACTIVATE = 0x0021,
- WM_CHILDACTIVATE = 0x0022,
- WM_QUEUESYNC = 0x0023,
- WM_GETMINMAXINFO = 0x0024,
- WM_PAINTICON = 0x0026,
- WM_ICONERASEBKGND = 0x0027,
- WM_NEXTDLGCTL = 0x0028,
- WM_SPOOLERSTATUS = 0x002A,
- WM_DRAWITEM = 0x002B,
- WM_MEASUREITEM = 0x002C,
- WM_DELETEITEM = 0x002D,
- WM_VKEYTOITEM = 0x002E,
- WM_CHARTOITEM = 0x002F,
- WM_SETFONT = 0x0030,
- WM_GETFONT = 0x0031,
- WM_SETHOTKEY = 0x0032,
- WM_GETHOTKEY = 0x0033,
- WM_QUERYDRAGICON = 0x0037,
- WM_COMPAREITEM = 0x0039,
- WM_GETOBJECT = 0x003D,
- WM_COMPACTING = 0x0041,
- WM_COMMNOTIFY = 0x0044 ,
- WM_WINDOWPOSCHANGING = 0x0046,
- WM_WINDOWPOSCHANGED = 0x0047,
- WM_POWER = 0x0048,
- WM_COPYDATA = 0x004A,
- WM_CANCELJOURNAL = 0x004B,
- WM_NOTIFY = 0x004E,
- WM_INPUTLANGCHANGEREQUEST = 0x0050,
- WM_INPUTLANGCHANGE = 0x0051,
- WM_TCARD = 0x0052,
- WM_HELP = 0x0053,
- WM_USERCHANGED = 0x0054,
- WM_NOTIFYFORMAT = 0x0055,
- WM_CONTEXTMENU = 0x007B,
- WM_STYLECHANGING = 0x007C,
- WM_STYLECHANGED = 0x007D,
- WM_DISPLAYCHANGE = 0x007E,
- WM_GETICON = 0x007F,
- WM_SETICON = 0x0080,
- WM_NCCREATE = 0x0081,
- WM_NCDESTROY = 0x0082,
- WM_NCCALCSIZE = 0x0083,
- WM_NCHITTEST = 0x0084,
- WM_NCPAINT = 0x0085,
- WM_NCACTIVATE = 0x0086,
- WM_GETDLGCODE = 0x0087,
- WM_SYNCPAINT = 0x0088,
- WM_NCMOUSEMOVE = 0x00A0,
- WM_NCLBUTTONDOWN = 0x00A1,
- WM_NCLBUTTONUP = 0x00A2,
- WM_NCLBUTTONDBLCLK = 0x00A3,
- WM_NCRBUTTONDOWN = 0x00A4,
- WM_NCRBUTTONUP = 0x00A5,
- WM_NCRBUTTONDBLCLK = 0x00A6,
- WM_NCMBUTTONDOWN = 0x00A7,
- WM_NCMBUTTONUP = 0x00A8,
- WM_NCMBUTTONDBLCLK = 0x00A9,
- WM_NCXBUTTONDOWN = 0x00AB,
- WM_NCXBUTTONUP = 0x00AC,
- WM_NCXBUTTONDBLCLK = 0x00AD,
- WM_KEYDOWN = 0x0100,
- WM_KEYUP = 0x0101,
- WM_CHAR = 0x0102,
- WM_DEADCHAR = 0x0103,
- WM_SYSKEYDOWN = 0x0104,
- WM_SYSKEYUP = 0x0105,
- WM_SYSCHAR = 0x0106,
- WM_SYSDEADCHAR = 0x0107,
- WM_KEYLAST = 0x0108,
- WM_IME_STARTCOMPOSITION = 0x010D,
- WM_IME_ENDCOMPOSITION = 0x010E,
- WM_IME_COMPOSITION = 0x010F,
- WM_IME_KEYLAST = 0x010F,
- WM_INITDIALOG = 0x0110,
- WM_COMMAND = 0x0111,
- WM_SYSCOMMAND = 0x0112,
- WM_TIMER = 0x0113,
- WM_HSCROLL = 0x0114,
- WM_VSCROLL = 0x0115,
- WM_INITMENU = 0x0116,
- WM_INITMENUPOPUP = 0x0117,
- WM_MENUSELECT = 0x011F,
- WM_MENUCHAR = 0x0120,
- WM_ENTERIDLE = 0x0121,
- WM_MENURBUTTONUP = 0x0122,
- WM_MENUDRAG = 0x0123,
- WM_MENUGETOBJECT = 0x0124,
- WM_UNINITMENUPOPUP = 0x0125,
- WM_MENUCOMMAND = 0x0126,
- WM_CTLCOLORMSGBOX = 0x0132,
- WM_CTLCOLOREDIT = 0x0133,
- WM_CTLCOLORLISTBOX = 0x0134,
- WM_CTLCOLORBTN = 0x0135,
- WM_CTLCOLORDLG = 0x0136,
- WM_CTLCOLORSCROLLBAR = 0x0137,
- WM_CTLCOLORSTATIC = 0x0138,
- WM_MOUSEMOVE = 0x0200,
- WM_LBUTTONDOWN = 0x0201,
- WM_LBUTTONUP = 0x0202,
- WM_LBUTTONDBLCLK = 0x0203,
- WM_RBUTTONDOWN = 0x0204,
- WM_RBUTTONUP = 0x0205,
- WM_RBUTTONDBLCLK = 0x0206,
- WM_MBUTTONDOWN = 0x0207,
- WM_MBUTTONUP = 0x0208,
- WM_MBUTTONDBLCLK = 0x0209,
- WM_MOUSEWHEEL = 0x020A,
- WM_XBUTTONDOWN = 0x020B,
- WM_XBUTTONUP = 0x020C,
- WM_XBUTTONDBLCLK = 0x020D,
- WM_PARENTNOTIFY = 0x0210,
- WM_ENTERMENULOOP = 0x0211,
- WM_EXITMENULOOP = 0x0212,
- WM_NEXTMENU = 0x0213,
- WM_SIZING = 0x0214,
- WM_CAPTURECHANGED = 0x0215,
- WM_MOVING = 0x0216,
- WM_DEVICECHANGE = 0x0219,
- WM_MDICREATE = 0x0220,
- WM_MDIDESTROY = 0x0221,
- WM_MDIACTIVATE = 0x0222,
- WM_MDIRESTORE = 0x0223,
- WM_MDINEXT = 0x0224,
- WM_MDIMAXIMIZE = 0x0225,
- WM_MDITILE = 0x0226,
- WM_MDICASCADE = 0x0227,
- WM_MDIICONARRANGE = 0x0228,
- WM_MDIGETACTIVE = 0x0229,
- WM_MDISETMENU = 0x0230,
- WM_ENTERSIZEMOVE = 0x0231,
- WM_EXITSIZEMOVE = 0x0232,
- WM_DROPFILES = 0x0233,
- WM_MDIREFRESHMENU = 0x0234,
- WM_IME_SETCONTEXT = 0x0281,
- WM_IME_NOTIFY = 0x0282,
- WM_IME_CONTROL = 0x0283,
- WM_IME_COMPOSITIONFULL = 0x0284,
- WM_IME_SELECT = 0x0285,
- WM_IME_CHAR = 0x0286,
- WM_IME_REQUEST = 0x0288,
- WM_IME_KEYDOWN = 0x0290,
- WM_IME_KEYUP = 0x0291,
- WM_MOUSEHOVER = 0x02A1,
- WM_MOUSELEAVE = 0x02A3,
- WM_CUT = 0x0300,
- WM_COPY = 0x0301,
- WM_PASTE = 0x0302,
- WM_CLEAR = 0x0303,
- WM_UNDO = 0x0304,
- WM_RENDERFORMAT = 0x0305,
- WM_RENDERALLFORMATS = 0x0306,
- WM_DESTROYCLIPBOARD = 0x0307,
- WM_DRAWCLIPBOARD = 0x0308,
- WM_PAINTCLIPBOARD = 0x0309,
- WM_VSCROLLCLIPBOARD = 0x030A,
- WM_SIZECLIPBOARD = 0x030B,
- WM_ASKCBFORMATNAME = 0x030C,
- WM_CHANGECBCHAIN = 0x030D,
- WM_HSCROLLCLIPBOARD = 0x030E,
- WM_QUERYNEWPALETTE = 0x030F,
- WM_PALETTEISCHANGING = 0x0310,
- WM_PALETTECHANGED = 0x0311,
- WM_HOTKEY = 0x0312,
- WM_PRINT = 0x0317,
- WM_PRINTCLIENT = 0x0318,
- WM_THEME_CHANGED = 0x031A,
- WM_HANDHELDFIRST = 0x0358,
- WM_HANDHELDLAST = 0x035F,
- WM_AFXFIRST = 0x0360,
- WM_AFXLAST = 0x037F,
- WM_PENWINFIRST = 0x0380,
- WM_PENWINLAST = 0x038F,
- WM_APP = 0x8000,
- WM_USER = 0x0400,
- WM_REFLECT = WM_USER + 0x1c00
- }
- #endregion
-
- #region SetWindowPosFlags
- [Author("Franco, Gustavo")]
- [Flags]
- public enum SetWindowPosFlags
- {
- SWP_NOSIZE = 0x0001,
- SWP_NOMOVE = 0x0002,
- SWP_NOZORDER = 0x0004,
- SWP_NOREDRAW = 0x0008,
- SWP_NOACTIVATE = 0x0010,
- SWP_FRAMECHANGED = 0x0020,
- SWP_SHOWWINDOW = 0x0040,
- SWP_HIDEWINDOW = 0x0080,
- SWP_NOCOPYBITS = 0x0100,
- SWP_NOOWNERZORDER = 0x0200,
- SWP_NOSENDCHANGING = 0x0400,
- SWP_DRAWFRAME = 0x0020,
- SWP_NOREPOSITION = 0x0200,
- SWP_DEFERERASE = 0x2000,
- SWP_ASYNCWINDOWPOS = 0x4000
- }
- #endregion
-}
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/JumpList.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/JumpList.cs index 3a3a442a92..d2baeebf3e 100644 --- a/main/src/addins/WindowsPlatform/WindowsPlatform/JumpList.cs +++ b/main/src/addins/WindowsPlatform/WindowsPlatform/JumpList.cs @@ -128,7 +128,7 @@ namespace MonoDevelop.Platform continue;
}
- RegistryKey openWithKey = Registry.ClassesRoot.OpenSubKey (Path.Combine (subkey, "OpenWithProgIds"));
+ RegistryKey openWithKey = Registry.ClassesRoot.OpenSubKey (Path.Combine (subkey, "OpenWithProgids"));
if (openWithKey == null) {
continue;
}
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/Win32.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/Win32.cs index d6a21f261e..b6476ea979 100644 --- a/main/src/addins/WindowsPlatform/WindowsPlatform/Win32.cs +++ b/main/src/addins/WindowsPlatform/WindowsPlatform/Win32.cs @@ -24,100 +24,16 @@ using System.Runtime.InteropServices; namespace CustomControls.OS
{
- [Author("Franco, Gustavo")]
public static class Win32
{
- public const uint SHGFI_ICON = 0x100;
- public const uint SHGFI_LARGEICON = 0x0; // 'Large icon
- public const uint SHGFI_SMALLICON = 0x1; // 'Small icon
- public const uint SHGFI_ICONLOCATION = 0x1000;
- public const uint SHGFI_TYPENAME = 0x400;
- public const uint SHGFI_USEFILEATTRIBUTES = 0x10;
- public const uint FILE_ATTRIBUTES_NORMAL = 0x80;
internal const string USER32 = "user32.dll";
internal const string SHELL32 = "shell32.dll";
- internal const string SHLWAPI = "Shlwapi.dll";
+ internal const string SHLWAPI = "Shlwapi.dll";
- #region Delegates
- public delegate bool EnumWindowsCallBack(IntPtr hWnd, int lParam);
- #endregion
-
- #region USER32
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern IntPtr GetParent(IntPtr hWnd);
- [DllImport(Win32.USER32)]
- public static extern int GetDlgCtrlID(IntPtr hWndCtl);
- [DllImport(Win32.USER32, CharSet = CharSet.Auto, ExactSpelling = true)]
- public static extern int MapWindowPoints(IntPtr hWnd, IntPtr hWndTo, ref POINT pt, int cPoints);
- [DllImport(Win32.USER32, SetLastError = true)]
- public static extern bool GetWindowInfo(IntPtr hwnd, out WINDOWINFO pwi);
- [DllImport(Win32.USER32)]
- public static extern void GetWindowText(IntPtr hWnd, StringBuilder param, int length);
- [DllImport(Win32.USER32)]
- public static extern void GetClassName(IntPtr hWnd, StringBuilder param, int length);
- [DllImport(Win32.USER32)]
- public static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowsCallBack lpEnumFunc, int lParam);
- [DllImport(Win32.USER32)]
- public static extern bool EnumWindows(EnumWindowsCallBack lpEnumFunc, int lParam);
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern bool ReleaseCapture();
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern IntPtr SetCapture(IntPtr hWnd);
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern IntPtr ChildWindowFromPointEx(IntPtr hParent, POINT pt, ChildFromPointFlags flags);
- [DllImport(Win32.USER32, EntryPoint = "FindWindowExA", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
- public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
- [DllImport(Win32.USER32)]
- public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern int PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern int PostMessage(IntPtr hWnd, int msg, int wParam, int lParam);
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern int SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, StringBuilder param);
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, char[] chars);
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern IntPtr BeginDeferWindowPos(int nNumWindows);
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern IntPtr DeferWindowPos(IntPtr hWinPosInfo, IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int Width, int Height, SetWindowPosFlags flags);
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern bool EndDeferWindowPos(IntPtr hWinPosInfo);
- [DllImport(Win32.USER32, CharSet = CharSet.Auto)]
- public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int Width, int Height, SetWindowPosFlags flags);
- [DllImport(Win32.USER32)]
- public static extern bool GetWindowRect(IntPtr hwnd, ref RECT rect);
- [DllImport(Win32.USER32)]
- public static extern bool GetClientRect(IntPtr hwnd, ref RECT rect);
- [DllImport(Win32.USER32)]
- public static extern bool DestroyIcon([In] IntPtr hIcon);
- [DllImport(Win32.SHELL32, CharSet = CharSet.Unicode)]
- public static extern IntPtr SHGetFileInfoW([In] string pszPath, uint dwFileAttributes, [In, Out] ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
- #endregion
-
- [DllImport (Win32.SHLWAPI, SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern int AssocQueryStringW (AssociationFlags flags, AssociationString str, string assoc, string extra, StringBuilder outBuffer, ref int outBufferSize);
+ [DllImport (Win32.SHLWAPI, SetLastError = true, CharSet = CharSet.Unicode)]
+ public static extern int AssocQueryStringW (AssociationFlags flags, AssociationString str, string assoc, string extra, StringBuilder outBuffer, ref int outBufferSize);
}
- [AttributeUsage(AttributeTargets.Class |
- AttributeTargets.Enum |
- AttributeTargets.Interface |
- AttributeTargets.Struct,
- AllowMultiple = true)]
- [Author("Franco, Gustavo")]
- internal class AuthorAttribute : Attribute
- {
- #region Constructors
- public AuthorAttribute(string authorName)
- {
- }
- #endregion
- }
-
[Flags]
public enum AssociationFlags {
None = 0x00000000,
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs index 4392189f51..9b6258af8a 100644 --- a/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs +++ b/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs @@ -87,7 +87,7 @@ namespace MonoDevelop.Platform return type ?? base.OnGetMimeTypeForUri (uri); } finally { - typeKey.Close (); + typeKey.Dispose (); } } @@ -103,10 +103,11 @@ namespace MonoDevelop.Platform public Gdk.Pixbuf CreateFromResource (Bitmap bitmap) { - MemoryStream ms = new MemoryStream (); - bitmap.Save (ms, ImageFormat.Png); - ms.Position = 0; - return new Gdk.Pixbuf (ms); + using (var ms = new MemoryStream ()) { + bitmap.Save (ms, ImageFormat.Png); + ms.Position = 0; + return new Gdk.Pixbuf (ms); + } } // Note: we can't reuse RectangleF because the layout is different... @@ -208,7 +209,7 @@ namespace MonoDevelop.Platform return psi; } - public override IProcessAsyncOperation StartConsoleProcess ( + public override ProcessAsyncOperation StartConsoleProcess ( string command, string arguments, string workingDirectory, IDictionary<string, string> environmentVariables, string title, bool pauseWhenFinished) diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.csproj b/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.csproj index 7a34098deb..c23f972d7b 100644 --- a/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.csproj +++ b/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.csproj @@ -87,9 +87,7 @@ <Compile Include="Dialogs\SelectFileDialogHandler.cs" /> <Compile Include="Dialogs\OpenFileDialogHandler.cs" /> <Compile Include="AssemblyInfo.cs" /> - <Compile Include="Enums.cs" /> <Compile Include="GdkWin32.cs" /> - <Compile Include="structs.cs" /> <Compile Include="Win32.cs" /> <Compile Include="WindowsPlatform.cs" /> <Compile Include="RecentFiles.cs" /> diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/structs.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/structs.cs deleted file mode 100644 index b39f00b566..0000000000 --- a/main/src/addins/WindowsPlatform/WindowsPlatform/structs.cs +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (c) 2006, Gustavo Franco
-// Email: gustavo_franco@hotmail.com
-// All rights reserved.
-
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-
-// Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-
-// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
-// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
-// PURPOSE. IT CAN BE DISTRIBUTED FREE OF CHARGE AS LONG AS THIS HEADER
-// REMAINS UNCHANGED.
-
-using System;
-using System.Text;
-using System.Drawing;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-
-namespace CustomControls.OS
-{
- #region WINDOWINFO
- [Author("Franco, Gustavo")]
- [StructLayout(LayoutKind.Sequential)]
- public struct WINDOWINFO
- {
- public UInt32 cbSize;
- public RECT rcWindow;
- public RECT rcClient;
- public UInt32 dwStyle;
- public UInt32 dwExStyle;
- public UInt32 dwWindowStatus;
- public UInt32 cxWindowBorders;
- public UInt32 cyWindowBorders;
- public UInt16 atomWindowType;
- public UInt16 wCreatorVersion;
- }
- #endregion
-
- #region POINT
- [Author("Franco, Gustavo")]
- [StructLayout(LayoutKind.Sequential)]
- public struct POINT
- {
- public int x;
- public int y;
-
- #region Constructors
- public POINT(int x, int y)
- {
- this.x = x;
- this.y = y;
- }
-
- public POINT(Point point)
- {
- x = point.X;
- y = point.Y;
- }
- #endregion
- }
- #endregion
-
- #region RECT
- [Author("Franco, Gustavo")]
- [StructLayout(LayoutKind.Sequential)]
- public struct RECT
- {
- public uint left;
- public uint top;
- public uint right;
- public uint bottom;
-
- #region Properties
- public POINT Location
- {
- get {return new POINT((int) left, (int) top);}
- set
- {
- right -= (left - (uint) value.x);
- bottom -= (bottom - (uint) value.y);
- left = (uint) value.x;
- top = (uint) value.y;
- }
- }
-
- public uint Width
- {
- get {return right - left;}
- set {right = left + value;}
- }
-
- public uint Height
- {
- get {return bottom - top;}
- set {bottom = top + value;}
- }
- #endregion
-
- #region Overrides
- public override string ToString()
- {
- return left + ":" + top + ":" + right + ":" + bottom;
- }
- #endregion
- }
- #endregion
-
- #region WINDOWPOS
- [Author("Franco, Gustavo")]
- [StructLayout(LayoutKind.Sequential)]
- public struct WINDOWPOS
- {
- public IntPtr hwnd;
- public IntPtr hwndAfter;
- public int x;
- public int y;
- public int cx;
- public int cy;
- public uint flags;
-
- #region Overrides
- public override string ToString()
- {
- return x + ":" + y + ":" + cx + ":" + cy + ":" + ((SWP_Flags) flags).ToString();
- }
- #endregion
- }
- #endregion
-
- #region NCCALCSIZE_PARAMS
- public struct NCCALCSIZE_PARAMS
- {
- public RECT rgrc1;
- public RECT rgrc2;
- public RECT rgrc3;
- public IntPtr lppos;
- }
- #endregion
-
- #region
- public struct NMHDR
- {
- public IntPtr hwndFrom;
- public IntPtr idFrom;
- public uint code;
- }
- #endregion
-
- #region OFNOTIFY
- [Author("Franco, Gustavo")]
- [StructLayout(LayoutKind.Sequential)]
- public struct OFNOTIFY
- {
- public NMHDR hdr;
- public IntPtr OPENFILENAME;
- public IntPtr fileNameShareViolation;
- }
- #endregion
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct SHFILEINFO
- {
- public IntPtr hIcon;
- public int iIcon;
- public uint dwAttributes;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
- public string szDisplayName;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
- public string szTypeName;
- };
-}
diff --git a/main/src/addins/Xml/Editor/BaseXmlEditorExtension.cs b/main/src/addins/Xml/Editor/BaseXmlEditorExtension.cs index 4a1f05cd07..f0395d0aea 100644 --- a/main/src/addins/Xml/Editor/BaseXmlEditorExtension.cs +++ b/main/src/addins/Xml/Editor/BaseXmlEditorExtension.cs @@ -61,7 +61,7 @@ namespace MonoDevelop.Xml.Editor MonoDevelop.Ide.Gui.Components.PadTreeView outlineTreeView; TreeStore outlineTreeStore; - List<DotNetProject> ownerProjects; + List<DotNetProject> ownerProjects = new List<DotNetProject> (); #region Setup and teardown @@ -80,7 +80,12 @@ namespace MonoDevelop.Xml.Editor { base.Initialize (); - UpdateOwnerProjects (); + // Delay the execution of UpdateOwnerProjects since it may end calling Document.AttachToProject, + // which shouldn't be called while the extension chain is being initialized. + // TODO: Move handling of owner projects to Document + Application.Invoke (delegate { + UpdateOwnerProjects (); + }); var parser = new XmlParser (CreateRootState (), false); tracker = new DocumentStateTracker<XmlParser> (parser, Editor); @@ -110,7 +115,7 @@ namespace MonoDevelop.Xml.Editor ownerProjects = new List<DotNetProject> (); return; } - var projects = new HashSet<DotNetProject> (IdeApp.Workspace.GetAllSolutionItems<DotNetProject> ().Where (p => p.IsFileInProject (Document.FileName))); + var projects = new HashSet<DotNetProject> (IdeApp.Workspace.GetAllItems<DotNetProject> ().Where (p => p.IsFileInProject (Document.FileName))); if (ownerProjects == null || !projects.SetEquals (ownerProjects)) { ownerProjects = projects.OrderBy (p => p.Name).ToList (); var dnp = Document.Project as DotNetProject; @@ -827,8 +832,11 @@ namespace MonoDevelop.Xml.Editor void UpdatePath () { - List<XObject> l = GetCurrentPath (); + //update timeout could get called after disposed + if (tracker == null) + return; + List<XObject> l = GetCurrentPath (); //build the list var path = new List<PathEntry> (); diff --git a/main/src/addins/Xml/Editor/XmlEditorService.cs b/main/src/addins/Xml/Editor/XmlEditorService.cs index 513b2e7458..c5b0f82730 100644 --- a/main/src/addins/Xml/Editor/XmlEditorService.cs +++ b/main/src/addins/Xml/Editor/XmlEditorService.cs @@ -57,7 +57,7 @@ namespace MonoDevelop.Xml.Editor error.IsWarning = false; //Task task = new Task(fileName, message, column, line); - Task task = new Task (error); + UserTask task = new UserTask (error); TaskService.Errors.Add(task);
}
#endregion
@@ -100,7 +100,7 @@ namespace MonoDevelop.Xml.Editor } }*/ - public static IProgressMonitor GetMonitor () + public static ProgressMonitor GetMonitor () { return IdeApp.Workbench.ProgressMonitors.GetOutputProgressMonitor ("XML", "md-xml-file-icon", true, true); }
@@ -198,7 +198,7 @@ namespace MonoDevelop.Xml.Editor /// <summary>
/// Checks that the xml in this view is well-formed.
/// </summary>
- public static XmlDocument ValidateWellFormedness (IProgressMonitor monitor, string xml, string fileName) + public static XmlDocument ValidateWellFormedness (ProgressMonitor monitor, string xml, string fileName) {
monitor.BeginTask (GettextCatalog.GetString ("Validating XML..."), 1); bool error = false;
@@ -227,7 +227,7 @@ namespace MonoDevelop.Xml.Editor /// <summary>
/// Validates the xml against known schemas.
/// </summary> - public static XmlDocument ValidateXml (IProgressMonitor monitor, string xml, string fileName) + public static XmlDocument ValidateXml (ProgressMonitor monitor, string xml, string fileName) { monitor.BeginTask (GettextCatalog.GetString ("Validating XML..."), 1); bool error = false;
@@ -293,7 +293,7 @@ namespace MonoDevelop.Xml.Editor /// <summary>
/// Validates the schema.
/// </summary> - public static XmlSchema ValidateSchema (IProgressMonitor monitor, string xml, string fileName) + public static XmlSchema ValidateSchema (ProgressMonitor monitor, string xml, string fileName) { monitor.BeginTask (GettextCatalog.GetString ("Validating schema..."), 1); bool error = false;
@@ -341,7 +341,7 @@ namespace MonoDevelop.Xml.Editor return error? null: schema;
}
- public static XslCompiledTransform ValidateStylesheet (IProgressMonitor monitor, string xml, string fileName)
+ public static XslCompiledTransform ValidateStylesheet (ProgressMonitor monitor, string xml, string fileName)
{
monitor.BeginTask (GettextCatalog.GetString ("Validating stylesheet..."), 1); bool error = true;
diff --git a/main/src/addins/Xml/Editor/XmlTextEditorExtension.cs b/main/src/addins/Xml/Editor/XmlTextEditorExtension.cs index a9dcf1d6b3..36685f8fa2 100644 --- a/main/src/addins/Xml/Editor/XmlTextEditorExtension.cs +++ b/main/src/addins/Xml/Editor/XmlTextEditorExtension.cs @@ -503,7 +503,7 @@ namespace MonoDevelop.Xml.Editor try {
TaskService.Errors.Clear ();
string xml = Editor.Text; - using (IProgressMonitor monitor = XmlEditorService.GetMonitor ()) { + using (ProgressMonitor monitor = XmlEditorService.GetMonitor ()) { XmlDocument doc = XmlEditorService.ValidateWellFormedness (monitor, xml, FileName); if (doc == null) return; @@ -570,7 +570,7 @@ namespace MonoDevelop.Xml.Editor public void ValidateCommand () { TaskService.Errors.Clear (); - using (IProgressMonitor monitor = XmlEditorService.GetMonitor()) { + using (ProgressMonitor monitor = XmlEditorService.GetMonitor()) { if (IsSchema) XmlEditorService.ValidateSchema (monitor, Editor.Text, FileName); else
@@ -596,7 +596,7 @@ namespace MonoDevelop.Xml.Editor return; } - using (IProgressMonitor monitor = XmlEditorService.GetMonitor()) { + using (ProgressMonitor monitor = XmlEditorService.GetMonitor()) { try { string xsltContent; try { diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/EmacsWordFindStrategy.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/EmacsWordFindStrategy.cs index 06eb0fb1ca..7272c56432 100644 --- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/EmacsWordFindStrategy.cs +++ b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/EmacsWordFindStrategy.cs @@ -34,11 +34,11 @@ namespace Mono.TextEditor { public class EmacsWordFindStrategy : WordFindStrategy {
- bool treat_;
+ bool includeUnderscore;
- public EmacsWordFindStrategy (bool treat_)
+ public EmacsWordFindStrategy (bool includeUnderscore = true)
{
- this.treat_ = treat_;
+ this.includeUnderscore = includeUnderscore;
}
int FindNextWordOffset (TextDocument doc, int offset, bool subword) @@ -46,11 +46,11 @@ namespace Mono.TextEditor if (offset + 1 >= doc.TextLength) return doc.TextLength; int result = offset + 1;
- CC previous = SW.GetCharacterClass (doc.GetCharAt (result), subword, treat_);
+ CC previous = SW.GetCharacterClass (doc.GetCharAt (result), subword, includeUnderscore);
bool inIndentifier = previous != CC.Unknown && previous != CC.Whitespace;
while (result < doc.TextLength) { char ch = doc.GetCharAt (result);
- CC current = SW.GetCharacterClass (ch, subword, treat_);
+ CC current = SW.GetCharacterClass (ch, subword, includeUnderscore);
//camelCase / PascalCase splitting
if (subword) {
@@ -61,7 +61,7 @@ namespace Mono.TextEditor } else if (current == CC.UppercaseLetter && previous != CC.UppercaseLetter) {
break;
} else if (current == CC.LowercaseLetter && previous == CC.UppercaseLetter && result - 2 > 0
- && SW.GetCharacterClass (doc.GetCharAt (result - 2), subword, treat_) != CC.LowercaseLetter)
+ && SW.GetCharacterClass (doc.GetCharAt (result - 2), subword, includeUnderscore) != CC.LowercaseLetter)
{
result--;
break;
@@ -90,11 +90,11 @@ namespace Mono.TextEditor if (offset <= 0) return 0; int result = offset - 1; - CC previous = SW.GetCharacterClass (doc.GetCharAt (result), subword, treat_);
+ CC previous = SW.GetCharacterClass (doc.GetCharAt (result), subword, includeUnderscore);
bool inIndentifier = previous != CC.Unknown && previous != CC.Whitespace;
while (result > 0) { char ch = doc.GetCharAt (result);
- CC current = SW.GetCharacterClass (ch, subword, treat_);
+ CC current = SW.GetCharacterClass (ch, subword, includeUnderscore);
//camelCase / PascalCase splitting
if (subword) {
@@ -107,7 +107,7 @@ namespace Mono.TextEditor } else if (current == CC.UppercaseLetter && previous != CC.UppercaseLetter) {
break;
} else if (current == CC.LowercaseLetter && previous == CC.UppercaseLetter && result + 2 < doc.TextLength
- && SW.GetCharacterClass (doc.GetCharAt (result + 2), subword, treat_) != CC.LowercaseLetter)
+ && SW.GetCharacterClass (doc.GetCharAt (result + 2), subword, includeUnderscore) != CC.LowercaseLetter)
{
result++;
break;
diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/IWordFindStrategy.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/IWordFindStrategy.cs index 0ebf5c8781..58d26955a7 100644 --- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/IWordFindStrategy.cs +++ b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/IWordFindStrategy.cs @@ -56,7 +56,7 @@ namespace Mono.TextEditor return GetCharacterClass (ch, false, false); } - public static CharacterClass GetCharacterClass (char ch, bool subword, bool treat_) + public static CharacterClass GetCharacterClass (char ch, bool subword, bool includeUnderscore) { if (Char.IsWhiteSpace (ch)) return CharacterClass.Whitespace; @@ -70,7 +70,7 @@ namespace Mono.TextEditor else return CharacterClass.LowercaseLetter; } - if (!subword && treat_ && ch == '_') + if (!subword && includeUnderscore && ch == '_') return CharacterClass.IdentifierPart; return CharacterClass.Unknown; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/DefaultExecutionHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/DefaultExecutionHandler.cs index e56f71e714..7cac46b2a8 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/DefaultExecutionHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/DefaultExecutionHandler.cs @@ -37,7 +37,7 @@ namespace MonoDevelop.Core.Execution return Runtime.ProcessService.GetDefaultExecutionHandler (command) != null; } - public IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) + public ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) { IExecutionHandler handler = Runtime.ProcessService.GetDefaultExecutionHandler (command); return handler.Execute (command, console); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/DotNetExecutionHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/DotNetExecutionHandler.cs index da3985afa5..c4a2dd0790 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/DotNetExecutionHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/DotNetExecutionHandler.cs @@ -35,7 +35,7 @@ namespace MonoDevelop.Core.Execution return command is DotNetExecutionCommand; } - public IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) + public ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) { DotNetExecutionCommand cmd = (DotNetExecutionCommand) command; if (cmd.TargetRuntime == null) diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/IExecutionHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/IExecutionHandler.cs index a0a1c7b6d0..fe12bceeb8 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/IExecutionHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/IExecutionHandler.cs @@ -28,6 +28,7 @@ using System; using System.Collections.Generic; +using System.Threading; namespace MonoDevelop.Core.Execution { @@ -56,6 +57,6 @@ namespace MonoDevelop.Core.Execution /// <param name='console'> /// Console where to log the output /// </param> - IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console); + ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console); } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/MonoPlatformExecutionHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/MonoPlatformExecutionHandler.cs index a164a13508..42451c68f2 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/MonoPlatformExecutionHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/MonoPlatformExecutionHandler.cs @@ -44,7 +44,7 @@ namespace MonoDevelop.Core.Execution this.monoPath = monoPath; } - public override IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) + public override ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) { DotNetExecutionCommand dotcmd = (DotNetExecutionCommand) command; diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/NativePlatformExecutionHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/NativePlatformExecutionHandler.cs index 6783653e3a..8c429a80ae 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/NativePlatformExecutionHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/NativePlatformExecutionHandler.cs @@ -45,7 +45,7 @@ namespace MonoDevelop.Core.Execution this.defaultEnvironmentVariables = defaultEnvironmentVariables; } - public virtual IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) + public virtual ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) { ProcessExecutionCommand cmd = (ProcessExecutionCommand) command; IDictionary<string, string> vars; diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/IProcessAsyncOperation.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessAsyncOperation.cs index 977ea67c7c..1cdeadd47f 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/IProcessAsyncOperation.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessAsyncOperation.cs @@ -29,25 +29,34 @@ using System; using MonoDevelop.Core; using MonoDevelop.Core.ProgressMonitoring; +using System.Threading.Tasks; +using System.Threading; namespace MonoDevelop.Core.Execution { - public interface IProcessAsyncOperation: IAsyncOperation, IDisposable + public class ProcessAsyncOperation: AsyncOperation { - int ExitCode { get; } + protected ProcessAsyncOperation () + { + } + + public ProcessAsyncOperation (Task task, CancellationTokenSource cancellationTokenSource): base (task, cancellationTokenSource) + { + } + + public int ExitCode { get; set; } - int ProcessId { get; } + public int ProcessId { get; set; } } - public class NullProcessAsyncOperation : NullAsyncOperation, IProcessAsyncOperation + public class NullProcessAsyncOperation : ProcessAsyncOperation { - public NullProcessAsyncOperation (bool success) : base (success, false) {} - public int ExitCode { get { return ((IAsyncOperation)this).Success? 0 : 1; } } - public int ProcessId { get { return 0; } } - - void IDisposable.Dispose () {} - - public new static NullProcessAsyncOperation Success = new NullProcessAsyncOperation (true); - public new static NullProcessAsyncOperation Failure = new NullProcessAsyncOperation (false); + public NullProcessAsyncOperation (int exitCode) + { + ExitCode = exitCode; + } + + public static NullProcessAsyncOperation Success = new NullProcessAsyncOperation (0); + public static NullProcessAsyncOperation Failure = new NullProcessAsyncOperation (1); } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessHostController.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessHostController.cs index 11be57b373..e22d48cba8 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessHostController.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessHostController.cs @@ -50,7 +50,7 @@ namespace MonoDevelop.Core.Execution DateTime lastReleaseTime; bool starting; bool stopping; - IProcessAsyncOperation process; + ProcessAsyncOperation process; Timer timer; string id; IExecutionHandler executionHandlerFactory; @@ -130,10 +130,10 @@ namespace MonoDevelop.Core.Execution cmd.UserAssemblyPaths = userAssemblyPaths; cmd.DebugMode = isDebugMode; ProcessHostConsole cons = new ProcessHostConsole (); - process = executionHandlerFactory.Execute (cmd, cons); + var p = process = executionHandlerFactory.Execute (cmd, cons); Counters.ExternalHostProcesses++; - process.Completed += ProcessExited; + process.Task.ContinueWith ((t) => ProcessExited (p)); } catch (Exception ex) { if (tmpFile != null) { @@ -155,7 +155,7 @@ namespace MonoDevelop.Core.Execution } } - void ProcessExited (IAsyncOperation oper) + void ProcessExited (ProcessAsyncOperation oper) { lock (this) { @@ -307,7 +307,7 @@ namespace MonoDevelop.Core.Execution void WaitTimeout (object sender, System.Timers.ElapsedEventArgs args) { try { - IProcessAsyncOperation oldProcess; + ProcessAsyncOperation oldProcess; lock (this) { if (references > 0) { @@ -395,75 +395,4 @@ namespace MonoDevelop.Core.Execution { } } - - class InernalProcessHost: Process, IProcessAsyncOperation - { - object doneLock = new object (); - bool finished; - OperationHandler completed; - - public InernalProcessHost () - { - Exited += delegate { - lock (doneLock) { - finished = true; - Monitor.PulseAll (doneLock); - if (completed != null) - completed (this); - } - }; - } - - public int ProcessId { - get { return Id; } - } - - public event OperationHandler Completed { - add { - lock (doneLock) { - completed += value; - if (finished) - value (this); - } - } - remove { - lock (doneLock) { - completed -= value; - } - } - } - - public void Cancel () - { - Kill (); - } - - public void WaitForCompleted () - { - lock (doneLock) { - while (!finished) - Monitor.Wait (doneLock); - } - } - - public bool IsCompleted { - get { - lock (doneLock) { - return finished; - } - } - } - - public bool Success { - get { - return true; - } - } - - public bool SuccessWithWarnings { - get { - return true; - } - } - } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessService.cs index b88803792d..94e679d891 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessService.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessService.cs @@ -155,15 +155,9 @@ namespace MonoDevelop.Core.Execution // p.Exited += exited; // p.EnableRaisingEvents = true; - if (exited != null) { - MonoDevelop.Core.OperationHandler handler = null; - handler = delegate (MonoDevelop.Core.IAsyncOperation op) { - op.Completed -= handler; - exited (p, EventArgs.Empty); - }; - ((MonoDevelop.Core.IAsyncOperation)p).Completed += handler; - } - + if (exited != null) + p.Task.ContinueWith (t => exited (p, EventArgs.Empty)); + Counters.ProcessesStarted++; p.Start (); return p; @@ -194,13 +188,13 @@ namespace MonoDevelop.Core.Execution return startInfo; } - public IProcessAsyncOperation StartConsoleProcess (string command, string arguments, string workingDirectory, IConsole console, + public ProcessAsyncOperation StartConsoleProcess (string command, string arguments, string workingDirectory, IConsole console, EventHandler exited) { return StartConsoleProcess (command, arguments, workingDirectory, null, console, exited); } - public IProcessAsyncOperation StartConsoleProcess (string command, string arguments, string workingDirectory, + public ProcessAsyncOperation StartConsoleProcess (string command, string arguments, string workingDirectory, IDictionary<string, string> environmentVariables, IConsole console, EventHandler exited) { if ((console == null || (console is ExternalConsole)) && externalConsoleHandler != null) { @@ -218,11 +212,8 @@ namespace MonoDevelop.Core.Execution console != null ? !console.CloseOnDispose : false); if (p != null) { - if (exited != null) { - p.Completed += delegate { - exited (p, EventArgs.Empty); - }; - } + if (exited != null) + p.Task.ContinueWith (t => exited (p, EventArgs.Empty)); Counters.ProcessesStarted++; return p; } else { @@ -234,8 +225,8 @@ namespace MonoDevelop.Core.Execution foreach (KeyValuePair<string, string> kvp in environmentVariables) psi.EnvironmentVariables [kvp.Key] = kvp.Value; ProcessWrapper pw = StartProcess (psi, console.Out, console.Error, null); - new ProcessMonitor (console, pw, exited); - return pw; + new ProcessMonitor (console, pw.ProcessAsyncOperation, exited); + return pw.ProcessAsyncOperation; } public IExecutionHandler GetDefaultExecutionHandler (ExecutionCommand command) @@ -420,22 +411,22 @@ namespace MonoDevelop.Core.Execution { public IConsole console; EventHandler exited; - IProcessAsyncOperation operation; + ProcessAsyncOperation operation; - public ProcessMonitor (IConsole console, IProcessAsyncOperation operation, EventHandler exited) + public ProcessMonitor (IConsole console, ProcessAsyncOperation operation, EventHandler exited) { this.exited = exited; this.operation = operation; this.console = console; - operation.Completed += new OperationHandler (OnOperationCompleted); - console.CancelRequested += new EventHandler (OnCancelRequest); + operation.Task.ContinueWith (t => OnOperationCompleted ()); + console.CancelRequested += OnCancelRequest; } - public void OnOperationCompleted (IAsyncOperation op) + public void OnOperationCompleted () { try { if (exited != null) - exited (op, null); + exited (operation, EventArgs.Empty); if (!Platform.IsWindows && Mono.Unix.Native.Syscall.WIFSIGNALED (operation.ExitCode)) console.Log.WriteLine (GettextCatalog.GetString ("The application was terminated by a signal: {0}"), Mono.Unix.Native.Syscall.WTERMSIG (operation.ExitCode)); @@ -451,7 +442,7 @@ namespace MonoDevelop.Core.Execution operation.Cancel (); //remove the cancel handler, it will be attached again when StartConsoleProcess is called - console.CancelRequested -= new EventHandler (OnCancelRequest); + console.CancelRequested -= OnCancelRequest; } } @@ -475,5 +466,5 @@ namespace MonoDevelop.Core.Execution } } - public delegate IProcessAsyncOperation ExternalConsoleHandler (string command, string arguments, string workingDirectory, IDictionary<string, string> environmentVariables, string title, bool pauseWhenFinished); + public delegate ProcessAsyncOperation ExternalConsoleHandler (string command, string arguments, string workingDirectory, IDictionary<string, string> environmentVariables, string title, bool pauseWhenFinished); } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessWrapper.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessWrapper.cs index a5f121882e..2aa4f7d099 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessWrapper.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessWrapper.cs @@ -2,36 +2,47 @@ using System; using System.Threading; using System.Diagnostics; +using System.Threading.Tasks; namespace MonoDevelop.Core.Execution { public delegate void ProcessEventHandler(object sender, string message); [System.ComponentModel.DesignerCategory ("Code")] - public class ProcessWrapper : Process, IProcessAsyncOperation + public class ProcessWrapper : Process { - private Thread captureOutputThread; private Thread captureErrorThread; ManualResetEvent endEventOut = new ManualResetEvent (false); ManualResetEvent endEventErr = new ManualResetEvent (false); bool done; object lockObj = new object (); + Task task; + ProcessAsyncOperation operation; + IDisposable customCancelToken; public ProcessWrapper () { } - public bool CancelRequested { get; private set; }
- + public bool CancelRequested { get; private set; } + + public Task Task { + get { return task; } + } + + public ProcessAsyncOperation ProcessAsyncOperation { + get { return operation; } + } + public new void Start () { CheckDisposed (); base.Start (); - - captureOutputThread = new Thread (new ThreadStart(CaptureOutput)); - captureOutputThread.Name = "Process output reader"; - captureOutputThread.IsBackground = true; - captureOutputThread.Start (); - + + task = Task.Factory.StartNew (CaptureOutput, TaskCreationOptions.LongRunning); + var cs = new CancellationTokenSource (); + operation = new ProcessAsyncOperation (task, cs); + cs.Token.Register (Cancel); + if (ErrorStreamChanged != null) { captureErrorThread = new Thread (new ThreadStart(CaptureError)); captureErrorThread.Name = "Process error reader"; @@ -40,6 +51,12 @@ namespace MonoDevelop.Core.Execution } else { endEventErr.Set (); } + operation.ProcessId = Id; + } + + public void SetCancellationToken (CancellationToken cancelToken) + { + customCancelToken = cancelToken.Register (Cancel); } public void WaitForOutput (int milliseconds) @@ -56,6 +73,7 @@ namespace MonoDevelop.Core.Execution private void CaptureOutput () { + Thread.CurrentThread.Name = "Process output reader"; try { if (OutputStreamChanged != null) { char[] buffer = new char [1024]; @@ -74,6 +92,9 @@ namespace MonoDevelop.Core.Execution if (endEventErr != null) endEventErr.WaitOne (); + if (HasExited) + operation.ExitCode = ExitCode; + OnExited (this, EventArgs.Empty); lock (lockObj) { @@ -108,9 +129,9 @@ namespace MonoDevelop.Core.Execution return; if (!done) - ((IAsyncOperation)this).Cancel (); + Cancel (); - captureOutputThread = captureErrorThread = null; + captureErrorThread = null; endEventOut.Close (); endEventErr.Close (); endEventOut = endEventErr = null; @@ -132,15 +153,7 @@ namespace MonoDevelop.Core.Execution throw new ObjectDisposedException ("ProcessWrapper"); } - int IProcessAsyncOperation.ExitCode { - get { return ExitCode; } - } - - int IProcessAsyncOperation.ProcessId { - get { return Id; } - } - - void IAsyncOperation.Cancel () + public void Cancel () { try { if (!done) { @@ -156,13 +169,12 @@ namespace MonoDevelop.Core.Execution } } - void IAsyncOperation.WaitForCompleted () - { - WaitForOutput (); - } - void OnExited (object sender, EventArgs args) { + if (customCancelToken != null) { + customCancelToken.Dispose (); + customCancelToken = null; + } try { if (!HasExited) WaitForExit (); @@ -171,49 +183,10 @@ namespace MonoDevelop.Core.Execution } finally { lock (lockObj) { done = true; - try { - if (completedEvent != null) - completedEvent (this); - } catch { - // Ignore - } } } } - event OperationHandler IAsyncOperation.Completed { - add { - bool raiseNow = false; - lock (lockObj) { - if (done) - raiseNow = true; - else - completedEvent += value; - } - if (raiseNow) - value (this); - } - remove { - lock (lockObj) { - completedEvent -= value; - } - } - } - - bool IAsyncOperation.Success { - get { return done ? ExitCode == 0 : false; } - } - - bool IAsyncOperation.SuccessWithWarnings { - get { return false; } - } - - bool IAsyncOperation.IsCompleted { - get { return done; } - } - - event OperationHandler completedEvent; - public event ProcessEventHandler OutputStreamChanged; public event ProcessEventHandler ErrorStreamChanged; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.FileSystem/DefaultFileSystemExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.FileSystem/DefaultFileSystemExtension.cs index c6667cd16b..ac77a0bb22 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.FileSystem/DefaultFileSystemExtension.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.FileSystem/DefaultFileSystemExtension.cs @@ -97,7 +97,7 @@ namespace MonoDevelop.Core.FileSystem public override void MoveDirectory (FilePath source, FilePath dest) { - Directory.Move (source, dest); + FileService.SystemDirectoryRename (source, dest); } public override void DeleteDirectory (FilePath path) diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/Counter.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/Counter.cs index 11ce9e69ad..5036c77e7a 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/Counter.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/Counter.cs @@ -35,6 +35,7 @@ namespace MonoDevelop.Core.Instrumentation { internal int count; int totalCount; + int lastStoredCount; string name; bool logMessages; CounterCategory category; @@ -45,8 +46,9 @@ namespace MonoDevelop.Core.Instrumentation bool disposed; bool storeValues; bool enabled; + string id; - List<IInstrumentationConsumer> handlers = new List<IInstrumentationConsumer> (); + List<InstrumentationConsumer> handlers = new List<InstrumentationConsumer> (); public bool StoreValues { get { @@ -56,14 +58,22 @@ namespace MonoDevelop.Core.Instrumentation storeValues = value; } } + + public bool Enabled { + get { return enabled; } + } - internal List<IInstrumentationConsumer> Handlers { - get { return handlers; } + internal List<InstrumentationConsumer> Handlers { + get { + InstrumentationService.InitializeHandlers (); + return handlers; + } } internal void UpdateStatus () { - enabled = InstrumentationService.Enabled || handlers.Count > 0; + InstrumentationService.InitializeHandlers (); + enabled = InstrumentationService.Enabled || Handlers.Count > 0; storeValues = InstrumentationService.Enabled; } @@ -76,6 +86,11 @@ namespace MonoDevelop.Core.Instrumentation public string Name { get { return name; } } + + public string Id { + get { return id ?? Name; } + internal set { id = value; } + } public CounterCategory Category { get { return category; } @@ -182,19 +197,29 @@ namespace MonoDevelop.Core.Instrumentation } } - internal int StoreValue (string message, TimerTraceList traces) + internal int StoreValue (string message, TimeCounter timer) { DateTime now = DateTime.Now; if (resolution.Ticks != 0) { if (now - lastValueTime < resolution) return -1; } - var val = new CounterValue (count, totalCount, now, message, traces); + var val = new CounterValue (count, totalCount, count - lastStoredCount, now, message, timer != null ? timer.TraceList : null); + lastStoredCount = count; + if (storeValues) values.Add (val); - if (handlers.Count > 0) { - foreach (var h in handlers) - h.ConsumeValue (this, val); + if (Handlers.Count > 0) { + if (timer != null) { + foreach (var h in handlers) { + var t = h.BeginTimer ((TimerCounter)this, val); + if (t != null) + timer.AddHandlerTracker (t); + } + } else { + foreach (var h in handlers) + h.ConsumeValue (this, val); + } } return values.Count - 1; } @@ -322,6 +347,7 @@ namespace MonoDevelop.Core.Instrumentation { int value; int totalCount; + int change; DateTime timestamp; string message; TimerTraceList traces; @@ -335,15 +361,17 @@ namespace MonoDevelop.Core.Instrumentation this.message = null; traces = null; threadId = 0; + change = 0; } - internal CounterValue (int value, int totalCount, DateTime timestamp, string message, TimerTraceList traces) + internal CounterValue (int value, int totalCount, int change, DateTime timestamp, string message, TimerTraceList traces) { this.value = value; this.timestamp = timestamp; this.totalCount = totalCount; this.message = message; this.traces = traces; + this.change = change; this.threadId = System.Threading.Thread.CurrentThread.ManagedThreadId; } @@ -358,6 +386,10 @@ namespace MonoDevelop.Core.Instrumentation public int TotalCount { get { return totalCount; } } + + public int ValueChange { + get { return change; } + } public int ThreadId { get { return this.threadId; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/IInstrumentationConsumer.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/InstrumentationConsumer.cs index 9f6af53387..8e0574fe64 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/IInstrumentationConsumer.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/InstrumentationConsumer.cs @@ -28,10 +28,18 @@ using System; namespace MonoDevelop.Core.Instrumentation { [Mono.Addins.TypeExtensionPoint] - public interface IInstrumentationConsumer + public abstract class InstrumentationConsumer { - bool SupportsCounter (Counter counter); - void ConsumeValue (Counter counter, CounterValue value); + public abstract bool SupportsCounter (Counter counter); + + public virtual void ConsumeValue (Counter counter, CounterValue value) + { + } + + public virtual IDisposable BeginTimer (TimerCounter counter, CounterValue value) + { + return null; + } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/InstrumentationService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/InstrumentationService.cs index 0cbe2dccbb..bd9358bbac 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/InstrumentationService.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/InstrumentationService.cs @@ -54,7 +54,7 @@ namespace MonoDevelop.Core.Instrumentation static Thread autoSaveThread; static bool stopping; static int autoSaveInterval; - static List<IInstrumentationConsumer> handlers = new List<IInstrumentationConsumer> (); + static List<InstrumentationConsumer> handlers = new List<InstrumentationConsumer> (); static bool handlersLoaded; static InstrumentationService () @@ -64,12 +64,12 @@ namespace MonoDevelop.Core.Instrumentation startTime = DateTime.Now; } - static void InitializeHandlers () + internal static void InitializeHandlers () { if (!handlersLoaded && AddinManager.IsInitialized) { lock (counters) { handlersLoaded = true; - AddinManager.AddExtensionNodeHandler (typeof(IInstrumentationConsumer), HandleInstrumentationHandlerExtension); + AddinManager.AddExtensionNodeHandler (typeof(InstrumentationConsumer), HandleInstrumentationHandlerExtension); } } } @@ -84,26 +84,37 @@ namespace MonoDevelop.Core.Instrumentation static void HandleInstrumentationHandlerExtension (object sender, ExtensionNodeEventArgs args) { - var handler = (IInstrumentationConsumer)args.ExtensionObject; + var handler = (InstrumentationConsumer)args.ExtensionObject; if (args.Change == ExtensionChange.Add) { - handlers.Add (handler); - lock (counters) { - foreach (var c in counters.Values) { - if (handler.SupportsCounter (c)) - c.Handlers.Add (handler); - } - } + RegisterInstrumentationConsumer (handler); } else { - handlers.Remove (handler); - lock (counters) { - foreach (var c in counters.Values) - c.Handlers.Remove (handler); + UnregisterInstrumentationConsumer (handler); + } + } + + public static void RegisterInstrumentationConsumer (InstrumentationConsumer consumer) + { + lock (counters) { + handlers.Add (consumer); + foreach (var c in counters.Values) { + if (consumer.SupportsCounter (c)) + c.Handlers.Add (consumer); } } UpdateCounterStatus (); } + public static void UnregisterInstrumentationConsumer (InstrumentationConsumer consumer) + { + lock (counters) { + handlers.Remove (consumer); + foreach (var c in counters.Values) + c.Handlers.Remove (consumer); + } + UpdateCounterStatus (); + } + public static int PublishService () { RemotingService.RegisterRemotingChannel (); @@ -123,7 +134,7 @@ namespace MonoDevelop.Core.Instrumentation throw new InvalidOperationException ("Service not published"); if (Platform.IsMac) { - var macOSDir = PropertyService.EntryAssemblyPath.ParentDirectory.ParentDirectory.ParentDirectory; + var macOSDir = PropertyService.EntryAssemblyPath.ParentDirectory.ParentDirectory.ParentDirectory.ParentDirectory.Combine ("MacOS"); var app = macOSDir.Combine ("MDMonitor.app"); if (Directory.Exists (app)) { var psi = new ProcessStartInfo ("open", string.Format ("-n '{0}' --args -c localhost:{1} ", app, publicPort)) { @@ -223,10 +234,15 @@ namespace MonoDevelop.Core.Instrumentation public static Counter CreateCounter (string name, string category, bool logMessages) { - return CreateCounter (name, category, logMessages, false); + return CreateCounter (name, category, logMessages, null, false); } - static Counter CreateCounter (string name, string category, bool logMessages, bool isTimer) + public static Counter CreateCounter (string name, string category = null, bool logMessages = false, string id = null) + { + return CreateCounter (name, category, logMessages, id, false); + } + + static Counter CreateCounter (string name, string category, bool logMessages, string id, bool isTimer) { InitializeHandlers (); @@ -241,6 +257,7 @@ namespace MonoDevelop.Core.Instrumentation } Counter c = isTimer ? new TimerCounter (name, cat) : new Counter (name, cat); + c.Id = id; c.LogMessages = logMessages; cat.AddCounter (c); @@ -289,7 +306,12 @@ namespace MonoDevelop.Core.Instrumentation public static TimerCounter CreateTimerCounter (string name, string category, double minSeconds, bool logMessages) { - TimerCounter c = (TimerCounter) CreateCounter (name, category, logMessages, true); + return CreateTimerCounter (name, category, minSeconds, logMessages, null); + } + + public static TimerCounter CreateTimerCounter (string name, string category = null, double minSeconds = 0, bool logMessages = false, string id = null) + { + TimerCounter c = (TimerCounter) CreateCounter (name, category, logMessages, id, true); c.DisplayMode = CounterDisplayMode.Line; c.LogMessages = logMessages; c.MinSeconds = minSeconds; @@ -357,7 +379,7 @@ namespace MonoDevelop.Core.Instrumentation } } - public static IProgressMonitor GetInstrumentedMonitor (IProgressMonitor monitor, TimerCounter counter) + public static ProgressMonitor GetInstrumentedMonitor (ProgressMonitor monitor, TimerCounter counter) { if (enabled) { AggregatedProgressMonitor mon = new AggregatedProgressMonitor (monitor); @@ -368,37 +390,23 @@ namespace MonoDevelop.Core.Instrumentation } } - class IntrumentationMonitor: NullProgressMonitor + class IntrumentationMonitor: ProgressMonitor { TimerCounter counter; Stack<ITimeTracker> timers = new Stack<ITimeTracker> (); - LogTextWriter logger = new LogTextWriter (); - + public IntrumentationMonitor (TimerCounter counter) { this.counter = counter; - logger.TextWritten += HandleLoggerTextWritten; } - void HandleLoggerTextWritten (string writtenText) + protected override void OnWriteLog (string message) { if (timers.Count > 0) - timers.Peek ().Trace (writtenText); - } - - public override void BeginTask (string name, int totalWork) - { - if (!string.IsNullOrEmpty (name)) { - ITimeTracker c = counter.BeginTiming (name); - c.Trace (name); - timers.Push (c); - } else { - timers.Push (null); - } - base.BeginTask (name, totalWork); + timers.Peek ().Trace (message); } - - public override void BeginStepTask (string name, int totalWork, int stepSize) + + protected override void OnBeginTask (string name, int totalWork, int stepWork) { if (!string.IsNullOrEmpty (name)) { ITimeTracker c = counter.BeginTiming (name); @@ -407,23 +415,15 @@ namespace MonoDevelop.Core.Instrumentation } else { timers.Push (null); } - base.BeginStepTask (name, totalWork, stepSize); } - public override void EndTask () + protected override void OnEndTask (string name, int totalWork, int stepWork) { if (timers.Count > 0) { ITimeTracker c = timers.Pop (); if (c != null) c.End (); } - base.EndTask (); - } - - public override System.IO.TextWriter Log { - get { - return logger; - } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/TimeCounter.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/TimeCounter.cs index 140f84f899..55227a859f 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/TimeCounter.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/TimeCounter.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; +using System.Collections.Generic; namespace MonoDevelop.Core.Instrumentation { @@ -55,6 +56,7 @@ namespace MonoDevelop.Core.Instrumentation TimerTraceList traceList; TimerTrace lastTrace; TimerCounter counter; + object linkedTrackers; internal TimeCounter (TimerCounter counter) { @@ -62,6 +64,18 @@ namespace MonoDevelop.Core.Instrumentation traceList = new TimerTraceList (); Begin (); } + + public void AddHandlerTracker (IDisposable t) + { + if (linkedTrackers == null) + linkedTrackers = t; + else if (!(linkedTrackers is List<IDisposable>)) { + var list = new List<IDisposable> (); + list.Add ((IDisposable)linkedTrackers); + list.Add (t); + } else + ((List<IDisposable>)linkedTrackers).Add (t); + } internal TimerTraceList TraceList { get { return this.traceList; } @@ -98,6 +112,13 @@ namespace MonoDevelop.Core.Instrumentation else counter.AddTime (traceList.TotalTime); counter = null; + + if (linkedTrackers is List<IDisposable>) { + foreach (var t in (List<IDisposable>)linkedTrackers) + t.Dispose (); + } else if (linkedTrackers != null) + ((IDisposable)linkedTrackers).Dispose (); + } void IDisposable.Dispose () diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/TimerCounter.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/TimerCounter.cs index ed2f54cd46..316d54f87e 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/TimerCounter.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/TimerCounter.cs @@ -82,7 +82,7 @@ namespace MonoDevelop.Core.Instrumentation public override void Trace (string message) { - if (InstrumentationService.Enabled) { + if (Enabled) { if (lastTimer != null) lastTimer.Trace (message); else { @@ -103,13 +103,14 @@ namespace MonoDevelop.Core.Instrumentation public ITimeTracker BeginTiming (string message) { ITimeTracker timer; - if (!InstrumentationService.Enabled) { + if (!Enabled) { timer = dummyTimer; } else { + var c = new TimeCounter (this); lock (values) { - timer = lastTimer = new TimeCounter (this); + timer = lastTimer = c; count++; - int i = StoreValue (message, lastTimer.TraceList); + int i = StoreValue (message, lastTimer); lastTimer.TraceList.ValueIndex = i; } } @@ -120,7 +121,7 @@ namespace MonoDevelop.Core.Instrumentation public void EndTiming () { - if (InstrumentationService.Enabled && lastTimer != null) + if (Enabled && lastTimer != null) lastTimer.End (); } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.LogReporting/CrashReporter.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.LogReporting/CrashReporter.cs new file mode 100644 index 0000000000..96b3c6e313 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.LogReporting/CrashReporter.cs @@ -0,0 +1,39 @@ +// +// CrashReporter.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using Mono.Addins; +using System.Collections.Generic; + +namespace MonoDevelop.Core.LogReporting +{ + [TypeExtensionPoint] + public abstract class CrashReporter + { + public abstract void ReportCrash (Exception ex, bool willShutDown, IEnumerable<string> tags); + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/AggregatedAsyncOperation.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/AggregatedAsyncOperation.cs deleted file mode 100644 index b4067d2923..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/AggregatedAsyncOperation.cs +++ /dev/null @@ -1,112 +0,0 @@ -// -// AggregatedAsyncOperation.cs -// -// Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Collections.Generic; - -namespace MonoDevelop.Core.ProgressMonitoring -{ - public class AggregatedAsyncOperation: IAsyncOperation - { - public event OperationHandler Completed; - - List<IAsyncOperation> operations = new List<IAsyncOperation> (); - bool started; - bool success = true; - bool successWithWarnings = true; - int completed; - - public void Add (IAsyncOperation oper) - { - if (started) - throw new InvalidOperationException ("Can't add more operations after calling StartMonitoring"); - operations.Add (oper); - } - - public void StartMonitoring () - { - started = true; - foreach (IAsyncOperation oper in operations) - oper.Completed += OperCompleted; - } - - void OperCompleted (IAsyncOperation op) - { - bool raiseEvent; - lock (operations) { - completed++; - success = success && op.Success; - successWithWarnings = success && op.SuccessWithWarnings; - raiseEvent = (completed == operations.Count); - } - if (raiseEvent && Completed != null) - Completed (this); - } - - public void Cancel () - { - CheckStarted (); - lock (operations) { - foreach (IAsyncOperation op in operations) - op.Cancel (); - } - } - - public void WaitForCompleted () - { - CheckStarted (); - foreach (IAsyncOperation op in operations) - op.WaitForCompleted (); - } - - public bool IsCompleted { - get { - CheckStarted (); - return completed == operations.Count; - } - } - - public bool Success { - get { - CheckStarted (); - return success; - } - } - - public bool SuccessWithWarnings { - get { - CheckStarted (); - return successWithWarnings; - } - } - - void CheckStarted () - { - if (!started) - throw new InvalidOperationException ("Operation not started"); - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/AggregatedOperationMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/AggregatedOperationMonitor.cs deleted file mode 100644 index c8ffc6fa50..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/AggregatedOperationMonitor.cs +++ /dev/null @@ -1,77 +0,0 @@ -// -// AggregatedOperationMonitor.cs -// -// Author: -// Lluis Sanchez Gual -// -// Copyright (C) 2005 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - - -using System; -using System.Collections.Generic; - -namespace MonoDevelop.Core.ProgressMonitoring -{ - public class AggregatedOperationMonitor: IDisposable - { - List<IAsyncOperation> list = new List<IAsyncOperation> (); - IProgressMonitor monitor; - - public AggregatedOperationMonitor (IProgressMonitor monitor, params IAsyncOperation[] operations) - { - this.monitor = monitor; - - if (operations != null) { - lock (list) { - foreach (IAsyncOperation operation in operations) - AddOperation (operation); - } - } - - monitor.CancelRequested += new MonitorHandler (OnCancel); - } - - public void AddOperation (IAsyncOperation operation) - { - lock (list) { - if (monitor.IsCancelRequested) - operation.Cancel (); - else - list.Add (operation); - } - } - - void OnCancel (IProgressMonitor m) - { - lock (list) { - foreach (IAsyncOperation operation in list) - operation.Cancel (); - } - } - - public void Dispose () - { - monitor.CancelRequested -= new MonitorHandler (OnCancel); - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/AggregatedProgressMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/AggregatedProgressMonitor.cs index cd8c4aed7b..6bf2638e99 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/AggregatedProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/AggregatedProgressMonitor.cs @@ -30,6 +30,8 @@ using System; using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; +using System.Threading; namespace MonoDevelop.Core.ProgressMonitoring { @@ -48,179 +50,145 @@ namespace MonoDevelop.Core.ProgressMonitoring All = 0xff } - public class AggregatedProgressMonitor: IProgressMonitor, IAsyncOperation + public class AggregatedProgressMonitor: ProgressMonitor { - IProgressMonitor masterMonitor; + ProgressMonitor masterMonitor; List<MonitorInfo> monitors = new List<MonitorInfo> (); - LogTextWriter logger; + CancellationTokenSource cancelSource; class MonitorInfo { public MonitorAction ActionMask; - public IProgressMonitor Monitor; + public ProgressMonitor Monitor; + public CancellationTokenRegistration CancellationTokenRegistration; } - public IProgressMonitor MasterMonitor { + public ProgressMonitor MasterMonitor { get { return this.masterMonitor; } } - public AggregatedProgressMonitor (): this (new NullProgressMonitor ()) + public AggregatedProgressMonitor (): this (new ProgressMonitor ()) { } - public AggregatedProgressMonitor (IProgressMonitor masterMonitor, params IProgressMonitor[] slaveMonitors) + public AggregatedProgressMonitor (ProgressMonitor masterMonitor, params ProgressMonitor[] slaveMonitors): this (masterMonitor, null, slaveMonitors) { + } + + internal AggregatedProgressMonitor (ProgressMonitor masterMonitor, CancellationTokenSource cancelSource, params ProgressMonitor[] slaveMonitors) + { + this.cancelSource = cancelSource ?? new CancellationTokenSource (); this.masterMonitor = masterMonitor; AddSlaveMonitor (masterMonitor, MonitorAction.All); - logger = new LogTextWriter (); - logger.TextWritten += new LogTextEventHandler (OnWriteLog); - foreach (IProgressMonitor mon in slaveMonitors) + foreach (ProgressMonitor mon in slaveMonitors) AddSlaveMonitor (mon); } - public void AddSlaveMonitor (IProgressMonitor slaveMonitor) + public new void AddSlaveMonitor (ProgressMonitor slaveMonitor) { AddSlaveMonitor (slaveMonitor, MonitorAction.All); } - public void AddSlaveMonitor (IProgressMonitor slaveMonitor, MonitorAction actionMask) + public void AddSlaveMonitor (ProgressMonitor slaveMonitor, MonitorAction actionMask) { MonitorInfo smon = new MonitorInfo (); smon.ActionMask = actionMask; smon.Monitor = slaveMonitor; monitors.Add (smon); if ((actionMask & MonitorAction.SlaveCancel) != 0) - slaveMonitor.CancelRequested += new MonitorHandler (OnSlaveCancelRequested); + smon.CancellationTokenRegistration = slaveMonitor.CancellationToken.Register (OnSlaveCancelRequested); } - - public void BeginTask (string name, int totalWork) + + protected override void OnBeginTask (string name, int totalWork, int stepWork) { - foreach (MonitorInfo info in monitors) - if ((info.ActionMask & MonitorAction.Tasks) != 0) - info.Monitor.BeginTask (name, totalWork); + if (stepWork == -1) { + foreach (MonitorInfo info in monitors) + if ((info.ActionMask & MonitorAction.Tasks) != 0) + info.Monitor.BeginTask (name, totalWork); + } else { + foreach (MonitorInfo info in monitors) + if ((info.ActionMask & MonitorAction.Tasks) != 0) { + info.Monitor.BeginStep (stepWork); + info.Monitor.BeginTask (name, totalWork); + } + } } - - public void BeginStepTask (string name, int totalWork, int stepSize) + + protected override void OnEndTask (string name, int totalWork, int stepWork) { foreach (MonitorInfo info in monitors) if ((info.ActionMask & MonitorAction.Tasks) != 0) - info.Monitor.BeginStepTask (name, totalWork, stepSize); + info.Monitor.EndTask (); } - - public void EndTask () + + protected override void OnStep (string message, int work) { foreach (MonitorInfo info in monitors) if ((info.ActionMask & MonitorAction.Tasks) != 0) - info.Monitor.EndTask (); + info.Monitor.Step (message, work); } - - public void Step (int work) + + protected override ProgressMonitor CreateAsyncStepMonitor () + { + return new AggregatedProgressMonitor (); + } + + protected override void OnBeginAsyncStep (string message, int work, ProgressMonitor stepMonitor) { + var am = (AggregatedProgressMonitor) stepMonitor; foreach (MonitorInfo info in monitors) if ((info.ActionMask & MonitorAction.Tasks) != 0) - info.Monitor.Step (work); + am.AddSlaveMonitor (info.Monitor.BeginAsyncStep (message, work)); } - - public TextWriter Log + + protected override void OnWriteLog (string message) { - get { return logger; } + foreach (MonitorInfo info in monitors) + if ((info.ActionMask & MonitorAction.WriteLog) != 0) + info.Monitor.Log.Write (message); } - - void OnWriteLog (string text) + + protected override void OnWriteErrorLog (string message) { foreach (MonitorInfo info in monitors) if ((info.ActionMask & MonitorAction.WriteLog) != 0) - info.Monitor.Log.Write (text); + info.Monitor.ErrorLog.Write (message); } - - public void ReportSuccess (string message) + + protected override void OnSuccessReported (string message) { foreach (MonitorInfo info in monitors) if ((info.ActionMask & MonitorAction.ReportSuccess) != 0) info.Monitor.ReportSuccess (message); } - - public void ReportWarning (string message) + + protected override void OnWarningReported (string message) { foreach (MonitorInfo info in monitors) if ((info.ActionMask & MonitorAction.ReportWarning) != 0) info.Monitor.ReportWarning (message); } - - public void ReportError (string message, Exception ex) + + protected override void OnErrorReported (string message, Exception exception) { foreach (MonitorInfo info in monitors) if ((info.ActionMask & MonitorAction.ReportError) != 0) - info.Monitor.ReportError (message, ex); + info.Monitor.ReportError (message, exception); } - - public void Dispose () + + public override void Dispose () { foreach (MonitorInfo info in monitors) { if ((info.ActionMask & MonitorAction.Dispose) != 0) info.Monitor.Dispose (); if ((info.ActionMask & MonitorAction.SlaveCancel) != 0) - info.Monitor.CancelRequested -= new MonitorHandler (OnSlaveCancelRequested); - } - } - - public bool IsCancelRequested - { - get { - foreach (MonitorInfo info in monitors) - if ((info.ActionMask & MonitorAction.SlaveCancel) != 0) { - if (info.Monitor.IsCancelRequested) return true; - } - return false; + info.CancellationTokenRegistration.Dispose (); } } - - public object SyncRoot { - get { return this; } - } - - void OnSlaveCancelRequested (IProgressMonitor sender) - { - AsyncOperation.Cancel (); - } - - public IAsyncOperation AsyncOperation - { - get { return this; } - } - - void IAsyncOperation.Cancel () - { - foreach (MonitorInfo info in monitors) - if ((info.ActionMask & MonitorAction.Cancel) != 0 && !info.Monitor.IsCancelRequested) - info.Monitor.AsyncOperation.Cancel (); - } - - void IAsyncOperation.WaitForCompleted () + + void OnSlaveCancelRequested () { - masterMonitor.AsyncOperation.WaitForCompleted (); - } - - public bool IsCompleted { - get { return masterMonitor.AsyncOperation.IsCompleted; } - } - - bool IAsyncOperation.Success { - get { return masterMonitor.AsyncOperation.Success; } - } - - bool IAsyncOperation.SuccessWithWarnings { - get { return masterMonitor.AsyncOperation.SuccessWithWarnings; } - } - - public event MonitorHandler CancelRequested { - add { masterMonitor.CancelRequested += value; } - remove { masterMonitor.CancelRequested -= value; } - } - - public event OperationHandler Completed { - add { masterMonitor.AsyncOperation.Completed += value; } - remove { masterMonitor.AsyncOperation.Completed -= value; } + cancelSource.Cancel (); } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/AsyncOperation.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/AsyncOperation.cs deleted file mode 100644 index 59201ae555..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/AsyncOperation.cs +++ /dev/null @@ -1,134 +0,0 @@ -// AsyncOperation.cs -// -// Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2008 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// - -using System; -using System.Threading; - -namespace MonoDevelop.Core -{ - public class AsyncOperation: IAsyncOperation - { - bool canceled; - bool completed; - bool success; - bool successWithWarnings; - IAsyncOperation trackedOperation; - object lck = new object (); - - OperationHandler completedEvent; - - public event OperationHandler Completed { - add { - bool done = false; - lock (lck) { - if (completed) - done = true; - else - completedEvent += value; - } - if (done) - value (this); - } - remove { - lock (lck) { - completedEvent -= value; - } - } - } - - public event OperationHandler CancelRequested; - - public bool Canceled { - get { return canceled; } - } - - public void Cancel () - { - canceled = true; - if (trackedOperation != null) - trackedOperation.Cancel (); - if (CancelRequested != null) - CancelRequested (this); - } - - void IAsyncOperation.WaitForCompleted () - { - lock (lck) { - if (!completed) - Monitor.Wait (lck); - } - } - - public bool IsCompleted { - get { - return completed; - } - } - - public bool Success { - get { - return success; - } - } - - public bool SuccessWithWarnings { - get { - return successWithWarnings; - } - } - - public void TrackOperation (IAsyncOperation oper, bool isFinal) - { - if (trackedOperation != null) - throw new InvalidOperationException ("An operation is already being tracked."); - trackedOperation = oper; - oper.Completed += delegate { - if (!oper.Success || isFinal) - SetCompleted (oper.Success, oper.SuccessWithWarnings); - trackedOperation = null; - }; - } - - public void SetCompleted (bool success) - { - SetCompleted (success, false); - } - - public void SetCompleted (bool success, bool hasWarnings) - { - lock (lck) { - completed = true; - this.success = success; - if (success && hasWarnings) - successWithWarnings = true; - Monitor.PulseAll (lck); - if (completedEvent != null) - completedEvent (this); - } - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ConsoleProgressMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ConsoleProgressMonitor.cs index 82410eae20..fb8fc26d40 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ConsoleProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ConsoleProgressMonitor.cs @@ -31,7 +31,7 @@ using System.IO; namespace MonoDevelop.Core.ProgressMonitoring { - public class ConsoleProgressMonitor: NullProgressMonitor + public class ConsoleProgressMonitor: ProgressMonitor { int columns = 0; bool leaveOpen; @@ -40,7 +40,6 @@ namespace MonoDevelop.Core.ProgressMonitoring int ilevel = 0; int isize = 3; int col = -1; - LogTextWriter logger; bool ignoreLogMessages; TextWriter writer; @@ -67,8 +66,6 @@ namespace MonoDevelop.Core.ProgressMonitoring { this.writer = writer; this.leaveOpen = leaveOpen; - logger = new LogTextWriter (); - logger.TextWritten += WriteLog; } public ConsoleProgressMonitor (TextWriter writer) : this (writer, false) @@ -77,9 +74,6 @@ namespace MonoDevelop.Core.ProgressMonitoring public override void Dispose () { - logger.TextWritten -= WriteLog; - logger.Dispose (); - if (!leaveOpen) writer.Dispose (); @@ -110,7 +104,7 @@ namespace MonoDevelop.Core.ProgressMonitoring set { indent = value; } } - public override void BeginTask (string name, int totalWork) + protected override void OnBeginTask (string name, int totalWork, int stepWork) { if (!ignoreLogMessages) { WriteText (name); @@ -118,38 +112,29 @@ namespace MonoDevelop.Core.ProgressMonitoring } } - public override void BeginStepTask (string name, int totalWork, int stepSize) - { - BeginTask (name, totalWork); - } - - public override void EndTask () + protected override void OnEndTask (string name, int totalWork, int stepWork) { if (!ignoreLogMessages) Unindent (); } - - void WriteLog (string text) + + protected override void OnWriteLog (string message) { if (!ignoreLogMessages) - WriteText (text); - } - - public override TextWriter Log { - get { return logger; } + WriteText (message); } - - public override void ReportSuccess (string message) + + protected override void OnSuccessReported (string message) { WriteText (message + "\n"); } - - public override void ReportWarning (string message) + + protected override void OnWarningReported (string message) { WriteText ("WARNING: " + message + "\n"); } - - public override void ReportError (string message, Exception ex) + + protected override void OnErrorReported (string message, Exception ex) { if (message == null && ex != null) message = ex.Message; diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ConsoleProjectLoadProgressMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ConsoleProjectLoadProgressMonitor.cs index 2447804b9b..22e3dce120 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ConsoleProjectLoadProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ConsoleProjectLoadProgressMonitor.cs @@ -27,17 +27,14 @@ using System; namespace MonoDevelop.Core.ProgressMonitoring { - public class ConsoleProjectLoadProgressMonitor : WrappedProgressMonitor, IProjectLoadProgressMonitor + public class ConsoleProjectLoadProgressMonitor : ProjectLoadProgressMonitor { - public MonoDevelop.Projects.Solution CurrentSolution { get; set; } - - public ConsoleProjectLoadProgressMonitor (IProgressMonitor monitor) - : base (monitor) + public ConsoleProjectLoadProgressMonitor (ConsoleProgressMonitor monitor) { - + AddSlaveMonitor (monitor); } - public MonoDevelop.Projects.Extensions.MigrationType ShouldMigrateProject () + public override MonoDevelop.Projects.Extensions.MigrationType ShouldMigrateProject () { Console.WriteLine ("Warning: One or more projects in this solution cannot be "); Console.WriteLine ("compiled unless they are migrated to a newer format. Please "); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/FilteredProgressMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/FilteredProgressMonitor.cs index 4c1f97df84..57fae2a68f 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/FilteredProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/FilteredProgressMonitor.cs @@ -34,12 +34,12 @@ namespace MonoDevelop.Core.ProgressMonitoring // the operation being monitorized provides. public class FilteredProgressMonitor: AggregatedProgressMonitor { - public FilteredProgressMonitor (IProgressMonitor targetMonitor) + public FilteredProgressMonitor (ProgressMonitor targetMonitor) : this (targetMonitor, MonitorAction.WriteLog | MonitorAction.ReportError | MonitorAction.ReportWarning | MonitorAction.ReportSuccess | MonitorAction.Cancel | MonitorAction.SlaveCancel) { } - public FilteredProgressMonitor (IProgressMonitor targetMonitor, MonitorAction actionMask) + public FilteredProgressMonitor (ProgressMonitor targetMonitor, MonitorAction actionMask) { AddSlaveMonitor (targetMonitor, actionMask); } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/NullAsyncOperation.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/NullAsyncOperation.cs deleted file mode 100644 index 4262120002..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/NullAsyncOperation.cs +++ /dev/null @@ -1,73 +0,0 @@ -// -// NullAsyncOperation.cs -// -// Author: -// Lluis Sanchez Gual -// -// Copyright (C) 2005 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - - -using System; - -namespace MonoDevelop.Core.ProgressMonitoring -{ - public class NullAsyncOperation: IAsyncOperation - { - public static NullAsyncOperation Success = new NullAsyncOperation (true, false); - public static NullAsyncOperation Failure = new NullAsyncOperation (false, false); - - bool success; - bool warnings; - - protected NullAsyncOperation (bool success, bool warnings) - { - this.success = success; - this.warnings = warnings; - } - - public void Cancel () - { - } - - public void WaitForCompleted () - { - } - - public bool IsCompleted { - get { return true; } - } - - bool IAsyncOperation.Success { - get { return success; } - } - - bool IAsyncOperation.SuccessWithWarnings { - get { return success && warnings; } - } - - public event OperationHandler Completed { - add { value (this); } - remove {} - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/NullProgressMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/NullProgressMonitor.cs deleted file mode 100644 index d79899c4f0..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/NullProgressMonitor.cs +++ /dev/null @@ -1,242 +0,0 @@ -// -// NullProgressMonitor.cs -// -// Author: -// Lluis Sanchez Gual -// -// Copyright (C) 2005 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - - -using System; -using System.Collections.Generic; -using System.Threading; -using System.IO; - -namespace MonoDevelop.Core.ProgressMonitoring -{ - public class NullProgressMonitor: IProgressMonitor, IAsyncOperation - { - bool done, canceled, error; - ManualResetEvent waitEvent; - List<ProgressError> errors; - List<string> warnings; - List<string> messages; - - public object SyncRoot { - get { return this; } - } - - public string[] Messages { - get { - if (messages != null) - return messages.ToArray (); - return new string [0]; - } - } - - public string[] Warnings { - get { - if (warnings != null) - return warnings.ToArray (); - return new string [0]; - } - } - - public ProgressError[] Errors { - get { - if (errors != null) - return errors.ToArray (); - return new ProgressError [0]; - } - } - - public virtual void BeginTask (string name, int totalWork) - { - } - - public virtual void EndTask () - { - } - - public virtual void BeginStepTask (string name, int totalWork, int stepSize) - { - } - - public virtual void Step (int work) - { - } - - public virtual TextWriter Log { - get { return TextWriter.Null; } - } - - public virtual void ReportSuccess (string message) - { - if (messages == null) - messages = new List<string> (); - messages.Add (message); - } - - public virtual void ReportWarning (string message) - { - if (warnings == null) - warnings = new List<string> (); - warnings.Add (message); - } - - public virtual void ReportError (string message, Exception ex) - { - if (errors == null) - errors = new List<ProgressError> (); - - if (message == null && ex != null) - message = ex.Message; - else if (message != null && ex != null) { - if (!message.EndsWith (".")) message += "."; - message += " " + ex.Message; - } - - errors.Add (new ProgressError (message, ex)); - error = true; - } - - public bool IsCancelRequested { - get { return canceled; } - } - - public virtual void Dispose () - { - lock (this) { - if (done) return; - done = true; - if (waitEvent != null) - waitEvent.Set (); - } - OnCompleted (); - } - - public IAsyncOperation AsyncOperation - { - get { return this; } - } - - void IAsyncOperation.Cancel () - { - OnCancelRequested (); - } - - void IAsyncOperation.WaitForCompleted () - { - lock (this) { - if (done) return; - if (waitEvent == null) - waitEvent = new ManualResetEvent (false); - } - waitEvent.WaitOne (); - } - - bool IAsyncOperation.IsCompleted - { - get { return done; } - } - - bool IAsyncOperation.Success { - get { return !error && !canceled; } - } - - bool IAsyncOperation.SuccessWithWarnings { - get { return !error && warnings != null; } - } - - public event OperationHandler Completed { - add { - bool alreadyCompleted = false; - lock (this) { - completedEvent += value; - alreadyCompleted = done; - } - if (alreadyCompleted) value (this); - } - remove { - lock (this) { - completedEvent -= value; - } - } - } - - public event MonitorHandler CancelRequested { - add { - bool alreadyCanceled = false; - lock (this) { - cancelRequestedEvent += value; - alreadyCanceled = canceled; - } - if (alreadyCanceled) value (this); - } - remove { - lock (this) { - cancelRequestedEvent -= value; - } - } - } - - protected virtual void OnCancelRequested () - { - lock (this) { - if (canceled) return; - canceled = true; - } - if (cancelRequestedEvent != null) - cancelRequestedEvent (this); - } - - protected virtual void OnCompleted () - { - if (completedEvent != null) - completedEvent (AsyncOperation); - } - - event MonitorHandler cancelRequestedEvent; - event OperationHandler completedEvent; - } - - public class ProgressError - { - Exception ex; - string message; - - public ProgressError (string message, Exception ex) - { - this.ex = ex; - this.message = message; - } - - public string Message { - get { return message; } - } - - public Exception Exception { - get { return ex; } - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ProgressStatusMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ProgressStatusMonitor.cs index b35e4043de..6f3c772b21 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ProgressStatusMonitor.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ProgressStatusMonitor.cs @@ -33,15 +33,16 @@ namespace MonoDevelop.Core.ProgressMonitoring { public class ProgressStatusMonitor: MarshalByRefObject, IProgressStatus, IDisposable { - IProgressMonitor monitor; + ProgressMonitor monitor; int step; int logLevel; + bool canceled; - public ProgressStatusMonitor (IProgressMonitor monitor): this (monitor, 1) + public ProgressStatusMonitor (ProgressMonitor monitor): this (monitor, 1) { } - public ProgressStatusMonitor (IProgressMonitor monitor, int logLevel) + public ProgressStatusMonitor (ProgressMonitor monitor, int logLevel) { this.logLevel = logLevel; this.monitor = monitor; @@ -77,7 +78,7 @@ namespace MonoDevelop.Core.ProgressMonitoring } public bool IsCanceled { - get { return monitor.IsCancelRequested; } + get { return monitor.CancellationToken.IsCancellationRequested || canceled; } } public int LogLevel { @@ -87,7 +88,7 @@ namespace MonoDevelop.Core.ProgressMonitoring public void Cancel () { - monitor.AsyncOperation.Cancel (); + canceled = true; } public void Dispose () diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/IProjectLoadProgressMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ProjectLoadProgressMonitor.cs index e6511a2215..e65d489a08 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/IProjectLoadProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ProjectLoadProgressMonitor.cs @@ -28,10 +28,10 @@ using MonoDevelop.Projects.Extensions; namespace MonoDevelop.Core { - public interface IProjectLoadProgressMonitor : IProgressMonitor + public abstract class ProjectLoadProgressMonitor : ProgressMonitor { - MonoDevelop.Projects.Solution CurrentSolution { get; set; } - MigrationType ShouldMigrateProject (); + public MonoDevelop.Projects.Solution CurrentSolution { get; set; } + public abstract MigrationType ShouldMigrateProject (); } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/SimpleProgressMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/SimpleProgressMonitor.cs deleted file mode 100644 index 13ff23051e..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/SimpleProgressMonitor.cs +++ /dev/null @@ -1,77 +0,0 @@ -// -// SimpleProgressMonitor.cs -// -// Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; - -namespace MonoDevelop.Core.ProgressMonitoring -{ - public class SimpleProgressMonitor: NullProgressMonitor - { - ProgressTracker tracker = new ProgressTracker (); - - protected ProgressTracker Tracker { - get { return tracker; } - } - - public SimpleProgressMonitor() - { - } - - public override void BeginTask (string name, int totalWork) - { - tracker.BeginTask (name, totalWork); - OnProgressChanged (); - } - - public override void BeginStepTask (string name, int totalWork, int stepSize) - { - tracker.BeginStepTask (name, totalWork, stepSize); - OnProgressChanged (); - } - - public override void EndTask () - { - tracker.EndTask (); - OnProgressChanged (); - } - - public override void Step (int work) - { - tracker.Step (work); - OnProgressChanged (); - } - - protected override void OnCompleted () - { - base.OnCompleted (); - OnProgressChanged (); - } - - protected virtual void OnProgressChanged () - { - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/SynchronizedProgressMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/SynchronizedProgressMonitor.cs deleted file mode 100644 index 083000735f..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/SynchronizedProgressMonitor.cs +++ /dev/null @@ -1,139 +0,0 @@ -// -// SynchronizedProgressMonitor.cs -// -// Author: -// Lluis Sanchez Gual -// -// Copyright (C) 2005 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - - -using System; -using System.Threading; -using System.IO; - -namespace MonoDevelop.Core.ProgressMonitoring -{ - public sealed class SynchronizedProgressMonitor: IProgressMonitor - { - IProgressMonitor monitor; - - public SynchronizedProgressMonitor (IProgressMonitor monitor) - { - this.monitor = monitor; - } - - public void BeginTask (string name, int totalWork) - { - lock (monitor.SyncRoot) { - monitor.BeginTask (name, totalWork); - } - } - - public void BeginStepTask (string name, int totalWork, int stepSize) - { - lock (monitor.SyncRoot) { - monitor.BeginStepTask (name, totalWork, stepSize); - } - } - - public void EndTask () - { - lock (monitor.SyncRoot) { - monitor.EndTask (); - } - } - - public void Step (int work) - { - lock (monitor.SyncRoot) { - monitor.Step (work); - } - } - - public TextWriter Log { - get { return monitor.Log; } - } - - public void ReportSuccess (string message) - { - lock (monitor.SyncRoot) { - monitor.ReportSuccess (message); - } - } - - public void ReportWarning (string message) - { - lock (monitor.SyncRoot) { - monitor.ReportWarning (message); - } - } - - public void ReportError (string message, Exception ex) - { - lock (monitor.SyncRoot) { - monitor.ReportError (message, ex); - } - } - - public bool IsCancelRequested { - get { - lock (monitor.SyncRoot) { - return monitor.IsCancelRequested; - } - } - } - - public void Dispose () - { - lock (monitor.SyncRoot) { - monitor.Dispose (); - } - } - - public IAsyncOperation AsyncOperation - { - get { - lock (monitor.SyncRoot) { - return monitor.AsyncOperation; - } - } - } - - public event MonitorHandler CancelRequested { - add { - lock (monitor.SyncRoot) { - monitor.CancelRequested += value; - } - } - remove { - lock (monitor.SyncRoot) { - monitor.CancelRequested -= value; - } - } - } - - public object SyncRoot { - get { return monitor.SyncRoot; } - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/WrappedProgressMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/WrappedProgressMonitor.cs deleted file mode 100644 index 66b961880a..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/WrappedProgressMonitor.cs +++ /dev/null @@ -1,103 +0,0 @@ -// -// ProjectLoadProgressMonitor.cs -// -// Author: -// Alan McGovern <alan@xamarin.com> -// -// Copyright 2011 Xamarin Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; - -namespace MonoDevelop.Core -{ - public class WrappedProgressMonitor : IProgressMonitor - { - public event MonitorHandler CancelRequested { - add { WrappedMonitor.CancelRequested += value; } - remove { WrappedMonitor.CancelRequested -= value; } - } - - public IAsyncOperation AsyncOperation { - get { return WrappedMonitor.AsyncOperation; } - } - - public bool IsCancelRequested { - get { return WrappedMonitor.IsCancelRequested; } - } - - public System.IO.TextWriter Log { - get { return WrappedMonitor.Log; } - } - - public object SyncRoot { - get { return WrappedMonitor.SyncRoot; } - } - - IProgressMonitor WrappedMonitor { - get; set; - } - - public WrappedProgressMonitor (IProgressMonitor monitor) - { - WrappedMonitor = monitor; - } - - public void BeginStepTask (string name, int totalWork, int stepSize) - { - WrappedMonitor.BeginStepTask (name, totalWork, stepSize); - } - - public void BeginTask (string name, int totalWork) - { - WrappedMonitor.BeginTask (name, totalWork); - } - - public void Dispose () - { - WrappedMonitor.Dispose (); - } - - public void EndTask () - { - WrappedMonitor.EndTask (); - } - - public void ReportError (string message, Exception exception) - { - WrappedMonitor.ReportError (message, exception); - } - - public void ReportSuccess (string message) - { - WrappedMonitor.ReportSuccess (message); - } - - public void ReportWarning (string message) - { - WrappedMonitor.ReportWarning (message); - } - - public void Step (int work) - { - WrappedMonitor.Step (work); - } - } -} - diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Serialization/SerializationContext.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Serialization/SerializationContext.cs index 37df92c37f..d3179c26b8 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Serialization/SerializationContext.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Serialization/SerializationContext.cs @@ -37,7 +37,7 @@ namespace MonoDevelop.Core.Serialization string file; IPropertyFilter propertyFilter; DataSerializer serializer; - IProgressMonitor monitor; + ProgressMonitor monitor; char directorySeparatorChar = System.IO.Path.DirectorySeparatorChar; HashSet<ItemProperty> forcedSerializationProps; @@ -73,7 +73,7 @@ namespace MonoDevelop.Core.Serialization } } - public IProgressMonitor ProgressMonitor { + public ProgressMonitor ProgressMonitor { get { return monitor; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.addin.xml b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.addin.xml index f91a6b60eb..abba41846d 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.addin.xml +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.addin.xml @@ -118,6 +118,23 @@ </ExtensionNode> </ExtensionPoint> + <ExtensionPoint path = "/MonoDevelop/ProjectModel/ProjectModelExtensions" name = "Project model extensions"> + <Description>Project model extensions</Description> + <ExtensionNode name="ObjectExtension" type="MonoDevelop.Projects.Extensions.ProjectModelExtensionNode"> + <Description>A subclass of WorkspaceObjectmExtension.</Description> + </ExtensionNode> + <ExtensionNode name="ProjectFlavor" type="MonoDevelop.Projects.Extensions.SolutionItemExtensionNode"> + <Description>A subclass of ProjectExtension.</Description> + </ExtensionNode> + </ExtensionPoint> + + <ExtensionPoint path = "/MonoDevelop/ProjectModel/MSBuildProjectExtensions" name = "MSBuild project extensions"> + <Description>MSBuild project extensions. Specified classes must be a subclass of MSBuildProjectExtension</Description> + <ExtensionNode name="Class"> + <Description>A subclass of MSBuildProjectExtension.</Description> + </ExtensionNode> + </ExtensionPoint> + <ExtensionPoint path = "/MonoDevelop/ProjectModel/LanguageBindings" name = "Language bindings"> <Description>Language bindings.</Description> <ExtensionNode name="LanguageBinding" type="MonoDevelop.Projects.Extensions.LanguageBindingCodon"/> @@ -125,9 +142,9 @@ <ExtensionPoint path = "/MonoDevelop/ProjectModel/MSBuildItemTypes" name = "MSBuild item types"> <Description>Item types supported by MSBuild</Description> - <ExtensionNode name="SolutionItem" type="MonoDevelop.Projects.Extensions.SolutionItemNode"/> - <ExtensionNode name="DotNetProject" type="MonoDevelop.Projects.Extensions.DotNetProjectNode"/> - <ExtensionNode name="DotNetProjectSubtype" type="MonoDevelop.Projects.Extensions.DotNetProjectSubtypeNode"/> + <ExtensionNode name="SolutionItemType" type="MonoDevelop.Projects.Extensions.SolutionItemTypeNode"/> + <ExtensionNode name="ProjectType" type="MonoDevelop.Projects.Extensions.ProjectTypeNode"/> + <ExtensionNode name="DotNetProjectType" type="MonoDevelop.Projects.Extensions.DotNetProjectTypeNode"/> </ExtensionPoint> <ExtensionPoint path = "/MonoDevelop/ProjectModel/PolicyTypes" name = "Policy types"> @@ -149,10 +166,6 @@ <ExtensionNode objectType="MonoDevelop.Projects.Formats.MSBuild.IMSBuildGlobalPropertyProvider"/> </ExtensionPoint> - <ExtensionPoint path = "/MonoDevelop/ProjectModel/MSBuildExtensions" name = "MSBuild Extensions"> - <ExtensionNode name="Class" objectType="MonoDevelop.Projects.Formats.MSBuild.MSBuildExtension"/> - </ExtensionPoint> - <ExtensionPoint path = "/MonoDevelop/ProjectModel/MonoDocSources" name = "MonoDoc Sources"> <ExtensionNode name="Source" type="MonoDevelop.Projects.Extensions.MonoDocSourceNode" /> </ExtensionPoint> @@ -222,7 +235,6 @@ <Extension path = "/MonoDevelop/ProjectModel/ProjectBindings"> <ProjectBinding id = "DotNet" class = "MonoDevelop.Projects.DotNetProjectBinding" /> <ProjectBinding id = "GenericProject" class = "MonoDevelop.Projects.GenericProjectBinding" /> - <ProjectBinding id = "PortableDotNet" class = "MonoDevelop.Projects.PortableDotNetProjectBinding" /> <ProjectBinding id = "SharedAssetsProject" class = "MonoDevelop.Projects.SharedAssetsProjects.SharedAssetsProjectBinding" /> </Extension> @@ -275,17 +287,16 @@ </Extension> <Extension path = "/MonoDevelop/ProjectModel/MSBuildItemTypes"> - <SolutionItem guid = "{8BC9CEB9-8B4A-11D0-8D11-00A0C91BC942}" + <MSBuildProject guid = "{8BC9CEB9-8B4A-11D0-8D11-00A0C91BC942}" type = "MonoDevelop.Projects.CompiledAssemblyProject" handlerType = "MonoDevelop.Projects.Formats.MSBuild.CompiledAssemblyProjectMSBuildHandler" /> - <SolutionItem guid = "{D954291E-2A0B-460D-934E-DC6B0785DB48}" + <MSBuildProject guid = "{D954291E-2A0B-460D-934E-DC6B0785DB48}" type = "MonoDevelop.Projects.SharedAssetsProjects.SharedAssetsProject" - extension = "shproj" - handlerType = "MonoDevelop.Projects.SharedAssetsProjects.SharedAssetsProjectMSBuildHandler" /> + extension = "shproj" /> </Extension> - <Extension path = "/MonoDevelop/ProjectModel/MSBuildExtensions"> - <Class class="MonoDevelop.Projects.SharedAssetsProjects.SharedAssetsProjectMSBuildExtension"/> + <Extension path = "/MonoDevelop/ProjectModel/ProjectModelExtensions"> + <ProjectExtension class="MonoDevelop.Projects.SharedAssetsProjects.SharedAssetsProjectMSBuildExtension"/> </Extension> diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj index 9d41f0a38d..54929d364b 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj @@ -70,9 +70,6 @@ <NoWarn>1591;1573</NoWarn> <DocumentationFile>..\..\..\build\bin\MonoDevelop.Core.xml</DocumentationFile> </PropertyGroup> - <PropertyGroup Condition="'$(BUILD_REVISION)' != ''"> - <DefineConstants>$(DefineConstants);ENABLE_RAYGUN</DefineConstants> - </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="Mono.Posix" /> @@ -88,6 +85,7 @@ <Reference Include="System.Web" /> <Reference Include="System.ServiceModel" /> <Reference Include="Microsoft.CSharp" /> + <Reference Include="Microsoft.Build.Engine" /> </ItemGroup> <ItemGroup> <Compile Include="MonoDevelop.Core\StringParserService.cs" /> @@ -104,21 +102,16 @@ <Compile Include="MonoDevelop.Core.Execution\RemoteProcessObject.cs" /> <Compile Include="MonoDevelop.Core.ProgressMonitoring\AggregatedProgressMonitor.cs" /> <Compile Include="MonoDevelop.Core.ProgressMonitoring\ConsoleProgressMonitor.cs" /> - <Compile Include="MonoDevelop.Core\IAsyncOperation.cs" /> <Compile Include="MonoDevelop.Core\IProgressMonitor.cs" /> <Compile Include="MonoDevelop.Core.ProgressMonitoring\LogTextWriter.cs" /> - <Compile Include="MonoDevelop.Core.ProgressMonitoring\NullAsyncOperation.cs" /> <Compile Include="MonoDevelop.Core.ProgressMonitoring\ProgressTracker.cs" /> <Compile Include="MonoDevelop.Core.Execution\DefaultExecutionHandler.cs" /> <Compile Include="MonoDevelop.Core.Execution\ExternalConsoleFactory.cs" /> <Compile Include="MonoDevelop.Core.Execution\IConsole.cs" /> <Compile Include="MonoDevelop.Core.Execution\IConsoleFactory.cs" /> <Compile Include="MonoDevelop.Core.Execution\IExecutionHandler.cs" /> - <Compile Include="MonoDevelop.Core.Execution\IProcessAsyncOperation.cs" /> <Compile Include="MonoDevelop.Core.Execution\MonoPlatformExecutionHandler.cs" /> <Compile Include="MonoDevelop.Core.Execution\NativePlatformExecutionHandler.cs" /> - <Compile Include="MonoDevelop.Core.ProgressMonitoring\AggregatedOperationMonitor.cs" /> - <Compile Include="MonoDevelop.Core.ProgressMonitoring\SynchronizedProgressMonitor.cs" /> <Compile Include="MonoDevelop.Core\ClrVersion.cs" /> <Compile Include="MonoDevelop.Core\FileService.cs" /> <Compile Include="MonoDevelop.Core\FileEventArgs.cs" /> @@ -178,7 +171,6 @@ <Compile Include="MonoDevelop.Core.Collections\Set.cs" /> <Compile Include="MonoDevelop.Core.Collections\ReadOnlyDictionary.cs" /> <Compile Include="MonoDevelop.Core\Gettext.cs" /> - <Compile Include="MonoDevelop.Core.ProgressMonitoring\AsyncOperation.cs" /> <Compile Include="MonoDevelop.Core.AddIns\PackageInstalledCondition.cs" /> <Compile Include="MonoDevelop.Core\ComponentModelLocalization.cs" /> <Compile Include="MonoDevelop.Core.AddIns\ITargetRuntimeFactory.cs" /> @@ -224,12 +216,9 @@ <Compile Include="MonoDevelop.Core.Logging\RemoteLogger.cs" /> <Compile Include="MonoDevelop.Core.Instrumentation\TimeCounter.cs" /> <Compile Include="MonoDevelop.Core.AddIns\PlatformCondition.cs" /> - <Compile Include="MonoDevelop.Core.ProgressMonitoring\AggregatedAsyncOperation.cs" /> <Compile Include="MonoDevelop.Core.Serialization\BinaryDataSerializer.cs" /> <Compile Include="MonoDevelop.Core.Execution\LocalConsole.cs" /> <Compile Include="MonoDevelop.Core\IconId.cs" /> - <Compile Include="MonoDevelop.Core.ProgressMonitoring\NullProgressMonitor.cs" /> - <Compile Include="MonoDevelop.Core.ProgressMonitoring\SimpleProgressMonitor.cs" /> <Compile Include="Mono.Options.cs" /> <Compile Include="MonoDevelop.Core.Logging\InstrumentationLogger.cs" /> <Compile Include="MonoDevelop.Core.Instrumentation\TimerCounter.cs" /> @@ -237,12 +226,10 @@ <Compile Include="MonoDevelop.Projects\ProjectService.cs" /> <Compile Include="MonoDevelop.Projects\ProjectPathItemPropertyAttribute.cs" /> <Compile Include="MonoDevelop.Projects\SolutionConfiguration.cs" /> - <Compile Include="MonoDevelop.Projects\SolutionEntityItem.cs" /> <Compile Include="MonoDevelop.Projects\SolutionItemEventArgs.cs" /> <Compile Include="MonoDevelop.Projects\CombineEntryRenamedEventArgs.cs" /> <Compile Include="MonoDevelop.Projects\SolutionItemConfiguration.cs" /> <Compile Include="MonoDevelop.Projects\ProjectConfiguration.cs" /> - <Compile Include="MonoDevelop.Projects\DotNetProjectBinding.cs" /> <Compile Include="MonoDevelop.Projects\DotNetProjectConfiguration.cs" /> <Compile Include="MonoDevelop.Projects\Project.cs" /> <Compile Include="MonoDevelop.Projects\ProjectFile.cs" /> @@ -252,7 +239,6 @@ <Compile Include="MonoDevelop.Projects\ProjectFileCollection.cs" /> <Compile Include="MonoDevelop.Projects\ProjectReferenceCollection.cs" /> <Compile Include="MonoDevelop.Projects\ProjectCreateInformation.cs" /> - <Compile Include="MonoDevelop.Projects\IProjectBinding.cs" /> <Compile Include="MonoDevelop.Projects\IDotNetLanguageBinding.cs" /> <Compile Include="MonoDevelop.Projects\SolutionItemConfigurationCollection.cs" /> <Compile Include="MonoDevelop.Projects\ConfigurationEventHandler.cs" /> @@ -264,8 +250,6 @@ <Compile Include="MonoDevelop.Projects\CustomCommand.cs" /> <Compile Include="MonoDevelop.Projects\CustomCommandType.cs" /> <Compile Include="MonoDevelop.Projects\GenericProject.cs" /> - <Compile Include="MonoDevelop.Projects\GenericProjectBinding.cs" /> - <Compile Include="MonoDevelop.Projects\CustomCommandExtension.cs" /> <Compile Include="MonoDevelop.Projects\ProjectConvertTool.cs" /> <Compile Include="MonoDevelop.Projects\ProjectsServices.cs" /> <Compile Include="MonoDevelop.Projects\UnknownSolutionItem.cs" /> @@ -279,13 +263,11 @@ <Compile Include="MonoDevelop.Projects\WorkspaceItemCollection.cs" /> <Compile Include="MonoDevelop.Projects\WorkspaceItemEventArgs.cs" /> <Compile Include="MonoDevelop.Projects\SolutionEventArgs.cs" /> - <Compile Include="MonoDevelop.Projects\IWorkspaceObject.cs" /> <Compile Include="MonoDevelop.Projects\SolutionConfigurationCollection.cs" /> <Compile Include="MonoDevelop.Projects\ItemConfiguration.cs" /> <Compile Include="MonoDevelop.Projects\ItemConfigurationCollection.cs" /> <Compile Include="MonoDevelop.Projects\IConfigurationTarget.cs" /> <Compile Include="MonoDevelop.Projects\ItemCollection.cs" /> - <Compile Include="MonoDevelop.Projects\SolutionItem.cs" /> <Compile Include="MonoDevelop.Projects\SolutionFolderItemCollection.cs" /> <Compile Include="MonoDevelop.Projects\SolutionItemReference.cs" /> <Compile Include="MonoDevelop.Projects\FileFormat.cs" /> @@ -297,14 +279,10 @@ <Compile Include="MonoDevelop.Projects\FileCopySet.cs" /> <Compile Include="MonoDevelop.Projects\ProjectItem.cs" /> <Compile Include="MonoDevelop.Projects\ProjectItemCollection.cs" /> - <Compile Include="MonoDevelop.Projects\SimpleProjectItem.cs" /> <Compile Include="MonoDevelop.Projects\IFolderItem.cs" /> <Compile Include="MonoDevelop.Projects\IFileItem.cs" /> <Compile Include="MonoDevelop.Projects\ProjectParameters.cs" /> - <Compile Include="MonoDevelop.Projects\ConfigurationParameters.cs" /> <Compile Include="MonoDevelop.Projects\CyclicDependencyException.cs" /> - <Compile Include="MonoDevelop.Projects\DotNetAssemblyProject.cs" /> - <Compile Include="MonoDevelop.Projects\DotNetProjectParameters.cs" /> <Compile Include="MonoDevelop.Projects\ItemConfigurationSelector.cs" /> <Compile Include="MonoDevelop.Projects\SolutionConfigurationSelector.cs" /> <Compile Include="MonoDevelop.Projects\DefaultConfigurationSelector.cs" /> @@ -315,41 +293,31 @@ <Compile Include="MonoDevelop.Projects.Extensions\ItemPropertyCodon.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\LanguageBindingCodon.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\DataTypeCodon.cs" /> - <Compile Include="MonoDevelop.Projects.Extensions\ProjectBindingCodon.cs" /> - <Compile Include="MonoDevelop.Projects.Extensions\ItemTypeNode.cs" /> - <Compile Include="MonoDevelop.Projects.Extensions\DotNetProjectNode.cs" /> - <Compile Include="MonoDevelop.Projects.Extensions\SolutionItemNode.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\SerlializationMapNode.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\IFileFormat.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\FileFormatNode.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\ProjectExtensionUtil.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\ISolutionItemHandler.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\SolutionItemHandler.cs" /> - <Compile Include="MonoDevelop.Projects.Extensions\DotNetProjectSubtypeNode.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\PolicySetNode.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\PolicyNode.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\ItemTypeCondition.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\MonoDocSourceNode.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\ProjectLanguageCondition.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\IResourceHandler.cs" /> - <Compile Include="MonoDevelop.Projects.Extensions\IPathHandler.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\IAssemblyReferenceHandler.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MD1\MD1DotNetProjectHandler.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MD1\MD1FileFormat.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MD1\MD1SolutionEntityItemHandler.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MD1\MD1SolutionItemHandler.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildFileFormat.cs" /> - <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildProjectHandler.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MSBuild\SlnFileFormat.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildProjectService.cs" /> - <Compile Include="MonoDevelop.Projects.Formats.MSBuild\SlnData.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildProject.cs" /> - <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildHandler.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildImportAttribute.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MSBuild\RemoteProjectBuilder.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MSBuild\IMSBuildImportProvider.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MergeToProjectAttribute.cs" /> - <Compile Include="MonoDevelop.Projects.Formats.MSBuild\CompiledAssemblyProjectMSBuildHandler.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MSBuild.Conditions\ConditionAndExpression.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MSBuild.Conditions\ConditionExpression.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MSBuild.Conditions\ConditionFactorExpresion.cs" /> @@ -413,8 +381,6 @@ <Compile Include="MonoDevelop.Core\UserProfile.cs" /> <Compile Include="MonoDevelop.Core\BrandingService.cs" /> <Compile Include="MonoDevelop.Projects\CleanEventHandler.cs" /> - <Compile Include="MonoDevelop.Core.ProgressMonitoring\IProjectLoadProgressMonitor.cs" /> - <Compile Include="MonoDevelop.Core.ProgressMonitoring\WrappedProgressMonitor.cs" /> <Compile Include="MonoDevelop.Core.ProgressMonitoring\ConsoleProjectLoadProgressMonitor.cs" /> <Compile Include="MonoDevelop.Core\SystemInformation.cs" /> <Compile Include="MonoDevelop.Core\MacSystemInformation.cs" /> @@ -430,11 +396,8 @@ <Compile Include="MonoDevelop.Core\PasswordService.cs" /> <Compile Include="MonoDevelop.Core\IPasswordProvider.cs" /> <Compile Include="MonoDevelop.Projects.Utility\ByteOrderMark.cs" /> - <Compile Include="MonoDevelop.Core.Instrumentation\IInstrumentationConsumer.cs" /> - <Compile Include="MonoDevelop.Projects\PortableDotNetProject.cs" /> <Compile Include="MonoDevelop.Core.AddIns\FilePathExtensionNode.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MSBuild\TargetsAvailableCondition.cs" /> - <Compile Include="MonoDevelop.Projects\PortableDotNetProjectBinding.cs" /> <Compile Include="MonoDevelop.Core.AddIns\AssemblyInstalledCondition.cs" /> <Compile Include="MonoDevelop.Core\WebCertificateService.cs" /> <Compile Include="MonoDevelop.Core\IWebCertificateProvider.cs" /> @@ -448,11 +411,8 @@ <Compile Include="MonoDevelop.Core.Logging\AssertLoggingTraceListener.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MD1\MD1ProjectService.cs" /> <Compile Include="MonoDevelop.Projects\UnknownProject.cs" /> - <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildExtension.cs" /> <Compile Include="MonoDevelop.Projects.SharedAssetsProjects\SharedAssetsProject.cs" /> <Compile Include="MonoDevelop.Projects.SharedAssetsProjects\SharedAssetsProjectMSBuildExtension.cs" /> - <Compile Include="MonoDevelop.Projects.SharedAssetsProjects\SharedAssetsProjectMSBuildHandler.cs" /> - <Compile Include="MonoDevelop.Projects.SharedAssetsProjects\SharedAssetsProjectBinding.cs" /> <Compile Include="MonoDevelop.Core\WebRequestHelper.cs" /> <Compile Include="MonoDevelop.Core.Web\IProxyAuthenticationHandler.cs" /> <Compile Include="MonoDevelop.Core.Web\CredentialStore.cs" /> @@ -473,6 +433,55 @@ <Compile Include="MonoDevelop.Projects\IDotNetFileContainer.cs" /> <Compile Include="MonoDevelop.Projects.Formats.MSBuild\IMSBuildGlobalPropertyProvider.cs" /> <Compile Include="MonoDevelop.Projects\DotNetProjectImport.cs" /> + <Compile Include="MonoDevelop.Core.LogReporting\CrashReporter.cs" /> + <Compile Include="MonoDevelop.Core.Instrumentation\InstrumentationConsumer.cs" /> + <Compile Include="MonoDevelop.Projects\DotNetProjectExtension.cs" /> + <Compile Include="MonoDevelop.Projects.Extensions\MSBuildProjectExtensionNode.cs" /> + <Compile Include="MonoDevelop.Projects\ChainedExtension.cs" /> + <Compile Include="MonoDevelop.Projects\ExtensionChain.cs" /> + <Compile Include="MonoDevelop.Projects\SolutionFolderItem.cs" /> + <Compile Include="MonoDevelop.Projects\SolutionItem.cs" /> + <Compile Include="MonoDevelop.Projects\SolutionItemExtension.cs" /> + <Compile Include="MonoDevelop.Projects\WorkspaceItemExtension.cs" /> + <Compile Include="MonoDevelop.Projects\SolutionExtension.cs" /> + <Compile Include="MonoDevelop.Projects.Extensions\ProjectModelExtensionNode.cs" /> + <Compile Include="MonoDevelop.Projects.Extensions\SolutionItemExtensionNode.cs" /> + <Compile Include="MonoDevelop.Projects.Extensions\FlavorTypeCondition.cs" /> + <Compile Include="MonoDevelop.Projects\WorkspaceObject.cs" /> + <Compile Include="MonoDevelop.Projects\WorkspaceObjectExtension.cs" /> + <Compile Include="MonoDevelop.Projects\IProject.cs" /> + <Compile Include="MonoDevelop.Core.Execution\ProcessAsyncOperation.cs" /> + <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildProperty.cs" /> + <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildPropertyGroupMerged.cs" /> + <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildPropertyGroup.cs" /> + <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildItem.cs" /> + <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildItemGroup.cs" /> + <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildEvaluationContext.cs" /> + <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildImport.cs" /> + <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildObject.cs" /> + <Compile Include="MonoDevelop.Projects\IPropertySet.cs" /> + <Compile Include="MonoDevelop.Projects\IMSBuildDataObject.cs" /> + <Compile Include="MonoDevelop.Projects.Formats.MSBuild\IMSBuildPropertySet.cs" /> + <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildPropertyGroupEvaluated.cs" /> + <Compile Include="MonoDevelop.Projects.Formats.MSBuild\SlnFile.cs" /> + <Compile Include="MonoDevelop.Projects.Formats.MSBuild\UnknownSolutionItemTypeException.cs" /> + <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildProjectHandler.cs" /> + <Compile Include="MonoDevelop.Projects\DotNetCompilerParameters.cs" /> + <Compile Include="MonoDevelop.Projects\PortableDotNetProjectFlavor.cs" /> + <Compile Include="MonoDevelop.Projects\SolutionItemFactory.cs" /> + <Compile Include="MonoDevelop.Projects.Extensions\ProjectMigrationHandler.cs" /> + <Compile Include="MonoDevelop.Projects.Extensions\ProjectMigrationHandlerNode.cs" /> + <Compile Include="MonoDevelop.Projects\RegisterProjectModelExtensionAttribute.cs" /> + <Compile Include="MonoDevelop.Projects\RegisterProjectFlavorAttribute.cs" /> + <Compile Include="MonoDevelop.Projects\RegisterSolutionItemTypeAttribute.cs" /> + <Compile Include="MonoDevelop.Projects\RegisterDotNetProject.cs" /> + <Compile Include="MonoDevelop.Projects\RegisterProjectAttribute.cs" /> + <Compile Include="MonoDevelop.Projects.Extensions\SolutionItemTypeNode.cs" /> + <Compile Include="MonoDevelop.Projects.Extensions\ProjectTypeNode.cs" /> + <Compile Include="MonoDevelop.Projects.Extensions\DotNetProjectTypeNode.cs" /> + <Compile Include="MonoDevelop.Projects\ProjectExtension.cs" /> + <Compile Include="MonoDevelop.Core\ProgressMonitor.cs" /> + <Compile Include="MonoDevelop.Core.ProgressMonitoring\ProjectLoadProgressMonitor.cs" /> </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> @@ -560,10 +569,6 @@ <Project>{2B8F4F83-C2B3-4E84-A27B-8DEE1BE0E006}</Project> <Name>ICSharpCode.NRefactory.Cecil</Name> </ProjectReference> - <ProjectReference Include="..\..\..\external\raygun4net\Mindscape.Raygun4Net\Mindscape.Raygun4Net.csproj"> - <Project>{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}</Project> - <Name>Mindscape.Raygun4Net</Name> - </ProjectReference> </ItemGroup> <ItemGroup> <Content Include="MonoDevelop.Core.dll.config"> diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs index b15350f37b..851b1e289c 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; namespace MonoDevelop.Core { @@ -156,6 +157,11 @@ namespace MonoDevelop.Core return new FilePath (path);
} + public Task DeleteAsync () + { + return Task.Factory.StartNew (Delete); + } + public void Delete () { // Ensure that this file/directory and all children are writable diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FileService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FileService.cs index 044704ec37..575e2fcead 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FileService.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FileService.cs @@ -566,6 +566,36 @@ namespace MonoDevelop.Core }
}
}
+
+ /// <summary>
+ /// Renames a directory
+ /// </summary>
+ /// <param name="sourceDir">Source directory</param>
+ /// <param name="destDir">Destination directory</param>
+ /// <remarks>
+ /// It works like Directory.Move, but it supports changing the case of a directory name in case-insensitive file systems
+ /// </remarks>
+ public static void SystemDirectoryRename (string sourceDir, string destDir)
+ {
+ if (Directory.Exists (destDir) && string.Equals (Path.GetFullPath (sourceDir), Path.GetFullPath (destDir), StringComparison.CurrentCultureIgnoreCase)) {
+ // If the destination directory exists but we can't find it with the provided name casing, then it means we are just changing the case
+ var existingDir = Directory.GetDirectories (Path.GetDirectoryName (destDir), Path.GetFileName (destDir)).FirstOrDefault ();
+ if (existingDir == null || (Path.GetFileName (existingDir) == Path.GetFileName (sourceDir))) {
+ var temp = destDir + ".renaming";
+ int n = 0;
+ while (Directory.Exists (temp) || File.Exists (temp))
+ temp = destDir + ".renaming_" + (n++);
+ Directory.Move (sourceDir, temp);
+ try {
+ Directory.Move (temp, destDir);
+ } catch {
+ Directory.Move (temp, sourceDir);
+ }
+ return;
+ }
+ }
+ Directory.Move (sourceDir, destDir);
+ }
/// <summary>
/// Removes the directory if it's empty.
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Gettext.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Gettext.cs index 8bf16f5fc7..8f0327c28e 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Gettext.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Gettext.cs @@ -84,6 +84,8 @@ namespace MonoDevelop.Core // MD is located at $prefix/lib/monodevelop/bin // adding "../../.." should give us $prefix string prefix = Path.Combine (Path.Combine (Path.Combine (location, ".."), ".."), ".."); + if (Platform.IsMac) + prefix = Path.Combine (prefix, "..", "MacOS"); //normalise it prefix = Path.GetFullPath (prefix); //catalogue is installed to "$prefix/share/locale" by default diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/IAsyncOperation.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/IAsyncOperation.cs deleted file mode 100644 index 214e9d7203..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/IAsyncOperation.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// IAsyncOperation.cs -// -// Author: -// Lluis Sanchez Gual -// -// Copyright (C) 2005 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.IO; - -namespace MonoDevelop.Core -{ - public delegate void OperationHandler (IAsyncOperation op); - - public interface IAsyncOperation - { - void Cancel (); - void WaitForCompleted (); - bool IsCompleted { get; } - bool Success { get; } - bool SuccessWithWarnings { get; } - - event OperationHandler Completed; - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/IProgressMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/IProgressMonitor.cs index f8a056ab73..5e4baec441 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/IProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/IProgressMonitor.cs @@ -29,36 +29,70 @@ using System; using System.IO; +using System.Threading; +using System.Threading.Tasks; +using MonoDevelop.Core.ProgressMonitoring; namespace MonoDevelop.Core { - public delegate void MonitorHandler (IProgressMonitor monitor); + public delegate void MonitorHandler (ProgressMonitor monitor); - public interface IProgressMonitor: IDisposable + public interface IProgressMonitorFactory { - void BeginTask (string name, int totalWork); - void BeginStepTask (string name, int totalWork, int stepSize); - void EndTask (); - void Step (int work); - - TextWriter Log { get; } - - void ReportWarning (string message); - - void ReportSuccess (string message); - void ReportError (string message, Exception exception); - - bool IsCancelRequested { get; } - event MonitorHandler CancelRequested; - - // The returned IAsyncOperation object must be thread safe - IAsyncOperation AsyncOperation { get; } - - object SyncRoot { get; } + ProgressMonitor CreateProgressMonitor (); } - - public interface IProgressMonitorFactory + + public class AsyncOperation + { + public static AsyncOperation CompleteOperation = new AsyncOperation (Task.FromResult(0), null); + + protected AsyncOperation () + { + Task = Task.FromResult (0); + } + + public AsyncOperation (Task task, CancellationTokenSource cancellationTokenSource) + { + Task = task; + this.CancellationTokenSource = cancellationTokenSource; + } + + public Task Task { get; protected set; } + + protected CancellationTokenSource CancellationTokenSource { get; set; } + + public bool IsCompleted { + get { return Task.IsCompleted; } + } + + public void Cancel () + { + if (CancellationTokenSource != null) + CancellationTokenSource.Cancel (); + } + + public void WaitForCompleted () + { + Task.Wait (); + } + } + + public class AsyncOperation<T>: AsyncOperation + { + public AsyncOperation (Task<T> task, CancellationTokenSource cancellationTokenSource): base (task, cancellationTokenSource) + { + } + + public new Task<T> Task { + get { return (Task<T>) base.Task; } + } + } + + public static class ProgressMonitorExtensions { - IProgressMonitor CreateProgressMonitor (); + public static ProgressMonitor WithCancellationSource (this ProgressMonitor monitor, CancellationTokenSource cancellationTokenSource) + { + return new AggregatedProgressMonitor (monitor, cancellationTokenSource); + } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs index 1bcbd46c3e..56e1db31f6 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs @@ -32,12 +32,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Diagnostics; - -#if ENABLE_RAYGUN -using System.Threading; -using Mindscape.Raygun4Net; -#endif - +using Mono.Addins; +using MonoDevelop.Core.LogReporting; using MonoDevelop.Core.Logging; using Mono.Unix.Native; @@ -49,9 +45,6 @@ namespace MonoDevelop.Core const string ReportCrashesKey = "MonoDevelop.LogAgent.ReportCrashes"; const string ReportUsageKey = "MonoDevelop.LogAgent.ReportUsage"; -#if ENABLE_RAYGUN - static RaygunClient raygunClient; -#endif static List<ILogger> loggers = new List<ILogger> (); static RemoteLogger remoteLogger; static DateTime timestamp; @@ -66,6 +59,8 @@ namespace MonoDevelop.Core // Thirdparameter shows if the exception is fatal or not public static Func<bool?, Exception, bool, bool?> UnhandledErrorOccured; + static List<CrashReporter> customCrashReporters = new List<CrashReporter> (); + static LoggingService () { var consoleLogger = new ConsoleLogger (); @@ -102,13 +97,6 @@ namespace MonoDevelop.Core timestamp = DateTime.Now; -#if ENABLE_RAYGUN - string raygunKey = BrandingService.GetString ("RaygunApiKey"); - if (raygunKey != null) { - raygunClient = new RaygunClient (raygunKey); - } -#endif - //remove the default trace listener on .NET, it throws up horrible dialog boxes for asserts Debug.Listeners.Clear (); @@ -186,6 +174,18 @@ namespace MonoDevelop.Core RestoreOutputRedirection (); } + public static void RegisterCrashReporter (CrashReporter reporter) + { + lock (customCrashReporters) + customCrashReporters.Add (reporter); + } + + public static void UnregisterCrashReporter (CrashReporter reporter) + { + lock (customCrashReporters) + customCrashReporters.Remove (reporter); + } + internal static void ReportUnhandledException (Exception ex, bool willShutDown) { ReportUnhandledException (ex, willShutDown, false, null); @@ -215,22 +215,10 @@ namespace MonoDevelop.Core if (ReportCrashes.HasValue && !ReportCrashes.Value) return; - var customData = new Hashtable (); - foreach (var cd in SystemInformation.GetDescription ()) - customData[cd.Title ?? ""] = cd.Description; - -#if ENABLE_RAYGUN - if (raygunClient != null) { - ThreadPool.QueueUserWorkItem (delegate { - try { - raygunClient.Send (ex, tags, customData, Runtime.Version.ToString ()); - } catch { - // If we get here then things have gone really wrong - we can't log anything or - // attempt to report anything. Drop any exception that ends up here. - } - }); + lock (customCrashReporters) { + foreach (var cr in customCrashReporters.Concat (AddinManager.GetExtensionObjects<CrashReporter> (true))) + cr.ReportCrash (ex, willShutDown, tags); } -#endif //ensure we don't lose the setting if (ReportCrashes != oldReportCrashes) { @@ -549,5 +537,4 @@ namespace MonoDevelop.Core #endregion } - } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Platform.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Platform.cs index cbcf9f619b..c973fa6308 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Platform.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Platform.cs @@ -35,11 +35,16 @@ namespace MonoDevelop.Core { public readonly static bool IsWindows; public readonly static bool IsMac; - + public readonly static bool IsLinux; + + public static Version OSVersion { get; private set; } + static Platform () { IsWindows = Path.DirectorySeparatorChar == '\\'; IsMac = !IsWindows && IsRunningOnMac (); + IsLinux = !IsMac && !IsWindows; + OSVersion = Environment.OSVersion.Version; // needed to make sure various p/invokes work if (Platform.IsWindows) { @@ -83,12 +88,31 @@ namespace MonoDevelop.Core static void InitMacFoundation () { dlopen ("/System/Library/Frameworks/Foundation.framework/Foundation", 0x1); + OSVersion = new Version (Gestalt ("sys1"), Gestalt ("sys2"), Gestalt ("sys3")); } [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool SetDllDirectory (string lpPathName); + [System.Runtime.InteropServices.DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")] + static extern int Gestalt (int selector, out int result); + + //TODO: there are other gestalt selectors that return info we might want to display + //mac API for obtaining info about the system + static int Gestalt (string selector) + { + System.Diagnostics.Debug.Assert (selector != null && selector.Length == 4); + int cc = selector[3] | (selector[2] << 8) | (selector[1] << 16) | (selector[0] << 24); + int result; + int ret = Gestalt (cc, out result); + if (ret != 0) { + LoggingService.LogError ("Error reading gestalt for selector '{0}': {1}", selector, ret); + return 0; + } + return result; + } + static void InitWindowsNativeLibs () { string location = null; diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/ProgressMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/ProgressMonitor.cs new file mode 100644 index 0000000000..66b7c8a6a9 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/ProgressMonitor.cs @@ -0,0 +1,673 @@ +// +// ProgressMonitor.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Linq; +using System.IO; +using System.Threading; +using MonoDevelop.Core.ProgressMonitoring; +using System.Collections.Generic; + +namespace MonoDevelop.Core +{ + public class ProgressMonitor: IDisposable + { + ProgressTask currentTask; + ProgressTask parentRootTask; + ProgressTask rootTask; + + LogTextWriter logWriter; + LogTextWriter errorLogWriter; + TextWriter customLogWriter; + TextWriter customErrorLogWriter; + + int openStepWork = -1; + ProgressMonitor parentMonitor; + SynchronizationContext context; + + List<ProgressError> errors = new List<ProgressError> (); + List<string> warnings = new List<string> (); + List<string> messages = new List<string> (); + + List<ProgressMonitor> slaveMonitors; + + public ProgressMonitor (): this (null, null) + { + } + + public ProgressMonitor (SynchronizationContext context): this (context, null) + { + } + + public ProgressMonitor (CancellationTokenSource cancellationTokenSource): this (null, cancellationTokenSource) + { + } + + public ProgressMonitor (SynchronizationContext context, CancellationTokenSource cancellationTokenSource) + { + this.cancellationTokenSource = cancellationTokenSource; + this.context = context; + logWriter = new LogTextWriter (); + logWriter.TextWritten += OnWriteLog; + + errorLogWriter = new LogTextWriter (); + errorLogWriter.TextWritten += OnWriteErrorLog; + } + + void SetParentTask (ProgressMonitor parent, ProgressTask task, int work) + { + parentMonitor = parent; + currentTask = parentRootTask = task; + openStepWork = work; + } + + public virtual void Dispose () + { + var t = parentRootTask; + parentRootTask = null; + while (currentTask != t && currentTask != null) + EndTask (); + + if (context != null) + context.Post ((o) => OnCompleted (), null); + else + OnCompleted (); + + if (slaveMonitors != null) { + foreach (var m in slaveMonitors) + m.Dispose (); + } + } + + protected void AddSlaveMonitor (ProgressMonitor monitor) + { + if (slaveMonitors == null) + slaveMonitors = new List<ProgressMonitor> (); + slaveMonitors.Add (monitor); + logWriter.ChainWriter (monitor.Log); + errorLogWriter.ChainWriter (monitor.ErrorLog); + } + + protected void RemoveSlaveMonitor (ProgressMonitor monitor) + { + if (slaveMonitors == null) + return; + slaveMonitors.Remove (monitor); + logWriter.UnchainWriter (monitor.Log); + errorLogWriter.UnchainWriter (monitor.ErrorLog); + } + + public ProgressTask CurrentTask { + get { + var t = currentTask; + while (t != null && t.Name == null) + t = t.ParentTask; + return t; + } + } + + public string CurrentTaskName { + get { + var t = CurrentTask; + return t != null ? t.Name ?? "" : ""; + } + } + + public IEnumerable<ProgressTask> GetRootTasks () + { + var t = rootTask; + if (t.Name != null) + return new [] {t}; + return t.GetChildrenTasks (); + } + + public IDisposable BeginTask (string name, int totalWork) + { + var t = new ProgressTask (this, name, totalWork); + if (openStepWork != -1) { + t.StepWork = openStepWork; + openStepWork = -1; + } + if (currentTask == null) + rootTask = t; + else + currentTask.AddChild (t); + + currentTask = t; + + if (name != null) { + if (context != null) + context.Post ((o) => OnBeginTask (name, totalWork, t.StepWork), null); + else + OnBeginTask (name, totalWork, t.StepWork); + } + + ReportProgressChanged (); + + if (slaveMonitors != null) { + foreach (var m in slaveMonitors) + m.BeginTask (name, totalWork); + } + return t; + } + + public void BeginTask (int totalWork) + { + BeginTask (null, totalWork); + } + + public void EndTask () + { + if (currentTask != null && currentTask != parentRootTask) { + openStepWork = -1; + var t = currentTask; + currentTask = t.ParentTask; + if (currentTask == null) + rootTask = null; + t.SetComplete (); + if (t.Name != null) { + if (context != null) + context.Post ((o) => OnEndTask (t.Name, t.TotalWork, t.StepWork), null); + else + OnEndTask (t.Name, t.TotalWork, t.StepWork); + } + } else + throw new InvalidOperationException ("Task not started"); + + ReportProgressChanged (); + + if (slaveMonitors != null) { + foreach (var m in slaveMonitors) + m.EndTask (); + } + } + + internal void EndTask (ProgressTask task) + { + while (currentTask != null && currentTask != task) + EndTask (); + EndTask (); + } + + public void Step (int work = 1) + { + Step (null, work); + } + + public void Step (string message, int work = 1) + { + if (currentTask == null) + throw new InvalidOperationException ("Task not started"); + if (work < 0) + throw new ArgumentException ("work can't be negative"); + + ConsumePendingWork (); + currentTask.Step (message, work); + + if (context != null) + context.Post ((o) => { + OnStep (message, work); + ReportProgressChanged (); + }, null); + else { + OnStep (message, work); + ReportProgressChanged (); + } + + if (slaveMonitors != null) { + foreach (var m in slaveMonitors) + m.Step (message, work); + } + } + + public void BeginStep (int work = 1) + { + BeginStep (null, work); + } + + public void BeginStep (string message, int work = 1) + { + if (currentTask == null) + throw new InvalidOperationException ("Task not started in progress monitor"); + if (work < 0) + throw new ArgumentException ("work can't be negative"); + + ConsumePendingWork (); + + openStepWork = work; + if (message != null) + currentTask.Step (message, 0); + + ReportProgressChanged (); + + if (slaveMonitors != null) { + foreach (var m in slaveMonitors) + m.BeginStep (message, work); + } + } + + public void EndStep () + { + ConsumePendingWork (); + + if (slaveMonitors != null) { + foreach (var m in slaveMonitors) + m.EndStep (); + } + } + + void ConsumePendingWork () + { + if (openStepWork != -1) { + currentTask.Step (null, openStepWork); + openStepWork = -1; + } + } + + public ProgressMonitor BeginAsyncStep (int work) + { + return BeginAsyncStep (null, work); + } + + public ProgressMonitor BeginAsyncStep (string message, int work) + { + if (currentTask == null) + throw new InvalidOperationException ("Task not started in progress monitor"); + if (work < 0) + throw new ArgumentException ("work can't be negative"); + + ConsumePendingWork (); + if (message != null) + currentTask.Step (message, 0); + + ProgressMonitor m = null; + if (context != null) + context.Send ((o) => m = CreateAsyncStepMonitor (), null); + else + m = CreateAsyncStepMonitor (); + + m.SetParentTask (this, currentTask, work); + + if (context != null) { + context.Post ((o) => { + OnBeginAsyncStep (message, work, m); + ReportProgressChanged (); + }, null); + } else { + OnBeginAsyncStep (message, work, m); + ReportProgressChanged (); + } + + if (slaveMonitors != null) { + foreach (var sm in slaveMonitors) + m.AddSlaveMonitor (sm.BeginAsyncStep (message, work)); + } + return m; + } + + public void ReportWarning (string message) + { + if (parentMonitor != null) + parentMonitor.ReportWarning (message); + lock (warnings) + warnings.Add (message); + + if (context != null) + context.Post ((o) => OnWarningReported (message), null); + else + OnWarningReported (message); + + if (slaveMonitors != null) { + foreach (var sm in slaveMonitors) + sm.ReportWarning (message); + } + } + + public void ReportSuccess (string message) + { + if (parentMonitor != null) + parentMonitor.ReportSuccess (message); + lock (messages) + messages.Add (message); + + if (context != null) + context.Post ((o) => OnSuccessReported (message), null); + else + OnSuccessReported (message); + + if (slaveMonitors != null) { + foreach (var sm in slaveMonitors) + sm.ReportSuccess (message); + } + } + + public void ReportError (string message, Exception exception = null) + { + if (parentMonitor != null) + parentMonitor.ReportError (message, exception); + + var msg = message; + if (message == null && exception != null) + msg = exception.Message; + + lock (errors) + errors.Add (new ProgressError (msg, exception)); + + if (context != null) + context.Post ((o) => OnErrorReported (msg, exception), null); + else + OnErrorReported (msg, exception); + + if (slaveMonitors != null) { + foreach (var sm in slaveMonitors) + sm.ReportError (message, exception); + } + } + + public bool HasErrors { + get { + lock (errors) + return errors.Count > 0; + } + } + + public bool HasWarnings { + get { + lock (warnings) + return warnings.Count > 0; + } + } + + public string[] SuccessMessages { + get { + lock (messages) + return messages.ToArray (); + } + } + + public string[] Warnings { + get { + lock (warnings) + return warnings.ToArray (); + } + } + + public ProgressError[] Errors { + get { + lock (errors) + return errors.ToArray (); + } + } + + public TextWriter Log { + get { + if (parentMonitor != null) + return parentMonitor.Log; + return logWriter; + } + protected set { + if (parentMonitor != null) + throw new InvalidOperationException ("Log writter can't be modified"); + if (customLogWriter != null) + logWriter.UnchainWriter (customLogWriter); + customLogWriter = value; + logWriter.ChainWriter (customLogWriter); + } + } + + public TextWriter ErrorLog { + get { + if (parentMonitor != null) + return parentMonitor.ErrorLog; + return errorLogWriter ?? Log; + } + protected set { + if (parentMonitor != null) + throw new InvalidOperationException ("Log writter can't be modified"); + if (customErrorLogWriter != null) + errorLogWriter.UnchainWriter (customErrorLogWriter); + customErrorLogWriter = value; + errorLogWriter.ChainWriter (customErrorLogWriter); + } + } + + public CancellationToken CancellationToken { + get { + if (parentMonitor != null) + return parentMonitor.CancellationToken; + else + return CancellationTokenSource.Token; + } + } + + public double Progress { + get { + return rootTask != null ? rootTask.Progress : 0; + } + } + + public bool ProgressIsUnknown { + get { + return rootTask == null; + } + } + + CancellationTokenSource cancellationTokenSource; + + protected CancellationTokenSource CancellationTokenSource { + get { + if (cancellationTokenSource == null) + cancellationTokenSource = new CancellationTokenSource (); + return cancellationTokenSource; + } set { + cancellationTokenSource = value; + } + } + + protected virtual void OnBeginTask (string name, int totalWork, int stepWork) + { + } + + protected virtual void OnEndTask (string name, int totalWork, int stepWork) + { + } + + protected virtual void OnStep (string message, int work) + { + } + + protected virtual void OnBeginAsyncStep (string message, int work, ProgressMonitor stepMonitor) + { + } + + protected virtual ProgressMonitor CreateAsyncStepMonitor () + { + return new ProgressMonitor (); + } + + protected virtual void OnSuccessReported (string message) + { + } + + protected virtual void OnWarningReported (string message) + { + } + + protected virtual void OnErrorReported (string message, Exception exception) + { + } + + protected virtual void OnWriteLog (string message) + { + } + + protected virtual void OnWriteErrorLog (string message) + { + } + + void ReportProgressChanged () + { + OnProgressChanged (); + if (parentMonitor != null) + parentMonitor.ReportProgressChanged (); + } + + protected virtual void OnProgressChanged () + { + } + + protected virtual void OnCompleted () + { + } + } + + public class ProgressTask: IDisposable + { + List<ProgressTask> childrenTasks = new List<ProgressTask> (); + + double currentWork; + double completedChildrenWork; + ProgressMonitor monitor; + + internal ProgressTask (ProgressMonitor monitor, string name, int totalWork) + { + this.monitor = monitor; + Name = name; + TotalWork = totalWork; + StepWork = -1; + } + + public int StepWork { get; set; } + + bool HasStepWork { + get { return StepWork != -1; } + } + + public string Name { get; private set; } + + public double Progress { get; private set; } + + public string StatusMessage { get; internal set; } + + public int TotalWork { get; private set; } + + public ProgressTask ParentTask { get; private set; } + + public ProgressTask[] GetChildrenTasks () + { + List<ProgressTask> children = new List<ProgressTask> (); + lock (childrenTasks) { + foreach (var t in childrenTasks) { + if (t.Name == null) + children.AddRange (t.GetChildrenTasks ()); + else + children.Add (t); + } + } + return children.ToArray (); + } + + internal void AddChild (ProgressTask task) + { + task.ParentTask = this; + lock (childrenTasks) + childrenTasks.Add (task); + } + + internal void Step (string message, double work) + { + if (message != null) + StatusMessage = message; + + IncCurrentWork (work); + } + + internal void SetComplete () + { + lock (childrenTasks) { + currentWork = TotalWork; + completedChildrenWork = 0; + Progress = 1; + if (ParentTask != null) + ParentTask.SetChildComplete (this); + } + } + + void SetChildComplete (ProgressTask child) + { + child.ParentTask = null; + lock (childrenTasks) { + if (child.HasStepWork) + currentWork += child.StepWork; + childrenTasks.Remove (child); + } + UpdateProgressFromChildren (); + } + + void IncCurrentWork (double work) + { + lock (childrenTasks) { + currentWork += work; + Progress = Math.Min (currentWork + completedChildrenWork, (double)TotalWork) / (double)TotalWork; + if (ParentTask != null && HasStepWork) + ParentTask.UpdateProgressFromChildren (); + } + } + + void UpdateProgressFromChildren () + { + lock (childrenTasks) { + completedChildrenWork = childrenTasks.Where (t => t.HasStepWork).Sum (t => t.Progress * (double)t.StepWork); + IncCurrentWork (0); + } + } + + void IDisposable.Dispose () + { + monitor.EndTask (this); + } + } + + public class ProgressError + { + Exception ex; + string message; + + public ProgressError (string message, Exception ex) + { + this.ex = ex; + this.message = message; + } + + public string Message { + get { return message; } + } + + public Exception Exception { + get { return ex; } + } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs index 653f215e61..53429cd8a2 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs @@ -54,6 +54,7 @@ namespace MonoDevelop.Core static ApplicationService applicationService; static bool initialized; static SynchronizationContext mainSynchronizationContext; + static SynchronizationContext defaultSynchronizationContext; public static void GetAddinRegistryLocation (out string configDir, out string addinsDir, out string databaseDir) { @@ -80,10 +81,12 @@ namespace MonoDevelop.Core SetupInstrumentation (); Platform.Initialize (); + + defaultSynchronizationContext = new SynchronizationContext (); // Set a default sync context if (SynchronizationContext.Current == null) - SynchronizationContext.SetSynchronizationContext (new SynchronizationContext ()); + SynchronizationContext.SetSynchronizationContext (defaultSynchronizationContext); // Hook up the SSL certificate validation codepath ServicePointManager.ServerCertificateValidationCallback += delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { @@ -281,7 +284,7 @@ namespace MonoDevelop.Core public static SynchronizationContext MainSynchronizationContext { get { - return mainSynchronizationContext ?? SynchronizationContext.Current; + return mainSynchronizationContext ?? defaultSynchronizationContext; } set { if (mainSynchronizationContext != null && value != null) @@ -327,10 +330,10 @@ namespace MonoDevelop.Core internal static class Counters { - public static TimerCounter RuntimeInitialization = InstrumentationService.CreateTimerCounter ("Runtime initialization", "Runtime"); + public static TimerCounter RuntimeInitialization = InstrumentationService.CreateTimerCounter ("Runtime initialization", "Runtime", id:"Core.RuntimeInitialization"); public static TimerCounter PropertyServiceInitialization = InstrumentationService.CreateTimerCounter ("Property Service initialization", "Runtime"); - public static Counter AddinsLoaded = InstrumentationService.CreateCounter ("Add-ins loaded", "Add-in Engine", true); + public static Counter AddinsLoaded = InstrumentationService.CreateCounter ("Add-ins loaded", "Add-in Engine", true, id:"Core.AddinsLoaded"); public static Counter ProcessesStarted = InstrumentationService.CreateCounter ("Processes started", "Process Service"); public static Counter ExternalObjects = InstrumentationService.CreateCounter ("External objects", "Process Service"); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/DotNetProjectNode.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/DotNetProjectNode.cs deleted file mode 100644 index 1b0759072d..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/DotNetProjectNode.cs +++ /dev/null @@ -1,77 +0,0 @@ -// MSBuildDotNetProjectExtensionNode.cs -// -// Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2008 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// - -using System; -using Mono.Addins; -using MonoDevelop.Core; -using MonoDevelop.Projects.Formats.MSBuild; -using MonoDevelop.Projects.Extensions; - -namespace MonoDevelop.Projects.Extensions -{ - public class DotNetProjectNode: ItemTypeNode - { - [NodeAttribute (Required=true)] - string language = null; - - [NodeAttribute] - string resourceHandler = null; - - public override bool CanHandleItem (SolutionEntityItem item) - { - return (item is DotNetProject) && ((DotNetProject)item).LanguageName == language; - } - - public override bool CanHandleFile (string fileName, string typeGuid) - { - if (base.CanHandleFile (fileName, typeGuid)) - return true; - else if (!string.IsNullOrEmpty (typeGuid) && typeGuid.Contains (Guid)) - { - DotNetProjectSubtypeNode node = MSBuildProjectService.GetDotNetProjectSubtype (typeGuid); - if (node != null && node.CanHandleFile (fileName, typeGuid)) - return true; - } - return false; - } - - public override SolutionEntityItem LoadSolutionItem (IProgressMonitor monitor, string fileName, MSBuildFileFormat expectedFormat, string itemGuid) - { - MSBuildProjectHandler handler = CreateHandler<MSBuildProjectHandler> (fileName, itemGuid); - handler.SetCustomResourceHandler (GetResourceHandler ()); - return handler.Load (monitor, fileName, expectedFormat, language, null); - } - - public IResourceHandler GetResourceHandler () - { - if (!string.IsNullOrEmpty (resourceHandler)) - return (IResourceHandler) Addin.CreateInstance (resourceHandler, true); - else - return new MSBuildResourceHandler (); - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/DotNetProjectSubtypeNode.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/DotNetProjectSubtypeNode.cs deleted file mode 100644 index 2da66dcfa6..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/DotNetProjectSubtypeNode.cs +++ /dev/null @@ -1,214 +0,0 @@ -// DotNetProjectSubtype.cs -// -// Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2008 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// - -using System; -using System.Linq; -using Mono.Addins; -using MonoDevelop.Projects.Formats.MSBuild; -using System.Collections.Generic; -using MonoDevelop.Core; - -namespace MonoDevelop.Projects.Extensions -{ - [ExtensionNodeChild (typeof(DotNetProjectSubtypeNodeImport), "AddImport")] - [ExtensionNodeChild (typeof(DotNetProjectSubtypeNodeImport), "RemoveImport")] - public class DotNetProjectSubtypeNode: ExtensionNode - { - #pragma warning disable 649 - - [NodeAttribute] - string guid = null; - - [NodeAttribute] - string type = null; - - [NodeAttribute] - string import = null; - - [NodeAttribute] - string extension = null; - - [NodeAttribute] - string exclude = null; - - [NodeAttribute] - bool useXBuild = false; - - [NodeAttribute] - bool requireXBuild = true; - - [NodeAttribute] - string migrationHandler; - - [NodeAttribute] - bool migrationRequired = true; - - #pragma warning restore 649 - - Type itemType; - - public string Import { - get { - return import; - } - } - - public Type Type { - get { - if (itemType == null) { - itemType = Addin.GetType (type, true); - if (!typeof(MonoDevelop.Projects.DotNetProject).IsAssignableFrom (itemType)) - throw new InvalidOperationException ("Type must be a subclass of DotNetProject"); - } - return itemType; - } - } - - public string Extension { - get { - return extension; - } - } - - public string Exclude { - get { - return exclude; - } - } - - public string Guid { - get { return guid; } - } - - public bool UseXBuild { - get { return useXBuild; } - } - - public bool RequireXBuild { - get { return useXBuild && requireXBuild; } - } - - public bool IsMigration { - get { return migrationHandler != null; } - } - - public bool IsMigrationRequired { - get { return migrationRequired; } - } - - public IDotNetSubtypeMigrationHandler MigrationHandler { - get { return (IDotNetSubtypeMigrationHandler) Addin.CreateInstance (migrationHandler); } - } - - public bool SupportsType (string guid) - { - return string.Compare (this.guid, guid, true) == 0; - } - - public DotNetProject CreateInstance (string language) - { - return (DotNetProject) Activator.CreateInstance (Type, language); - } - - public virtual bool CanHandleItem (SolutionEntityItem item) - { - return !(IsMigration && IsMigrationRequired) && Type.IsAssignableFrom (item.GetType ()); - } - - public virtual bool CanHandleType (Type type) - { - return !(IsMigration && IsMigrationRequired) && Type.IsAssignableFrom (type); - } - - public virtual bool CanHandleFile (string fileName, string typeGuid) - { - if (typeGuid != null && typeGuid.ToLower().Contains(guid.ToLower())) - return true; - if (!string.IsNullOrEmpty (extension) && System.IO.Path.GetExtension (fileName) == "." + extension) - return true; - return false; - } - - public virtual void InitializeHandler (SolutionEntityItem item) - { - MSBuildProjectHandler h = (MSBuildProjectHandler) ProjectExtensionUtil.GetItemHandler (item); - UpdateImports (item, h.TargetImports); - h.SubtypeGuids.Add (guid); - h.UseMSBuildEngineByDefault |= UseXBuild; - h.RequireMSBuildEngine |= RequireXBuild; - } - - public void UpdateImports (SolutionEntityItem item, List<string> imports) - { - DotNetProject p = (DotNetProject) item; - if (!string.IsNullOrEmpty (import)) - imports.AddRange (import.Split (':')); - if (!string.IsNullOrEmpty (exclude)) - exclude.Split (':').ToList ().ForEach (i => imports.Remove (i)); - - foreach (DotNetProjectSubtypeNodeImport iob in ChildNodes) { - if (iob.Language == p.LanguageName) { - if (iob.IsAdd) - imports.AddRange (iob.Projects.Split (':')); - else - iob.Projects.Split (':').ToList ().ForEach (i => imports.Remove (i)); - } - } - } - } - - class DotNetProjectSubtypeNodeImport: ExtensionNode - { - protected override void Read (NodeElement elem) - { - IsAdd = elem.NodeName == "AddImport"; - base.Read (elem); - } - - [NodeAttribute ("language")] - public string Language { get; set; } - - [NodeAttribute ("projects")] - public string Projects { get; set; } - - public bool IsAdd { get; private set; } - } - - public interface IDotNetSubtypeMigrationHandler - { - IEnumerable<string> FilesToBackup (string filename); - Type Migrate (IProjectLoadProgressMonitor monitor, MSBuildProject project, string fileName, string language); - bool CanPromptForMigration { get; } - MigrationType PromptForMigration (IProjectLoadProgressMonitor monitor, MSBuildProject project, string fileName, string language); - } - - public enum MigrationType { - Ignore, - Migrate, - BackupAndMigrate, - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemNode.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/DotNetProjectTypeNode.cs index 1dc81dafca..2a75bcf347 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemNode.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/DotNetProjectTypeNode.cs @@ -1,4 +1,4 @@ -// SolutionItemNode.cs +// MSBuildDotNetProjectExtensionNode.cs // // Author: // Lluis Sanchez Gual <lluis@novell.com> @@ -26,32 +26,34 @@ // using System; -using System.IO; -using System.Xml; using Mono.Addins; -using MonoDevelop.Projects.Formats.MSBuild; using MonoDevelop.Core; +using MonoDevelop.Projects.Formats.MSBuild; +using MonoDevelop.Projects.Extensions; +using System.Threading.Tasks; +using System.Collections.Generic; namespace MonoDevelop.Projects.Extensions { - public class SolutionItemNode: ItemTypeNode + [ExtensionNode (ExtensionAttributeType=typeof(RegisterDotNetProjectTypeAttribute))] + public class DotNetProjectTypeNode: ProjectTypeNode { [NodeAttribute (Required=true)] - string type = null; + string language = null; - public Type ItemType { - get { return Addin.GetType (type, true); } + public string Language { + get { return language; } } - public override bool CanHandleItem (SolutionEntityItem item) + public DotNetProjectTypeNode () { - return ItemType != null && ItemType.IsAssignableFrom (item.GetType ()); + Alias = "DotNet"; } - - public override SolutionEntityItem LoadSolutionItem (IProgressMonitor monitor, string fileName, MSBuildFileFormat expectedFormat, string itemGuid) + + public override bool CanCreateSolutionItem (string type, ProjectCreateInformation info, System.Xml.XmlElement projectOptions) { - MSBuildProjectHandler handler = CreateHandler<MSBuildProjectHandler> (fileName, itemGuid); - return handler.Load (monitor, fileName, expectedFormat, null, ItemType); + string lang = projectOptions.GetAttribute ("language"); + return base.CanCreateSolutionItem (type, info, projectOptions) && lang == Language; } } -}
\ No newline at end of file +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/IPathHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/FlavorTypeCondition.cs index e987803100..855a09dd15 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/IPathHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/FlavorTypeCondition.cs @@ -1,21 +1,21 @@ -// -// ISolutionItemHandler.cs -// +// +// FlavorCondition.cs +// // Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,19 +23,24 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - using System; -using MonoDevelop.Core; +using System.Linq; namespace MonoDevelop.Projects.Extensions { - /// <summary> - /// This interface can be implemented by a ISolutionItemHandler class to provide - /// custom rules for encoding and decoding paths - /// </summary> - public interface IPathHandler + public class FlavorTypeCondition: ItemTypeCondition { - string EncodePath (string path, string oldPath); - string DecodePath (string path); + Project project; + + public FlavorTypeCondition (Project project) + { + this.project = project; + } + + protected override System.Collections.Generic.IEnumerable<Type> GetObjectTypes () + { + return project.GetFlavors ().Select (e => e.GetType ()); + } } } + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/IFileFormat.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/IFileFormat.cs index 6c02e7d1f2..2a24523429 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/IFileFormat.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/IFileFormat.cs @@ -30,6 +30,7 @@ using System; using MonoDevelop.Core; using System.Collections.Generic; +using System.Threading.Tasks; namespace MonoDevelop.Projects.Extensions { @@ -48,10 +49,10 @@ namespace MonoDevelop.Projects.Extensions // Makes the required changes in the object to support this file format. // It usually means setting the ISolutionItemHandler of the item. - void ConvertToFormat (object obj);
+ Task ConvertToFormat (object obj);
- void WriteFile (FilePath file, object obj, IProgressMonitor monitor);
- object ReadFile (FilePath file, Type expectedType, IProgressMonitor monitor); + Task WriteFile (FilePath file, object obj, ProgressMonitor monitor);
+ Task<object> ReadFile (FilePath file, Type expectedType, ProgressMonitor monitor); // Returns the list of files where the object is stored
List<FilePath> GetItemFiles (object obj); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ISolutionItemHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ISolutionItemHandler.cs index 83b0603b79..636abf31a4 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ISolutionItemHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ISolutionItemHandler.cs @@ -27,6 +27,7 @@ using System; using MonoDevelop.Core; +using System.Threading.Tasks; namespace MonoDevelop.Projects.Extensions { @@ -50,7 +51,7 @@ namespace MonoDevelop.Projects.Extensions /// <param name='configuration'> /// Selector to be used to get the target configuration /// </param> - BuildResult RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration); + Task<BuildResult> RunTarget (ProgressMonitor monitor, string target, ConfigurationSelector configuration); /// <summary> /// Saves the solution item @@ -58,7 +59,7 @@ namespace MonoDevelop.Projects.Extensions /// <param name='monitor'> /// A progress monitor /// </param> - void Save (IProgressMonitor monitor); + Task Save (ProgressMonitor monitor); /// <summary> /// Gets a value indicating whether the name of the solution item should be the same as the name of the file diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ItemTypeCondition.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ItemTypeCondition.cs index 48824db647..5bd95f10eb 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ItemTypeCondition.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ItemTypeCondition.cs @@ -34,7 +34,7 @@ namespace MonoDevelop.Projects.Extensions public class ItemTypeCondition: ConditionType { Type objType; - List<string> typeNames; + HashSet<string> typeNames; IDictionary<string,string> aliases; public ItemTypeCondition () @@ -87,7 +87,7 @@ namespace MonoDevelop.Projects.Extensions aliases [alias] = fullName; } - bool MatchesType (string type) + protected bool MatchesType (string type) { if (type.IndexOf ('.') == -1) { string res; @@ -106,29 +106,36 @@ namespace MonoDevelop.Projects.Extensions // use of the condition. if (typeNames == null) { - typeNames = new List<string> (); - - typeNames.Add (objType.FullName); - typeNames.Add (objType.AssemblyQualifiedName); + typeNames = new HashSet<string> (); + + foreach (var t in GetObjectTypes ()) { + typeNames.Add (t.FullName); + typeNames.Add (t.AssemblyQualifiedName); - // base class hierarchy + // base class hierarchy - Type baseType = objType.BaseType; - while (baseType != null) { - typeNames.Add (baseType.FullName); - typeNames.Add (baseType.AssemblyQualifiedName); - baseType = baseType.BaseType; - } + Type baseType = t.BaseType; + while (baseType != null) { + typeNames.Add (baseType.FullName); + typeNames.Add (baseType.AssemblyQualifiedName); + baseType = baseType.BaseType; + } - // Implemented interfaces + // Implemented interfaces - Type[] interfaces = objType.GetInterfaces(); - foreach (Type itype in interfaces) { - typeNames.Add (itype.FullName); - typeNames.Add (itype.AssemblyQualifiedName); + Type[] interfaces = t.GetInterfaces (); + foreach (Type itype in interfaces) { + typeNames.Add (itype.FullName); + typeNames.Add (itype.AssemblyQualifiedName); + } } } return typeNames.Contains (type); } + + protected virtual IEnumerable<Type> GetObjectTypes () + { + yield return objType; + } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/MSBuildProjectExtensionNode.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/MSBuildProjectExtensionNode.cs new file mode 100644 index 0000000000..85daa23c06 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/MSBuildProjectExtensionNode.cs @@ -0,0 +1,46 @@ +// +// MSBuildProjectExtensionNode.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Mono.Addins; + +namespace MonoDevelop.Projects.Extensions +{ + public class MSBuildProjectExtensionNode: TypeExtensionNode + { + [NodeAttribute (Description = "GUID of the extension. The extension will be loaded if the project has this GUID in the project type GUID list. " + + "If not specified, the SupportsItem method will be called on the extension to determine if it is supported or not.")] + string guid; + + public MSBuildProjectExtensionNode () + { + } + + public string Guid { + get { return guid; } + } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectBindingCodon.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectBindingCodon.cs deleted file mode 100644 index c0cda37f63..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectBindingCodon.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// ProjectBindingCodon.cs -// -// Author: -// Lluis Sanchez Gual -// - -// -// Copyright (C) 2005 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - - -using System; -using System.Collections; -using System.ComponentModel; - -using Mono.Addins; -using MonoDevelop.Projects; - -namespace MonoDevelop.Projects.Extensions -{ - [ExtensionNode (Description="A project binding. The specified class must implement MonoDevelop.Projects.IProjectBinding.")] - internal class ProjectBindingCodon : TypeExtensionNode - { - public IProjectBinding ProjectBinding { - get { return (IProjectBinding) base.GetInstance (); } - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectExtensionUtil.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectExtensionUtil.cs index 6004da536e..926dcf07e8 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectExtensionUtil.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectExtensionUtil.cs @@ -30,6 +30,7 @@ using System.IO; using System.Collections.Generic; using System.Threading; using MonoDevelop.Core; +using System.Threading.Tasks; namespace MonoDevelop.Projects.Extensions { @@ -43,28 +44,13 @@ namespace MonoDevelop.Projects.Extensions loadControlSlot = Thread.AllocateDataSlot (); } - public static ISolutionItemHandler GetItemHandler (SolutionItem item) - { - return item.GetItemHandler (); - } - - public static void InstallHandler (ISolutionItemHandler handler, SolutionItem item) - { - item.SetItemHandler (handler); - } - - public static SolutionEntityItem LoadSolutionItem (IProgressMonitor monitor, string fileName, ItemLoadCallback callback) + public async static Task<SolutionItem> LoadSolutionItem (ProgressMonitor monitor, string fileName, ItemLoadCallback callback) { using (Counters.ReadSolutionItem.BeginTiming ("Read project " + fileName)) { - return Services.ProjectService.GetExtensionChain (null).LoadSolutionItem (monitor, fileName, callback); + return await Services.ProjectService.GetExtensionChain (null).LoadSolutionItem (monitor, fileName, callback); } } - - public static BuildResult Compile (IProgressMonitor monitor, SolutionEntityItem item, BuildData buildData, ItemCompileCallback callback) - { - return Services.ProjectService.GetExtensionChain (item).Compile (monitor, item, buildData, callback); - } - + public static void BeginLoadOperation () { Interlocked.Increment (ref loading); @@ -94,28 +80,6 @@ namespace MonoDevelop.Projects.Extensions if (op != null) op.Add (rc); } - - public static string EncodePath (SolutionEntityItem item, string path, string oldPath) - { - IPathHandler ph = item.GetItemHandler () as IPathHandler; - if (ph != null) - return ph.EncodePath (path, oldPath); - else { - string basePath = Path.GetDirectoryName (item.FileName); - return FileService.RelativeToAbsolutePath (basePath, path); - } - } - - public static string DecodePath (SolutionEntityItem item, string path) - { - IPathHandler ph = item.GetItemHandler () as IPathHandler; - if (ph != null) - return ph.DecodePath (path); - else { - string basePath = Path.GetDirectoryName (item.FileName); - return FileService.AbsoluteToRelativePath (basePath, path); - } - } } class LoadOperation @@ -141,7 +105,7 @@ namespace MonoDevelop.Projects.Extensions - public delegate SolutionEntityItem ItemLoadCallback (IProgressMonitor monitor, string fileName); + public delegate Task<SolutionItem> ItemLoadCallback (ProgressMonitor monitor, string fileName); - public delegate BuildResult ItemCompileCallback (IProgressMonitor monitor, SolutionEntityItem item, BuildData buildData); + public delegate BuildResult ItemCompileCallback (ProgressMonitor monitor, SolutionItem item, BuildData buildData); } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IWorkspaceObject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectMigrationHandler.cs index 502337e651..976dc06b42 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IWorkspaceObject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectMigrationHandler.cs @@ -1,4 +1,4 @@ -// IWorkspaceObject.cs +// DotNetProjectSubtype.cs // // Author: // Lluis Sanchez Gual <lluis@novell.com> @@ -26,29 +26,37 @@ // using System; +using System.Linq; +using Mono.Addins; +using MonoDevelop.Projects.Formats.MSBuild; using System.Collections.Generic; using MonoDevelop.Core; -using MonoDevelop.Core.Serialization; +using System.Threading.Tasks; - -namespace MonoDevelop.Projects +namespace MonoDevelop.Projects.Extensions { - public interface IWorkspaceObject: IExtendedDataItem, IFolderItem, IDisposable + public abstract class ProjectMigrationHandler { - string Name { get; set; }
- FilePath ItemDirectory { get; }
- new FilePath BaseDirectory { get; set; } - void Save (IProgressMonitor monitor); + public virtual IEnumerable<string> FilesToBackup (string filename) + { + yield break; + } + + public abstract bool Migrate (ProjectLoadProgressMonitor monitor, MSBuildProject project, string fileName, string language); + + public virtual bool CanPromptForMigration { + get { return false; } + } + + public virtual MigrationType PromptForMigration (ProjectLoadProgressMonitor monitor, MSBuildProject project, string fileName, string language) + { + throw new NotImplementedException (); + } } - public interface IWorkspaceFileObject: IWorkspaceObject, IFileItem - { - FileFormat FileFormat { get; } - void ConvertToFormat (FileFormat format, bool convertChildren); - bool SupportsFormat (FileFormat format);
- List<FilePath> GetItemFiles (bool includeReferencedFiles); - new FilePath FileName { get; set; } - bool NeedsReload { get; set; } - bool ItemFilesChanged { get; } + public enum MigrationType { + Ignore, + Migrate, + BackupAndMigrate, } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectMigrationHandlerNode.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectMigrationHandlerNode.cs new file mode 100644 index 0000000000..9e61188b88 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectMigrationHandlerNode.cs @@ -0,0 +1,45 @@ +// +// ProjectMigrationHandlerNode.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Mono.Addins; + +namespace MonoDevelop.Projects.Extensions +{ + public class ProjectMigrationHandlerNode: TypeExtensionNode + { + [NodeAttribute] + bool migrationRequired = true; + + public bool IsMigrationRequired { + get { return migrationRequired; } + } + + public ProjectMigrationHandler MigrationHandler { + get { return (ProjectMigrationHandler) CreateInstance (typeof(ProjectMigrationHandler)); } + } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectModelExtensionNode.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectModelExtensionNode.cs new file mode 100644 index 0000000000..bcd5bf6a81 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectModelExtensionNode.cs @@ -0,0 +1,45 @@ +// +// ProjectModelExtensionNode.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Mono.Addins; + +namespace MonoDevelop.Projects.Extensions +{ + [ExtensionNode (ExtensionAttributeType = typeof(RegisterProjectModelExtensionAttribute))] + public class ProjectModelExtensionNode: TypeExtensionNode + { + public virtual bool CanHandleObject (object ob) + { + return ob is WorkspaceObject; + } + + public virtual WorkspaceObjectExtension CreateExtension () + { + return (WorkspaceObjectExtension) CreateInstance (typeof(WorkspaceObjectExtension)); + } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectTypeNode.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectTypeNode.cs new file mode 100644 index 0000000000..407a77db63 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectTypeNode.cs @@ -0,0 +1,62 @@ +// +// MSBuildProjectNode.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using MonoDevelop.Projects.Formats.MSBuild; +using Mono.Addins; +using MonoDevelop.Core; + +namespace MonoDevelop.Projects.Extensions +{ + [ExtensionNode (ExtensionAttributeType=typeof(RegisterProjectTypeAttribute))] + public class ProjectTypeNode: SolutionItemTypeNode + { + public override async Task<SolutionItem> CreateSolutionItem (ProgressMonitor monitor, string fileName, string typeGuid) + { + MSBuildProject p = null; + + if (!string.IsNullOrEmpty (fileName)) { + p = await MSBuildProject.LoadAsync (fileName); +// if (MSBuildProjectService.CanMigrateFlavor (p.ProjectTypeGuids)) +// await MSBuildProjectService.MigrateFlavor (monitor, fileName, typeGuid, this, p); + } + + if (p != null) + Project.CreationContext.LockContext (p, typeGuid); + try { + var project = await base.CreateSolutionItem (monitor, fileName, typeGuid) as Project; + if (project == null) + throw new InvalidOperationException ("Project node type is not a subclass of MonoDevelop.Projects.Project"); + return project; + } finally { + if (p != null) + Project.CreationContext.UnlockContext (); + } + } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemExtensionNode.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemExtensionNode.cs new file mode 100644 index 0000000000..4b64b1f20e --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemExtensionNode.cs @@ -0,0 +1,64 @@ +// +// SolutionItemExtensionNode.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Mono.Addins; +using System.Linq; + +namespace MonoDevelop.Projects.Extensions +{ + [ExtensionNode (ExtensionAttributeType = typeof(RegisterProjectFlavorAttribute))] + public class SolutionItemExtensionNode: ProjectModelExtensionNode + { + [NodeAttribute (Description = "GUID of the extension. The extension will be loaded if the project has this GUID in the project type GUID list. " + + "If not specified, the extension will be applied to all projects.")] + string guid; + + public string Guid { + get { return guid; } + } + + public override bool CanHandleObject (object ob) + { + SolutionItem p = ob as SolutionItem; + if (p == null) + return false; + + if (guid == null) + return true; + + var typeGuids = p.GetItemTypeGuids (); + return typeGuids.Any (g => string.Equals (g, guid, StringComparison.InvariantCultureIgnoreCase)); + } + + public override WorkspaceObjectExtension CreateExtension () + { + var ext = (ProjectExtension) CreateInstance (typeof(ProjectExtension)); + ext.FlavorGuid = Guid; + return ext; + } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemHandler.cs index 835a0c2d92..887af95949 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemHandler.cs @@ -29,14 +29,15 @@ using System; using System.CodeDom.Compiler; using MonoDevelop.Core; using MonoDevelop.Projects.Extensions; +using System.Threading.Tasks; namespace MonoDevelop.Projects.Extensions { public abstract class SolutionItemHandler: ISolutionItemHandler { - SolutionItem item; + SolutionFolderItem item; - public SolutionItemHandler (SolutionItem item) + public SolutionItemHandler (SolutionFolderItem item) { this.item = item; } @@ -45,30 +46,30 @@ namespace MonoDevelop.Projects.Extensions get { return true; } } - public SolutionItem Item { + public SolutionFolderItem Item { get { return item; } } - public virtual BuildResult RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration) + public async virtual Task<BuildResult> RunTarget (ProgressMonitor monitor, string target, ConfigurationSelector configuration) { switch (target) { case "Build": - return OnBuild (monitor, configuration); + return await OnBuild (monitor, configuration); case "Clean": - return OnClean (monitor, configuration); + return await OnClean (monitor, configuration); } return new BuildResult (new CompilerResults (null), ""); } - protected virtual BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration) + protected virtual Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { - return null; + return Task.FromResult (BuildResult.Success); } - protected virtual BuildResult OnClean (IProgressMonitor monitor, ConfigurationSelector configuration) + protected virtual Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration) { - return null; + return Task.FromResult (BuildResult.Success); } public virtual void Dispose () @@ -77,7 +78,7 @@ namespace MonoDevelop.Projects.Extensions public abstract string ItemId { get; } - public abstract void Save (IProgressMonitor monitor); + public abstract Task Save (ProgressMonitor monitor); public virtual void OnModified (string hint) { diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ItemTypeNode.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemTypeNode.cs index 7608071bee..3b9a46a8db 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ItemTypeNode.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemTypeNode.cs @@ -31,10 +31,13 @@ using System.Xml; using Mono.Addins; using MonoDevelop.Projects.Formats.MSBuild; using MonoDevelop.Core; +using System.Threading.Tasks; +using MonoDevelop.Core.ProgressMonitoring; namespace MonoDevelop.Projects.Extensions { - public abstract class ItemTypeNode: ExtensionNode + [ExtensionNode (ExtensionAttributeType=typeof(RegisterSolutionItemTypeAttribute))] + public abstract class SolutionItemTypeNode: ExtensionNode { [NodeAttribute (Required=true)] string guid = null; @@ -46,13 +49,16 @@ namespace MonoDevelop.Projects.Extensions string import = null; [NodeAttribute] - string handlerType = null; - - public ItemTypeNode () + string type = null; + + [NodeAttribute ("alias")] + public string Alias { get; protected set; } + + public SolutionItemTypeNode () { } - public ItemTypeNode (string guid, string extension, string import) + public SolutionItemTypeNode (string guid, string extension, string import) { this.guid = guid; this.extension = extension; @@ -74,14 +80,13 @@ namespace MonoDevelop.Projects.Extensions return import; } } - - public abstract bool CanHandleItem (SolutionEntityItem item); - - public virtual void InitializeHandler (SolutionEntityItem item) - { - MSBuildHandler h = CreateHandler<MSBuildHandler> (null, null); - h.Item = item; - item.SetItemHandler (h); + + internal string ItenTypeName { + get { return type; } + } + + public virtual Type ItemType { + get { return Addin.GetType (type, true); } } public virtual bool CanHandleFile (string fileName, string typeGuid) @@ -92,32 +97,29 @@ namespace MonoDevelop.Projects.Extensions return true; return false; } + + SolutionItemFactory factory; - protected T CreateHandler<T> (string fileName, string itemGuid) where T:MSBuildHandler + public virtual async Task<SolutionItem> CreateSolutionItem (ProgressMonitor monitor, string fileName, string typeGuid) { - MSBuildHandler h = OnCreateHandler (fileName, itemGuid); - if (!(h is T)) - throw new InvalidOperationException ("Error while creating a MSBuildHandler. Expected an object of type '" + typeof(T).FullName + ", found type '" + h.GetType ()); - return (T)h; + if (typeof(SolutionItemFactory).IsAssignableFrom (ItemType)) { + if (factory == null) + factory = (SolutionItemFactory) Activator.CreateInstance (ItemType); + return await factory.CreateItem (fileName, typeGuid); + } + return (SolutionItem) Activator.CreateInstance (ItemType); } - - protected virtual MSBuildHandler OnCreateHandler (string fileName, string itemGuid) + + public virtual bool CanCreateSolutionItem (string type, ProjectCreateInformation info, System.Xml.XmlElement projectOptions) { - MSBuildHandler h; - if (!string.IsNullOrEmpty (handlerType)) { - h = Addin.CreateInstance (handlerType, true) as MSBuildHandler; - if (h == null) - throw new InvalidOperationException ("Type '" + handlerType + "' must be a subclass of 'MonoDevelop.Projects.Formats.MSBuild.MSBuildHandler'"); - if (h is MSBuildProjectHandler) - ((MSBuildProjectHandler)h).Initialize (Guid, Import, itemGuid); - else - h.Initialize (Guid, itemGuid); - } else { - h = new MSBuildProjectHandler (Guid, Import, itemGuid); - } - return h; + return type.Equals (Guid, StringComparison.OrdinalIgnoreCase) || type == Alias; + } + + public virtual SolutionItem CreateSolutionItem (string type, ProjectCreateInformation info, System.Xml.XmlElement projectOptions) + { + var item = CreateSolutionItem (new ProgressMonitor (), null, Guid).Result; + item.InitializeNew (info, projectOptions); + return item; } - - public abstract SolutionEntityItem LoadSolutionItem (IProgressMonitor monitor, string fileName, MSBuildFileFormat expectedFormat, string itemGuid); } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1DotNetProjectHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1DotNetProjectHandler.cs index c370403ffa..605464cee2 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1DotNetProjectHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1DotNetProjectHandler.cs @@ -35,6 +35,7 @@ using MonoDevelop.Core; using MonoDevelop.Core.Execution; using MonoDevelop.Projects.Extensions; using Microsoft.Build.BuildEngine; +using System.Threading.Tasks; namespace MonoDevelop.Projects.Formats.MD1 { @@ -48,9 +49,9 @@ namespace MonoDevelop.Projects.Formats.MD1 get { return (DotNetProject) Item; } } - protected override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration) + protected async override Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { - if (!Project.InternalCheckNeedsBuild (configuration)) { + if (!Project.OnGetNeedsBuilding (configuration)) { monitor.Log.WriteLine (GettextCatalog.GetString ("Skipping project since output files are up to date")); return new BuildResult (); } @@ -150,25 +151,36 @@ namespace MonoDevelop.Projects.Formats.MD1 buildData.Configuration.SetParentItem (project); buildData.ConfigurationSelector = configuration; - return ProjectExtensionUtil.Compile (monitor, project, buildData, delegate { + return await Task<BuildResult>.Factory.StartNew (delegate { ProjectItemCollection items = buildData.Items; - BuildResult res = BuildResources (buildData.Configuration, ref items, monitor); - if (res != null) - return res; - - res = project.LanguageBinding.Compile (items, buildData.Configuration, buildData.ConfigurationSelector, monitor); + BuildResult br = BuildResources (buildData.Configuration, ref items, monitor); + if (br != null) + return br; + + br = project.LanguageBinding.Compile (items, buildData.Configuration, buildData.ConfigurationSelector, monitor); if (refres != null) { - refres.Append (res); + refres.Append (br); return refres; - } - else - return res; + } else + return br; + }); + + } + + internal static Task<BuildResult> Compile (ProgressMonitor monitor, DotNetProject project, BuildData buildData) + { + return Task<BuildResult>.Factory.StartNew (delegate { + ProjectItemCollection items = buildData.Items; + BuildResult br = BuildResources (buildData.Configuration, ref items, monitor); + if (br != null) + return br; + return project.LanguageBinding.Compile (items, buildData.Configuration, buildData.ConfigurationSelector, monitor); }); - } + } // Builds the EmbedAsResource files. If any localized resources are found then builds the satellite assemblies // and sets @projectItems to a cloned collection minus such resource files. - private BuildResult BuildResources (DotNetProjectConfiguration configuration, ref ProjectItemCollection projectItems, IProgressMonitor monitor) + internal static BuildResult BuildResources (DotNetProjectConfiguration configuration, ref ProjectItemCollection projectItems, ProgressMonitor monitor) { string resgen = configuration.TargetRuntime.GetToolPath (configuration.TargetFramework, "resgen"); ExecutionEnvironment env = configuration.TargetRuntime.GetToolsExecutionEnvironment (configuration.TargetFramework); @@ -220,7 +232,7 @@ namespace MonoDevelop.Projects.Formats.MD1 return null; } - CompilerError GetResourceId (FilePath outputFile, ExecutionEnvironment env, ProjectFile finfo, ref string fname, string resgen, out string resourceId, IProgressMonitor monitor) + static CompilerError GetResourceId (FilePath outputFile, ExecutionEnvironment env, ProjectFile finfo, ref string fname, string resgen, out string resourceId, ProgressMonitor monitor) { resourceId = finfo.ResourceId; if (resourceId == null) { @@ -326,7 +338,7 @@ namespace MonoDevelop.Projects.Formats.MD1 return finfo_first.LastWriteTime > finfo_second.LastWriteTime; } - CompilerError GenerateSatelliteAssemblies (Dictionary<string, string> resourcesByCulture, string outputDir, string al, string defaultns, IProgressMonitor monitor) + static CompilerError GenerateSatelliteAssemblies (Dictionary<string, string> resourcesByCulture, string outputDir, string al, string defaultns, ProgressMonitor monitor) { foreach (KeyValuePair<string, string> pair in resourcesByCulture) { string culture = pair.Key; diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1FileFormat.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1FileFormat.cs index 669a0e92c7..a4ec7999ee 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1FileFormat.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1FileFormat.cs @@ -33,6 +33,7 @@ using System.Xml; using MonoDevelop.Core.Serialization; using MonoDevelop.Projects.Extensions; using MonoDevelop.Core; +using System.Threading.Tasks; namespace MonoDevelop.Projects.Formats.MD1 { @@ -65,7 +66,7 @@ namespace MonoDevelop.Projects.Formats.MD1 return new List<FilePath> (); }
- public void WriteFile (FilePath file, object node, IProgressMonitor monitor) + async public Task WriteFile (FilePath file, object node, ProgressMonitor monitor) { string tmpfilename = null; try { @@ -76,9 +77,9 @@ namespace MonoDevelop.Projects.Formats.MD1 } if (tmpfilename == null) { - WriteFileInternal (file, file, node, monitor); + await WriteFileInternal (file, file, node, monitor); } else { - WriteFileInternal (file, tmpfilename, node, monitor); + await WriteFileInternal (file, tmpfilename, node, monitor); File.Delete (file); File.Move (tmpfilename, file); } @@ -89,45 +90,47 @@ namespace MonoDevelop.Projects.Formats.MD1 } }
- void WriteFileInternal (FilePath actualFile, FilePath outFile, object node, IProgressMonitor monitor) + Task WriteFileInternal (FilePath actualFile, FilePath outFile, object node, ProgressMonitor monitor) { - WriteWorkspaceItem (actualFile, outFile, (WorkspaceItem) node, monitor); + return WriteWorkspaceItem (actualFile, outFile, (WorkspaceItem) node, monitor); } - void WriteWorkspaceItem (FilePath actualFile, FilePath outFile, WorkspaceItem item, IProgressMonitor monitor) + async Task WriteWorkspaceItem (FilePath actualFile, FilePath outFile, WorkspaceItem item, ProgressMonitor monitor) { Workspace ws = item as Workspace; if (ws != null) { monitor.BeginTask (null, ws.Items.Count); try { foreach (WorkspaceItem it in ws.Items) { - it.Save (monitor); + await it.SaveAsync (monitor); monitor.Step (1); } } finally { monitor.EndTask (); } } - - StreamWriter sw = new StreamWriter (outFile); - try { - monitor.BeginTask (GettextCatalog.GetString ("Saving item: {0}", actualFile), 1); - XmlTextWriter tw = new XmlTextWriter (sw); - tw.Formatting = Formatting.Indented; - XmlDataSerializer ser = new XmlDataSerializer (MD1ProjectService.DataContext); - ser.SerializationContext.BaseFile = actualFile; - ser.SerializationContext.ProgressMonitor = monitor; - ser.Serialize (sw, item, typeof(WorkspaceItem)); - } catch (Exception ex) { - monitor.ReportError (GettextCatalog.GetString ("Could not save item: {0}", actualFile), ex); - throw; - } finally { - monitor.EndTask (); - sw.Close (); - } + + await Task.Factory.StartNew (delegate { + StreamWriter sw = new StreamWriter (outFile); + try { + monitor.BeginTask (GettextCatalog.GetString ("Saving item: {0}", actualFile), 1); + XmlTextWriter tw = new XmlTextWriter (sw); + tw.Formatting = Formatting.Indented; + XmlDataSerializer ser = new XmlDataSerializer (MD1ProjectService.DataContext); + ser.SerializationContext.BaseFile = actualFile; + ser.SerializationContext.ProgressMonitor = monitor; + ser.Serialize (sw, item, typeof(WorkspaceItem)); + } catch (Exception ex) { + monitor.ReportError (GettextCatalog.GetString ("Could not save item: {0}", actualFile), ex); + throw; + } finally { + monitor.EndTask (); + sw.Close (); + } + }); }
- public object ReadFile (FilePath fileName, Type expectedType, IProgressMonitor monitor) + public async Task<object> ReadFile (FilePath fileName, Type expectedType, ProgressMonitor monitor) { string ext = Path.GetExtension (fileName).ToLower (); if (ext != ".mdw") @@ -137,43 +140,44 @@ namespace MonoDevelop.Projects.Formats.MD1 ProjectExtensionUtil.BeginLoadOperation (); try { - readObject = ReadWorkspaceItemFile (fileName, monitor); + readObject = await ReadWorkspaceItemFile (fileName, monitor); } finally { ProjectExtensionUtil.EndLoadOperation (); } IWorkspaceFileObject fo = readObject as IWorkspaceFileObject; if (fo != null) - fo.ConvertToFormat (MD1ProjectService.FileFormat, false); + await fo.ConvertToFormat (MD1ProjectService.FileFormat, false); return readObject; }
- object ReadWorkspaceItemFile (FilePath fileName, IProgressMonitor monitor) + Task<object> ReadWorkspaceItemFile (FilePath fileName, ProgressMonitor monitor) { - XmlTextReader reader = new XmlTextReader (new StreamReader (fileName)); - try { - monitor.BeginTask (string.Format (GettextCatalog.GetString ("Loading workspace item: {0}"), fileName), 1); - reader.MoveToContent (); - XmlDataSerializer ser = new XmlDataSerializer (MD1ProjectService.DataContext); - ser.SerializationContext.BaseFile = fileName; - ser.SerializationContext.ProgressMonitor = monitor; - WorkspaceItem entry = (WorkspaceItem) ser.Deserialize (reader, typeof(WorkspaceItem)); - entry.ConvertToFormat (MD1ProjectService.FileFormat, false); - entry.FileName = fileName; - return entry; - } - catch (Exception ex) { - monitor.ReportError (string.Format (GettextCatalog.GetString ("Could not load solution item: {0}"), fileName), ex); - throw; - } - finally { - monitor.EndTask (); - reader.Close (); - } + return Task<object>.Factory.StartNew (delegate { + XmlTextReader reader = new XmlTextReader (new StreamReader (fileName)); + try { + monitor.BeginTask (string.Format (GettextCatalog.GetString ("Loading workspace item: {0}"), fileName), 1); + reader.MoveToContent (); + XmlDataSerializer ser = new XmlDataSerializer (MD1ProjectService.DataContext); + ser.SerializationContext.BaseFile = fileName; + ser.SerializationContext.ProgressMonitor = monitor; + WorkspaceItem entry = (WorkspaceItem)ser.Deserialize (reader, typeof(WorkspaceItem)); + entry.ConvertToFormat (MD1ProjectService.FileFormat, false).Wait (); + entry.FileName = fileName; + return entry; + } catch (Exception ex) { + monitor.ReportError (string.Format (GettextCatalog.GetString ("Could not load solution item: {0}"), fileName), ex); + throw; + } finally { + monitor.EndTask (); + reader.Close (); + } + }); } - public void ConvertToFormat (object obj) + public Task ConvertToFormat (object obj) { + return Task.FromResult (0); }
public IEnumerable<string> GetCompatibilityWarnings (object obj) diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1SolutionEntityItemHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1SolutionEntityItemHandler.cs index 6034c074c4..7515e2b50a 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1SolutionEntityItemHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1SolutionEntityItemHandler.cs @@ -29,19 +29,20 @@ using System; using System.CodeDom.Compiler; using MonoDevelop.Core; using MonoDevelop.Projects.Extensions; +using System.Threading.Tasks; namespace MonoDevelop.Projects.Formats.MD1 { internal class MD1SolutionEntityItemHandler: MD1SolutionItemHandler { - public MD1SolutionEntityItemHandler (SolutionEntityItem item): base (item) + public MD1SolutionEntityItemHandler (SolutionItem item): base (item) { } - public override void Save (IProgressMonitor monitor) + public override Task Save (ProgressMonitor monitor) { - SolutionEntityItem it = (SolutionEntityItem) Item; - it.FileFormat.Format.WriteFile (it.FileName, it, monitor); + SolutionItem it = (SolutionItem) Item; + return it.FileFormat.Format.WriteFile (it.FileName, it, monitor); } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1SolutionItemHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1SolutionItemHandler.cs index 4d971784bb..544f48a3de 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1SolutionItemHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1SolutionItemHandler.cs @@ -29,16 +29,17 @@ using System; using System.CodeDom.Compiler; using MonoDevelop.Core; using MonoDevelop.Projects.Extensions; +using System.Threading.Tasks; namespace MonoDevelop.Projects.Formats.MD1 { internal class MD1SolutionItemHandler: SolutionItemHandler { - public MD1SolutionItemHandler (SolutionItem item): base (item) + public MD1SolutionItemHandler (SolutionFolderItem item): base (item) { } - public override void Save (IProgressMonitor monitor) + public override Task Save (ProgressMonitor monitor) { throw new NotSupportedException (); } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/CompiledAssemblyProjectMSBuildHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/CompiledAssemblyProjectMSBuildHandler.cs deleted file mode 100644 index 513a286921..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/CompiledAssemblyProjectMSBuildHandler.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// CompiledAssemblyProjectMSBuildHandler.cs -// -// Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using MonoDevelop.Core.Serialization; -using MonoDevelop.Core; - -namespace MonoDevelop.Projects.Formats.MSBuild -{ - class CompiledAssemblyProjectMSBuildHandler: MSBuildProjectHandler - { - public override bool HasSlnData { - get { - return true; - } - } - - public override DataItem WriteSlnData () - { - DataSerializer ser = new DataSerializer (MSBuildProjectService.DataContext); - ser.SerializationContext.BaseFile = EntityItem.FileName; - ser.SerializationContext.DirectorySeparatorChar = '\\'; - DataItem data = (DataItem) ser.Serialize (EntityItem, typeof(CompiledAssemblyProject)); - return data; - } - - public override void ReadSlnData (DataItem item) - { - // Remove the default configuration, since new ones will be loaded - CompiledAssemblyProject project = (CompiledAssemblyProject) EntityItem; - project.Configurations.Clear (); - - DataSerializer ser = new DataSerializer (MSBuildProjectService.DataContext); - ser.SerializationContext.BaseFile = EntityItem.FileName; - ser.SerializationContext.DirectorySeparatorChar = '\\'; - ser.Deserialize (project, item); - } - - protected override void SaveItem (IProgressMonitor monitor) - { - // Do nothing, since info is saved to the .sln - } - } -} - diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/IMSBuildImportProvider.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/IMSBuildImportProvider.cs index 397e432eaf..65f43a52b5 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/IMSBuildImportProvider.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/IMSBuildImportProvider.cs @@ -31,6 +31,6 @@ namespace MonoDevelop.Projects.Formats.MSBuild { public interface IMSBuildImportProvider { - void UpdateImports (SolutionEntityItem item, List<string> imports); + void UpdateImports (SolutionItem item, List<string> imports); } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/IMSBuildProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/IMSBuildProject.cs new file mode 100644 index 0000000000..a43393337c --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/IMSBuildProject.cs @@ -0,0 +1,519 @@ +// +// IMSBuildProject.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using MonoDevelop.Core; +using System.Collections.Generic; +using System.Xml; +using System.Xml.Linq; +using System.Linq; + +namespace MonoDevelop.Projects.Formats.MSBuildInternal +{ + public abstract class MSBuildProject + { + Dictionary<object,Dictionary<Type,IMSBuildDataObject>> customDataObjects = new Dictionary<object,Dictionary<Type,IMSBuildDataObject>> (); + Dictionary<string, MSBuildItemGroup> bestGroups; + + public abstract FilePath FileName { get; } + + public FilePath BaseDirectory { + get { return FileName.ParentDirectory; } + } + + public abstract void Load (FilePath file); + + public abstract void Save (string fileName); + + public abstract string SaveToString (); + + public MonoDevelop.Projects.Formats.MSBuild.MSBuildFileFormat Format { + get; + set; + } + + public abstract string DefaultTargets { get; set; } + + public abstract string ToolsVersion { get; set; } + + public T GetObject<T> () where T : IMSBuildDataObject, new() + { + return GetObject<T> (this); + } + + public void SetObject<T> (T t) where T : IMSBuildDataObject + { + SetObject<T> (this, t); + } + + internal T GetObject<T> (object owner) where T : IMSBuildDataObject, new() + { + Dictionary<Type,IMSBuildDataObject> col; + if (!customDataObjects.TryGetValue (owner, out col)) + return default(T); + IMSBuildDataObject res; + col.TryGetValue (typeof(T), out res); + return (T)res; + } + + internal void SetObject<T> (object owner, T t) where T : IMSBuildDataObject + { + Dictionary<Type,IMSBuildDataObject> col; + if (!customDataObjects.TryGetValue (owner, out col)) + col = customDataObjects [owner] = new Dictionary<Type, IMSBuildDataObject> (); + col [typeof(T)] = t; + } + + internal IEnumerable<IMSBuildDataObject> GetDataObjects (object owner) + { + Dictionary<Type,IMSBuildDataObject> col; + if (!customDataObjects.TryGetValue (owner, out col)) + return new IMSBuildDataObject[0]; + else + return col.Values; + } + + public abstract void AddNewImport (string name, MSBuildImport beforeImport = null); + + public abstract void RemoveImport (MSBuildImport import); + + public abstract IEnumerable<MSBuildImport> Imports { get; } + + public MSBuildPropertyGroup GetGlobalPropertyGroup () + { + return PropertyGroups.FirstOrDefault (p => string.IsNullOrEmpty (p.Condition)); + } + + public abstract MSBuildPropertyGroup AddNewPropertyGroup (MSBuildPropertyGroup beforeGroup = null); + + public abstract void RemovePropertyGroup (MSBuildPropertyGroup grp); + + public abstract IEnumerable<MSBuildItem> GetAllItems (); + + public abstract IEnumerable<MSBuildItem> GetAllItems (params string[] names); + + public abstract IEnumerable<MSBuildPropertyGroup> PropertyGroups { get; } + + public abstract IEnumerable<MSBuildItemGroup> ItemGroups { get; } + + public abstract MSBuildItemGroup AddNewItemGroup (); + + public abstract MSBuildItem AddNewItem (string name, string include); + + public MSBuildItemGroup FindBestGroupForItem (string itemName) + { + MSBuildItemGroup group; + + if (bestGroups == null) + bestGroups = new Dictionary<string, MSBuildItemGroup> (); + else { + if (bestGroups.TryGetValue (itemName, out group)) + return group; + } + + foreach (MSBuildItemGroup grp in ItemGroups) { + foreach (MSBuildItem it in grp.Items) { + if (it.Name == itemName) { + bestGroups [itemName] = grp; + return grp; + } + } + } + group = AddNewItemGroup (); + bestGroups [itemName] = group; + return group; + } + + public abstract XmlElement GetProjectExtensions (string section); + + public abstract void SetProjectExtensions (string section, string value); + + public abstract void RemoveProjectExtensions (string section); + + public abstract void RemoveItem (MSBuildItem item); + } + + public abstract class MSBuildItemGroup + { + internal MSBuildItemGroup (MSBuildProject parent) + { + Project = parent; + } + + public abstract MSBuildItem AddNewItem (string name, string include); + + public abstract IEnumerable<MSBuildItem> Items { get; } + + public MSBuildProject Project { get; private set; } + } + + public abstract class MSBuildPropertyGroup: MSBuildPropertySet + { + MSBuildProject project; + + internal MSBuildPropertyGroup (MSBuildProject project): base (project) + { + this.project = project; + } + + public abstract string Label { get; set; } + public abstract string Condition { get; set; } + } + + internal interface IPropertySetImpl + { + bool HasProperty (string name); + MSBuildProperty GetProperty (string name, string condition = null); + MSBuildProperty AddProperty (string name, string condition = null); + bool RemoveProperty (MSBuildProperty prop); + bool RemoveProperty (string name); + void RemoveAllProperties (); + IEnumerable<MSBuildProperty> Properties { get; } + } + + public abstract class MSBuildPropertySet: IMSBuildPropertySet + { + MSBuildProject project; + Dictionary<Type,IMSBuildDataObject> customDataObjects = new Dictionary<Type,IMSBuildDataObject> (); + + internal MSBuildPropertySet (MSBuildProject project) + { + this.project = project; + } + + internal abstract IPropertySetImpl PropertySet { get; } + + public T GetObject<T> () where T : IMSBuildDataObject, new() + { + IMSBuildDataObject res; + customDataObjects.TryGetValue (typeof(T), out res); + return (T)res; + } + + public void SetObject<T> (T t) where T : IMSBuildDataObject + { + customDataObjects [typeof(T)] = t; + } + + internal void WriteDataObjects () + { + foreach (IMSBuildDataObject ob in customDataObjects.Values) + ob.Write (this, project.Format); + } + + public bool HasProperty (string name) + { + return PropertySet.HasProperty (name); + } + + public MSBuildProperty GetProperty (string name, string condition = null) + { + return PropertySet.GetProperty (name, condition); + } + + public MSBuildProperty AddProperty (string name, string condition = null) + { + return PropertySet.AddProperty (name, condition); + } + + MSBuildProperty SafeGetProperty (string name, string condition) + { + var prop = GetProperty (name, condition); + if (prop == null) { + prop = GetProperty (name); + if (prop != null) { + prop.Condition = condition; + return prop; + } + } + return AddProperty (name, condition); + } + + public void SetValue (string name, string value, string defaultValue = null, bool preserveExistingCase = false, bool isXmlValue = false, bool mergeToMainGroup = false, string condition = null) + { + var prop = SafeGetProperty (name, condition); + if (value == defaultValue) { + RemoveProperty (prop); + return; + } + prop.SetValue (value, preserveExistingCase, isXmlValue, mergeToMainGroup); + } + + public void SetValue (string name, XmlElement elem, bool mergeToMainGroup = false, string condition = null) + { + SafeGetProperty (name, condition).SetValue (elem, mergeToMainGroup); + } + + public void SetValue (string name, XElement elem, bool mergeToMainGroup = false, string condition = null) + { + SafeGetProperty (name, condition).SetValue (elem, mergeToMainGroup); + } + + public void SetValue (string name, FilePath value, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath), bool mergeToMainGroup = false, string condition = null) + { + SafeGetProperty (name, condition).SetValue (value, relativeToProject, relativeToPath, mergeToMainGroup); + } + + public void SetValue (string name, bool value, bool? defaultValue = false, bool mergeToMainGroup = false, string condition = null) + { + SafeGetProperty (name, condition).SetValue (value, mergeToMainGroup); + } + + public string GetValue (string name, string defaultValue = null) + { + var prop = GetProperty (name); + if (prop != null) + return prop.GetValue (); + else + return defaultValue; + } + + public XElement GetXmlValue (string name) + { + var prop = GetProperty (name); + if (prop != null) + return XElement.Parse (prop.GetValue ()); + else + return null; + } + + public FilePath GetPathValue (string name, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)) + { + var prop = GetProperty (name); + if (prop != null) + return prop.GetPathValue (relativeToProject, relativeToPath); + else + return defaultValue; + } + + public bool TryGetPathValue (string name, out FilePath value, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)) + { + var prop = GetProperty (name); + if (prop != null) + return prop.TryGetPathValue (out value, relativeToProject, relativeToPath); + else { + value = defaultValue; + return value != default(FilePath); + } + } + + public bool GetBoolValue (string name, bool defaultValue = false) + { + var prop = GetProperty (name); + if (prop != null) + return prop.GetBoolValue (); + else + return defaultValue; + } + + public virtual bool RemoveProperty (string name) + { + return PropertySet.RemoveProperty (name); + } + + public bool RemoveProperty (MSBuildProperty prop) + { + return PropertySet.RemoveProperty (prop); + } + + public void RemoveAllProperties () + { + PropertySet.RemoveAllProperties (); + } + + public IEnumerable<MSBuildProperty> Properties { + get { return PropertySet.Properties; } + } + } + + public interface IMSBuildPropertySet + { + T GetObject<T> () where T:IMSBuildDataObject, new(); + void SetObject<T> (T t) where T:IMSBuildDataObject; + + bool HasProperty (string name); + MSBuildProperty GetProperty (string name, string condition = null); + IEnumerable<MSBuildProperty> Properties { get; } + + void SetValue (string name, string value, string defaultValue = null, bool preserveExistingCase = false, bool isXmlValue = false, bool mergeToMainGroup = false, string condition = null); + void SetValue (string name, XmlElement elem, bool mergeToMainGroup = false, string condition = null); + void SetValue (string name, XElement elem, bool mergeToMainGroup = false, string condition = null); + void SetValue (string name, FilePath value, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath), bool mergeToMainGroup = false, string condition = null); + void SetValue (string name, bool value, bool? defaultValue = false, bool mergeToMainGroup = false, string condition = null); + + string GetValue (string name, string defaultValue = null); + XElement GetXmlValue (string name); + FilePath GetPathValue (string name, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)); + bool TryGetPathValue (string name, out FilePath value, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)); + bool GetBoolValue (string name, bool defaultValue = false); + + bool RemoveProperty (string name); + void RemoveAllProperties (); + } + + public abstract class MSBuildImport + { + public abstract string Target { get; set; } + + public abstract string Label { get; set; } + + public abstract string Condition { get; set; } + } + + public abstract class MSBuildProperty + { + MSBuildProject project; + + internal MSBuildProperty (MSBuildProject project) + { + this.project = project; + } + + public abstract string Name { + get; + } + + public abstract string Condition { get; set; } + + public void SetValue (string value, bool preserveExistingCase = false, bool isXmlValue = false, bool mergeToMainGroup = false) + { + if (value == null) + value = String.Empty; + + if (preserveExistingCase) { + var current = GetPropertyValue (); + if (current != null) { + if (current.Equals (value, preserveExistingCase ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture)) + return; + } + } + SetPropertyValue (value, isXmlValue); + } + + public void SetValue (XmlElement elem, bool mergeToMainGroup = false) + { + SetPropertyValue (elem.OuterXml, true); + } + + public void SetValue (XElement elem, bool mergeToMainGroup = false) + { + SetPropertyValue (elem.ToString (), true); + } + + public void SetValue (FilePath value, bool relativeToProject = true, FilePath relativeToPath = default(FilePath), bool mergeToMainGroup = false) + { + string baseDir = null; + if (relativeToProject) { + if (relativeToPath != default(FilePath)) + throw new ArgumentException ("relativeToPath argument can't be used together with relativeToProject"); + baseDir = project.BaseDirectory; + } else if (relativeToPath != null) { + baseDir = relativeToPath; + } + SetPropertyValue (MonoDevelop.Projects.Formats.MSBuild.MSBuildProjectService.ToMSBuildPath (baseDir, value), false); + } + + public void SetValue (bool value, bool mergeToMainGroup = false) + { + SetPropertyValue (value ? "True" : "False", false); + } + + public string GetValue () + { + return GetPropertyValue (); + } + + public XElement GetXmlValue () + { + var val = GetPropertyValue (); + if (val == null) + return null; + return XElement.Parse (val); + } + + public FilePath GetPathValue (bool relativeToProject = true, FilePath relativeToPath = default(FilePath)) + { + var val = GetPropertyValue (); + string baseDir = null; + if (relativeToProject) { + if (relativeToPath != default(FilePath)) + throw new ArgumentException ("relativeToPath argument can't be used together with relativeToProject"); + baseDir = project.BaseDirectory; + } else if (relativeToPath != null) { + baseDir = relativeToPath; + } + return MonoDevelop.Projects.Formats.MSBuild.MSBuildProjectService.FromMSBuildPath (baseDir, val); + } + + public bool TryGetPathValue (out FilePath value, bool relativeToProject = true, FilePath relativeToPath = default(FilePath)) + { + var val = GetPropertyValue (); + string baseDir = null; + if (relativeToProject) { + if (relativeToPath != default(FilePath)) + throw new ArgumentException ("relativeToPath argument can't be used together with relativeToProject"); + baseDir = project.BaseDirectory; + } else if (relativeToPath != null) { + baseDir = relativeToPath; + } + string path; + var res = MonoDevelop.Projects.Formats.MSBuild.MSBuildProjectService.FromMSBuildPath (baseDir, val, out path); + value = path; + return res; + } + + public bool GetBoolValue () + { + var val = GetPropertyValue (); + return val.Equals ("true", StringComparison.InvariantCultureIgnoreCase); + } + + protected abstract void SetPropertyValue (string value, bool isXml); + protected abstract string GetPropertyValue (); + } + + public abstract class MSBuildItem: MSBuildPropertySet + { + MSBuildProject project; + + internal MSBuildItem (MSBuildProject project): base (project) + { + this.project = project; + } + + public abstract string Include { get; } + + public abstract string UnevaluatedInclude { get; } + + public abstract string Name { get; } + } + + public interface IMSBuildDataObject + { + void Read (IMSBuildPropertySet pset, MonoDevelop.Projects.Formats.MSBuild.MSBuildFileFormat format); + void Write (IMSBuildPropertySet pset, MonoDevelop.Projects.Formats.MSBuild.MSBuildFileFormat format); + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/IMSBuildPropertySet.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/IMSBuildPropertySet.cs new file mode 100644 index 0000000000..83a96d9f4c --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/IMSBuildPropertySet.cs @@ -0,0 +1,173 @@ +// +// MSBuildPropertySet.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Linq; +using System.IO; +using System.Collections.Generic; +using System.Xml; +using System.Text; + +using Microsoft.Build.BuildEngine; +using MonoDevelop.Core; +using System.Xml.Linq; +using System.Reflection; +using MonoDevelop.Core.Serialization; +using System.Globalization; + +namespace MonoDevelop.Projects.Formats.MSBuild +{ + + public interface IMSBuildPropertySet + { + string Label { get; set; } + T GetObject<T> () where T:IMSBuildDataObject, new(); + void SetObject<T> (T t) where T:IMSBuildDataObject; + + bool HasProperty (string name); + MSBuildProperty GetProperty (string name); + IEnumerable<MSBuildProperty> Properties { get; } + + void SetValue (string name, string value, string defaultValue = null, bool preserveExistingCase = false, bool mergeToMainGroup = false, string condition = null); + void SetValue (string name, FilePath value, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath), bool mergeToMainGroup = false, string condition = null); + void SetValue (string name, object value, object defaultValue = null, bool mergeToMainGroup = false, string condition = null); + + string GetValue (string name, string defaultValue = null); + FilePath GetPathValue (string name, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)); + bool TryGetPathValue (string name, out FilePath value, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)); + T GetValue<T> (string name); + T GetValue<T> (string name, T defaultValue); + object GetValue (string name, Type type, object defaultValue); + + bool RemoveProperty (string name); + void RemoveAllProperties (); + + void SetPropertyOrder (params string[] propertyNames); + + MSBuildProject Project { get; } + } + + public static class IMSBuildPropertySetExtensions + { + class PropInfo + { + public MemberInfo Member; + public ItemPropertyAttribute Attribute; + public bool MergeToMainGroup; + + public Type ReturnType { + get { return (Member is FieldInfo) ? ((FieldInfo)Member).FieldType : ((PropertyInfo)Member).PropertyType; } + } + public object GetValue (object instance) + { + if (Member is FieldInfo) + return ((FieldInfo)Member).GetValue (instance); + else + return ((PropertyInfo)Member).GetValue (instance, null); + } + public void SetValue (object instance, object value) + { + if (Member is FieldInfo) + ((FieldInfo)Member).SetValue (instance, value); + else + ((PropertyInfo)Member).SetValue (instance, value, null); + } + public string Name { + get { return Attribute.Name ?? Member.Name; } + } + } + + static Dictionary<Type,PropInfo[]> types = new Dictionary<Type, PropInfo[]> (); + + static PropInfo[] GetMembers (Type type) + { + PropInfo[] pinfo; + if (types.TryGetValue (type, out pinfo)) + return pinfo; + + List<PropInfo> list = new List<PropInfo> (); + + foreach (var m in type.GetMembers (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { + if (m.DeclaringType != type) + continue; + if (!(m is FieldInfo) && !(m is PropertyInfo)) + continue; + var attr = Attribute.GetCustomAttribute (m, typeof(ItemPropertyAttribute)) as ItemPropertyAttribute; + if (attr == null) + continue; + bool merge = Attribute.IsDefined (m, typeof(MergeToProjectAttribute)); + + list.Add (new PropInfo { + Member = m, + Attribute = attr, + MergeToMainGroup = merge + }); + } + return types [type] = list.ToArray (); + } + + public static void WriteObjectProperties (this IMSBuildPropertySet pset, object ob, Type typeToScan) + { + var props = GetMembers (typeToScan); + foreach (var prop in props) { + if (prop.ReturnType == typeof(FilePath)) { + var val = (FilePath)prop.GetValue (ob); + FilePath def = prop.Attribute.DefaultValue != null ? (string)prop.Attribute.DefaultValue : (string)null; + pset.SetValue (prop.Name, val, def, mergeToMainGroup: prop.MergeToMainGroup); + } else if (prop.Attribute is ProjectPathItemProperty && prop.ReturnType == typeof(string)) { + FilePath val = (string)prop.GetValue (ob); + FilePath def = prop.Attribute.DefaultValue != null ? (string)prop.Attribute.DefaultValue : (string)null; + pset.SetValue (prop.Name, val, def, mergeToMainGroup: prop.MergeToMainGroup); + } else if (prop.ReturnType == typeof(string)) { + pset.SetValue (prop.Name, (string)prop.GetValue (ob), (string)prop.Attribute.DefaultValue, prop.MergeToMainGroup); + } else { + pset.SetValue (prop.Name, prop.GetValue (ob), prop.Attribute.DefaultValue, prop.MergeToMainGroup); + } + } + } + + public static void ReadObjectProperties (this IMSBuildPropertySet pset, object ob, Type typeToScan) + { + var props = GetMembers (typeToScan); + foreach (var prop in props) { + object readVal = null; + if (prop.ReturnType == typeof(FilePath)) { + FilePath def = prop.Attribute.DefaultValue != null ? (string)prop.Attribute.DefaultValue : (string)null; + readVal = pset.GetPathValue (prop.Name, def); + } else if (prop.Attribute is ProjectPathItemProperty && prop.ReturnType == typeof(string)) { + FilePath def = prop.Attribute.DefaultValue != null ? (string)prop.Attribute.DefaultValue : (string)null; + readVal = pset.GetPathValue (prop.Name, def); + readVal = readVal.ToString (); + } else if (prop.ReturnType == typeof(string)) { + readVal = pset.GetValue (prop.Name, (string)prop.Attribute.DefaultValue); + } else { + readVal = pset.GetValue (prop.Name, prop.ReturnType, prop.Attribute.DefaultValue); + } + prop.SetValue (ob, readVal); + } + } + } +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildEvaluationContext.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildEvaluationContext.cs new file mode 100644 index 0000000000..c681f46c94 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildEvaluationContext.cs @@ -0,0 +1,177 @@ +// +// MSBuildEvaluationContext.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Linq; +using System.IO; +using System.Collections.Generic; +using System.Xml; +using System.Text; + +using Microsoft.Build.BuildEngine; + +namespace MonoDevelop.Projects.Formats.MSBuild +{ + + public class MSBuildEvaluationContext: IExpressionContext + { + Dictionary<string,string> properties = new Dictionary<string, string> (); + bool allResolved; + MSBuildProject project; + + public MSBuildEvaluationContext () + { + } + + internal void InitEvaluation (MSBuildProject project) + { + this.project = project; + SetPropertyValue ("MSBuildThisFile", Path.GetFileName (project.FileName)); + SetPropertyValue ("MSBuildThisFileName", Path.GetFileNameWithoutExtension (project.FileName)); + SetPropertyValue ("MSBuildThisFileDirectory", Path.GetDirectoryName (project.FileName) + Path.DirectorySeparatorChar); + SetPropertyValue ("MSBuildThisFileExtension", Path.GetExtension (project.FileName)); + SetPropertyValue ("MSBuildThisFileFullPath", Path.GetFullPath (project.FileName)); + SetPropertyValue ("VisualStudioReferenceAssemblyVersion", project.ToolsVersion + ".0.0"); + } + + public string GetPropertyValue (string name) + { + string val; + if (properties.TryGetValue (name, out val)) + return val; + else + return Environment.GetEnvironmentVariable (name); + } + + public void SetPropertyValue (string name, string value) + { + properties [name] = value; + } + + public void ClearPropertyValue (string name) + { + properties.Remove (name); + } + + public bool Evaluate (XmlElement source, out XmlElement result) + { + allResolved = true; + result = (XmlElement) EvaluateNode (source); + return allResolved; + } + + XmlNode EvaluateNode (XmlNode source) + { + var elemSource = source as XmlElement; + if (elemSource != null) { + var elem = source.OwnerDocument.CreateElement (elemSource.Prefix, elemSource.LocalName, elemSource.NamespaceURI); + foreach (XmlAttribute attr in elemSource.Attributes) + elem.Attributes.Append ((XmlAttribute)EvaluateNode (attr)); + foreach (XmlNode child in elemSource.ChildNodes) + elem.AppendChild (EvaluateNode (child)); + return elem; + } + + var attSource = source as XmlAttribute; + if (attSource != null) { + bool oldResolved = allResolved; + var att = source.OwnerDocument.CreateAttribute (attSource.Prefix, attSource.LocalName, attSource.NamespaceURI); + att.Value = Evaluate (attSource.Value); + + // Condition attributes don't change the resolution status. Conditions are handled in the property and item objects + if (attSource.Name == "Condition") + allResolved = oldResolved; + + return att; + } + var textSource = source as XmlText; + if (textSource != null) { + return source.OwnerDocument.CreateTextNode (Evaluate (textSource.InnerText)); + } + return source.Clone (); + } + + public bool Evaluate (string str, out string result) + { + allResolved = true; + result = Evaluate (str); + return allResolved; + } + + string Evaluate (string str) + { + int i = str.IndexOf ("$("); + if (i == -1) + return str; + + int last = 0; + + StringBuilder sb = new StringBuilder (); + do { + sb.Append (str, last, i - last); + i += 2; + int j = str.IndexOf (")", i); + if (j == -1) { + allResolved = false; + return ""; + } + + string prop = str.Substring (i, j - i); + string val = GetPropertyValue (prop); + if (val == null) { + allResolved = false; + return ""; + } + + sb.Append (val); + last = j + 1; + i = str.IndexOf ("$(", last); + } + while (i != -1); + + sb.Append (str, last, str.Length - last); + return sb.ToString (); + } + + #region IExpressionContext implementation + + public string EvaluateString (string value) + { + if (value.StartsWith ("$(") && value.EndsWith (")")) + return GetPropertyValue (value.Substring (2, value.Length - 3)) ?? value; + else + return value; + } + + public string FullFileName { + get { + return project.FileName; + } + } + + #endregion + } +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildFileFormat.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildFileFormat.cs index 05314dfdb7..282f7c0b3d 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildFileFormat.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildFileFormat.cs @@ -33,18 +33,24 @@ using System.IO; using MonoDevelop.Core; using MonoDevelop.Core.Assemblies; using MonoDevelop.Projects.Extensions; +using System.Threading.Tasks; namespace MonoDevelop.Projects.Formats.MSBuild { public abstract class MSBuildFileFormat: IFileFormat { - readonly SlnFileFormat slnFileFormat = new SlnFileFormat (); + readonly SlnFileFormat slnFileFormat; + + protected MSBuildFileFormat () + { + slnFileFormat = new SlnFileFormat (this); + } public string Name { get { return "MSBuild"; } } - public SlnFileFormat SlnFileFormat { + internal SlnFileFormat SlnFileFormat { get { return slnFileFormat; } } @@ -70,7 +76,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild if (slnFileFormat.CanWriteFile (obj, this)) return slnFileFormat.GetValidFormatName (obj, fileName, this); else { - string ext = MSBuildProjectService.GetExtensionForItem ((SolutionEntityItem)obj); + string ext = MSBuildProjectService.GetExtensionForItem ((SolutionItem)obj); if (!string.IsNullOrEmpty (ext)) return fileName.ChangeExtension ("." + ext); else @@ -82,7 +88,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild { if (expectedType.IsAssignableFrom (typeof(Solution)) && slnFileFormat.CanReadFile (file, this)) return true; - else if (expectedType.IsAssignableFrom (typeof(SolutionEntityItem))) { + else if (expectedType.IsAssignableFrom (typeof(SolutionItem))) { if (!MSBuildProjectService.CanReadFile (file)) return false; //TODO: check ProductVersion first @@ -95,12 +101,12 @@ namespace MonoDevelop.Projects.Formats.MSBuild { if (slnFileFormat.CanWriteFile (obj, this)) { Solution sol = (Solution) obj; - foreach (SolutionEntityItem si in sol.GetAllSolutionItems<SolutionEntityItem> ()) + foreach (SolutionItem si in sol.GetAllItems<SolutionItem> ()) if (!CanWriteFile (si)) return false; return true; } - else if (obj is SolutionEntityItem) { + else if (obj is SolutionItem) { DotNetProject p = obj as DotNetProject; // Check the framework only if the project is not loading, since otherwise the // project may not yet have the framework info set. @@ -118,7 +124,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild { if (obj is Solution) { List<string> msg = new List<string> (); - foreach (SolutionEntityItem si in ((Solution)obj).GetAllSolutionItems<SolutionEntityItem> ()) { + foreach (SolutionItem si in ((Solution)obj).GetAllItems<SolutionItem> ()) { IEnumerable<string> ws = GetCompatibilityWarnings (si); if (ws != null) msg.AddRange (ws); @@ -135,26 +141,21 @@ namespace MonoDevelop.Projects.Formats.MSBuild return null; } - public void WriteFile (FilePath file, object obj, IProgressMonitor monitor) + public async Task WriteFile (FilePath file, object obj, ProgressMonitor monitor) { if (slnFileFormat.CanWriteFile (obj, this)) { - slnFileFormat.WriteFile (file, obj, this, true, monitor); + await slnFileFormat.WriteFile (file, obj, true, monitor); } else { - SolutionEntityItem item = (SolutionEntityItem) obj; - if (!(item.ItemHandler is MSBuildProjectHandler)) - MSBuildProjectService.InitializeItemHandler (item); - MSBuildProjectHandler handler = (MSBuildProjectHandler) item.ItemHandler; - handler.SetSolutionFormat (this, false); - handler.Save (monitor); + throw new NotSupportedException (); } }
- public object ReadFile (FilePath file, Type expectedType, MonoDevelop.Core.IProgressMonitor monitor) + public async Task<object> ReadFile (FilePath file, Type expectedType, MonoDevelop.Core.ProgressMonitor monitor) { if (slnFileFormat.CanReadFile (file, this)) - return slnFileFormat.ReadFile (file, this, monitor); + return await slnFileFormat.ReadFile (file, monitor); else - return MSBuildProjectService.LoadItem (monitor, file, null, null, null); + return await MSBuildProjectService.LoadItem (monitor, file, null, null, null); }
public List<FilePath> GetItemFiles (object obj) @@ -162,24 +163,17 @@ namespace MonoDevelop.Projects.Formats.MSBuild return new List<FilePath> (); } - public void ConvertToFormat (object obj) + public Task ConvertToFormat (object obj) { if (obj == null) - return; + return Task.FromResult(0); - MSBuildHandler handler; - SolutionItem item = obj as SolutionItem; + SolutionFolderItem item = obj as SolutionFolderItem; if (item != null) { - handler = item.GetItemHandler() as MSBuildHandler; - if (handler != null) { - handler.SetSolutionFormat (this, true); - return; - } + item.SetSolutionFormat (this, true); + return Task.FromResult(0); } - - MSBuildProjectService.InitializeItemHandler (item); - handler = (MSBuildHandler) item.ItemHandler; - handler.SetSolutionFormat (this, true); + return Task.FromResult (0); } public bool SupportsMixedFormats { diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildHandler.cs deleted file mode 100644 index 29e862cb26..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildHandler.cs +++ /dev/null @@ -1,172 +0,0 @@ -// MSBuildHandler.cs -// -// Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2008 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// - -using System; -using System.IO; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using MonoDevelop.Core; -using MonoDevelop.Core.Serialization; -using MonoDevelop.Projects; -using MonoDevelop.Projects.Extensions; - -namespace MonoDevelop.Projects.Formats.MSBuild -{ - public class MSBuildHandler: ISolutionItemHandler - { - SolutionItem item; - string typeGuid; - string id; - string[] slnProjectContent; - DataItem customSlnData; - - internal List<string> UnresolvedProjectDependencies { get; set; } - - internal protected MSBuildHandler () - { - } - - public MSBuildHandler (string typeGuid, string itemId) - { - Initialize (typeGuid, itemId); - } - - internal void Initialize (string typeGuid, string itemId) - { - this.typeGuid = typeGuid; - this.id = itemId; - } - - // When set, it means this item is saved as part of a global solution save operation - internal bool SavingSolution { get; set; } - - internal protected SolutionItem Item { - get { return item; } - set { item = value; } - } - - public virtual bool SyncFileName { - get { return true; } - } - - public string TypeGuid { - get { - return typeGuid; - } - } - - internal string[] SlnProjectContent { - get { - return slnProjectContent; - } - set { - slnProjectContent = value; - } - } - - public string ItemId { - get { - if (id == null) - id = String.Format ("{{{0}}}", System.Guid.NewGuid ().ToString ().ToUpper ()); - return id; - } - set { id = value; } - } - - internal MSBuildFileFormat SolutionFormat { get; private set; } - - internal virtual void SetSolutionFormat (MSBuildFileFormat format, bool converting) - { - SolutionFormat = format; - } - - public virtual BuildResult RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration) - { - throw new NotSupportedException (); - } - - public void Save (IProgressMonitor monitor) - { - if (HasSlnData && !SavingSolution && Item.ParentSolution != null) { - // The project has data that has to be saved in the solution, but the solution is not being saved. Do it now. - monitor.BeginTask (null, 2); - SaveItem (monitor); - monitor.Step (1); - Solution sol = Item.ParentSolution; - SolutionFormat.SlnFileFormat.WriteFile (sol.FileName, sol, SolutionFormat, false, monitor); - sol.NeedsReload = false; - monitor.EndTask (); - } else - SaveItem (monitor); - } - - protected virtual void SaveItem (MonoDevelop.Core.IProgressMonitor monitor) - { - throw new NotSupportedException (); - } - - public virtual void OnModified (string hint) - { - } - - public virtual void Dispose () - { - } - - public virtual bool HasSlnData { - get { return false; } - } - - public virtual DataItem WriteSlnData () - { - return customSlnData; - } - - public virtual void ReadSlnData (DataItem item) - { - customSlnData = item; - } - - /// <summary> - /// Gets a service instance of a given type - /// </summary> - /// <returns> - /// The service. - /// </returns> - /// <param name='t'> - /// Type of the service - /// </param> - /// <remarks> - /// This method looks for an imlpementation of a service of the given type. - /// </remarks> - public virtual object GetService (Type t) - { - return null; - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildImport.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildImport.cs new file mode 100644 index 0000000000..0948c2a0b9 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildImport.cs @@ -0,0 +1,56 @@ +// +// MSBuildImport.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Xml; + + +namespace MonoDevelop.Projects.Formats.MSBuild +{ + + public class MSBuildImport: MSBuildObject + { + string evaluatedProjectPath; + + public MSBuildImport (XmlElement elem): base (elem) + { + } + + public string Project { + get { return Element.GetAttribute ("Project"); } + set { Element.SetAttribute ("Project", value); } + } + + public string EvaluatedProject { + get { return evaluatedProjectPath ?? Project; } + } + + internal void SetEvalResult (string evaluatedProjectPath) + { + this.evaluatedProjectPath = evaluatedProjectPath; + } + } + +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildItem.cs new file mode 100644 index 0000000000..9858088f45 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildItem.cs @@ -0,0 +1,152 @@ +// +// MSBuildItem.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Xml; + + +namespace MonoDevelop.Projects.Formats.MSBuild +{ + public class MSBuildItem: MSBuildObject, IMSBuildItemEvaluated + { + MSBuildPropertyGroup metadata; + MSBuildPropertyGroupEvaluated evaluatedMetadata; + MSBuildProject parent; + string evaluatedInclude; + + internal MSBuildItem (MSBuildProject parent, XmlElement elem): base (elem) + { + this.parent = parent; + } + + public string Include { + get { return evaluatedInclude ?? UnevaluatedInclude; } + set { evaluatedInclude = UnevaluatedInclude = value; } + } + + public string UnevaluatedInclude { + get { return Element.GetAttribute ("Include"); } + set { Element.SetAttribute ("Include", value); } + } + + internal void SetEvalResult (string value) + { + this.evaluatedInclude = value; + } + + public bool IsImported { + get; + set; + } + + public string Name { + get { return Element.Name; } + } + + public IMSBuildPropertySet Metadata { + get { + if (metadata == null) { + metadata = new MSBuildPropertyGroup (parent, Element); + metadata.UppercaseBools = true; + } + return metadata; + } + } + + public IMSBuildPropertyGroupEvaluated EvaluatedMetadata { + get { + if (evaluatedMetadata == null) + evaluatedMetadata = new MSBuildPropertyGroupEvaluated (parent); + return evaluatedMetadata; + } + } + + IMSBuildPropertyGroupEvaluated IMSBuildItemEvaluated.Metadata { + get { return EvaluatedMetadata; } + } + + public void WriteDataObjects () + { + metadata.WriteDataObjects (); + if (!Element.HasChildNodes) + Element.IsEmpty = true; + } + } + + class MSBuildItemEvaluated: MSBuildObject, IMSBuildItemEvaluated + { + MSBuildPropertyGroupEvaluated metadata; + MSBuildProject parent; + string evaluatedInclude; + string include; + + internal MSBuildItemEvaluated (MSBuildProject parent, string name, string include, string evaluatedInclude): base (null) + { + this.include = include; + this.evaluatedInclude = evaluatedInclude; + this.parent = parent; + Name = name; + } + + public string Include { + get { return evaluatedInclude; } + } + + public string UnevaluatedInclude { + get { return include; } + } + + public bool IsImported { + get; + internal set; + } + + public string Name { get; private set; } + + public IMSBuildPropertyGroupEvaluated Metadata { + get { + if (metadata == null) + metadata = new MSBuildPropertyGroupEvaluated (parent); + return metadata; + } + } + } + + + public interface IMSBuildItemEvaluated + { + string Include { get; } + + string UnevaluatedInclude { get; } + + string Condition { get; } + + bool IsImported { get; } + + string Name { get; } + + IMSBuildPropertyGroupEvaluated Metadata { get; } + } +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildItemGroup.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildItemGroup.cs new file mode 100644 index 0000000000..5f1a2eab17 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildItemGroup.cs @@ -0,0 +1,73 @@ +// +// MSBuildItemGroup.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Collections.Generic; +using System.Xml; + + +namespace MonoDevelop.Projects.Formats.MSBuild +{ + + public class MSBuildItemGroup: MSBuildObject + { + MSBuildProject parent; + + internal MSBuildItemGroup (MSBuildProject parent, XmlElement elem): base (elem) + { + this.parent = parent; + } + + public bool IsImported { + get; + set; + } + + public MSBuildItem AddNewItem (string name, string include) + { + XmlElement elem = AddChildElement (name); + MSBuildItem it = parent.GetItem (elem); + it.Include = include; + return it; + } + + public IEnumerable<MSBuildItem> Items { + get { + foreach (XmlNode node in Element.ChildNodes) { + XmlElement elem = node as XmlElement; + if (elem != null) + yield return parent.GetItem (elem); + } + } + } + + internal override void Evaluate (MSBuildEvaluationContext context) + { + foreach (var item in Items) + item.Evaluate (context); + } + } + +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildObject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildObject.cs new file mode 100644 index 0000000000..4c74f54285 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildObject.cs @@ -0,0 +1,75 @@ +// +// MSBuildObject.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Xml; + + +namespace MonoDevelop.Projects.Formats.MSBuild +{ + + public class MSBuildObject + { + XmlElement elem; + + public MSBuildObject (XmlElement elem) + { + this.elem = elem; + } + + public XmlElement Element { + get { return elem; } + } + + protected XmlElement AddChildElement (string name) + { + XmlElement e = elem.OwnerDocument.CreateElement (null, name, MSBuildProject.Schema); + elem.AppendChild (e); + return e; + } + + public string Label { + get { return Element.GetAttribute ("Label"); } + set { Element.SetAttribute ("Label", value); } + } + + public string Condition { + get { + return Element != null ? Element.GetAttribute ("Condition") : null; + } + set { + if (string.IsNullOrEmpty (value)) + Element.RemoveAttribute ("Condition"); + else + Element.SetAttribute ("Condition", value); + } + } + + internal virtual void Evaluate (MSBuildEvaluationContext context) + { + } + } + +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProject.cs index 2976287a16..4674d3f027 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProject.cs @@ -26,33 +26,39 @@ // using System; -using System.Linq; using System.IO; using System.Collections.Generic; using System.Xml; using System.Text; +using MonoDevelop.Core; using MonoDevelop.Projects.Utility; -using MonoDevelop.Projects.Text; using Microsoft.Build.BuildEngine; +using MSProject = Microsoft.Build.BuildEngine.Project; +using System.Linq; +using MonoDevelop.Projects.Text; +using System.Threading.Tasks; namespace MonoDevelop.Projects.Formats.MSBuild { public class MSBuildProject { XmlDocument doc; - string file; + FilePath file; Dictionary<XmlElement,MSBuildObject> elemCache = new Dictionary<XmlElement,MSBuildObject> (); Dictionary<string, MSBuildItemGroup> bestGroups; - + List<MSBuildItemEvaluated> evaluatedItems = new List<MSBuildItemEvaluated> (); + List<MSBuildItemEvaluated> evaluatedItemsIgnoringCondition; + MSBuildEvaluatedPropertyCollection evaluatedProperties; + public const string Schema = "http://schemas.microsoft.com/developer/msbuild/2003"; static XmlNamespaceManager manager; bool endsWithEmptyLine; string newLine = Environment.NewLine; ByteOrderMark bom; - - internal static XmlNamespaceManager XmlNamespaceManager { + + public static XmlNamespaceManager XmlNamespaceManager { get { if (manager == null) { manager = new XmlNamespaceManager (new NameTable ()); @@ -62,9 +68,21 @@ namespace MonoDevelop.Projects.Formats.MSBuild } } - public string FileName { + public FilePath FileName { get { return file; } + set { file = value; } + } + + public FilePath BaseDirectory { + get { return file.ParentDirectory; } } + + public MSBuildFileFormat Format { + get; + set; + } + + public bool IsNewProject { get; private set; } public XmlDocument Document { get { return doc; } @@ -72,14 +90,27 @@ namespace MonoDevelop.Projects.Formats.MSBuild public MSBuildProject () { + evaluatedProperties = new MSBuildEvaluatedPropertyCollection (this); + evaluatedItemsIgnoringCondition = new List<MSBuildItemEvaluated> (); doc = new XmlDocument (); doc.PreserveWhitespace = false; doc.AppendChild (doc.CreateElement (null, "Project", Schema)); + IsNewProject = true; + } + + public static Task<MSBuildProject> LoadAsync (string file) + { + return Task<MSBuildProject>.Factory.StartNew (delegate { + var p = new MSBuildProject (); + p.Load (file); + return p; + }); } public void Load (string file) { this.file = file; + IsNewProject = false; using (FileStream fs = File.OpenRead (file)) { byte[] buf = new byte [1024]; int nread, i; @@ -172,18 +203,87 @@ namespace MonoDevelop.Projects.Formats.MSBuild return content; } + void WriteDataObjects () + { + foreach (var ob in elemCache.Values) { + if (ob is MSBuildPropertyGroup) + ((MSBuildPropertyGroup)ob).WriteDataObjects (); + else if (ob is MSBuildItem) + ((MSBuildItem)ob).WriteDataObjects (); + } + } + public void Evaluate () { - Evaluate (new MSBuildEvaluationContext ()); + try { + Engine e = new Engine (); + MSProject project = new MSProject (e); + project.Load (FileName); + SyncBuildProject (project); + } catch (Exception ex) { + // If the project can't be evaluated don't crash + LoggingService.LogError ("MSBuild project could not be evaluated", ex); + } } - public void Evaluate (MSBuildEvaluationContext context) + void SyncBuildProject (MSProject project) { - context.InitEvaluation (this); - foreach (var pg in PropertyGroups) - pg.Evaluate (context); - foreach (var pg in ItemGroups) - pg.Evaluate (context); + var xmlGroups = PropertyGroups.ToArray (); + var buildGroups = project.PropertyGroups.Cast<BuildPropertyGroup> ().ToArray (); + for (int n=0; n<xmlGroups.Length && n<buildGroups.Length; n++) + SyncBuildPropertyGroup (xmlGroups [n], buildGroups [n]); + + var xmlItems = ItemGroups.ToArray (); + var buildItems = project.ItemGroups.Cast<BuildItemGroup> ().Where (g => !g.IsImported).ToArray (); + for (int n=0; n<xmlItems.Length && n<buildItems.Length; n++) + SyncBuildItemGroup (xmlItems [n], buildItems [n]); + + var xmlImports = Imports.ToArray (); + var buildImports = project.Imports.Cast<Import> ().ToArray (); + for (int n = 0; n < xmlImports.Length && n < buildImports.Length; n++) + xmlImports [n].SetEvalResult (buildImports [n].EvaluatedProjectPath); + + foreach (BuildItem it in project.EvaluatedItems) { + var xit = new MSBuildItemEvaluated (this, it.Name, it.Include, it.FinalItemSpec); + xit.IsImported = it.IsImported; + ((MSBuildPropertyGroupEvaluated)xit.Metadata).Sync (it); + evaluatedItems.Add (xit); + } + + foreach (BuildItem it in project.EvaluatedItemsIgnoringCondition) { + var xit = new MSBuildItemEvaluated (this, it.Name, it.Include, it.FinalItemSpec); + xit.IsImported = it.IsImported; + ((MSBuildPropertyGroupEvaluated)xit.Metadata).Sync (it); + evaluatedItemsIgnoringCondition.Add (xit); + } + + evaluatedProperties.Sync (project.EvaluatedProperties); + } + + void SyncBuildPropertyGroup (MSBuildPropertyGroup xmlGroup, BuildPropertyGroup buildGroup) + { + var xmlProps = xmlGroup.Properties.ToArray (); + var buildProps = buildGroup.Cast<BuildProperty> ().ToArray (); + for (int n = 0; n < xmlProps.Length && n < buildProps.Length; n++) + SyncBuildProperty (xmlProps [n], buildProps [n]); + } + + void SyncBuildProperty (MSBuildProperty xmlProp, BuildProperty buildProp) + { + } + + void SyncBuildItemGroup (MSBuildItemGroup xmlGroup, BuildItemGroup buildGroup) + { + var xmlItems = xmlGroup.Items.ToArray (); + var buildItems = buildGroup.Cast<BuildItem> ().ToArray (); + for (int n = 0; n < xmlItems.Length && n < buildItems.Length; n++) + SyncBuildItem (xmlItems [n], buildItems [n]); + } + + void SyncBuildItem (MSBuildItem xmlItem, BuildItem buildItem) + { + xmlItem.SetEvalResult (buildItem.FinalItemSpec); + ((MSBuildPropertyGroupEvaluated)xmlItem.EvaluatedMetadata).Sync (buildItem); } public string DefaultTargets { @@ -200,11 +300,43 @@ namespace MonoDevelop.Projects.Formats.MSBuild doc.DocumentElement.RemoveAttribute ("ToolsVersion"); } } + + public string[] ProjectTypeGuids { + get { return GetGlobalPropertyGroup ().GetValue ("ProjectTypeGuids", "").Split (new []{';'}, StringSplitOptions.RemoveEmptyEntries).Select (t => t.Trim()).ToArray (); } + set { GetGlobalPropertyGroup ().SetValue ("ProjectTypeGuids", string.Join (";", value), preserveExistingCase:true); } + } + + public bool AddProjectTypeGuid (string guid) + { + var guids = GetGlobalPropertyGroup ().GetValue ("ProjectTypeGuids", "").Trim (); + if (guids.IndexOf (guid, StringComparison.OrdinalIgnoreCase) == -1) { + if (!string.IsNullOrEmpty (guids)) + guids += ";" + guid; + else + guids = guid; + GetGlobalPropertyGroup ().SetValue ("ProjectTypeGuids", guids, preserveExistingCase: true); + return true; + } + return false; + } - public MSBuildImport AddNewImport (string name, MSBuildImport beforeImport = null) + public bool RemoveProjectTypeGuid (string guid) + { + var guids = ProjectTypeGuids; + var newGuids = guids.Where (g => !g.Equals (guid, StringComparison.OrdinalIgnoreCase)).ToArray (); + if (newGuids.Length != guids.Length) { + ProjectTypeGuids = newGuids; + return true; + } else + return false; + } + + public MSBuildImport AddNewImport (string name, string condition = null, MSBuildImport beforeImport = null) { XmlElement elem = doc.CreateElement (null, "Import", MSBuildProject.Schema); elem.SetAttribute ("Project", name); + if (condition != null) + elem.SetAttribute ("Condition", condition); if (beforeImport != null) { doc.DocumentElement.InsertBefore (elem, beforeImport.Element); @@ -215,7 +347,12 @@ namespace MonoDevelop.Projects.Formats.MSBuild else doc.DocumentElement.AppendChild (elem); } - return new MSBuildImport (elem); + return GetImport (elem); + } + + public MSBuildImport GetImport (string name, string condition = null) + { + return Imports.FirstOrDefault (i => i.Project == name && i.Condition == condition); } public void RemoveImport (string name) @@ -228,21 +365,37 @@ namespace MonoDevelop.Projects.Formats.MSBuild Console.WriteLine ("ppnf:"); } + public void RemoveImport (MSBuildImport import) + { + import.Element.ParentNode.RemoveChild (import.Element); + } + public IEnumerable<MSBuildImport> Imports { get { foreach (XmlElement elem in doc.DocumentElement.SelectNodes ("tns:Import", XmlNamespaceManager)) - yield return new MSBuildImport (elem); + yield return GetImport (elem); } } - - public MSBuildPropertySet GetGlobalPropertyGroup () + + public IMSBuildEvaluatedPropertyCollection EvaluatedProperties { + get { return evaluatedProperties; } + } + + public IEnumerable<IMSBuildItemEvaluated> EvaluatedItems { + get { return evaluatedItems; } + } + + public IEnumerable<IMSBuildItemEvaluated> EvaluatedItemsIgnoringCondition { + get { return evaluatedItemsIgnoringCondition; } + } + + public IMSBuildPropertySet GetGlobalPropertyGroup () { - MSBuildPropertyGroupMerged res = new MSBuildPropertyGroupMerged (); foreach (MSBuildPropertyGroup grp in PropertyGroups) { if (grp.Condition.Length == 0) - res.Add (grp); + return grp; } - return res.GroupCount > 0 ? res : null; + return null; } public MSBuildPropertyGroup AddNewPropertyGroup (bool insertAtEnd) @@ -336,31 +489,67 @@ namespace MonoDevelop.Projects.Formats.MSBuild return group; } - public string GetProjectExtensions (string section) + public XmlElement GetProjectExtension (string section) { - XmlElement elem = doc.DocumentElement.SelectSingleNode ("tns:ProjectExtensions/tns:" + section, XmlNamespaceManager) as XmlElement; - if (elem != null) - return elem.InnerXml; - else - return string.Empty; + return doc.DocumentElement.SelectSingleNode ("tns:ProjectExtensions/tns:" + section, XmlNamespaceManager) as XmlElement; } - public void SetProjectExtensions (string section, string value) + public XmlElement GetMonoDevelopProjectExtension (string section) { + return doc.DocumentElement.SelectSingleNode ("tns:ProjectExtensions/tns:MonoDevelop/tns:Properties/tns:" + section, XmlNamespaceManager) as XmlElement; + } + + public void SetProjectExtension (string section, XmlElement value) + { + if (value.OwnerDocument != doc) + value = (XmlElement)doc.ImportNode (value, true); + + XmlElement elem = doc.DocumentElement ["ProjectExtensions", MSBuildProject.Schema]; + if (elem == null) { + elem = doc.CreateElement (null, "ProjectExtensions", MSBuildProject.Schema); + doc.DocumentElement.AppendChild (elem); + } + XmlElement sec = elem [section]; + if (sec == null) + elem.AppendChild (value); + else { + elem.InsertAfter (value, sec); + elem.RemoveChild (sec); + } + } + + public void SetMonoDevelopProjectExtension (string section, XmlElement value) + { + if (value.OwnerDocument != doc) + value = (XmlElement)doc.ImportNode (value, true); + XmlElement elem = doc.DocumentElement ["ProjectExtensions", MSBuildProject.Schema]; if (elem == null) { elem = doc.CreateElement (null, "ProjectExtensions", MSBuildProject.Schema); doc.DocumentElement.AppendChild (elem); } + var parent = elem; + elem = parent ["MonoDevelop", MSBuildProject.Schema]; + if (elem == null) { + elem = doc.CreateElement (null, "MonoDevelop", MSBuildProject.Schema); + parent.AppendChild (elem); + } + parent = elem; + elem = parent ["Properties", MSBuildProject.Schema]; + if (elem == null) { + elem = doc.CreateElement (null, "Properties", MSBuildProject.Schema); + parent.AppendChild (elem); + } XmlElement sec = elem [section]; - if (sec == null) { - sec = doc.CreateElement (null, section, MSBuildProject.Schema); - elem.AppendChild (sec); + if (sec == null) + elem.AppendChild (value); + else { + elem.InsertAfter (value, sec); + elem.RemoveChild (sec); } - sec.InnerXml = value; } - public void RemoveProjectExtensions (string section) + public void RemoveProjectExtension (string section) { XmlElement elem = doc.DocumentElement.SelectSingleNode ("tns:ProjectExtensions/tns:" + section, XmlNamespaceManager) as XmlElement; if (elem != null) { @@ -371,6 +560,19 @@ namespace MonoDevelop.Projects.Formats.MSBuild } } + public void RemoveMonoDevelopProjectExtension (string section) + { + XmlElement elem = doc.DocumentElement.SelectSingleNode ("tns:ProjectExtensions/tns:MonoDevelop/tns:Properties/tns:" + section, XmlNamespaceManager) as XmlElement; + if (elem != null) { + do { + XmlElement parent = (XmlElement) elem.ParentNode; + parent.RemoveChild (elem); + elem = parent; + } + while (!elem.HasChildNodes); + } + } + public void RemoveItem (MSBuildItem item) { elemCache.Remove (item.Element); @@ -383,12 +585,22 @@ namespace MonoDevelop.Projects.Formats.MSBuild } } + internal MSBuildImport GetImport (XmlElement elem) + { + MSBuildObject ob; + if (elemCache.TryGetValue (elem, out ob)) + return (MSBuildImport) ob; + MSBuildImport it = new MSBuildImport (elem); + elemCache [elem] = it; + return it; + } + internal MSBuildItem GetItem (XmlElement elem) { MSBuildObject ob; if (elemCache.TryGetValue (elem, out ob)) return (MSBuildItem) ob; - MSBuildItem it = new MSBuildItem (elem); + MSBuildItem it = new MSBuildItem (this, elem); elemCache [elem] = it; return it; } @@ -420,628 +632,12 @@ namespace MonoDevelop.Projects.Formats.MSBuild } } - public class MSBuildObject - { - XmlElement elem; - XmlElement evaluatedElem; - public MSBuildObject (XmlElement elem) - { - this.elem = elem; - } - - public XmlElement Element { - get { return elem; } - } - - public XmlElement EvaluatedElement { - get { return evaluatedElem ?? elem; } - protected set { evaluatedElem = value; } - } - - public bool IsEvaluated { - get { return evaluatedElem != null; } - } - - protected XmlElement AddChildElement (string name) - { - XmlElement e = elem.OwnerDocument.CreateElement (null, name, MSBuildProject.Schema); - elem.AppendChild (e); - return e; - } - - public string Label { - get { return EvaluatedElement.GetAttribute ("Label"); } - set { Element.SetAttribute ("Label", value); } - } - - public string Condition { - get { - return Element.GetAttribute ("Condition"); - } - set { - if (string.IsNullOrEmpty (value)) - Element.RemoveAttribute ("Condition"); - else - Element.SetAttribute ("Condition", value); - } - } - - internal virtual void Evaluate (MSBuildEvaluationContext context) - { - } - } - - public class MSBuildImport: MSBuildObject - { - public MSBuildImport (XmlElement elem): base (elem) - { - } - - public string Project { - get { return EvaluatedElement.GetAttribute ("Project"); } - set { Element.SetAttribute ("Project", value); } - } - - public string Condition { - get { return EvaluatedElement.GetAttribute ("Condition"); } - set { Element.SetAttribute ("Condition", value); } - } - } - public class MSBuildProperty: MSBuildObject - { - public MSBuildProperty (XmlElement elem): base (elem) - { - } - - public string Name { - get { return Element.Name; } - } - - internal bool Overwritten { get; set; } - - public string GetValue (bool isXml = false) - { - if (isXml) - return EvaluatedElement.InnerXml; - return EvaluatedElement.InnerText; - } - - public void SetValue (string value, bool isXml = false) - { - if (isXml) - Element.InnerXml = value; - else - Element.InnerText = value; - } - - internal override void Evaluate (MSBuildEvaluationContext context) - { - EvaluatedElement = null; - - if (!string.IsNullOrEmpty (Condition)) { - string cond; - if (!context.Evaluate (Condition, out cond)) { - // The value could not be evaluated, so if there is an existing value, it is not valid anymore - context.ClearPropertyValue (Name); - return; - } - if (!ConditionParser.ParseAndEvaluate (cond, context)) - return; - } - - XmlElement elem; - - if (context.Evaluate (Element, out elem)) { - EvaluatedElement = elem; - context.SetPropertyValue (Name, GetValue ()); - } else { - // The value could not be evaluated, so if there is an existing value, it is not valid anymore - context.ClearPropertyValue (Name); - } - } - } - public interface MSBuildPropertySet - { - MSBuildProperty GetProperty (string name); - IEnumerable<MSBuildProperty> Properties { get; } - MSBuildProperty SetPropertyValue (string name, string value, bool preserveExistingCase, bool isXml = false); - string GetPropertyValue (string name, bool isXml = false); - bool RemoveProperty (string name); - void RemoveAllProperties (); - void UnMerge (MSBuildPropertySet baseGrp, ISet<string> propertiesToExclude); - } - class MSBuildPropertyGroupMerged: MSBuildPropertySet - { - List<MSBuildPropertyGroup> groups = new List<MSBuildPropertyGroup> (); - - public void Add (MSBuildPropertyGroup g) - { - groups.Add (g); - } - - public int GroupCount { - get { return groups.Count; } - } - - public MSBuildProperty GetProperty (string name) - { - // Find property in reverse order, since the last set - // value is the good one - for (int n=groups.Count - 1; n >= 0; n--) { - var g = groups [n]; - MSBuildProperty p = g.GetProperty (name); - if (p != null) - return p; - } - return null; - } - - public MSBuildProperty SetPropertyValue (string name, string value, bool preserveExistingCase, bool isXml = false) - { - MSBuildProperty p = GetProperty (name); - if (p != null) { - if (!preserveExistingCase || !string.Equals (value, p.GetValue (isXml), StringComparison.OrdinalIgnoreCase)) { - p.SetValue (value, isXml); - } - return p; - } - return groups [0].SetPropertyValue (name, value, preserveExistingCase, isXml); - } - - public string GetPropertyValue (string name, bool isXml = false) - { - MSBuildProperty prop = GetProperty (name); - return prop != null ? prop.GetValue (isXml) : null; - } - - public bool RemoveProperty (string name) - { - bool found = false; - foreach (var g in groups) { - if (g.RemoveProperty (name)) { - Prune (g); - found = true; - } - } - return found; - } - - public void RemoveAllProperties () - { - foreach (var g in groups) { - g.RemoveAllProperties (); - Prune (g); - } - } - - public void UnMerge (MSBuildPropertySet baseGrp, ISet<string> propertiesToExclude) - { - foreach (var g in groups) { - g.UnMerge (baseGrp, propertiesToExclude); - } - } - - public IEnumerable<MSBuildProperty> Properties { - get { - foreach (var g in groups) { - foreach (var p in g.Properties) - yield return p; - } - } - } - - void Prune (MSBuildPropertyGroup g) - { - if (g != groups [0] && !g.Properties.Any()) { - // Remove this group since it's now empty - g.Parent.RemoveGroup (g); - } - } - } - public class MSBuildPropertyGroup: MSBuildObject, MSBuildPropertySet - { - Dictionary<string,MSBuildProperty> properties = new Dictionary<string,MSBuildProperty> (); - List<MSBuildProperty> propertyList = new List<MSBuildProperty> (); - MSBuildProject parent; - - public MSBuildPropertyGroup (MSBuildProject parent, XmlElement elem): base (elem) - { - this.parent = parent; - - foreach (var pelem in Element.ChildNodes.OfType<XmlElement> ()) { - MSBuildProperty prevSameName; - if (properties.TryGetValue (pelem.Name, out prevSameName)) - prevSameName.Overwritten = true; - - var prop = new MSBuildProperty (pelem); - propertyList.Add (prop); - properties [pelem.Name] = prop; // If a property is defined more than once, we only care about the last registered value - } - } - - public MSBuildProject Parent { - get { - return this.parent; - } - } - - public MSBuildProperty GetProperty (string name) - { - MSBuildProperty prop; - properties.TryGetValue (name, out prop); - return prop; - } - - public IEnumerable<MSBuildProperty> Properties { - get { - return propertyList.Where (p => !p.Overwritten); - } - } - - public MSBuildProperty SetPropertyValue (string name, string value, bool preserveExistingCase, bool isXml = false) - { - MSBuildProperty prop = GetProperty (name); - if (prop == null) { - XmlElement pelem = AddChildElement (name); - prop = new MSBuildProperty (pelem); - properties [name] = prop; - propertyList.Add (prop); - prop.SetValue (value, isXml); - } else if (!preserveExistingCase || !string.Equals (value, prop.GetValue (isXml), StringComparison.OrdinalIgnoreCase)) { - prop.SetValue (value, isXml); - } - return prop; - } - - public string GetPropertyValue (string name, bool isXml = false) - { - MSBuildProperty prop = GetProperty (name); - if (prop == null) - return null; - else - return prop.GetValue (isXml); - } - - public bool RemoveProperty (string name) - { - MSBuildProperty prop = GetProperty (name); - if (prop != null) { - properties.Remove (name); - propertyList.Remove (prop); - Element.RemoveChild (prop.Element); - return true; - } - return false; - } - - public void RemoveAllProperties () - { - List<XmlNode> toDelete = new List<XmlNode> (); - foreach (XmlNode node in Element.ChildNodes) { - if (node is XmlElement) - toDelete.Add (node); - } - foreach (XmlNode node in toDelete) - Element.RemoveChild (node); - properties.Clear (); - propertyList.Clear (); - } - - public void UnMerge (MSBuildPropertySet baseGrp, ISet<string> propsToExclude) - { - foreach (MSBuildProperty prop in baseGrp.Properties) { - if (propsToExclude != null && propsToExclude.Contains (prop.Name)) - continue; - MSBuildProperty thisProp = GetProperty (prop.Name); - if (thisProp != null && prop.GetValue (true).Equals (thisProp.GetValue (true), StringComparison.OrdinalIgnoreCase)) - RemoveProperty (prop.Name); - } - } - - internal override void Evaluate (MSBuildEvaluationContext context) - { - if (!string.IsNullOrEmpty (Condition)) { - string cond; - if (!context.Evaluate (Condition, out cond)) { - // The condition could not be evaluated. Clear all properties that this group defines - // since we don't know if they will have a value or not - foreach (var prop in Properties) - context.ClearPropertyValue (prop.Name); - return; - } - if (!ConditionParser.ParseAndEvaluate (cond, context)) - return; - } - - foreach (var prop in propertyList) - prop.Evaluate (context); - } - - public override string ToString() - { - string s = "[MSBuildPropertyGroup:"; - foreach (MSBuildProperty prop in Properties) - s += " " + prop.Name + "=" + prop.GetValue (true); - return s + "]"; - } - - } - public class MSBuildItem: MSBuildObject - { - public MSBuildItem (XmlElement elem): base (elem) - { - } - - public string Include { - get { return EvaluatedElement.GetAttribute ("Include"); } - set { Element.SetAttribute ("Include", value); } - } - - public string UnevaluatedInclude { - get { return Element.GetAttribute ("Include"); } - set { Element.SetAttribute ("Include", value); } - } - - public string Name { - get { return Element.Name; } - } - - public bool HasMetadata (string name) - { - return EvaluatedElement [name, MSBuildProject.Schema] != null; - } - - public void SetMetadata (string name, bool value) - { - SetMetadata (name, value ? "True" : "False"); - } - - public void SetMetadata (string name, string value, bool isXml = false) - { - // Don't overwrite the metadata value if the new value is the same as the old - // This will keep the old metadata string, which can contain property references - if (GetMetadata (name, isXml) == value) - return; - - XmlElement elem = Element [name, MSBuildProject.Schema]; - if (elem == null) { - elem = AddChildElement (name); - Element.AppendChild (elem); - } - if (isXml) - elem.InnerXml = value; - else - elem.InnerText = value; - } - - public void UnsetMetadata (string name) - { - XmlElement elem = Element [name, MSBuildProject.Schema]; - if (elem != null) { - Element.RemoveChild (elem); - if (!Element.HasChildNodes) - Element.IsEmpty = true; - } - } - - public string GetMetadata (string name, bool isXml = false) - { - XmlElement elem = EvaluatedElement [name, MSBuildProject.Schema]; - if (elem != null) - return isXml ? elem.InnerXml : elem.InnerText; - else - return null; - } - - public bool? GetBoolMetadata (string name) - { - var val = GetMetadata (name); - if (String.Equals (val, "False", StringComparison.OrdinalIgnoreCase)) - return false; - if (String.Equals (val, "True", StringComparison.OrdinalIgnoreCase)) - return true; - return null; - } - - public bool GetMetadataIsFalse (string name) - { - return String.Compare (GetMetadata (name), "False", StringComparison.OrdinalIgnoreCase) == 0; - } - - public void MergeFrom (MSBuildItem other) - { - foreach (XmlNode node in Element.ChildNodes) { - if (node is XmlElement) - SetMetadata (node.LocalName, node.InnerXml, true); - } - } - - internal override void Evaluate (MSBuildEvaluationContext context) - { - XmlElement elem; - if (context.Evaluate (Element, out elem)) - EvaluatedElement = elem; - else - EvaluatedElement = null; - } - } - public class MSBuildItemGroup: MSBuildObject - { - MSBuildProject parent; - - internal MSBuildItemGroup (MSBuildProject parent, XmlElement elem): base (elem) - { - this.parent = parent; - } - - public MSBuildItem AddNewItem (string name, string include) - { - XmlElement elem = AddChildElement (name); - MSBuildItem it = parent.GetItem (elem); - it.Include = include; - return it; - } - - public IEnumerable<MSBuildItem> Items { - get { - foreach (XmlNode node in Element.ChildNodes) { - XmlElement elem = node as XmlElement; - if (elem != null) - yield return parent.GetItem (elem); - } - } - } - - internal override void Evaluate (MSBuildEvaluationContext context) - { - foreach (var item in Items) - item.Evaluate (context); - } - } - public class MSBuildEvaluationContext: IExpressionContext - { - Dictionary<string,string> properties = new Dictionary<string, string> (); - bool allResolved; - MSBuildProject project; - - public MSBuildEvaluationContext () - { - } - - internal void InitEvaluation (MSBuildProject project) - { - this.project = project; - SetPropertyValue ("MSBuildThisFile", Path.GetFileName (project.FileName)); - SetPropertyValue ("MSBuildThisFileName", Path.GetFileNameWithoutExtension (project.FileName)); - SetPropertyValue ("MSBuildThisFileDirectory", Path.GetDirectoryName (project.FileName) + Path.DirectorySeparatorChar); - SetPropertyValue ("MSBuildThisFileExtension", Path.GetExtension (project.FileName)); - SetPropertyValue ("MSBuildThisFileFullPath", Path.GetFullPath (project.FileName)); - SetPropertyValue ("VisualStudioReferenceAssemblyVersion", project.ToolsVersion + ".0.0"); - } - - public string GetPropertyValue (string name) - { - string val; - if (properties.TryGetValue (name, out val)) - return val; - else - return Environment.GetEnvironmentVariable (name); - } - - public void SetPropertyValue (string name, string value) - { - properties [name] = value; - } - - public void ClearPropertyValue (string name) - { - properties.Remove (name); - } - - public bool Evaluate (XmlElement source, out XmlElement result) - { - allResolved = true; - result = (XmlElement) EvaluateNode (source); - return allResolved; - } - - XmlNode EvaluateNode (XmlNode source) - { - var elemSource = source as XmlElement; - if (elemSource != null) { - var elem = source.OwnerDocument.CreateElement (elemSource.Prefix, elemSource.LocalName, elemSource.NamespaceURI); - foreach (XmlAttribute attr in elemSource.Attributes) - elem.Attributes.Append ((XmlAttribute)EvaluateNode (attr)); - foreach (XmlNode child in elemSource.ChildNodes) - elem.AppendChild (EvaluateNode (child)); - return elem; - } - - var attSource = source as XmlAttribute; - if (attSource != null) { - bool oldResolved = allResolved; - var att = source.OwnerDocument.CreateAttribute (attSource.Prefix, attSource.LocalName, attSource.NamespaceURI); - att.Value = Evaluate (attSource.Value); - - // Condition attributes don't change the resolution status. Conditions are handled in the property and item objects - if (attSource.Name == "Condition") - allResolved = oldResolved; - - return att; - } - var textSource = source as XmlText; - if (textSource != null) { - return source.OwnerDocument.CreateTextNode (Evaluate (textSource.InnerText)); - } - return source.Clone (); - } - - public bool Evaluate (string str, out string result) - { - allResolved = true; - result = Evaluate (str); - return allResolved; - } - - string Evaluate (string str) - { - int i = str.IndexOf ("$("); - if (i == -1) - return str; - - int last = 0; - - StringBuilder sb = new StringBuilder (); - do { - sb.Append (str, last, i - last); - i += 2; - int j = str.IndexOf (")", i); - if (j == -1) { - allResolved = false; - return ""; - } - - string prop = str.Substring (i, j - i); - string val = GetPropertyValue (prop); - if (val == null) { - allResolved = false; - return ""; - } - - sb.Append (val); - last = j + 1; - i = str.IndexOf ("$(", last); - } - while (i != -1); - - sb.Append (str, last, str.Length - last); - return sb.ToString (); - } - - #region IExpressionContext implementation - - public string EvaluateString (string value) - { - if (value.StartsWith ("$(") && value.EndsWith (")")) - return GetPropertyValue (value.Substring (2, value.Length - 3)) ?? value; - else - return value; - } - - public string FullFileName { - get { - return project.FileName; - } - } - - #endregion - } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectFromFile.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectFromFile.cs new file mode 100644 index 0000000000..5dc76c4283 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectFromFile.cs @@ -0,0 +1,324 @@ +// +// MSBuildProjectFromFile.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using MSProject = Microsoft.Build.BuildEngine.Project; +using Microsoft.Build.BuildEngine; +using System.Collections.Generic; + +namespace MonoDevelop.Projects.Formats.MSBuildInternal +{ + public class MSBuildProjectFromFile: MSBuildProject + { + MSProject project; + List<ImportData> imports = new List<ImportData> (); + List<MSBuildPropertyGroup> propertyGroups = new List<MSBuildPropertyGroup> (); + + class ImportData: MSBuildImport + { + #region implemented abstract members of MSBuildImport + + public override string Target { get; set; } + + public override string Label { get; set; } + + public override string Condition { get; set; } + + #endregion + } + + class ProperyGroupData: MSBuildPropertyGroup, IPropertySetImpl + { + public List<MSBuildProperty> Properties = new List<MSBuildProperty> (); + + public ProperyGroupData (MSBuildProject project) : base (project) + { + } + + internal override IPropertySetImpl PropertySet { + get { + throw new NotImplementedException (); + } + } + + public override string Label { get; set; } + + public override string Condition { get; set; } + } + + class ItemGroupData: MSBuildItemGroup + { + public List<MSBuildItem> GroupItems = new List<MSBuildItem> (); + + public ItemGroupData (MSBuildProject project): base (project) + { + } + + public override MSBuildItem AddNewItem (string name, string include) + { + var it = new ItemData (Project, name, include, include); + GroupItems.Add (it); + return it; + } + + public override IEnumerable<MSBuildItem> Items { + get { + return GroupItems; + } + } + } + + class ItemData: MSBuildItem + { + string name; + string unevaluatedInclude; + string include; + + public ItemData (MSBuildProject project, string name, string include, string unevaluatedInclude): base (project) + { + this.name = name; + this.include = include; + this.unevaluatedInclude = unevaluatedInclude; + } + + internal override IPropertySetImpl PropertySet { + get { + throw new NotImplementedException (); + } + } + + public override string Include { + get { return include; } + } + + public override string UnevaluatedInclude { + get { + return unevaluatedInclude; + } + } + + public override string Name { + get { + return name; + } + } + } + + class PropertyData: MSBuildProperty + { + public string Value; + public string RawValue; + string name; + + public PropertyData (string name, MSBuildProject project) : base (project) + { + this.name = name; + } + + public override string Name { + get { return name; } + } + + protected override void SetPropertyValue (string value, bool isXml) + { + Value = value; + } + + protected override string GetPropertyValue () + { + return Value; + } + + public override string Condition { get; set; } + } + + public MSBuildProjectFromFile () + { + } + + #region IMSBuildProjectImpl implementation + + public override void Load (MonoDevelop.Core.FilePath file) + { + foreach (Import im in project.Imports) { + imports.Add (new ImportData { + Condition = im.Condition + }); + } + foreach (BuildPropertyGroup pg in project.PropertyGroups) { + var g = new ProperyGroupData (this) { + Condition = pg.Condition + }; + foreach (BuildProperty p in pg) { + var prop = new PropertyData (p.Name, this) { + Value = p.FinalValue, + RawValue = p.Value + }; + g.Properties.Add (prop); + } + propertyGroups.Add (g); + } + foreach (BuildItemGroup ig in project.ItemGroups) { + + } + } + + public override void AddNewImport (string name, MSBuildImport beforeImport = null) + { + var data = new ImportData { + Target = name + }; + if (beforeImport != null) { + var other = (ImportData)beforeImport; + int i = imports.IndexOf (other); + if (i != -1) { + imports.Insert (i, data); + return; + } + } + imports.Add (data); + } + + public override void RemoveImport (MSBuildImport import) + { + var data = (ImportData)import; + imports.Remove (data); + } + + public override void Save (string fileName) + { + throw new NotImplementedException (); + } + + public override string SaveToString () + { + throw new NotImplementedException (); + } + + public override MSBuildPropertyGroup AddNewPropertyGroup (MSBuildPropertyGroup beforeGroup = null) + { + var g = new ProperyGroupData (this); + if (beforeGroup != null) { + var i = propertyGroups.IndexOf (beforeGroup); + if (i != -1) { + propertyGroups.Insert (i, g); + return g; + } + } + propertyGroups.Add (g); + return g; + } + + public override void RemovePropertyGroup (MSBuildPropertyGroup grp) + { + propertyGroups.Remove (grp); + } + + public override IEnumerable<MSBuildItem> GetAllItems () + { + throw new NotImplementedException (); + } + + public override IEnumerable<MSBuildItem> GetAllItems (params string[] names) + { + throw new NotImplementedException (); + } + + public override MSBuildItemGroup AddNewItemGroup () + { + throw new NotImplementedException (); + } + + public override MSBuildItem AddNewItem (string name, string include) + { + throw new NotImplementedException (); + } + + public override System.Xml.XmlElement GetProjectExtensions (string section) + { + throw new NotImplementedException (); + } + + public override void SetProjectExtensions (string section, string value) + { + throw new NotImplementedException (); + } + + public override void RemoveProjectExtensions (string section) + { + throw new NotImplementedException (); + } + + public override void RemoveItem (MSBuildItem item) + { + throw new NotImplementedException (); + } + + public override MonoDevelop.Core.FilePath FileName { + get { + throw new NotImplementedException (); + } + } + + public override string DefaultTargets { + get { + throw new NotImplementedException (); + } + set { + throw new NotImplementedException (); + } + } + + public override string ToolsVersion { + get { + throw new NotImplementedException (); + } + set { + throw new NotImplementedException (); + } + } + + public override IEnumerable<MSBuildImport> Imports { + get { + throw new NotImplementedException (); + } + } + + public override IEnumerable<MSBuildPropertyGroup> PropertyGroups { + get { + throw new NotImplementedException (); + } + } + + public override IEnumerable<MSBuildItemGroup> ItemGroups { + get { + throw new NotImplementedException (); + } + } + + #endregion + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectHandler.cs index 96e68d4cef..7aded71f36 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectHandler.cs @@ -41,2004 +41,10 @@ using Mono.Addins; using System.Linq; using MonoDevelop.Core.Instrumentation; using MonoDevelop.Core.ProgressMonitoring; +using System.Threading.Tasks; namespace MonoDevelop.Projects.Formats.MSBuild { - public class MSBuildProjectHandler: MSBuildHandler, IResourceHandler, IPathHandler, IAssemblyReferenceHandler - { - List<string> targetImports = new List<string> (); - IResourceHandler customResourceHandler; - List<string> subtypeGuids = new List<string> (); - const string Unspecified = null; - RemoteProjectBuilder projectBuilder; - ITimeTracker timer; - bool modifiedInMemory; - UnknownProjectTypeNode unknownProjectTypeInfo; - - string lastBuildToolsVersion; - string lastBuildRuntime; - string lastFileName; - string lastSlnFileName; - - struct ItemInfo { - public MSBuildItem Item; - public bool Added; - } - - protected SolutionEntityItem EntityItem { - get { return (SolutionEntityItem) Item; } - } - - public string ToolsVersion { get; private set; } - string productVersion; - string schemaVersion; - - internal bool ProjectTypeIsUnsupported { - get { return unknownProjectTypeInfo != null; } - } - - internal UnknownProjectTypeNode UnknownProjectTypeInfo { - get { return unknownProjectTypeInfo; } - } - - public List<string> TargetImports { - get { return targetImports; } - } - - internal void SetUnsupportedType (UnknownProjectTypeNode typeInfo) - { - unknownProjectTypeInfo = typeInfo; - } - - internal override void SetSolutionFormat (MSBuildFileFormat format, bool converting) - { - // when converting formats, set ToolsVersion, ProductVersion, SchemaVersion to default values written by VS - // this happens on creation too - // else we leave them alone and just roundtrip them - if (converting) { - ToolsVersion = format.DefaultToolsVersion; - productVersion = format.DefaultProductVersion; - schemaVersion = format.DefaultSchemaVersion; - } - - base.SetSolutionFormat (format, converting); - } - - //HACK: the solution's format is irrelevant to MSBuild projects, what matters is the ToolsVersion - // but other parts of the MD API expect a FileFormat - MSBuildFileFormat GetToolsFormat () - { - switch (ToolsVersion) { - case "2.0": - return new MSBuildFileFormatVS05 (); - case "3.5": - return new MSBuildFileFormatVS08 (); - case "4.0": - if (SolutionFormat != null && SolutionFormat.Id == "MSBuild10") - return SolutionFormat; - return new MSBuildFileFormatVS12 (); - case "12.0": - return new MSBuildFileFormatVS12 (); - default: - throw new Exception ("Unknown ToolsVersion '" + ToolsVersion + "'"); - } - } - - public void SetCustomResourceHandler (IResourceHandler value) - { - customResourceHandler = value; - } - - public List<string> SubtypeGuids { - get { - return subtypeGuids; - } - } - - public MSBuildProjectHandler () - { - } - - public MSBuildProjectHandler (string typeGuid, string import, string itemId) - { - Initialize (typeGuid, import, itemId); - } - - internal void Initialize (string typeGuid, string import, string itemId) - { - base.Initialize (typeGuid, itemId); - if (import != null && import.Trim().Length > 0) - this.targetImports.AddRange (import.Split (':')); - - Runtime.SystemAssemblyService.DefaultRuntimeChanged += OnDefaultRuntimeChanged; - } - - public override object GetService (Type t) - { - foreach (var ex in GetMSBuildExtensions ()) { - var s = ex.GetService (t); - if (s != null) - return s; - } - return null; - } - - void OnDefaultRuntimeChanged (object o, EventArgs args) - { - // If the default runtime changes, the project builder for this project may change - // so it has to be created again. - if (projectBuilder != null) { - projectBuilder.Dispose (); - projectBuilder = null; - } - } - - RemoteProjectBuilder GetProjectBuilder () - { - var item = (SolutionEntityItem) Item; - - //FIXME: we can't really have per-project runtimes, has to be per-solution - TargetRuntime runtime = null; - var ap = item as IAssemblyProject; - runtime = ap != null ? ap.TargetRuntime : Runtime.SystemAssemblyService.CurrentRuntime; - - var sln = item.ParentSolution; - var slnFile = sln != null ? sln.FileName : null; - - if (projectBuilder == null || lastBuildToolsVersion != ToolsVersion || lastBuildRuntime != runtime.Id || lastFileName != item.FileName || lastSlnFileName != slnFile) { - if (projectBuilder != null) { - projectBuilder.Dispose (); - projectBuilder = null; - } - projectBuilder = MSBuildProjectService.GetProjectBuilder (runtime, ToolsVersion, item.FileName, slnFile); - lastBuildToolsVersion = ToolsVersion; - lastBuildRuntime = runtime.Id; - lastFileName = item.FileName; - lastSlnFileName = slnFile; - } - else if (modifiedInMemory) { - modifiedInMemory = false; - var p = SaveProject (new NullProgressMonitor ()); - projectBuilder.RefreshWithContent (p.SaveToString ()); - } - return projectBuilder; - } - - void CleanupProjectBuilder () - { - if (projectBuilder != null) { - projectBuilder.Dispose (); - projectBuilder = null; - } - } - - public override void Dispose () - { - base.Dispose (); - CleanupProjectBuilder (); - Runtime.SystemAssemblyService.DefaultRuntimeChanged -= OnDefaultRuntimeChanged; - } - - //for some reason, MD internally handles "AnyCPU" as "", but we need to be explicit when - //passing it to the build engine - static string GetExplicitPlatform (SolutionItemConfiguration configObject) - { - if (string.IsNullOrEmpty (configObject.Platform)) { - return "AnyCPU"; - } - return configObject.Platform; - } - - ProjectConfigurationInfo[] GetConfigurations (SolutionEntityItem item, ConfigurationSelector configuration) - { - // Returns a list of project/configuration information for the provided item and all its references - List<ProjectConfigurationInfo> configs = new List<ProjectConfigurationInfo> (); - var c = item.GetConfiguration (configuration); - configs.Add (new ProjectConfigurationInfo () { - ProjectFile = item.FileName, - Configuration = c.Name, - Platform = GetExplicitPlatform (c) - }); - foreach (var refProject in item.GetReferencedItems (configuration).OfType<Project> ()) { - var refConfig = refProject.GetConfiguration (configuration); - if (refConfig != null) { - configs.Add (new ProjectConfigurationInfo () { - ProjectFile = refProject.FileName, - Configuration = refConfig.Name, - Platform = GetExplicitPlatform (refConfig) - }); - } - } - return configs.ToArray (); - } - - IEnumerable<string> IAssemblyReferenceHandler.GetAssemblyReferences (ConfigurationSelector configuration) - { - if (UseMSBuildEngineForItem (Item, configuration)) { - // Get the references list from the msbuild project - SolutionEntityItem item = (SolutionEntityItem) Item; - RemoteProjectBuilder builder = GetProjectBuilder (); - var configs = GetConfigurations (item, configuration); - - var result = builder.Run ( - configs, null, MSBuildVerbosity.Normal, - new[] { "ResolveAssemblyReferences" }, new [] { "ReferencePath" }, null - ); - - List<MSBuildEvaluatedItem> items; - if (result.Items.TryGetValue ("ReferencePath", out items) && items != null) { - foreach (var i in items) - yield return i.ItemSpec; - } - } - else { - CleanupProjectBuilder (); - DotNetProject item = Item as DotNetProject; - if (item == null) - yield break; - foreach (ProjectReference pref in item.References.Where (pr => pr.ReferenceType != ReferenceType.Project)) { - foreach (string asm in pref.GetReferencedFileNames (configuration)) - yield return asm; - } - } - } - - public override BuildResult RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration) - { - if (UseMSBuildEngineForItem (Item, configuration)) { - SolutionEntityItem item = Item as SolutionEntityItem; - if (item != null) { - LogWriter logWriter = new LogWriter (monitor.Log); - RemoteProjectBuilder builder = GetProjectBuilder (); - var configs = GetConfigurations (item, configuration); - var result = builder.Run (configs, logWriter, MSBuildProjectService.DefaultMSBuildVerbosity, new[] { target }, null, null); - System.Runtime.Remoting.RemotingServices.Disconnect (logWriter); - - var br = new BuildResult (); - foreach (var err in result.Errors) { - FilePath file = null; - if (err.File != null) - file = Path.Combine (Path.GetDirectoryName (err.ProjectFile), err.File); - - if (err.IsWarning) - br.AddWarning (file, err.LineNumber, err.ColumnNumber, err.Code, err.Message); - else - br.AddError (file, err.LineNumber, err.ColumnNumber, err.Code, err.Message); - } - return br; - } - } - else { - CleanupProjectBuilder (); - if (Item is DotNetProject) { - MD1DotNetProjectHandler handler = new MD1DotNetProjectHandler ((DotNetProject)Item); - return handler.RunTarget (monitor, target, configuration); - } - } - return null; - } - - public string GetDefaultResourceId (ProjectFile file) - { - if (customResourceHandler != null) - return customResourceHandler.GetDefaultResourceId (file); - else - return MSBuildResourceHandler.Instance.GetDefaultResourceId (file); - } - - public string EncodePath (string path, string oldPath) - { - string basePath = Path.GetDirectoryName (EntityItem.FileName); - return FileService.RelativeToAbsolutePath (basePath, path); - } - - public string DecodePath (string path) - { - string basePath = Path.GetDirectoryName (EntityItem.FileName); - return FileService.AbsoluteToRelativePath (basePath, path); - } - - public SolutionEntityItem Load (IProgressMonitor monitor, string fileName, MSBuildFileFormat format, string language, Type itemClass) - { - timer = Counters.ReadMSBuildProject.BeginTiming (); - - timer.Trace ("Reading project file"); - MSBuildProject p = new MSBuildProject (); - p.Load (fileName); - - ToolsVersion = p.ToolsVersion; - if (string.IsNullOrEmpty (ToolsVersion)) - ToolsVersion = "2.0"; - - SetSolutionFormat (format ?? new MSBuildFileFormatVS12 (), false); - - timer.Trace ("Read project guids"); - - MSBuildPropertySet globalGroup = p.GetGlobalPropertyGroup (); - - // Avoid crash if there is not global group - if (globalGroup == null) - globalGroup = p.AddNewPropertyGroup (false); - - productVersion = globalGroup.GetPropertyValue ("ProductVersion"); - schemaVersion = globalGroup.GetPropertyValue ("SchemaVersion"); - - string itemGuid = globalGroup.GetPropertyValue ("ProjectGuid"); - if (itemGuid == null) - throw new UserException ("Project file doesn't have a valid ProjectGuid"); - - // Workaround for a VS issue. VS doesn't include the curly braces in the ProjectGuid - // of shared projects. - if (!itemGuid.StartsWith ("{")) - itemGuid = "{" + itemGuid + "}"; - - itemGuid = itemGuid.ToUpper (); - string projectTypeGuids = globalGroup.GetPropertyValue ("ProjectTypeGuids"); - string itemType = globalGroup.GetPropertyValue ("ItemType"); - - subtypeGuids.Clear (); - if (projectTypeGuids != null) { - foreach (string guid in projectTypeGuids.Split (';')) { - string sguid = guid.Trim (); - if (sguid.Length > 0 && string.Compare (sguid, TypeGuid, true) != 0) - subtypeGuids.Add (guid); - } - } - - try { - timer.Trace ("Create item instance"); - ProjectExtensionUtil.BeginLoadOperation (); - Item = CreateSolutionItem (monitor, p, fileName, language, itemType, itemClass); - - if (subtypeGuids.Any ()) { - string gg = string.Join (";", subtypeGuids) + ";" + TypeGuid; - Item.ExtendedProperties ["ProjectTypeGuids"] = gg.ToUpper (); - } - - Item.SetItemHandler (this); - MSBuildProjectService.SetId (Item, itemGuid); - - SolutionEntityItem it = (SolutionEntityItem) Item; - - it.FileName = fileName; - it.Name = System.IO.Path.GetFileNameWithoutExtension (fileName); - - RemoveDuplicateItems (p, fileName); - - LoadProject (monitor, p); - return it; - - } finally { - ProjectExtensionUtil.EndLoadOperation (); - timer.End (); - } - } - - /// <summary>Whether to use the MSBuild engine for the specified item.</summary> - internal bool UseMSBuildEngineForItem (SolutionItem item, ConfigurationSelector sel, bool checkReferences = true) - { - // if the item mandates MSBuild, always use it - if (RequireMSBuildEngine) - return true; - // if the user has set the option, use the setting - if (item.UseMSBuildEngine.HasValue) - return item.UseMSBuildEngine.Value; - - // If the item type defaults to using MSBuild, only use MSBuild if its direct references also use MSBuild. - // This prevents a not-uncommon common error referencing non-MSBuild projects from MSBuild projects - // NOTE: This adds about 11ms to the load/build/etc times of the MonoDevelop solution. Doing it recursively - // adds well over a second. - return UseMSBuildEngineByDefault && ( - !checkReferences || - item.GetReferencedItems (sel).All (i => { - var h = i.ItemHandler as MSBuildProjectHandler; - return h != null && h.UseMSBuildEngineForItem (i, sel, false); - }) - ); - } - - /// <summary>Whether to use the MSBuild engine by default.</summary> - internal bool UseMSBuildEngineByDefault { get; set; } - - /// <summary>Forces the MSBuild engine to be used.</summary> - internal bool RequireMSBuildEngine { get; set; } - - // All of the last 4 parameters are optional, but at least one must be provided. - SolutionItem CreateSolutionItem (IProgressMonitor monitor, MSBuildProject p, string fileName, string language, - string itemType, Type itemClass) - { - if (ProjectTypeIsUnsupported) - return new UnknownProject (fileName, UnknownProjectTypeInfo.GetInstructions ()); - - if (subtypeGuids.Any ()) { - DotNetProjectSubtypeNode st = MSBuildProjectService.GetDotNetProjectSubtype (subtypeGuids); - if (st != null) { - UseMSBuildEngineByDefault = st.UseXBuild; - RequireMSBuildEngine = st.RequireXBuild; - Type migratedType = null; - - if (st.IsMigration && (migratedType = MigrateProject (monitor, st, p, fileName, language)) != null) { - var oldSt = st; - st = MSBuildProjectService.GetItemSubtypeNodes ().Last (t => t.CanHandleType (migratedType)); - - for (int i = 0; i < subtypeGuids.Count; i++) { - if (string.Equals (subtypeGuids [i], oldSt.Guid, StringComparison.OrdinalIgnoreCase)) { - subtypeGuids [i] = st.Guid; - oldSt = null; - break; - } - } - - if (oldSt != null) - throw new Exception ("Unable to correct flavor GUID"); - - var gg = string.Join (";", subtypeGuids) + ";" + TypeGuid; - p.GetGlobalPropertyGroup ().SetPropertyValue ("ProjectTypeGuids", gg.ToUpper (), true); - p.Save (fileName); - } - - var item = st.CreateInstance (language); - st.UpdateImports ((SolutionEntityItem)item, targetImports); - return item; - } else { - var projectInfo = MSBuildProjectService.GetUnknownProjectTypeInfo (subtypeGuids.ToArray (), fileName); - if (projectInfo != null && projectInfo.LoadFiles) { - SetUnsupportedType (projectInfo); - return new UnknownProject (fileName, UnknownProjectTypeInfo.GetInstructions ()); - } - throw new UnknownSolutionItemTypeException (ProjectTypeIsUnsupported ? TypeGuid : string.Join (";", subtypeGuids)); - } - } - - if (itemClass != null) - return (SolutionItem) Activator.CreateInstance (itemClass); - - if (!string.IsNullOrEmpty (language)) { - //enable msbuild by default .NET assembly projects - UseMSBuildEngineByDefault = true; - RequireMSBuildEngine = false; - return new DotNetAssemblyProject (language); - } - - if (string.IsNullOrEmpty (itemType)) - throw new UnknownSolutionItemTypeException (); - - DataType dt = MSBuildProjectService.DataContext.GetConfigurationDataType (itemType); - if (dt == null) - throw new UnknownSolutionItemTypeException (itemType); - - return (SolutionItem) Activator.CreateInstance (dt.ValueType); - } - - Type MigrateProject (IProgressMonitor monitor, DotNetProjectSubtypeNode st, MSBuildProject p, string fileName, string language) - { - var projectLoadMonitor = monitor as IProjectLoadProgressMonitor; - if (projectLoadMonitor == null) { - // projectLoadMonitor will be null when running through md-tool, but - // this is not fatal if migration is not required, so just ignore it. --abock - if (!st.IsMigrationRequired) - return null; - - LoggingService.LogError (Environment.StackTrace); - monitor.ReportError ("Could not open unmigrated project and no migrator was supplied", null); - throw new Exception ("Could not open unmigrated project and no migrator was supplied"); - } - - var migrationType = st.MigrationHandler.CanPromptForMigration - ? st.MigrationHandler.PromptForMigration (projectLoadMonitor, p, fileName, language) - : projectLoadMonitor.ShouldMigrateProject (); - if (migrationType == MigrationType.Ignore) { - if (st.IsMigrationRequired) { - monitor.ReportError (string.Format ("{1} cannot open the project '{0}' unless it is migrated.", Path.GetFileName (fileName), BrandingService.ApplicationName), null); - throw new Exception ("The user choose not to migrate the project"); - } else - return null; - } - - var baseDir = (FilePath) Path.GetDirectoryName (fileName); - if (migrationType == MigrationType.BackupAndMigrate) { - var backupDirFirst = baseDir.Combine ("backup"); - string backupDir = backupDirFirst; - int i = 0; - while (Directory.Exists (backupDir)) { - backupDir = backupDirFirst + "-" + i.ToString (); - if (i++ > 20) { - throw new Exception ("Too many backup directories"); - } - } - Directory.CreateDirectory (backupDir); - foreach (var file in st.MigrationHandler.FilesToBackup (fileName)) - File.Copy (file, Path.Combine (backupDir, Path.GetFileName (file))); - } - - var type = st.MigrationHandler.Migrate (projectLoadMonitor, p, fileName, language); - if (type == null) - throw new Exception ("Could not migrate the project"); - - return type; - } - - FileFormat GetFileFormat (MSBuildFileFormat fmt) - { - return new FileFormat (fmt, fmt.Id, fmt.Name); - } - - void RemoveDuplicateItems (MSBuildProject msproject, string fileName) - { - timer.Trace ("Checking for duplicate items"); - - var uniqueIncludes = new Dictionary<string,object> (); - var toRemove = new List<MSBuildItem> (); - foreach (MSBuildItem bi in msproject.GetAllItems ()) { - object existing; - string key = bi.Name + "<" + bi.Include; - if (!uniqueIncludes.TryGetValue (key, out existing)) { - uniqueIncludes[key] = bi; - continue; - } - var exBi = existing as MSBuildItem; - if (exBi != null) { - if (exBi.Condition != bi.Condition || exBi.Element.InnerXml != bi.Element.InnerXml) { - uniqueIncludes[key] = new List<MSBuildItem> { exBi, bi }; - } else { - toRemove.Add (bi); - } - continue; - } - - var exList = (List<MSBuildItem>)existing; - bool found = false; - foreach (var m in (exList)) { - if (m.Condition == bi.Condition && m.Element.InnerXml == bi.Element.InnerXml) { - found = true; - break; - } - } - if (!found) { - exList.Add (bi); - } else { - toRemove.Add (bi); - } - } - if (toRemove.Count == 0) - return; - - timer.Trace ("Removing duplicate items"); - - foreach (var t in toRemove) - msproject.RemoveItem (t); - - msproject.Save (fileName); - } - - void LoadConfiguration (MSBuildSerializer serializer, List<ConfigData> configData, string conf, string platform) - { - MSBuildPropertySet grp = GetMergedConfiguration (configData, conf, platform, null); - SolutionItemConfiguration config = EntityItem.CreateConfiguration (conf); - - config.Platform = platform; - DataItem data = ReadPropertyGroupMetadata (serializer, grp, config); - serializer.Deserialize (config, data); - EntityItem.Configurations.Add (config); - - if (config is DotNetProjectConfiguration) { - DotNetProjectConfiguration dpc = (DotNetProjectConfiguration) config; - if (dpc.CompilationParameters != null) { - data = ReadPropertyGroupMetadata (serializer, grp, dpc.CompilationParameters); - serializer.Deserialize (dpc.CompilationParameters, data); - } - } - } - - protected virtual void LoadProject (IProgressMonitor monitor, MSBuildProject msproject) - { - timer.Trace ("Initialize serialization"); - - MSBuildSerializer ser = CreateSerializer (); - ser.SerializationContext.BaseFile = EntityItem.FileName; - ser.SerializationContext.ProgressMonitor = monitor; - - MSBuildPropertySet globalGroup = msproject.GetGlobalPropertyGroup (); - - Item.SetItemHandler (this); - - DotNetProject dotNetProject = Item as DotNetProject; - - // Read all items - - timer.Trace ("Read project items"); - - LoadProjectItems (msproject, ser, ProjectItemFlags.None); - - timer.Trace ("Read configurations"); - - TargetFrameworkMoniker targetFx = null; - - if (dotNetProject != null) { - string frameworkIdentifier = globalGroup.GetPropertyValue ("TargetFrameworkIdentifier"); - string frameworkVersion = globalGroup.GetPropertyValue ("TargetFrameworkVersion"); - string frameworkProfile = globalGroup.GetPropertyValue ("TargetFrameworkProfile"); - - //determine the default target framework from the project type's default - //overridden by the components in the project - var def = dotNetProject.GetDefaultTargetFrameworkForFormat (GetFileFormat (GetToolsFormat ())); - targetFx = new TargetFrameworkMoniker ( - string.IsNullOrEmpty (frameworkIdentifier)? def.Identifier : frameworkIdentifier, - string.IsNullOrEmpty (frameworkVersion)? def.Version : frameworkVersion, - string.IsNullOrEmpty (frameworkProfile)? def.Profile : frameworkProfile); - - if (dotNetProject.LanguageParameters != null) { - DataItem data = ReadPropertyGroupMetadata (ser, globalGroup, dotNetProject.LanguageParameters); - ser.Deserialize (dotNetProject.LanguageParameters, data); - } - } - - // Read configurations - - List<ConfigData> configData = GetConfigData (msproject, false); - List<ConfigData> partialConfigurations = new List<ConfigData> (); - HashSet<string> handledConfigurations = new HashSet<string> (); - var configurations = new HashSet<string> (); - var platforms = new HashSet<string> (); - - MSBuildPropertyGroup mergedToProjectProperties = ExtractMergedtoprojectProperties (ser, globalGroup, EntityItem.CreateConfiguration ("Dummy")); - configData.Insert (0, new ConfigData (Unspecified, Unspecified, mergedToProjectProperties)); - - // Load configurations, skipping the dummy config at index 0. - for (int i = 1; i < configData.Count; i++) { - ConfigData cgrp = configData[i]; - string platform = cgrp.Platform; - string conf = cgrp.Config; - - if (platform != Unspecified) - platforms.Add (platform); - - if (conf != Unspecified) - configurations.Add (conf); - - if (conf == Unspecified || platform == Unspecified) { - // skip partial configurations for now... - partialConfigurations.Add (cgrp); - continue; - } - - string key = conf + "|" + platform; - if (handledConfigurations.Contains (key)) - continue; - - LoadConfiguration (ser, configData, conf, platform); - - handledConfigurations.Add (key); - } - - // Now we can load any partial configurations by combining them with known configs or platforms. - if (partialConfigurations.Count > 0) { - if (platforms.Count == 0) - platforms.Add (string.Empty); // AnyCpu - - foreach (ConfigData cgrp in partialConfigurations) { - if (cgrp.Config != Unspecified && cgrp.Platform == Unspecified) { - string conf = cgrp.Config; - - foreach (var platform in platforms) { - string key = conf + "|" + platform; - - if (handledConfigurations.Contains (key)) - continue; - - LoadConfiguration (ser, configData, conf, platform); - - handledConfigurations.Add (key); - } - } else if (cgrp.Config == Unspecified && cgrp.Platform != Unspecified) { - string platform = cgrp.Platform; - - foreach (var conf in configurations) { - string key = conf + "|" + platform; - - if (handledConfigurations.Contains (key)) - continue; - - LoadConfiguration (ser, configData, conf, platform); - - handledConfigurations.Add (key); - } - } - } - } - - // Read extended properties - - timer.Trace ("Read extended properties"); - - DataItem globalData = ReadPropertyGroupMetadata (ser, globalGroup, Item); - - string extendedData = msproject.GetProjectExtensions ("MonoDevelop"); - if (!string.IsNullOrEmpty (extendedData)) { - StringReader sr = new StringReader (extendedData); - DataItem data = (DataItem) XmlConfigurationReader.DefaultReader.Read (new XmlTextReader (sr)); - globalData.ItemData.AddRange (data.ItemData); - } - ser.Deserialize (Item, globalData); - - // Final initializations - - timer.Trace ("Final initializations"); - - //clean up the "InternalTargetFrameworkVersion" hack from MD 2.2, 2.4 - if (dotNetProject != null) { - string fx = Item.ExtendedProperties ["InternalTargetFrameworkVersion"] as string; - if (!string.IsNullOrEmpty (fx)) { - targetFx = TargetFrameworkMoniker.Parse (fx); - Item.ExtendedProperties.Remove ("InternalTargetFrameworkVersion"); - } - - dotNetProject.TargetFramework = Runtime.SystemAssemblyService.GetTargetFramework (targetFx); - } - - LoadFromMSBuildProject (monitor, msproject); - - Item.NeedsReload = false; - } - - internal void LoadProjectItems (MSBuildProject msproject, MSBuildSerializer ser, ProjectItemFlags flags) - { - foreach (MSBuildItem buildItem in msproject.GetAllItems ()) { - ProjectItem it = ReadItem (ser, buildItem); - if (it == null) - continue; - it.Flags = flags; - if (it is ProjectFile) { - var file = (ProjectFile)it; - if (file.Name.IndexOf ('*') > -1) { - // Thanks to IsOriginatedFromWildcard, these expanded items will not be saved back to disk. - foreach (var expandedItem in ResolveWildcardItems (file)) - EntityItem.Items.Add (expandedItem); - // Add to wildcard items (so it can be re-saved) instead of Items (where tools will - // try to compile and display these nonstandard items - EntityItem.WildcardItems.Add (it); - continue; - } - if (ProjectTypeIsUnsupported && !File.Exists (file.FilePath)) - continue; - } - EntityItem.Items.Add (it); - it.ExtendedProperties ["MSBuild.SourceProject"] = msproject.FileName; - } - } - - protected virtual void LoadFromMSBuildProject (IProgressMonitor monitor, MSBuildProject msproject) - { - foreach (var ext in GetMSBuildExtensions ()) - ext.LoadProject (monitor, EntityItem, msproject); - } - - const string RecursiveDirectoryWildcard = "**"; - static readonly char[] directorySeparators = new [] { - Path.DirectorySeparatorChar, - Path.AltDirectorySeparatorChar - }; - - static string GetWildcardDirectoryName (string path) - { - int indexOfLast = path.LastIndexOfAny (directorySeparators); - if (indexOfLast < 0) - return String.Empty; - return path.Substring (0, indexOfLast); - } - - static string GetWildcardFileName (string path) - { - int indexOfLast = path.LastIndexOfAny (directorySeparators); - if (indexOfLast < 0) - return path; - if (indexOfLast == path.Length) - return String.Empty; - return path.Substring (indexOfLast + 1, path.Length - (indexOfLast + 1)); - } - - static IEnumerable<string> ExpandWildcardFilePath (string filePath) - { - if (String.IsNullOrWhiteSpace (filePath)) - throw new ArgumentException ("Not a wildcard path"); - - string dir = GetWildcardDirectoryName (filePath); - string file = GetWildcardFileName (filePath); - - if (String.IsNullOrEmpty (dir) || String.IsNullOrEmpty (file)) - return null; - - SearchOption searchOption = SearchOption.TopDirectoryOnly; - if (dir.EndsWith (RecursiveDirectoryWildcard, StringComparison.Ordinal)) { - dir = dir.Substring (0, dir.Length - RecursiveDirectoryWildcard.Length); - searchOption = SearchOption.AllDirectories; - } - - if (!Directory.Exists (dir)) - return null; - - return Directory.GetFiles (dir, file, searchOption); - } - - static IEnumerable<ProjectFile> ResolveWildcardItems (ProjectFile wildcardFile) - { - var paths = ExpandWildcardFilePath (wildcardFile.Name); - if (paths == null) - yield break; - foreach (var resolvedFilePath in paths) { - var projectFile = (ProjectFile)wildcardFile.Clone (); - projectFile.Name = resolvedFilePath; - projectFile.IsOriginatedFromWildcard = true; - yield return projectFile; - } - } - - MSBuildPropertyGroup ExtractMergedtoprojectProperties (MSBuildSerializer ser, MSBuildPropertySet pgroup, SolutionItemConfiguration ob) - { - XmlDocument doc = new XmlDocument (); - MSBuildPropertyGroup res = new MSBuildPropertyGroup (null, doc.CreateElement ("PropGroup")); - - // When reading a project, all configuration properties specified in the global property group have to - // be merged with all project configurations, no matter if they have the MergeToProject attribute or not - - ClassDataType dt = (ClassDataType) ser.DataContext.GetConfigurationDataType (ob.GetType ()); - foreach (ItemProperty prop in dt.GetProperties (ser.SerializationContext, ob)) { - MSBuildProperty bp = pgroup.GetProperty (prop.Name); - if (bp != null) { - var preserveCase = prop.DataType is MSBuildBoolDataType; - res.SetPropertyValue (bp.Name, bp.Element.InnerXml, preserveCase, true); - } - } - if (ob is DotNetProjectConfiguration) { - object cparams = ((DotNetProjectConfiguration)ob).CompilationParameters; - dt = (ClassDataType) ser.DataContext.GetConfigurationDataType (cparams.GetType ()); - foreach (ItemProperty prop in dt.GetProperties (ser.SerializationContext, cparams)) { - MSBuildProperty bp = pgroup.GetProperty (prop.Name); - if (bp != null) { - var preserveCase = prop.DataType is MSBuildBoolDataType; - res.SetPropertyValue (bp.Name, bp.Element.InnerXml, preserveCase, true); - } - } - } - return res; - } - - IEnumerable<MergedProperty> GetMergeToProjectProperties (MSBuildSerializer ser, object ob) - { - ClassDataType dt = (ClassDataType) ser.DataContext.GetConfigurationDataType (ob.GetType ()); - foreach (ItemProperty prop in dt.GetProperties (ser.SerializationContext, ob)) { - if (IsMergeToProjectProperty (prop)) { - yield return new MergedProperty (prop.Name, prop.DataType is MSBuildBoolDataType); - } - } - } - - struct MergedProperty - { - public readonly string Name; - public readonly bool PreserveExistingCase; - - public MergedProperty (string name, bool preserveExistingCase) - { - this.Name = name; - this.PreserveExistingCase = preserveExistingCase; - } - } - - internal ProjectItem ReadItem (MSBuildSerializer ser, MSBuildItem buildItem) - { - Project project = Item as Project; - DotNetProject dotNetProject = Item as DotNetProject; - - DataType dt = ser.DataContext.GetConfigurationDataType (buildItem.Name); - - if (project != null) { - if (buildItem.Name == "Folder") { - // Read folders - string path = MSBuildProjectService.FromMSBuildPath (project.ItemDirectory, buildItem.Include); - return new ProjectFile () { Name = Path.GetDirectoryName (path), Subtype = Subtype.Directory }; - } - else if (buildItem.Name == "Reference" && dotNetProject != null) { - ProjectReference pref; - if (buildItem.HasMetadata ("HintPath")) { - string hintPath = buildItem.GetMetadata ("HintPath"); - string path; - if (!MSBuildProjectService.FromMSBuildPath (dotNetProject.ItemDirectory, hintPath, out path)) { - pref = new ProjectReference (ReferenceType.Assembly, path); - pref.SetInvalid (GettextCatalog.GetString ("Invalid file path")); - pref.ExtendedProperties ["_OriginalMSBuildReferenceInclude"] = buildItem.Include; - pref.ExtendedProperties ["_OriginalMSBuildReferenceHintPath"] = hintPath; - } else { - var type = File.Exists (path) ? ReferenceType.Assembly : ReferenceType.Package; - pref = new ProjectReference (type, buildItem.Include, path); - pref.ExtendedProperties ["_OriginalMSBuildReferenceHintPath"] = hintPath; - if (MSBuildProjectService.IsAbsoluteMSBuildPath (hintPath)) - pref.ExtendedProperties ["_OriginalMSBuildReferenceIsAbsolute"] = true; - } - } else { - string asm = buildItem.Include; - // This is a workaround for a VS bug. Looks like it is writing this assembly incorrectly - if (asm == "System.configuration") - asm = "System.Configuration"; - else if (asm == "System.XML") - asm = "System.Xml"; - else if (asm == "system") - asm = "System"; - pref = new ProjectReference (ReferenceType.Package, asm); - } - var privateCopy = buildItem.GetBoolMetadata ("Private"); - if (privateCopy != null) - pref.LocalCopy = privateCopy.Value; - - pref.Condition = buildItem.Condition; - string specificVersion = buildItem.GetMetadata ("SpecificVersion"); - if (string.IsNullOrWhiteSpace (specificVersion)) { - // If the SpecificVersion element isn't present, check if the Assembly Reference specifies a Version - pref.SpecificVersion = ReferenceStringHasVersion (buildItem.Include); - } - else { - bool value; - // if we can't parse the value, default to false which is more permissive - pref.SpecificVersion = bool.TryParse (specificVersion, out value) && value; - } - ReadBuildItemMetadata (ser, buildItem, pref, typeof(ProjectReference)); - return pref; - } - else if (buildItem.Name == "ProjectReference" && dotNetProject != null) { - // Get the project name from the path, since the Name attribute may other stuff other than the name - string path = MSBuildProjectService.FromMSBuildPath (project.ItemDirectory, buildItem.Include); - string name = Path.GetFileNameWithoutExtension (path); - ProjectReference pref = new ProjectReference (ReferenceType.Project, name); - pref.Condition = buildItem.Condition; - var privateCopy = buildItem.GetBoolMetadata ("Private"); - if (privateCopy != null) - pref.LocalCopy = privateCopy.Value; - return pref; - } - else if (dt == null && !string.IsNullOrEmpty (buildItem.Include)) { - // Unknown item. Must be a file. - if (!UnsupportedItems.Contains (buildItem.Name) && IsValidFile (buildItem.Include)) - return ReadProjectFile (ser, project, buildItem, typeof(ProjectFile)); - } - } - - // ProjectReference objects only make sense on a DotNetProject, so don't load them - // if that's not the type of the project. - if (dt != null && dt.ValueType == typeof(ProjectReference) && dotNetProject == null) - dt = null; - - if (dt != null && typeof(ProjectItem).IsAssignableFrom (dt.ValueType)) { - ProjectItem obj = (ProjectItem) Activator.CreateInstance (dt.ValueType); - ReadBuildItemMetadata (ser, buildItem, obj, dt.ValueType); - return obj; - } - - UnknownProjectItem uitem = new UnknownProjectItem (buildItem.Name, ""); - ReadBuildItemMetadata (ser, buildItem, uitem, typeof(UnknownProjectItem)); - - return uitem; - } - - bool ReferenceStringHasVersion (string asmName) - { - int commaPos = asmName.IndexOf (','); - return commaPos >= 0 && asmName.IndexOf ("Version", commaPos) >= 0; - } - - bool IsValidFile (string path) - { - // If it is an absolute uri, it's not a valid file - try { - if (Uri.IsWellFormedUriString (path, UriKind.Absolute)) { - var f = new Uri (path); - return f.Scheme == "file"; - } - } catch { - // Old mono versions may crash in IsWellFormedUriString if the path - // is not an uri. - } - return true; - } - - class ConfigData - { - public ConfigData (string conf, string plt, MSBuildPropertyGroup grp) - { - Config = conf; - Platform = plt; - Group = grp; - } - - public bool FullySpecified { - get { return Config != Unspecified && Platform != Unspecified; } - } - - public string Config; - public string Platform; - public MSBuildPropertyGroup Group; - public bool Exists; - public bool IsNew; // The group did not exist in the original file - } - - MSBuildPropertySet GetMergedConfiguration (List<ConfigData> configData, string conf, string platform, MSBuildPropertyGroup propGroupLimit) - { - MSBuildPropertySet merged = null; - - foreach (ConfigData grp in configData) { - if (grp.Group == propGroupLimit) - break; - if ((grp.Config == conf || grp.Config == Unspecified || conf == Unspecified) && (grp.Platform == platform || grp.Platform == Unspecified || platform == Unspecified)) { - if (merged == null) - merged = grp.Group; - else if (merged is MSBuildPropertyGroupMerged) - ((MSBuildPropertyGroupMerged)merged).Add (grp.Group); - else { - MSBuildPropertyGroupMerged m = new MSBuildPropertyGroupMerged (); - m.Add ((MSBuildPropertyGroup)merged); - m.Add (grp.Group); - merged = m; - } - } - } - return merged; - } - - bool ContainsSpecificPlatformConfiguration (List<ConfigData> configData, string conf) - { - foreach (ConfigData grp in configData) { - if (grp.Config == conf && grp.Platform != Unspecified) - return true; - } - return false; - } - - public override void OnModified (string hint) - { - base.OnModified (hint); - modifiedInMemory = true; - } - - protected override void SaveItem (MonoDevelop.Core.IProgressMonitor monitor) - { - modifiedInMemory = false; - - MSBuildProject msproject = SaveProject (monitor); - if (msproject == null) - return; - - // Don't save the file to disk if the content did not change - msproject.Save (EntityItem.FileName); - - if (projectBuilder != null) - projectBuilder.Refresh (); - } - - protected virtual MSBuildProject SaveProject (IProgressMonitor monitor) - { - if (Item is UnknownSolutionItem) - return null; - - var toolsFormat = GetToolsFormat (); - - bool newProject; - SolutionEntityItem eitem = EntityItem; - - MSBuildSerializer ser = CreateSerializer (); - ser.SerializationContext.BaseFile = eitem.FileName; - ser.SerializationContext.ProgressMonitor = monitor; - - DotNetProject dotNetProject = Item as DotNetProject; - - MSBuildProject msproject = new MSBuildProject (); - newProject = EntityItem.FileName == null || !File.Exists (EntityItem.FileName); - if (newProject) { - msproject.DefaultTargets = "Build"; - } else { - msproject.Load (EntityItem.FileName); - } - - // Global properties - - MSBuildPropertySet globalGroup = msproject.GetGlobalPropertyGroup (); - if (globalGroup == null) { - globalGroup = msproject.AddNewPropertyGroup (false); - } - - if (eitem.Configurations.Count > 0) { - ItemConfiguration conf = eitem.Configurations.FirstOrDefault<ItemConfiguration> (c => c.Name == "Debug"); - if (conf == null) conf = eitem.Configurations [0]; - MSBuildProperty bprop = globalGroup.SetPropertyValue ("Configuration", conf.Name, false); - bprop.Condition = " '$(Configuration)' == '' "; - - string platform = conf.Platform.Length == 0 ? "AnyCPU" : conf.Platform; - bprop = globalGroup.SetPropertyValue ("Platform", platform, false); - bprop.Condition = " '$(Platform)' == '' "; - } - - if (TypeGuid == MSBuildProjectService.GenericItemGuid) { - DataType dt = MSBuildProjectService.DataContext.GetConfigurationDataType (Item.GetType ()); - globalGroup.SetPropertyValue ("ItemType", dt.Name, false); - } - - Item.ExtendedProperties ["ProjectGuid"] = Item.ItemId; - if (subtypeGuids.Count > 0) { - string gg = ""; - foreach (string sg in subtypeGuids) { - if (gg.Length > 0) - gg += ";"; - gg += sg; - } - gg += ";" + TypeGuid; - Item.ExtendedProperties ["ProjectTypeGuids"] = gg.ToUpper (); - globalGroup.SetPropertyValue ("ProjectTypeGuids", gg.ToUpper (), true); - } else { - Item.ExtendedProperties.Remove ("ProjectTypeGuids"); - globalGroup.RemoveProperty ("ProjectTypeGuids"); - } - - Item.ExtendedProperties ["ProductVersion"] = productVersion; - Item.ExtendedProperties ["SchemaVersion"] = schemaVersion; - - // having no ToolsVersion is equivalent to 2.0, roundtrip that correctly - if (ToolsVersion != "2.0") - msproject.ToolsVersion = ToolsVersion; - else if (string.IsNullOrEmpty (msproject.ToolsVersion)) - msproject.ToolsVersion = null; - else - msproject.ToolsVersion = "2.0"; - - // This serialize call will write data to ser.InternalItemProperties and ser.ExternalItemProperties - ser.Serialize (Item, Item.GetType ()); - - object langParams = null; - - if (dotNetProject != null && dotNetProject.LanguageParameters != null) { - // Remove all language parameters properties from the data item, since we are going to write them again. - ClassDataType dt = (ClassDataType) ser.DataContext.GetConfigurationDataType (dotNetProject.LanguageParameters.GetType ()); - foreach (ItemProperty prop in dt.GetProperties (ser.SerializationContext, dotNetProject.LanguageParameters)) { - DataNode n = ser.InternalItemProperties.ItemData [prop.Name]; - if (n != null) - ser.InternalItemProperties.ItemData.Remove (n); - } - DataItem ditemComp = (DataItem) ser.Serialize (dotNetProject.LanguageParameters); - ser.InternalItemProperties.ItemData.AddRange (ditemComp.ItemData); - langParams = dotNetProject.LanguageParameters; - } - - if (newProject) - ser.InternalItemProperties.ItemData.Sort (globalConfigOrder); - - WritePropertyGroupMetadata (globalGroup, ser.InternalItemProperties.ItemData, ser, Item, langParams); - - // Convert debug property - - foreach (SolutionItemConfiguration conf in eitem.Configurations) { - if (newProject && conf is DotNetProjectConfiguration) { - conf.ExtendedProperties ["ErrorReport"] = "prompt"; - } - } - - // Configurations - - if (eitem.Configurations.Count > 0) { - List<ConfigData> configData = GetConfigData (msproject, true); - - var mergeToProjectPropertyValues = new Dictionary<string,MergedPropertyValue> (); - var mergeToProjectProperties = new HashSet<MergedProperty> (GetMergeToProjectProperties (ser, eitem.Configurations [0])); - var mergeToProjectPropertyNames = new HashSet<string> (mergeToProjectProperties.Select (p => p.Name)); - - foreach (SolutionItemConfiguration conf in eitem.Configurations) { - bool newConf = false; - ConfigData cdata = FindPropertyGroup (configData, conf); - if (cdata == null) { - MSBuildPropertyGroup pg = msproject.AddNewPropertyGroup (true); - pg.Condition = BuildConfigCondition (conf.Name, conf.Platform); - cdata = new ConfigData (conf.Name, conf.Platform, pg); - cdata.IsNew = true; - configData.Add (cdata); - newConf = true; - } - - MSBuildPropertyGroup propGroup = cdata.Group; - cdata.Exists = true; - - MSBuildPropertySet baseGroup = GetMergedConfiguration (configData, conf.Name, conf.Platform, propGroup); - - // Force the serialization of properties defined in - // the base group, so that they can be later unmerged - if (baseGroup != null) - ForceDefaultValueSerialization (ser, baseGroup, conf); - DataItem ditem = (DataItem) ser.Serialize (conf); - ser.SerializationContext.ResetDefaultValueSerialization (); - - DotNetProjectConfiguration netConfig = conf as DotNetProjectConfiguration; - - if (netConfig != null && netConfig.CompilationParameters != null) { - // Remove all compilation parameters properties from the data item, since we are going to write them again. - ClassDataType dt = (ClassDataType) ser.DataContext.GetConfigurationDataType (netConfig.CompilationParameters.GetType ()); - foreach (ItemProperty prop in dt.GetProperties (ser.SerializationContext, netConfig.CompilationParameters)) { - DataNode n = ditem.ItemData [prop.Name]; - if (n != null) - ditem.ItemData.Remove (n); - } - if (baseGroup != null) - ForceDefaultValueSerialization (ser, baseGroup, netConfig.CompilationParameters); - DataItem ditemComp = (DataItem) ser.Serialize (netConfig.CompilationParameters); - ser.SerializationContext.ResetDefaultValueSerialization (); - ditem.ItemData.AddRange (ditemComp.ItemData); - } - - if (newConf) - ditem.ItemData.Sort (configOrder); - - WritePropertyGroupMetadata (propGroup, ditem.ItemData, ser, conf, netConfig != null ? netConfig.CompilationParameters : null); - - CollectMergetoprojectProperties (propGroup, mergeToProjectProperties, mergeToProjectPropertyValues); - - if (baseGroup != null) - propGroup.UnMerge (baseGroup, mergeToProjectPropertyNames); - } - - // Move properties with common values from configurations to the main - // property group - foreach (KeyValuePair<string,MergedPropertyValue> prop in mergeToProjectPropertyValues) - globalGroup.SetPropertyValue (prop.Key, prop.Value.XmlValue, prop.Value.PreserveExistingCase, true); - foreach (string prop in mergeToProjectPropertyNames) { - if (!mergeToProjectPropertyValues.ContainsKey (prop)) - globalGroup.RemoveProperty (prop); - } - foreach (SolutionItemConfiguration conf in eitem.Configurations) { - MSBuildPropertyGroup propGroup = FindPropertyGroup (configData, conf).Group; - foreach (string mp in mergeToProjectPropertyValues.Keys) - propGroup.RemoveProperty (mp); - } - - // Remove groups corresponding to configurations that have been removed - // or groups which don't have any property and did not already exist - foreach (ConfigData cd in configData) { - if ((!cd.Exists && cd.FullySpecified) || (cd.IsNew && !cd.Group.Properties.Any ())) - msproject.RemoveGroup (cd.Group); - } - } - - SaveProjectItems (monitor, toolsFormat, ser, msproject); - - if (dotNetProject != null) { - var moniker = dotNetProject.TargetFramework.Id; - bool supportsMultipleFrameworks = toolsFormat.SupportsMonikers || toolsFormat.SupportedFrameworks.Length > 0; - var def = dotNetProject.GetDefaultTargetFrameworkForFormat (GetFileFormat (toolsFormat)); - - // If the format only supports one fx version, or the version is the default, there is no need to store it. - // However, is there is already a value set, do not remove it. - if (supportsMultipleFrameworks) { - SetIfPresentOrNotDefaultValue (globalGroup, "TargetFrameworkVersion", "v" + moniker.Version, "v" + def.Version); - } - - if (toolsFormat.SupportsMonikers) { - SetIfPresentOrNotDefaultValue (globalGroup, "TargetFrameworkIdentifier", moniker.Identifier, def.Identifier); - SetIfPresentOrNotDefaultValue (globalGroup, "TargetFrameworkProfile", moniker.Profile, def.Profile); - } - } - - // Impdate the imports section - - List<DotNetProjectImport> currentImports = msproject.Imports.Select (i => new DotNetProjectImport (i.Project)).ToList (); - List<DotNetProjectImport> imports = new List<DotNetProjectImport> (currentImports); - - // If the project is not new, don't add the default project imports, - // just assume that the current imports are correct - UpdateImports (imports, dotNetProject, newProject); - foreach (DotNetProjectImport imp in imports) { - if (!currentImports.Contains (imp)) { - MSBuildImport import = msproject.AddNewImport (imp.Name); - if (imp.HasCondition ()) - import.Condition = imp.Condition; - currentImports.Add (imp); - } - } - foreach (DotNetProjectImport imp in currentImports) { - if (!imports.Contains (imp)) - msproject.RemoveImport (imp.Name); - } - - DataItem extendedData = ser.ExternalItemProperties; - if (extendedData.HasItemData) { - extendedData.Name = "Properties"; - StringWriter sw = new StringWriter (); - XmlConfigurationWriter.DefaultWriter.Write (new XmlTextWriter (sw), extendedData); - msproject.SetProjectExtensions ("MonoDevelop", sw.ToString ()); - } else - msproject.RemoveProjectExtensions ("MonoDevelop"); - - SaveToMSBuildProject (monitor, msproject); - - return msproject; - } - - internal void SaveProjectItems (IProgressMonitor monitor, MSBuildFileFormat toolsFormat, MSBuildSerializer ser, MSBuildProject msproject, string pathPrefix = null) - { - // Remove old items - Dictionary<string, ItemInfo> oldItems = new Dictionary<string, ItemInfo> (); - foreach (MSBuildItem item in msproject.GetAllItems ()) - oldItems [item.Name + "<" + item.UnevaluatedInclude + "<" + item.Condition] = new ItemInfo () { - Item = item - }; - // Add the new items - foreach (object ob in ((SolutionEntityItem)Item).Items.Concat (((SolutionEntityItem)Item).WildcardItems).Where (it => !it.Flags.HasFlag (ProjectItemFlags.DontPersist))) - SaveItem (monitor, toolsFormat, ser, msproject, ob, oldItems, pathPrefix); - foreach (ItemInfo itemInfo in oldItems.Values) { - if (!itemInfo.Added) - msproject.RemoveItem (itemInfo.Item); - } - } - - protected void SaveToMSBuildProject (IProgressMonitor monitor, MSBuildProject msproject) - { - foreach (var ext in GetMSBuildExtensions ()) - ext.SaveProject (monitor, EntityItem, msproject); - } - - void SetIfPresentOrNotDefaultValue (MSBuildPropertySet propGroup, string name, string value, string defaultValue, bool isXml = false) - { - bool hasDefaultValue = string.IsNullOrEmpty (value) || value == defaultValue; - var prop = propGroup.GetProperty (name); - if (prop != null) { - //if the value is default or empty, only remove the element if it was not already the default or empty - //to avoid unnecessary project file churn - if (hasDefaultValue) { - var existing = prop.GetValue (isXml); - bool alreadyHadDefaultValue = string.IsNullOrEmpty (existing) || existing == defaultValue; - if (!alreadyHadDefaultValue) - propGroup.RemoveProperty (name); - } else { - prop.SetValue (value, isXml); - } - } else if (!hasDefaultValue) { - propGroup.SetPropertyValue (name, value, false, isXml); - } - } - - void ForceDefaultValueSerialization (MSBuildSerializer ser, MSBuildPropertySet baseGroup, object ob) - { - ClassDataType dt = (ClassDataType) ser.DataContext.GetConfigurationDataType (ob.GetType()); - foreach (ItemProperty prop in dt.GetProperties (ser.SerializationContext, ob)) { - if (baseGroup.GetProperty (prop.Name) != null) - ser.SerializationContext.ForceDefaultValueSerialization (prop); - } - } - - void CollectMergetoprojectProperties (MSBuildPropertyGroup pgroup, HashSet<MergedProperty> properties, Dictionary<string,MergedPropertyValue> mergeToProjectProperties) - { - // This method checks every property in pgroup which has the MergeToProject flag. - // If the value of this property is the same as the one stored in mergeToProjectProperties - // it means that the property can be merged to the main project property group (so far). - - foreach (var pinfo in new List<MergedProperty> (properties)) { - MSBuildProperty prop = pgroup.GetProperty (pinfo.Name); - - MergedPropertyValue mvalue; - if (!mergeToProjectProperties.TryGetValue (pinfo.Name, out mvalue)) { - if (prop != null) { - // This is the first time the value is checked. Just assign it. - mergeToProjectProperties.Add (pinfo.Name, new MergedPropertyValue (prop.GetValue (true), pinfo.PreserveExistingCase)); - continue; - } - // If there is no value, it can't be merged - } - else if (prop != null && string.Equals (prop.GetValue (true), mvalue.XmlValue, StringComparison.OrdinalIgnoreCase)) - // Same value. It can be merged. - continue; - - // The property can't be merged because different configurations have different - // values for it. Remove it from the list. - properties.Remove (pinfo); - mergeToProjectProperties.Remove (pinfo.Name); - } - } - - struct MergedPropertyValue - { - public readonly string XmlValue; - public readonly bool PreserveExistingCase; - - public MergedPropertyValue (string xmlValue, bool preserveExistingCase) - { - this.XmlValue = xmlValue; - this.PreserveExistingCase = preserveExistingCase; - } - } - - void SaveItem (IProgressMonitor monitor, MSBuildFileFormat fmt, MSBuildSerializer ser, MSBuildProject msproject, object ob, Dictionary<string,ItemInfo> oldItems, string pathPrefix = null) - { - if (ob is ProjectReference) { - SaveReference (monitor, fmt, ser, msproject, (ProjectReference) ob, oldItems); - } - else if (ob is ProjectFile) { - SaveProjectFile (ser, msproject, (ProjectFile) ob, oldItems, pathPrefix); - } - else { - string itemName; - if (ob is UnknownProjectItem) { - var ui = (UnknownProjectItem)ob; - itemName = ui.ItemName; - var buildItem = AddOrGetBuildItem (msproject, oldItems, itemName, ui.Include, ui.Condition); - WriteBuildItemMetadata (ser, buildItem, ob, oldItems); - } - else { - DataType dt = ser.DataContext.GetConfigurationDataType (ob.GetType ()); - var buildItem = msproject.AddNewItem (dt.Name, ""); - WriteBuildItemMetadata (ser, buildItem, ob, oldItems); - } - } - } - - void SaveProjectFile (MSBuildSerializer ser, MSBuildProject msproject, ProjectFile file, Dictionary<string,ItemInfo> oldItems, string pathPrefix = null) - { - if (file.IsOriginatedFromWildcard) return; - - string itemName = (file.Subtype == Subtype.Directory)? "Folder" : file.BuildAction; - - string path = pathPrefix + MSBuildProjectService.ToMSBuildPath (Item.ItemDirectory, file.FilePath); - if (path.Length == 0) - return; - - //directory paths must end with '/' - if ((file.Subtype == Subtype.Directory) && path[path.Length-1] != '\\') - path = path + "\\"; - - MSBuildItem buildItem = AddOrGetBuildItem (msproject, oldItems, itemName, path, file.Condition); - WriteBuildItemMetadata (ser, buildItem, file, oldItems); - - if (!string.IsNullOrEmpty (file.DependsOn)) - buildItem.SetMetadata ("DependentUpon", MSBuildProjectService.ToMSBuildPath (Path.GetDirectoryName (file.FilePath), file.DependsOn)); - else - buildItem.UnsetMetadata ("DependentUpon"); - - if (!string.IsNullOrEmpty (file.ContentType)) - buildItem.SetMetadata ("SubType", file.ContentType); - - if (!string.IsNullOrEmpty (file.Generator)) - buildItem.SetMetadata ("Generator", file.Generator); - else - buildItem.UnsetMetadata ("Generator"); - - if (!string.IsNullOrEmpty (file.CustomToolNamespace)) - buildItem.SetMetadata ("CustomToolNamespace", file.CustomToolNamespace); - else - buildItem.UnsetMetadata ("CustomToolNamespace"); - - if (!string.IsNullOrEmpty (file.LastGenOutput)) - buildItem.SetMetadata ("LastGenOutput", file.LastGenOutput); - else - buildItem.UnsetMetadata ("LastGenOutput"); - - if (!string.IsNullOrEmpty (file.Link)) - buildItem.SetMetadata ("Link", MSBuildProjectService.ToMSBuildPathRelative (Item.ItemDirectory, file.Link)); - else - buildItem.UnsetMetadata ("Link"); - - buildItem.Condition = file.Condition; - - if (file.CopyToOutputDirectory == FileCopyMode.None) { - buildItem.UnsetMetadata ("CopyToOutputDirectory"); - } else { - buildItem.SetMetadata ("CopyToOutputDirectory", file.CopyToOutputDirectory.ToString ()); - } - - if (!file.Visible) { - buildItem.SetMetadata ("Visible", "False"); - } else { - buildItem.UnsetMetadata ("Visible"); - } - - var resId = file.ResourceId; - - //For EmbeddedResource, emit LogicalName only when it does not match the default Id - if (file.BuildAction == BuildAction.EmbeddedResource && GetDefaultResourceId (file) == resId) - resId = null; - - if (!string.IsNullOrEmpty (resId)) { - buildItem.SetMetadata ("LogicalName", resId); - } else { - buildItem.UnsetMetadata ("LogicalName"); - } - } - - void SaveReference (IProgressMonitor monitor, MSBuildFileFormat fmt, MSBuildSerializer ser, MSBuildProject msproject, ProjectReference pref, Dictionary<string,ItemInfo> oldItems) - { - MSBuildItem buildItem; - if (pref.ReferenceType == ReferenceType.Assembly) { - string asm = null; - string hintPath = null; - if (pref.ExtendedProperties.Contains ("_OriginalMSBuildReferenceInclude")) { - asm = (string) pref.ExtendedProperties ["_OriginalMSBuildReferenceInclude"]; - hintPath = (string) pref.ExtendedProperties ["_OriginalMSBuildReferenceHintPath"]; - } - else { - if (File.Exists (pref.HintPath)) { - try { - var aname = AssemblyName.GetAssemblyName (pref.HintPath); - if (pref.SpecificVersion) { - asm = aname.FullName; - } else { - asm = aname.Name; - } - } catch (Exception ex) { - string msg = string.Format ("Could not get full name for assembly '{0}'.", pref.Reference); - monitor.ReportWarning (msg); - LoggingService.LogError (msg, ex); - } - } - string basePath = Item.ItemDirectory; - if (pref.ExtendedProperties.Contains ("_OriginalMSBuildReferenceIsAbsolute")) - basePath = null; - hintPath = MSBuildProjectService.ToMSBuildPath (basePath, pref.HintPath); - } - if (asm == null) - asm = Path.GetFileNameWithoutExtension (pref.Reference); - - buildItem = AddOrGetBuildItem (msproject, oldItems, "Reference", asm, pref.Condition); - - if (!pref.SpecificVersion && ReferenceStringHasVersion (asm)) { - buildItem.SetMetadata ("SpecificVersion", "False"); - } else { - buildItem.UnsetMetadata ("SpecificVersion"); - } - - buildItem.SetMetadata ("HintPath", hintPath); - } - else if (pref.ReferenceType == ReferenceType.Package) { - string include = pref.StoredReference; - SystemPackage pkg = pref.Package; - if (pkg != null && pkg.IsFrameworkPackage) { - int i = include.IndexOf (','); - if (i != -1) - include = include.Substring (0, i).Trim (); - } - buildItem = AddOrGetBuildItem (msproject, oldItems, "Reference", include, pref.Condition); - if (!pref.SpecificVersion && ReferenceStringHasVersion (include)) - buildItem.SetMetadata ("SpecificVersion", "False"); - else - buildItem.UnsetMetadata ("SpecificVersion"); - - //RequiredTargetFramework is undocumented, maybe only a hint for VS. Only seems to be used for .NETFramework - var dnp = pref.OwnerProject as DotNetProject; - IList supportedFrameworks = fmt.SupportedFrameworks; - if (supportedFrameworks != null && dnp != null && pkg != null - && dnp.TargetFramework.Id.Identifier == TargetFrameworkMoniker.ID_NET_FRAMEWORK - && pkg.IsFrameworkPackage && supportedFrameworks.Contains (pkg.TargetFramework) - && pkg.TargetFramework.Version != "2.0" && supportedFrameworks.Count > 1) - { - TargetFramework fx = Runtime.SystemAssemblyService.GetTargetFramework (pkg.TargetFramework); - buildItem.SetMetadata ("RequiredTargetFramework", fx.Id.Version); - } else { - buildItem.UnsetMetadata ("RequiredTargetFramework"); - } - - string hintPath = (string) pref.ExtendedProperties ["_OriginalMSBuildReferenceHintPath"]; - if (hintPath != null) - buildItem.SetMetadata ("HintPath", hintPath); - else - buildItem.UnsetMetadata ("HintPath"); - } - else if (pref.ReferenceType == ReferenceType.Project) { - Project refProj = Item.ParentSolution.FindProjectByName (pref.Reference); - if (refProj != null) { - buildItem = AddOrGetBuildItem (msproject, oldItems, "ProjectReference", MSBuildProjectService.ToMSBuildPath (Item.ItemDirectory, refProj.FileName), pref.Condition); - MSBuildProjectHandler handler = refProj.ItemHandler as MSBuildProjectHandler; - if (handler != null) - buildItem.SetMetadata ("Project", handler.Item.ItemId); - else - buildItem.UnsetMetadata ("Project"); - buildItem.SetMetadata ("Name", refProj.Name); - } else { - monitor.ReportWarning (GettextCatalog.GetString ("Reference to unknown project '{0}' ignored.", pref.Reference)); - return; - } - } - else { - // Custom - DataType dt = ser.DataContext.GetConfigurationDataType (pref.GetType ()); - buildItem = AddOrGetBuildItem (msproject, oldItems, dt.Name, pref.Reference, pref.Condition); - } - - if (pref.LocalCopy != pref.DefaultLocalCopy) - buildItem.SetMetadata ("Private", pref.LocalCopy); - else - buildItem.UnsetMetadata ("Private"); - - WriteBuildItemMetadata (ser, buildItem, pref, oldItems); - buildItem.Condition = pref.Condition; - } - - void UpdateImports (List<DotNetProjectImport> imports, DotNetProject project, bool addItemTypeImports) - { - if (targetImports != null && addItemTypeImports) { - AddMissingImports (imports, targetImports); - } - - List <string> updatedImports = imports.Select (import => import.Name).ToList (); - foreach (IMSBuildImportProvider ip in AddinManager.GetExtensionObjects ("/MonoDevelop/ProjectModel/MSBuildImportProviders")) { - ip.UpdateImports (EntityItem, updatedImports); - } - - UpdateImports (imports, updatedImports); - - if (project != null) { - AddMissingImports (imports, project.ImportsAdded); - RemoveImports (imports, project.ImportsRemoved); - project.ImportsSaved (); - } - } - - void AddMissingImports (List<DotNetProjectImport> existingImports, IEnumerable<string> newImports) - { - AddMissingImports (existingImports, newImports.Select (import => new DotNetProjectImport (import))); - } - - void AddMissingImports (List<DotNetProjectImport> existingImports, IEnumerable<DotNetProjectImport> newImports) - { - foreach (DotNetProjectImport imp in newImports) - if (!existingImports.Contains (imp)) - existingImports.Add (imp); - } - - void UpdateImports (List<DotNetProjectImport> existingImports, List<string> updatedImports) - { - RemoveMissingImports (existingImports, updatedImports); - AddMissingImports (existingImports, updatedImports); - } - - void RemoveMissingImports (List<DotNetProjectImport> existingImports, List<string> updatedImports) - { - List <DotNetProjectImport> importsToRemove = existingImports.Where (import => !updatedImports.Contains (import.Name)).ToList (); - RemoveImports (existingImports, importsToRemove); - } - - void RemoveImports (List<DotNetProjectImport> existingImports, IEnumerable<DotNetProjectImport> importsToRemove) - { - foreach (DotNetProjectImport imp in importsToRemove) - existingImports.Remove (imp); - } - - IEnumerable<MSBuildExtension> GetMSBuildExtensions () - { - foreach (var e in AddinManager.GetExtensionObjects<MSBuildExtension> ("/MonoDevelop/ProjectModel/MSBuildExtensions")) { - e.Handler = this; - yield return e; - } - } - - void ReadBuildItemMetadata (DataSerializer ser, MSBuildItem buildItem, object dataItem, Type extendedType) - { - DataItem ditem = new DataItem (); - foreach (ItemProperty prop in ser.GetProperties (dataItem)) { - string name = ToMsbuildItemName (prop.Name); - if (name == "Include") - ditem.ItemData.Add (new DataValue ("Include", buildItem.Include)); - else if (buildItem.HasMetadata (name)) { - string data = buildItem.GetMetadata (name, !prop.DataType.IsSimpleType); - ditem.ItemData.Add (GetDataNode (prop, data)); - } - } - ConvertFromMsbuildFormat (ditem); - ser.Deserialize (dataItem, ditem); - } - - void WriteBuildItemMetadata (DataSerializer ser, MSBuildItem buildItem, object dataItem, Dictionary<string,ItemInfo> oldItems) - { - var notWrittenProps = new HashSet<string> (); - foreach (ItemProperty prop in ser.GetProperties (dataItem)) - notWrittenProps.Add (prop.Name); - - DataItem ditem = (DataItem) ser.Serialize (dataItem, dataItem.GetType ()); - if (ditem.HasItemData) { - foreach (DataNode node in ditem.ItemData) { - notWrittenProps.Remove (node.Name); - if (node.Name == "Include" && node is DataValue) - buildItem.Include = ((DataValue) node).Value; - else { - ConvertToMsbuildFormat (node); - buildItem.SetMetadata (node.Name, GetXmlString (node), node is DataItem); - } - } - } - foreach (string prop in notWrittenProps) - buildItem.UnsetMetadata (prop); - } - - MSBuildItem AddOrGetBuildItem (MSBuildProject msproject, Dictionary<string,ItemInfo> oldItems, string name, string include, string condition) - { - ItemInfo itemInfo; - string key = name + "<" + include + "<" + condition; - if (oldItems.TryGetValue (key, out itemInfo)) { - if (!itemInfo.Added) { - itemInfo.Added = true; - oldItems [key] = itemInfo; - } - return itemInfo.Item; - } else { - return msproject.AddNewItem (name, include); - } - } - - DataItem ReadPropertyGroupMetadata (DataSerializer ser, MSBuildPropertySet propGroup, object dataItem) - { - DataItem ditem = new DataItem (); - - foreach (MSBuildProperty bprop in propGroup.Properties) { - DataNode node = null; - foreach (XmlNode xnode in bprop.Element.ChildNodes) { - if (xnode is XmlElement) { - node = XmlConfigurationReader.DefaultReader.Read ((XmlElement)xnode); - break; - } - } - if (node == null) { - node = new DataValue (bprop.Name, bprop.GetValue (false)); - } - - ConvertFromMsbuildFormat (node); - ditem.ItemData.Add (node); - } - - return ditem; - } - - void WritePropertyGroupMetadata (MSBuildPropertySet propGroup, DataCollection itemData, MSBuildSerializer ser, params object[] itemsToReplace) - { - var notWrittenProps = new HashSet<string> (); - - foreach (object ob in itemsToReplace) { - if (ob == null) - continue; - ClassDataType dt = (ClassDataType) ser.DataContext.GetConfigurationDataType (ob.GetType ()); - foreach (ItemProperty prop in dt.GetProperties (ser.SerializationContext, ob)) - notWrittenProps.Add (prop.Name); - } - - foreach (DataNode node in itemData) { - notWrittenProps.Remove (node.Name); - ConvertToMsbuildFormat (node); - - // In the other msbuild contexts (metadata, solution properties, etc) we TitleCase by default, so the node.Value is TitleCase. - // However, for property value, we lowercase by default and preserve existing case to reduce noise on VS-created files. - var boolNode = node as MSBuildBoolDataValue; - string value; - bool preserveExistingCase; - if (boolNode != null) { - value = boolNode.RawValue? "true" : "false"; - preserveExistingCase = true; - } else { - value = GetXmlString (node); - preserveExistingCase = false; - } - - propGroup.SetPropertyValue (node.Name, value, preserveExistingCase, node is DataItem); - } - foreach (string prop in notWrittenProps) - propGroup.RemoveProperty (prop); - } - - string ToMsbuildItemName (string name) - { - return name.Replace ('.', '-'); - } - - void ConvertToMsbuildFormat (DataNode node) - { - ReplaceChar (node, true, '.', '-'); - } - - void ConvertFromMsbuildFormat (DataNode node) - { - ReplaceChar (node, true, '-', '.'); - } - - void ReplaceChar (DataNode node, bool force, char oldChar, char newChar) - { - DataItem it = node as DataItem; - if ((force || it != null) && node.Name != null) - node.Name = node.Name.Replace (oldChar, newChar); - if (it != null) { - foreach (DataNode cnode in it.ItemData) - ReplaceChar (cnode, !it.UniqueNames, oldChar, newChar); - } - } - - List<ConfigData> GetConfigData (MSBuildProject msproject, bool includeGlobalGroups) - { - List<ConfigData> configData = new List<ConfigData> (); - foreach (MSBuildPropertyGroup cgrp in msproject.PropertyGroups) { - string conf, platform; - if (ParseConfigCondition (cgrp.Condition, out conf, out platform) || includeGlobalGroups) - configData.Add (new ConfigData (conf, platform, cgrp)); - } - return configData; - } - - ConfigData FindPropertyGroup (List<ConfigData> configData, SolutionItemConfiguration config) - { - foreach (ConfigData data in configData) { - if (data.Config == config.Name && data.Platform == config.Platform) - return data; - } - return null; - } - - ProjectFile ReadProjectFile (DataSerializer ser, Project project, MSBuildItem buildItem, Type type) - { - string path = MSBuildProjectService.FromMSBuildPath (project.ItemDirectory, buildItem.Include); - ProjectFile file = (ProjectFile) Activator.CreateInstance (type); - file.Name = path; - file.BuildAction = buildItem.Name; - - ReadBuildItemMetadata (ser, buildItem, file, type); - - string dependentFile = buildItem.GetMetadata ("DependentUpon"); - if (!string.IsNullOrEmpty (dependentFile)) { - dependentFile = MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (path), dependentFile); - file.DependsOn = dependentFile; - } - - string copyToOutputDirectory = buildItem.GetMetadata ("CopyToOutputDirectory"); - if (!string.IsNullOrEmpty (copyToOutputDirectory)) { - switch (copyToOutputDirectory) { - case "None": break; - case "Always": file.CopyToOutputDirectory = FileCopyMode.Always; break; - case "PreserveNewest": file.CopyToOutputDirectory = FileCopyMode.PreserveNewest; break; - default: - MonoDevelop.Core.LoggingService.LogWarning ( - "Unrecognised value {0} for CopyToOutputDirectory MSBuild property", - copyToOutputDirectory); - break; - } - } - - if (buildItem.GetMetadataIsFalse ("Visible")) - file.Visible = false; - - - string resourceId = buildItem.GetMetadata ("LogicalName"); - if (!string.IsNullOrEmpty (resourceId)) - file.ResourceId = resourceId; - - string contentType = buildItem.GetMetadata ("SubType"); - if (!string.IsNullOrEmpty (contentType)) - file.ContentType = contentType; - - string generator = buildItem.GetMetadata ("Generator"); - if (!string.IsNullOrEmpty (generator)) - file.Generator = generator; - - string customToolNamespace = buildItem.GetMetadata ("CustomToolNamespace"); - if (!string.IsNullOrEmpty (customToolNamespace)) - file.CustomToolNamespace = customToolNamespace; - - string lastGenOutput = buildItem.GetMetadata ("LastGenOutput"); - if (!string.IsNullOrEmpty (lastGenOutput)) - file.LastGenOutput = lastGenOutput; - - string link = buildItem.GetMetadata ("Link"); - if (!string.IsNullOrEmpty (link)) { - if (!Platform.IsWindows) - link = MSBuildProjectService.UnescapePath (link); - file.Link = link; - } - - file.Condition = buildItem.Condition; - return file; - } - - bool ParseConfigCondition (string cond, out string config, out string platform) - { - config = platform = Unspecified; - int i = cond.IndexOf ("=="); - if (i == -1) - return false; - if (cond.Substring (0, i).Trim () == "'$(Configuration)|$(Platform)'") { - cond = cond.Substring (i+2).Trim (' ','\''); - i = cond.IndexOf ('|'); - if (i != -1) { - config = cond.Substring (0, i); - platform = cond.Substring (i+1); - } else { - // Invalid configuration - return false; - } - if (platform == "AnyCPU") - platform = string.Empty; - return true; - } - else if (cond.Substring (0, i).Trim () == "'$(Configuration)'") { - config = cond.Substring (i+2).Trim (' ','\''); - platform = Unspecified; - return true; - } - else if (cond.Substring (0, i).Trim () == "'$(Platform)'") { - config = Unspecified; - platform = cond.Substring (i+2).Trim (' ','\''); - if (platform == "AnyCPU") - platform = string.Empty; - return true; - } - return false; - } - - string BuildConfigCondition (string config, string platform) - { - if (platform.Length == 0) - platform = "AnyCPU"; - return " '$(Configuration)|$(Platform)' == '" + config + "|" + platform + "' "; - } - - bool IsMergeToProjectProperty (ItemProperty prop) - { - foreach (object at in prop.CustomAttributes) { - if (at is MergeToProjectAttribute) - return true; - } - return false; - } - - string GetXmlString (DataNode node) - { - if (node is DataValue) - return ((DataValue)node).Value; - else { - StringWriter sw = new StringWriter (); - XmlTextWriter xw = new XmlTextWriter (sw); - XmlConfigurationWriter.DefaultWriter.Write (xw, node); - return sw.ToString (); - } - } - - DataNode GetDataNode (ItemProperty prop, string xmlString) - { - if (prop.DataType.IsSimpleType) - return new DataValue (prop.Name, xmlString); - else { - StringReader sr = new StringReader (xmlString); - return XmlConfigurationReader.DefaultReader.Read (new XmlTextReader (sr)); - } - } - - internal virtual MSBuildSerializer CreateSerializer () - { - return new MSBuildSerializer (EntityItem.FileName); - } - - static readonly MSBuildElementOrder globalConfigOrder = new MSBuildElementOrder ( - "Configuration","Platform","ProductVersion","SchemaVersion","ProjectGuid", "OutputType", - "AppDesignerFolder","RootNamespace","AssemblyName","StartupObject" - ); - static readonly MSBuildElementOrder configOrder = new MSBuildElementOrder ( - "DebugSymbols","DebugType","Optimize","OutputPath","DefineConstants","ErrorReport","WarningLevel", - "TreatWarningsAsErrors","DocumentationFile" - ); - - // Those are properties which are dynamically set by this file format - - internal static readonly ItemMember[] ExtendedMSBuildProperties = new ItemMember [] { - new ItemMember (typeof(SolutionEntityItem), "ProductVersion"), - new ItemMember (typeof(SolutionEntityItem), "SchemaVersion"), - new ItemMember (typeof(SolutionEntityItem), "ProjectGuid"), - new ItemMember (typeof(DotNetProjectConfiguration), "ErrorReport"), - new ItemMember (typeof(DotNetProjectConfiguration), "TargetFrameworkVersion", new object[] { new MergeToProjectAttribute () }), - new ItemMember (typeof(ProjectReference), "RequiredTargetFramework"), - new ItemMember (typeof(Project), "InternalTargetFrameworkVersion", true), - }; - - // Items generated by VS but which MD is not using and should be ignored - - internal static readonly IList<string> UnsupportedItems = new string[] { - "BootstrapperFile", "AppDesigner", "WebReferences", "WebReferenceUrl", "Service", - "ProjectReference", "Reference", // Reference elements are included here because they are special-cased for DotNetProject, and they are unsupported in other types of projects - "InternalsVisibleTo", - "InternalsVisibleToTest" - }; - } - class MSBuildSerializer: DataSerializer { public DataItem InternalItemProperties = new DataItem (); @@ -2061,8 +67,8 @@ namespace MonoDevelop.Projects.Formats.MSBuild if (prop.Name == "References" || prop.Name == "LanguageParameters") return false; } - if (instance is SolutionEntityItem) { - if (prop.IsExtendedProperty (typeof(SolutionEntityItem))) + if (instance is SolutionItem) { + if (prop.IsExtendedProperty (typeof(SolutionItem))) return true; return prop.Name != "name" && prop.Name != "Configurations"; } @@ -2086,7 +92,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild internal protected override DataNode OnSerializeProperty (ItemProperty prop, SerializationContext serCtx, object instance, object value) { DataNode data = base.OnSerializeProperty (prop, serCtx, instance, value); - if (instance is SolutionEntityItem && data != null) { + if (instance is SolutionItem && data != null) { if (prop.IsExternal) ExternalItemProperties.ItemData.Add (data); else @@ -2096,22 +102,6 @@ namespace MonoDevelop.Projects.Formats.MSBuild } } - class UnknownSolutionItemTypeException : InvalidOperationException - { - public UnknownSolutionItemTypeException () - : base ("Unknown solution item type") - { - } - - public UnknownSolutionItemTypeException (string name) - : base ("Unknown solution item type: " + name) - { - this.TypeName = name; - } - - public string TypeName { get; private set; } - } - class MSBuildElementOrder: Dictionary<string, int> { public MSBuildElementOrder (params string[] elements) diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectService.cs index ac766786b6..3059abfd4e 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectService.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectService.cs @@ -41,12 +41,14 @@ using MonoDevelop.Core; using MonoDevelop.Core.Assemblies; using Cecil = Mono.Cecil; using System.Threading; +using System.Threading.Tasks; +using System.Xml; namespace MonoDevelop.Projects.Formats.MSBuild { public static class MSBuildProjectService { - const string ItemTypesExtensionPath = "/MonoDevelop/ProjectModel/MSBuildItemTypes"; + internal const string ItemTypesExtensionPath = "/MonoDevelop/ProjectModel/MSBuildItemTypes"; public const string GenericItemGuid = "{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}"; public const string FolderTypeGuid = "{2150E333-8FDC-42A3-9474-1A3956D46DE8}"; @@ -58,7 +60,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild static IMSBuildGlobalPropertyProvider[] globalPropertyProviders; static Dictionary<string,RemoteBuildEngine> builders = new Dictionary<string, RemoteBuildEngine> (); - static GenericItemTypeNode genericItemTypeNode = new GenericItemTypeNode (); + static Dictionary<string,Type> genericProjectTypes = new Dictionary<string, Type> (); internal static bool ShutDown { get; private set; } @@ -67,13 +69,6 @@ namespace MonoDevelop.Projects.Formats.MSBuild if (dataContext == null) { dataContext = new MSBuildDataContext (); Services.ProjectService.InitializeDataContext (dataContext); - foreach (ItemMember prop in MSBuildProjectHandler.ExtendedMSBuildProperties) { - ItemProperty iprop = new ItemProperty (prop.Name, prop.Type); - iprop.IsExternal = prop.IsExternal; - if (prop.CustomAttributes != null) - iprop.CustomAttributes = prop.CustomAttributes; - dataContext.RegisterProperty (prop.DeclaringType, iprop); - } } return dataContext; } @@ -88,10 +83,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild PropertyService.PropertyChanged += HandlePropertyChanged; DefaultMSBuildVerbosity = PropertyService.Get ("MonoDevelop.Ide.MSBuildVerbosity", MSBuildVerbosity.Normal); - Runtime.ShuttingDown += delegate { - ShutDown = true; - CleanProjectBuilders (); - }; + Runtime.ShuttingDown += (sender, e) => ShutDown = true; const string gppPath = "/MonoDevelop/ProjectModel/MSBuildGlobalPropertyProviders"; globalPropertyProviders = AddinManager.GetExtensionObjects<IMSBuildGlobalPropertyProvider> (gppPath); @@ -118,84 +110,184 @@ namespace MonoDevelop.Projects.Formats.MSBuild internal static MSBuildVerbosity DefaultMSBuildVerbosity { get; private set; } - public static SolutionEntityItem LoadItem (IProgressMonitor monitor, string fileName, MSBuildFileFormat expectedFormat, string typeGuid, string itemGuid) + public async static Task<SolutionItem> LoadItem (ProgressMonitor monitor, string fileName, MSBuildFileFormat expectedFormat, string typeGuid, string itemGuid) { - foreach (ItemTypeNode node in GetItemTypeNodes ()) { + foreach (SolutionItemTypeNode node in GetItemTypeNodes ()) { if (node.CanHandleFile (fileName, typeGuid)) - return node.LoadSolutionItem (monitor, fileName, expectedFormat, itemGuid); + return await LoadProjectAsync (monitor, fileName, expectedFormat, typeGuid, null, node); } - if (string.IsNullOrEmpty (typeGuid) && IsProjectSubtypeFile (fileName)) { - typeGuid = LoadProjectTypeGuids (fileName); - foreach (ItemTypeNode node in GetItemTypeNodes ()) { - if (node.CanHandleFile (fileName, typeGuid)) - return node.LoadSolutionItem (monitor, fileName, expectedFormat, itemGuid); - } - } - // If it is a known unsupported project, load it as UnknownProject var projectInfo = MSBuildProjectService.GetUnknownProjectTypeInfo (typeGuid != null ? new [] { typeGuid } : new string[0], fileName); if (projectInfo != null && projectInfo.LoadFiles) { if (typeGuid == null) typeGuid = projectInfo.Guid; - var h = new MSBuildProjectHandler (typeGuid, "", itemGuid); - h.SetUnsupportedType (projectInfo); - return h.Load (monitor, fileName, expectedFormat, "", null); + var p = (UnknownProject) await LoadProjectAsync (monitor, fileName, expectedFormat, "", typeof(UnknownProject), null); + p.UnsupportedProjectMessage = projectInfo.GetInstructions (); + return p; } - return null; } - - internal static IResourceHandler GetResourceHandlerForItem (DotNetProject project) + + internal static async Task<SolutionItem> LoadProjectAsync (ProgressMonitor monitor, string fileName, MSBuildFileFormat format, string typeGuid, Type itemType, SolutionItemTypeNode node) { - foreach (ItemTypeNode node in GetItemTypeNodes ()) { - DotNetProjectNode pNode = node as DotNetProjectNode; - if (pNode != null && pNode.CanHandleItem (project)) - return pNode.GetResourceHandler (); + try { + ProjectExtensionUtil.BeginLoadOperation (); + var item = await CreateSolutionItem (monitor, fileName, typeGuid, itemType, node); + item.TypeGuid = typeGuid ?? node.Guid; + await item.LoadAsync (monitor, fileName, format); + return item; + } finally { + ProjectExtensionUtil.EndLoadOperation (); } - return new MSBuildResourceHandler (); } - - internal static MSBuildHandler GetItemHandler (SolutionEntityItem item) + + // All of the last 4 parameters are optional, but at least one must be provided. + static async Task<SolutionItem> CreateSolutionItem (ProgressMonitor monitor, string fileName, string typeGuid, Type itemClass, SolutionItemTypeNode node) { - MSBuildHandler handler = item.ItemHandler as MSBuildHandler; - if (handler != null) - return handler; - else - throw new InvalidOperationException ("Not an MSBuild project"); + if (itemClass != null) + return (SolutionItem)Activator.CreateInstance (itemClass); + + return await node.CreateSolutionItem (monitor, fileName, typeGuid ?? node.Guid); } - - internal static void SetId (SolutionItem item, string id) + + internal static bool CanCreateSolutionItem (string type, ProjectCreateInformation info, System.Xml.XmlElement projectOptions) { - MSBuildHandler handler = item.ItemHandler as MSBuildHandler; - if (handler != null) - handler.ItemId = id; - else - throw new InvalidOperationException ("Not an MSBuild project"); + foreach (var node in GetItemTypeNodes ()) { + if (node.CanCreateSolutionItem (type, info, projectOptions)) + return true; + } + return false; } - - internal static void InitializeItemHandler (SolutionItem item) - { - SolutionEntityItem eitem = item as SolutionEntityItem; - if (eitem != null) { - foreach (ItemTypeNode node in GetItemTypeNodes ()) { - if (node.CanHandleItem (eitem)) { - node.InitializeHandler (eitem); - foreach (DotNetProjectSubtypeNode snode in GetItemSubtypeNodes ()) { - if (snode.CanHandleItem (eitem)) - snode.InitializeHandler (eitem); - } - return; + + internal static SolutionItem CreateSolutionItem (string typeGuid) + { + foreach (var node in GetItemTypeNodes ()) { + if (node.Guid.Equals (typeGuid, StringComparison.OrdinalIgnoreCase)) { + return node.CreateSolutionItem (new ProgressMonitor (), null, typeGuid).Result; + } + } + throw new InvalidOperationException ("Unknown project type: " + typeGuid); + } + + internal static SolutionItem CreateSolutionItem (string type, ProjectCreateInformation info, System.Xml.XmlElement projectOptions) + { + foreach (var node in GetItemTypeNodes ()) { + if (node.CanCreateSolutionItem (type, info, projectOptions)) + return node.CreateSolutionItem (type, info, projectOptions); + } + throw new InvalidOperationException ("Unknown project type: " + type); + } + +/* internal static bool CanMigrateFlavor (string[] guids) + { + + } + + internal static async Task<bool> MigrateFlavor (IProgressMonitor monitor, string fileName, string typeGuid, MSBuildProjectNode node, MSBuildProject p) + { + var language = GetLanguageFromGuid (typeGuid); + + if (MigrateProject (monitor, node, p, fileName, language)) { + p.Save (fileName); + return true; + } + + return false; + } + + static async Task<bool> MigrateProject (IProgressMonitor monitor, MSBuildProjectNode st, MSBuildProject p, string fileName, string language) + { + var projectLoadMonitor = monitor as IProjectLoadProgressMonitor; + if (projectLoadMonitor == null) { + // projectLoadMonitor will be null when running through md-tool, but + // this is not fatal if migration is not required, so just ignore it. --abock + if (!st.IsMigrationRequired) + return false; + + LoggingService.LogError (Environment.StackTrace); + monitor.ReportError ("Could not open unmigrated project and no migrator was supplied", null); + throw new Exception ("Could not open unmigrated project and no migrator was supplied"); + } + + var migrationType = st.MigrationHandler.CanPromptForMigration + ? st.MigrationHandler.PromptForMigration (projectLoadMonitor, p, fileName, language) + : projectLoadMonitor.ShouldMigrateProject (); + if (migrationType == MigrationType.Ignore) { + if (st.IsMigrationRequired) { + monitor.ReportError (string.Format ("{1} cannot open the project '{0}' unless it is migrated.", Path.GetFileName (fileName), BrandingService.ApplicationName), null); + throw new Exception ("The user choose not to migrate the project"); + } else + return false; + } + + var baseDir = (FilePath) Path.GetDirectoryName (fileName); + if (migrationType == MigrationType.BackupAndMigrate) { + var backupDirFirst = baseDir.Combine ("backup"); + string backupDir = backupDirFirst; + int i = 0; + while (Directory.Exists (backupDir)) { + backupDir = backupDirFirst + "-" + i.ToString (); + if (i++ > 20) { + throw new Exception ("Too many backup directories"); } } + Directory.CreateDirectory (backupDir); + foreach (var file in st.MigrationHandler.FilesToBackup (fileName)) + File.Copy (file, Path.Combine (backupDir, Path.GetFileName (file))); } - else if (item is SolutionFolder) { - MSBuildHandler h = new MSBuildHandler (FolderTypeGuid, null); - h.Item = item; - item.SetItemHandler (h); + + var res = await st.MigrationHandler.Migrate (projectLoadMonitor, p, fileName, language); + if (!res) + throw new Exception ("Could not migrate the project"); + + return true; + }*/ + + internal static string GetLanguageGuid (string language) + { + foreach (var node in GetItemTypeNodes ().OfType<DotNetProjectTypeNode> ()) { + if (node.Language == language) + return node.Guid; } + throw new InvalidOperationException ("Language not supported: " + language); } - + + internal static string GetLanguageFromGuid (string guid) + { + foreach (var node in GetItemTypeNodes ().OfType<DotNetProjectTypeNode> ()) { + if (node.Guid.Equals (guid, StringComparison.OrdinalIgnoreCase)) + return node.Language; + } + throw new InvalidOperationException ("Language not supported: " + guid); + } + + internal static bool IsKnownTypeGuid (string guid) + { + foreach (var node in GetItemTypeNodes ()) { + if (node.Guid.Equals (guid, StringComparison.OrdinalIgnoreCase)) + return true; + } + return false; + } + + internal static string GetTypeGuidFromAlias (string alias) + { + foreach (var node in GetItemTypeNodes ()) { + if (node.Alias.Equals (alias, StringComparison.OrdinalIgnoreCase)) + return node.Guid; + } + return null; + } + + internal static IEnumerable<string> GetDefaultImports (string typeGuid) + { + foreach (var node in GetItemTypeNodes ()) { + if (node.Guid == typeGuid && !string.IsNullOrEmpty (node.Import)) + yield return node.Import; + } + } + public static bool SupportsProjectType (string projectFile) { if (!string.IsNullOrWhiteSpace (projectFile)) { @@ -212,9 +304,9 @@ namespace MonoDevelop.Projects.Formats.MSBuild return false; } - public static void CheckHandlerUsesMSBuildEngine (SolutionItem item, out bool useByDefault, out bool require) + public static void CheckHandlerUsesMSBuildEngine (SolutionFolderItem item, out bool useByDefault, out bool require) { - var handler = item.ItemHandler as MSBuildProjectHandler; + var handler = item as Project; if (handler == null) { useByDefault = require = false; return; @@ -223,88 +315,92 @@ namespace MonoDevelop.Projects.Formats.MSBuild require = handler.RequireMSBuildEngine; } - internal static DotNetProjectSubtypeNode GetDotNetProjectSubtype (string typeGuids) - { - if (!string.IsNullOrEmpty (typeGuids)) - return GetDotNetProjectSubtype (typeGuids.Split (';').Select (t => t.Trim ())); - else - return null; - } - - internal static DotNetProjectSubtypeNode GetDotNetProjectSubtype (IEnumerable<string> typeGuids) - { - Type ptype = null; - DotNetProjectSubtypeNode foundNode = null; - foreach (string guid in typeGuids) { - foreach (DotNetProjectSubtypeNode st in GetItemSubtypeNodes ()) { - if (st.SupportsType (guid)) { - if (ptype == null || ptype.IsAssignableFrom (st.Type)) { - ptype = st.Type; - foundNode = st; - } - } - } - } - return foundNode; - } - - static IEnumerable<ItemTypeNode> GetItemTypeNodes () - { - foreach (ExtensionNode node in AddinManager.GetExtensionNodes (ItemTypesExtensionPath)) { - if (node is ItemTypeNode) - yield return (ItemTypeNode) node; - } - yield return genericItemTypeNode; - } - - internal static IEnumerable<DotNetProjectSubtypeNode> GetItemSubtypeNodes () + static IEnumerable<SolutionItemTypeNode> GetItemTypeNodes () { foreach (ExtensionNode node in AddinManager.GetExtensionNodes (ItemTypesExtensionPath)) { - if (node is DotNetProjectSubtypeNode) - yield return (DotNetProjectSubtypeNode) node; + if (node is SolutionItemTypeNode) + yield return (SolutionItemTypeNode) node; } } internal static bool CanReadFile (FilePath file) { - foreach (ItemTypeNode node in GetItemTypeNodes ()) { + foreach (SolutionItemTypeNode node in GetItemTypeNodes ()) { if (node.CanHandleFile (file, null)) { return true; } } - if (IsProjectSubtypeFile (file)) { - string typeGuids = LoadProjectTypeGuids (file); - foreach (ItemTypeNode node in GetItemTypeNodes ()) { - if (node.CanHandleFile (file, typeGuids)) { - return true; - } - } - } return GetUnknownProjectTypeInfo (new string[0], file) != null; } - internal static string GetExtensionForItem (SolutionEntityItem item) + internal static string GetExtensionForItem (SolutionItem item) { - foreach (DotNetProjectSubtypeNode node in GetItemSubtypeNodes ()) { - if (!string.IsNullOrEmpty (node.Extension) && node.CanHandleItem (item)) - return node.Extension; - } - foreach (ItemTypeNode node in GetItemTypeNodes ()) { - if (node.CanHandleItem (item)) { + foreach (SolutionItemTypeNode node in GetItemTypeNodes ()) { + if (node.Guid.Equals (item.TypeGuid, StringComparison.OrdinalIgnoreCase)) return node.Extension; - } } // The generic handler should always be found throw new InvalidOperationException (); } - - static bool IsProjectSubtypeFile (FilePath file) + + internal static string GetTypeGuidForItem (SolutionItem item) { - foreach (DotNetProjectSubtypeNode node in GetItemSubtypeNodes ()) { - if (!string.IsNullOrEmpty (node.Extension) && node.CanHandleFile (file, null)) - return true; + var className = item.GetType ().FullName; + foreach (SolutionItemTypeNode node in GetItemTypeNodes ()) { + if (node.ItenTypeName == className) + return node.Guid; + } + return GenericItemGuid; + } + + public static void RegisterGenericProjectType (string projectId, Type type) + { + lock (genericProjectTypes) { + if (!typeof(Project).IsAssignableFrom (type)) + throw new ArgumentException ("Type is not a subclass of MonoDevelop.Projects.Project"); + genericProjectTypes [projectId] = type; + } + } + + internal static Task<SolutionItem> CreateGenericProject (string file) + { + return Task<SolutionItem>.Factory.StartNew (delegate { + var t = ReadGenericProjectType (file); + if (t == null) + throw new UserException ("Unknown project type"); + + Type type; + lock (genericProjectTypes) { + if (!genericProjectTypes.TryGetValue (t, out type)) + throw new UserException ("Unknown project type: " + t); + } + return (SolutionItem)Activator.CreateInstance (type); + }); + } + + static string ReadGenericProjectType (string file) + { + using (XmlTextReader tr = new XmlTextReader (file)) { + tr.MoveToContent (); + if (tr.LocalName != "Project") + return null; + if (tr.IsEmptyElement) + return null; + tr.ReadStartElement (); + tr.MoveToContent (); + if (tr.LocalName != "PropertyGroup") + return null; + if (tr.IsEmptyElement) + return null; + tr.ReadStartElement (); + tr.MoveToContent (); + while (tr.NodeType != XmlNodeType.EndElement) { + if (tr.NodeType == XmlNodeType.Element && !tr.IsEmptyElement && tr.LocalName == "ItemType") + return tr.ReadElementString (); + tr.Skip (); + } + return null; } - return false; } static char[] specialCharacters = new char [] {'%', '$', '@', '(', ')', '\'', ';', '?' }; @@ -342,10 +438,14 @@ namespace MonoDevelop.Projects.Formats.MSBuild return str; } - public static string ToMSBuildPath (string baseDirectory, string absPath) + public static string ToMSBuildPath (string baseDirectory, string absPath, bool normalize = true) { + if (string.IsNullOrEmpty (absPath)) + return absPath; if (baseDirectory != null) { - absPath = FileService.NormalizeRelativePath (FileService.AbsoluteToRelativePath (baseDirectory, absPath)); + absPath = FileService.AbsoluteToRelativePath (baseDirectory, absPath); + if (normalize) + absPath = FileService.NormalizeRelativePath (absPath); } return EscapeString (absPath).Replace ('/', '\\'); } @@ -501,6 +601,8 @@ namespace MonoDevelop.Projects.Formats.MSBuild extn = fname.Substring (last_dot + 1); return true; } + + static bool runLocal = false; internal static RemoteProjectBuilder GetProjectBuilder (TargetRuntime runtime, string minToolsVersion, string file, string solutionFile) { @@ -537,6 +639,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild //always start the remote process explicitly, even if it's using the current runtime and fx //else it won't pick up the assembly redirects from the builder exe var exe = GetExeLocation (runtime, toolsVersion); + MonoDevelop.Core.Execution.RemotingService.RegisterRemotingChannel (); var pinfo = new ProcessStartInfo (exe) { UseShellExecute = false, @@ -547,22 +650,30 @@ namespace MonoDevelop.Projects.Formats.MSBuild runtime.GetToolsExecutionEnvironment ().MergeTo (pinfo); Process p = null; + try { - p = runtime.ExecuteAssembly (pinfo); - p.StandardInput.WriteLine (Process.GetCurrentProcess ().Id.ToString ()); - string responseKey = "[MonoDevelop]"; - string sref; - while (true) { - sref = p.StandardError.ReadLine (); - if (sref.StartsWith (responseKey, StringComparison.Ordinal)) { - sref = sref.Substring (responseKey.Length); - break; + IBuildEngine engine; + if (!runLocal) { + p = runtime.ExecuteAssembly (pinfo); + p.StandardInput.WriteLine (Process.GetCurrentProcess ().Id.ToString ()); + string responseKey = "[MonoDevelop]"; + string sref; + while (true) { + sref = p.StandardError.ReadLine (); + if (sref.StartsWith (responseKey, StringComparison.Ordinal)) { + sref = sref.Substring (responseKey.Length); + break; + } } + byte[] data = Convert.FromBase64String (sref); + MemoryStream ms = new MemoryStream (data); + BinaryFormatter bf = new BinaryFormatter (); + engine = (IBuildEngine)bf.Deserialize (ms); + } else { + var asm = System.Reflection.Assembly.LoadFrom (exe); + var t = asm.GetType ("MonoDevelop.Projects.Formats.MSBuild.BuildEngine"); + engine = (IBuildEngine)Activator.CreateInstance (t); } - byte[] data = Convert.FromBase64String (sref); - MemoryStream ms = new MemoryStream (data); - BinaryFormatter bf = new BinaryFormatter (); - var engine = (IBuildEngine)bf.Deserialize (ms); engine.SetCulture (GettextCatalog.UICulture); engine.SetGlobalProperties (GetCoreGlobalProperties (solutionFile)); foreach (var gpp in globalPropertyProviders) @@ -572,13 +683,19 @@ namespace MonoDevelop.Projects.Formats.MSBuild if (p != null) { try { p.Kill (); - } catch { } + } catch { + } } throw; } - + + builders [builderKey] = builder; builder.ReferenceCount = 1; + builder.Disconnected += delegate { + lock (builders) + builders.Remove (builderKey); + }; return new RemoteProjectBuilder (file, builder); } } @@ -623,45 +740,11 @@ namespace MonoDevelop.Projects.Formats.MSBuild internal static void ReleaseProjectBuilder (RemoteBuildEngine engine) { lock (builders) { - if (engine.ReferenceCount > 0) { - if (--engine.ReferenceCount == 0) { - engine.ReleaseTime = DateTime.Now.AddSeconds (3); - ScheduleProjectBuilderCleanup (engine.ReleaseTime.AddMilliseconds (500)); - } - } - } - } - - static DateTime nextCleanup = DateTime.MinValue; - - static void ScheduleProjectBuilderCleanup (DateTime cleanupTime) - { - lock (builders) { - if (cleanupTime < nextCleanup) + if (--engine.ReferenceCount != 0) return; - nextCleanup = cleanupTime; - System.Threading.ThreadPool.QueueUserWorkItem (delegate { - DateTime tnow = DateTime.Now; - while (tnow < nextCleanup) { - System.Threading.Thread.Sleep ((int)(nextCleanup - tnow).TotalMilliseconds); - CleanProjectBuilders (); - tnow = DateTime.Now; - } - }); - } - } - - static void CleanProjectBuilders () - { - lock (builders) { - DateTime tnow = DateTime.Now; - foreach (var val in new Dictionary<string,RemoteBuildEngine> (builders)) { - if (val.Value.ReferenceCount == 0 && val.Value.ReleaseTime <= tnow) { - builders.Remove (val.Key); - val.Value.Dispose (); - } - } + builders.Remove (builders.First (kvp => kvp.Value == engine).Key); } + engine.Dispose (); } static Dictionary<string, string> cultureNamesTable; @@ -682,11 +765,11 @@ namespace MonoDevelop.Projects.Formats.MSBuild MSBuildProject project = new MSBuildProject (); project.Load (fileName); - MSBuildPropertySet globalGroup = project.GetGlobalPropertyGroup (); + IMSBuildPropertySet globalGroup = project.GetGlobalPropertyGroup (); if (globalGroup == null) return null; - return globalGroup.GetPropertyValue ("ProjectTypeGuids"); + return globalGroup.GetValue ("ProjectTypeGuids"); } internal static UnknownProjectTypeNode GetUnknownProjectTypeInfo (string[] guids, string fileName = null) @@ -696,11 +779,6 @@ namespace MonoDevelop.Projects.Formats.MSBuild .Where (p => guids.Any (p.MatchesGuid) || (ext != null && p.Extension == ext)).ToList (); return nodes.FirstOrDefault (n => !n.IsSolvable) ?? nodes.FirstOrDefault (n => n.IsSolvable); } - - public static MSBuildProjectHandler GetHandler (Project project) - { - return (MSBuildProjectHandler) project.GetItemHandler (); - } } class MSBuildDataContext: DataContext @@ -807,21 +885,12 @@ namespace MonoDevelop.Projects.Formats.MSBuild } } - class GenericItemTypeNode: ItemTypeNode + [RegisterProjectType (MSBuildProjectService.GenericItemGuid, Extension="mdproj")] + class GenericItemFactory: SolutionItemFactory { - public GenericItemTypeNode (): base (MSBuildProjectService.GenericItemGuid, "mdproj", null) - { - } - - public override bool CanHandleItem (SolutionEntityItem item) - { - return true; - } - - public override SolutionEntityItem LoadSolutionItem (IProgressMonitor monitor, string fileName, MSBuildFileFormat expectedFormat, string itemGuid) + public override Task<SolutionItem> CreateItem (string fileName, string typeGuid) { - MSBuildProjectHandler handler = new MSBuildProjectHandler (Guid, Import, itemGuid); - return handler.Load (monitor, fileName, expectedFormat, null, null); + return MSBuildProjectService.CreateGenericProject (fileName); } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProperty.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProperty.cs new file mode 100644 index 0000000000..0f5fa0422f --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProperty.cs @@ -0,0 +1,259 @@ +// +// MSBuildProperty.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Xml; +using Microsoft.Build.BuildEngine; +using System.Xml.Linq; +using MonoDevelop.Core; +using System.Globalization; + + +namespace MonoDevelop.Projects.Formats.MSBuild +{ + + public sealed class MSBuildProperty: MSBuildPropertyCore + { + bool preserverCase; + string defaultValue; + + internal MSBuildProperty (MSBuildProject project, XmlElement elem): base (project, elem) + { + } + + public string Name { + get { return Element.Name; } + } + + public bool IsImported { + get; + set; + } + + internal bool Overwritten { get; set; } + + internal MSBuildPropertyGroup Owner { get; set; } + + public bool MergeToMainGroup { get; set; } + internal bool HasDefaultValue { get; set; } + + internal MergedProperty CreateMergedProperty () + { + return new MergedProperty (Name, preserverCase, HasDefaultValue); + } + + internal void SetDefaultValue (string value) + { + defaultValue = value; + } + + public void SetValue (string value, bool preserveCase = false, bool mergeToMainGroup = false) + { + MergeToMainGroup = mergeToMainGroup; + this.preserverCase = preserveCase; + + if (value == null) + value = String.Empty; + + if (preserveCase) { + var current = GetPropertyValue (); + if (current != null) { + if (current.Equals (value, preserveCase ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture)) + return; + } + } + SetPropertyValue (value); + } + + public void SetValue (FilePath value, bool relativeToProject = true, FilePath relativeToPath = default(FilePath), bool mergeToMainGroup = false) + { + MergeToMainGroup = mergeToMainGroup; + this.preserverCase = false; + + string baseDir = null; + if (relativeToPath != null) { + baseDir = relativeToPath; + } else if (relativeToProject) { + baseDir = Project.BaseDirectory; + } + SetPropertyValue (MSBuildProjectService.ToMSBuildPath (baseDir, value, false)); + } + + public void SetValue (object value, bool mergeToMainGroup = false) + { + if (value is bool) { + if (Owner != null && Owner.UppercaseBools) + SetValue ((bool)value ? "True" : "False", preserveCase: true, mergeToMainGroup: mergeToMainGroup); + else + SetValue ((bool)value ? "true" : "false", preserveCase: true, mergeToMainGroup: mergeToMainGroup); + } + else + SetValue (Convert.ToString (value, CultureInfo.InvariantCulture), false, mergeToMainGroup); + } + + void SetPropertyValue (string value) + { + Element.InnerText = value; + } + + internal override string GetPropertyValue () + { + return Element.InnerText; + } + + public override string UnevaluatedValue { + get { + return Value; + } + } + } + + class MSBuildPropertyEvaluated: MSBuildPropertyCore + { + string value; + string evaluatedValue; + + internal MSBuildPropertyEvaluated (MSBuildProject project, string name, string value, string evaluatedValue): base (project, null) + { + this.evaluatedValue = evaluatedValue; + this.value = value; + Name = name; + } + + public string Name { get; private set; } + + public bool IsImported { get; set; } + + public override string UnevaluatedValue { + get { return value; } + } + + internal override string GetPropertyValue () + { + return evaluatedValue; + } + } + + public abstract class MSBuildPropertyCore: MSBuildObject, IMSBuildPropertyEvaluated + { + MSBuildProject project; + + internal MSBuildPropertyCore (MSBuildProject project, XmlElement elem): base (elem) + { + this.project = project; + } + + public MSBuildProject Project { + get { return project; } + } + + public string Value { + get { return GetPropertyValue (); } + } + + public T GetValue<T> () + { + var val = GetPropertyValue (); + if (typeof(T) == typeof(bool)) + return (T) (object) val.Equals ("true", StringComparison.InvariantCultureIgnoreCase); + if (typeof(T).IsEnum) + return (T) Enum.Parse (typeof(T), val, true); + return (T) Convert.ChangeType (Value, typeof(T), CultureInfo.InvariantCulture); + } + + public object GetValue (Type t) + { + var val = GetPropertyValue (); + if (t == typeof(bool)) + return (object) val.Equals ("true", StringComparison.InvariantCultureIgnoreCase); + return Convert.ChangeType (Value, t, CultureInfo.InvariantCulture); + } + + public FilePath GetPathValue (bool relativeToProject = true, FilePath relativeToPath = default(FilePath)) + { + var val = GetPropertyValue (); + string baseDir = null; + + if (relativeToPath != null) { + baseDir = relativeToPath; + } else if (relativeToProject) { + baseDir = project.BaseDirectory; + } + return MSBuildProjectService.FromMSBuildPath (baseDir, val); + } + + public bool TryGetPathValue (out FilePath value, bool relativeToProject = true, FilePath relativeToPath = default(FilePath)) + { + var val = GetPropertyValue (); + string baseDir = null; + + if (relativeToPath != null) { + baseDir = relativeToPath; + } else if (relativeToProject) { + baseDir = project.BaseDirectory; + } + string path; + var res = MSBuildProjectService.FromMSBuildPath (baseDir, val, out path); + value = path; + return res; + } + + public abstract string UnevaluatedValue { get; } + + internal abstract string GetPropertyValue (); + } + + public interface IMSBuildPropertyEvaluated + { + MSBuildProject Project { get; } + + string Value { get; } + + string UnevaluatedValue { get; } + + T GetValue<T> (); + + object GetValue (Type t); + + FilePath GetPathValue (bool relativeToProject = true, FilePath relativeToPath = default(FilePath)); + + bool TryGetPathValue (out FilePath value, bool relativeToProject = true, FilePath relativeToPath = default(FilePath)); + } + + class MergedProperty + { + public readonly string Name; + public readonly bool IsDefault; + public readonly bool PreserveExistingCase; + + public MergedProperty (string name, bool preserveExistingCase, bool isDefault) + { + this.Name = name; + IsDefault = isDefault; + this.PreserveExistingCase = preserveExistingCase; + } + } +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildPropertyGroup.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildPropertyGroup.cs new file mode 100644 index 0000000000..2c7fb09bd5 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildPropertyGroup.cs @@ -0,0 +1,415 @@ +// +// MSBuildPropertyGroup.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Linq; +using System.Collections.Generic; +using System.Xml; + +using MonoDevelop.Core; +using System.Xml.Linq; +using Microsoft.Build.BuildEngine; + +namespace MonoDevelop.Projects.Formats.MSBuild +{ + public class MSBuildPropertyGroup: MSBuildObject, IMSBuildPropertySet, IMSBuildPropertyGroupEvaluated + { + Dictionary<string,MSBuildProperty> properties; + List<MSBuildProperty> propertyList = new List<MSBuildProperty> (); + MSBuildProject parent; + + public MSBuildPropertyGroup (MSBuildProject parent, XmlElement elem): base (elem) + { + this.parent = parent; + } + + void InitProperties () + { + if (properties != null) + return; + + properties = new Dictionary<string,MSBuildProperty> (); + propertyList = new List<MSBuildProperty> (); + + foreach (var pelem in Element.ChildNodes.OfType<XmlElement> ()) { + MSBuildProperty prevSameName; + if (properties.TryGetValue (pelem.Name, out prevSameName)) + prevSameName.Overwritten = true; + + var prop = new MSBuildProperty (parent, pelem); + prop.Owner = this; + propertyList.Add (prop); + properties [pelem.Name] = prop; // If a property is defined more than once, we only care about the last registered value + } + } + + public bool IsImported { + get; + set; + } + + public MSBuildProject Project { + get { + return this.parent; + } + } + + internal bool IgnoreDefaultValues { get; set; } + + internal bool UppercaseBools { get; set; } + + IMSBuildPropertyEvaluated IMSBuildPropertyGroupEvaluated.GetProperty (string name) + { + return GetProperty (name); + } + + public MSBuildProperty GetProperty (string name) + { + return GetProperty (name, null); + } + + public MSBuildProperty GetProperty (string name, string condition) + { + InitProperties (); + MSBuildProperty prop; + properties.TryGetValue (name, out prop); + return prop; + } + + public IEnumerable<MSBuildProperty> Properties { + get { + InitProperties (); + return propertyList.Where (p => !p.Overwritten); + } + } + + public string GetValue (string name, string defaultValue = null) + { + var prop = GetProperty (name); + if (prop != null) + return prop.Value; + else + return defaultValue; + } + + public FilePath GetPathValue (string name, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)) + { + var prop = GetProperty (name); + if (prop != null) + return prop.GetPathValue (relativeToProject, relativeToPath); + else + return defaultValue; + } + + public bool TryGetPathValue (string name, out FilePath value, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)) + { + var prop = GetProperty (name); + if (prop != null) + return prop.TryGetPathValue (out value, relativeToProject, relativeToPath); + else { + value = defaultValue; + return value != default(FilePath); + } + } + + public T GetValue<T> (string name) + { + var prop = GetProperty (name); + if (prop != null) + return prop.GetValue<T> (); + else + return default(T); + } + + public T GetValue<T> (string name, T defaultValue) + { + var prop = GetProperty (name); + if (prop != null) + return prop.GetValue<T> (); + else + return defaultValue; + } + + public object GetValue (string name, Type type, object defaultValue) + { + var prop = GetProperty (name); + if (prop != null) + return prop.GetValue (type); + else + return defaultValue; + } + + Dictionary<Type,object> customDataObjects = new Dictionary<Type, object> (); + + public T GetObject<T> () where T:IMSBuildDataObject, new() + { + object ob; + if (!customDataObjects.TryGetValue (typeof(T), out ob)) { + customDataObjects [typeof(T)] = ob = new T (); + ((IMSBuildDataObject)ob).Read (this, parent.Format); + } + return (T)ob; + } + + public void SetObject<T> (T t, bool persist = true) where T:IMSBuildDataObject + { + customDataObjects [typeof(T)] = t; + } + + public void WriteDataObjects () + { + foreach (IMSBuildDataObject ob in customDataObjects.Values) + ob.Write (this, parent.Format); + } + + MSBuildProperty AddProperty (string name, string condition = null) + { + InitProperties (); + int i = propertyOrder.IndexOf (name); + var pelem = Element.OwnerDocument.CreateElement (null, name, MSBuildProject.Schema); + int insertIndex = -1; + if (i != -1) { + var foundProp = FindExistingProperty (i - 1, -1); + if (foundProp != null) { + Element.InsertAfter (pelem, foundProp.Element); + insertIndex = propertyList.IndexOf (foundProp) + 1; + } else { + foundProp = FindExistingProperty (i + 1, 1); + if (foundProp != null) { + Element.InsertBefore (pelem, foundProp.Element); + insertIndex = propertyList.IndexOf (foundProp) - 1; + } + else + Element.AppendChild (pelem); + } + } else + Element.AppendChild (pelem); + + var prop = new MSBuildProperty (parent, pelem); + prop.Owner = this; + properties [name] = prop; + + if (insertIndex != -1) + propertyList.Insert (insertIndex, prop); + else + propertyList.Add (prop); + + if (condition != null) + prop.Condition = condition; + return prop; + } + + MSBuildProperty FindExistingProperty (int index, int inc) + { + while (index >= 0 && index < propertyOrder.Count) { + var ep = GetProperty (propertyOrder[index]); + if (ep != null) + return ep; + index += inc; + } + return null; + } + + MSBuildProperty SafeGetProperty (string name, string condition) + { + var prop = GetProperty (name, condition); + if (prop == null) { + prop = GetProperty (name); + if (prop != null) { + prop.Condition = condition; + return prop; + } + } + return AddProperty (name, condition); + } + + public void SetValue (string name, string value, string defaultValue = null, bool preserveExistingCase = false, bool mergeToMainGroup = false, string condition = null) + { + if (value == null && defaultValue == "") + value = ""; + var prop = GetProperty (name, condition); + var isDefault = value == defaultValue; + if (isDefault && !mergeToMainGroup && !IgnoreDefaultValues) { + // if the value is default, only remove the property if it was not already the default + // to avoid unnecessary project file churn + if (prop != null && (defaultValue == null || !string.Equals (defaultValue, prop.Value, preserveExistingCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal))) + RemoveProperty (prop); + return; + } + if (prop == null) + prop = AddProperty (name, condition); + prop.SetValue (value, preserveExistingCase, mergeToMainGroup); + prop.HasDefaultValue = isDefault; + } + + public void SetValue (string name, FilePath value, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath), bool mergeToMainGroup = false, string condition = null) + { + var prop = GetProperty (name, condition); + var isDefault = value.CanonicalPath == defaultValue.CanonicalPath; + if (isDefault && !mergeToMainGroup && !IgnoreDefaultValues) { + // if the value is default, only remove the property if it was not already the default + // to avoid unnecessary project file churn + if (prop != null && (defaultValue == null || defaultValue != prop.GetPathValue (relativeToProject, relativeToPath))) + RemoveProperty (prop); + return; + } + if (prop == null) + prop = AddProperty (name, condition); + prop.SetValue (value, relativeToProject, relativeToPath, mergeToMainGroup); + prop.HasDefaultValue = isDefault; + } + + public void SetValue (string name, object value, object defaultValue = null, bool mergeToMainGroup = false, string condition = null) + { + var prop = GetProperty (name, condition); + var isDefault = object.Equals (value, defaultValue); + if (isDefault && !mergeToMainGroup && !IgnoreDefaultValues) { + // if the value is default, only remove the property if it was not already the default + // to avoid unnecessary project file churn + if (prop != null && (defaultValue == null || !object.Equals (defaultValue, prop.GetValue (defaultValue.GetType ())))) + RemoveProperty (prop); + return; + } + if (prop == null) + prop = AddProperty (name, condition); + prop.SetValue (value, mergeToMainGroup); + prop.HasDefaultValue = isDefault; + } + + public bool RemoveProperty (string name) + { + MSBuildProperty prop = GetProperty (name); + if (prop != null) { + RemoveProperty (prop); + return true; + } + return false; + } + + public void RemoveProperty (MSBuildProperty prop) + { + InitProperties (); + properties.Remove (prop.Name); + propertyList.Remove (prop); + Element.RemoveChild (prop.Element); + } + + public void RemoveAllProperties () + { + InitProperties (); + List<XmlNode> toDelete = new List<XmlNode> (); + foreach (XmlNode node in Element.ChildNodes) { + if (node is XmlElement) + toDelete.Add (node); + } + foreach (XmlNode node in toDelete) + Element.RemoveChild (node); + properties.Clear (); + propertyList.Clear (); + } + + public void UnMerge (IMSBuildPropertySet baseGrp, ISet<string> propsToExclude) + { + HashSet<string> baseProps = new HashSet<string> (); + foreach (MSBuildProperty prop in baseGrp.Properties) { + if (propsToExclude != null && propsToExclude.Contains (prop.Name)) + continue; + baseProps.Add (prop.Name); + MSBuildProperty thisProp = GetProperty (prop.Name); + if (thisProp != null && prop.Value.Equals (thisProp.Value, StringComparison.OrdinalIgnoreCase)) + RemoveProperty (prop.Name); + } + + // Remove properties which have the default value and which are not defined in the main group + foreach (var p in Properties.ToArray ()) { + if (baseProps.Contains (p.Name)) + continue; + if (p.HasDefaultValue) + RemoveProperty (p); + } + } + + public override string ToString() + { + string s = "[MSBuildPropertyGroup:"; + foreach (MSBuildProperty prop in Properties) + s += " " + prop.Name + "=" + prop.Value; + return s + "]"; + } + + public void SetObject<T> (T t) where T : IMSBuildDataObject + { + throw new NotImplementedException (); + } + + public bool HasProperty (string name) + { + InitProperties (); + return properties.ContainsKey (name); + } + + List<string> propertyOrder = new List<string> (); + + public void SetPropertyOrder (params string[] propertyNames) + { + int i = 0; + foreach (var name in propertyNames) { + if (i < propertyOrder.Count) { + var pos = propertyOrder.IndexOf (name, i); + if (pos != -1) { + i = pos + 1; + continue; + } else { + propertyOrder.Insert (i, name); + i++; + continue; + } + } + propertyOrder.Add (name); + i++; + } + } + } + + public interface IMSBuildPropertyGroupEvaluated + { + bool HasProperty (string name); + + IMSBuildPropertyEvaluated GetProperty (string name); + + string GetValue (string name, string defaultValue = null); + + FilePath GetPathValue (string name, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)); + + bool TryGetPathValue (string name, out FilePath value, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)); + + T GetValue<T> (string name); + + T GetValue<T> (string name, T defaultValue); + + object GetValue (string name, Type type, object defaultValue); + } +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildPropertyGroupEvaluated.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildPropertyGroupEvaluated.cs new file mode 100644 index 0000000000..2ffc9d9d1b --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildPropertyGroupEvaluated.cs @@ -0,0 +1,155 @@ +// +// MSBuildPropertyGroupEvaluated.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using System.Xml.Linq; +using MonoDevelop.Core; +using Microsoft.Build.BuildEngine; +using MSProject = Microsoft.Build.BuildEngine.Project; + +namespace MonoDevelop.Projects.Formats.MSBuild +{ + class MSBuildPropertyGroupEvaluated: IMSBuildPropertyGroupEvaluated + { + internal Dictionary<string,MSBuildPropertyEvaluated> properties = new Dictionary<string, MSBuildPropertyEvaluated> (); + internal MSBuildProject parent; + BuildItem sourceItem; + + internal MSBuildPropertyGroupEvaluated (MSBuildProject parent) + { + this.parent = parent; + } + + internal void Sync (BuildItem item) + { + properties.Clear (); + sourceItem = item; + } + + public bool HasProperty (string name) + { + if (!properties.ContainsKey (name)) { + if (sourceItem != null) + return sourceItem.HasMetadata (name); + } + return false; + } + + public IMSBuildPropertyEvaluated GetProperty (string name) + { + MSBuildPropertyEvaluated prop; + if (!properties.TryGetValue (name, out prop)) { + if (sourceItem != null) { + if (sourceItem.HasMetadata (name)) { + prop = new MSBuildPropertyEvaluated (parent, name, sourceItem.GetMetadata (name), sourceItem.GetEvaluatedMetadata (name)); + properties [name] = prop; + } + } + } + return prop; + } + + public string GetValue (string name, string defaultValue = null) + { + var prop = GetProperty (name); + if (prop != null) + return prop.Value; + else + return defaultValue; + } + + public FilePath GetPathValue (string name, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)) + { + var prop = GetProperty (name); + if (prop != null) + return prop.GetPathValue (relativeToProject, relativeToPath); + else + return defaultValue; + } + + public bool TryGetPathValue (string name, out FilePath value, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)) + { + var prop = GetProperty (name); + if (prop != null) + return prop.TryGetPathValue (out value, relativeToProject, relativeToPath); + else { + value = defaultValue; + return value != default(FilePath); + } + } + + public T GetValue<T> (string name) + { + var prop = GetProperty (name); + if (prop != null) + return prop.GetValue<T> (); + else + return default(T); + } + + public T GetValue<T> (string name, T defaultValue) + { + var prop = GetProperty (name); + if (prop != null) + return prop.GetValue<T> (); + else + return defaultValue; + } + + public object GetValue (string name, Type type, object defaultValue) + { + var prop = GetProperty (name); + if (prop != null) + return prop.GetValue (type); + else + return defaultValue; + } + } + + class MSBuildEvaluatedPropertyCollection: MSBuildPropertyGroupEvaluated, IMSBuildEvaluatedPropertyCollection + { + public MSBuildEvaluatedPropertyCollection (MSBuildProject parent): base (parent) + { + } + + internal void Sync (BuildPropertyGroup msgroup) + { + properties.Clear (); + foreach (BuildProperty p in msgroup) + properties [p.Name] = new MSBuildPropertyEvaluated (parent, p.Name, p.Value, p.FinalValue); + } + + public IEnumerable<IMSBuildPropertyEvaluated> Properties { + get { return properties.Values; } + } + } + + public interface IMSBuildEvaluatedPropertyCollection: IMSBuildPropertyGroupEvaluated + { + IEnumerable<IMSBuildPropertyEvaluated> Properties { get; } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildPropertyGroupMerged.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildPropertyGroupMerged.cs new file mode 100644 index 0000000000..11117a97e6 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildPropertyGroupMerged.cs @@ -0,0 +1,234 @@ +// +// MSBuildPropertyGroupMerged.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Linq; +using System.Collections.Generic; +using System.Xml; + +using MonoDevelop.Core; +using System.Xml.Linq; + +namespace MonoDevelop.Projects.Formats.MSBuild +{ + + class MSBuildPropertyGroupMerged: IMSBuildPropertySet + { + List<IMSBuildPropertySet> groups = new List<IMSBuildPropertySet> (); + MSBuildFileFormat format; + + public MSBuildPropertyGroupMerged (MSBuildProject project, MSBuildFileFormat format) + { + this.format = format; + Project = project; + } + + public MSBuildProject Project { get; private set; } + + public string Label { get; set; } + + public void Add (IMSBuildPropertySet g) + { + groups.Add (g); + } + + public int GroupCount { + get { return groups.Count; } + } + + public MSBuildProperty GetProperty (string name) + { + // Find property in reverse order, since the last set + // value is the good one + for (int n=groups.Count - 1; n >= 0; n--) { + var g = groups [n]; + MSBuildProperty p = g.GetProperty (name); + if (p != null) + return p; + } + return null; + } + + public IMSBuildPropertySet GetGroupForProperty (string name) + { + // Find property in reverse order, since the last set + // value is the good one + for (int n=groups.Count - 1; n >= 1; n--) { + var g = groups [n]; + MSBuildProperty p = g.GetProperty (name); + if (p != null) + return g; + } + return groups[0]; + } + + Dictionary<Type,object> customDataObjects = new Dictionary<Type, object> (); + + public T GetObject<T> () where T:IMSBuildDataObject, new() + { + object ob; + if (!customDataObjects.TryGetValue (typeof(T), out ob)) { + customDataObjects [typeof(T)] = ob = new T (); + ((IMSBuildDataObject)ob).Read (this, format); + } + return (T)ob; + } + + public void SetObject<T> (T t, bool persist = true) where T:IMSBuildDataObject + { + customDataObjects [typeof(T)] = t; + } + + public void WriteDataObjects () + { + foreach (IMSBuildDataObject ob in customDataObjects.Values) + ob.Write (this, format); + } + + public void SetPropertyValue (string name, string value, bool preserveExistingCase) + { + MSBuildProperty p = GetProperty (name); + if (p != null) { + if (!preserveExistingCase || !string.Equals (value, p.Value, StringComparison.OrdinalIgnoreCase)) { + p.SetValue (value); + } + return; + } + groups [0].SetValue (name, value, preserveExistingCase:preserveExistingCase); + } + + public void SetValue (string name, string value, string defaultValue = null, bool preserveExistingCase = false, bool mergeToMainGroup = false, string condition = null) + { + GetGroupForProperty (name).SetValue (name, value, defaultValue, preserveExistingCase, mergeToMainGroup, condition); + } + + public void SetValue (string name, FilePath value, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath), bool mergeToMainGroup = false, string condition = null) + { + GetGroupForProperty (name).SetValue (name, value, defaultValue, relativeToProject, relativeToPath, mergeToMainGroup, condition); + } + + public void SetValue (string name, object value, object defaultValue = null, bool mergeToMainGroup = false, string condition = null) + { + GetGroupForProperty (name).SetValue (name, value, defaultValue, mergeToMainGroup, condition); + } + + public string GetValue (string name, string defaultValue = null) + { + return GetGroupForProperty (name).GetValue (name, defaultValue); + } + + public string GetPathValue (string name, FilePath defaultValue = default(FilePath), bool relativeToFile = true) + { + return GetGroupForProperty (name).GetPathValue (name, defaultValue, relativeToFile); + } + + public T GetValue<T> (string name) + { + return GetGroupForProperty (name).GetValue<T> (name); + } + + public T GetValue<T> (string name, T defaultValue) + { + return GetGroupForProperty (name).GetValue<T> (name, defaultValue); + } + + public object GetValue (string name, Type type, object defaultValue) + { + return GetGroupForProperty (name).GetValue (name, type, defaultValue); + } + + public bool RemoveProperty (string name) + { + bool found = false; + foreach (var g in groups) { + if (g.RemoveProperty (name)) { + Prune ((MSBuildPropertyGroup)g); + found = true; + } + } + return found; + } + + public void RemoveAllProperties () + { + foreach (var g in groups) { + g.RemoveAllProperties (); + Prune ((MSBuildPropertyGroup)g); + } + } + + public void UnMerge (IMSBuildPropertySet baseGrp, ISet<string> propertiesToExclude) + { + foreach (var g in groups) { + ((MSBuildPropertyGroup)g).UnMerge (baseGrp, propertiesToExclude); + } + } + + public IEnumerable<MSBuildProperty> Properties { + get { + foreach (var g in groups) { + foreach (var p in g.Properties) + yield return p; + } + } + } + + void Prune (MSBuildPropertyGroup g) + { + if (g != groups [0] && !g.Properties.Any()) { + // Remove this group since it's now empty + g.Project.RemoveGroup (g); + } + } + + public void SetObject<T> (T t) where T : IMSBuildDataObject + { + throw new NotImplementedException (); + } + + public bool HasProperty (string name) + { + throw new NotImplementedException (); + } + + public FilePath GetPathValue (string name, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)) + { + return GetGroupForProperty (name).GetPathValue (name, defaultValue, relativeToProject, relativeToPath); + } + + public bool TryGetPathValue (string name, out FilePath value, FilePath defaultValue = default(FilePath), bool relativeToProject = true, FilePath relativeToPath = default(FilePath)) + { + return GetGroupForProperty (name).TryGetPathValue (name, out value, defaultValue, relativeToProject, relativeToPath); + } + + public void SetPropertyOrder (params string[] propertyNames) + { + foreach (var g in groups) + g.SetPropertyOrder (propertyNames); + } + } + +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/RemoteProjectBuilder.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/RemoteProjectBuilder.cs index e5d99fb724..d2cefb444b 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/RemoteProjectBuilder.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/RemoteProjectBuilder.cs @@ -30,6 +30,9 @@ using System.Globalization; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using MonoDevelop.Core; +using System.IO; +using System.Linq; namespace MonoDevelop.Projects.Formats.MSBuild { @@ -37,6 +40,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild { IBuildEngine engine; Process proc; + bool alive = true; public int ReferenceCount { get; set; } public DateTime ReleaseTime { get; set; } @@ -47,36 +51,92 @@ namespace MonoDevelop.Projects.Formats.MSBuild this.engine = engine; } + public event EventHandler Disconnected; + public IProjectBuilder LoadProject (string projectFile) { - return engine.LoadProject (projectFile); + try { + return engine.LoadProject (projectFile); + } catch { + CheckDisconnected (); + throw; + } } public void UnloadProject (IProjectBuilder pb) { - engine.UnloadProject (pb); + try { + engine.UnloadProject (pb); + } catch (Exception ex) { + LoggingService.LogError ("Project unloading failed", ex); + if (!CheckDisconnected ()) + throw; + } } public void SetCulture (CultureInfo uiCulture) { - engine.SetCulture (uiCulture); + try { + engine.SetCulture (uiCulture); + } catch { + CheckDisconnected (); + throw; + } } public void SetGlobalProperties (IDictionary<string, string> properties) { - engine.SetGlobalProperties (properties); + try { + engine.SetGlobalProperties (properties); + } catch { + CheckDisconnected (); + throw; + } + } + + void IBuildEngine.Ping () + { + engine.Ping (); } - + + bool CheckAlive () + { + if (!alive) + return false; + try { + engine.Ping (); + return true; + } catch { + alive = false; + return false; + } + } + + internal bool CheckDisconnected () + { + if (!CheckAlive ()) { + if (Disconnected != null) + Disconnected (this, EventArgs.Empty); + return true; + } + return false; + } + public void Dispose () { - if (proc != null) { - try { - proc.Kill (); - } catch { + try { + alive = false; + if (proc != null) { + try { + proc.Kill (); + } catch { + } } + else + engine.Dispose (); + } catch { + // Ignore } - else - engine.Dispose (); } } @@ -84,11 +144,25 @@ namespace MonoDevelop.Projects.Formats.MSBuild { RemoteBuildEngine engine; IProjectBuilder builder; - + Dictionary<string,string[]> referenceCache; + string file; + internal RemoteProjectBuilder (string file, RemoteBuildEngine engine) { + this.file = file; this.engine = engine; builder = engine.LoadProject (file); + referenceCache = new Dictionary<string, string[]> (); + } + + public event EventHandler Disconnected; + + void CheckDisconnected () + { + if (engine.CheckDisconnected ()) { + if (Disconnected != null) + Disconnected (this, EventArgs.Empty); + } } public MSBuildResult Run ( @@ -99,17 +173,70 @@ namespace MonoDevelop.Projects.Formats.MSBuild string[] evaluateItems, string[] evaluateProperties) { - return builder.Run (configurations, logWriter, verbosity, runTargets, evaluateItems, evaluateProperties); + try { + return builder.Run (configurations, logWriter, verbosity, runTargets, evaluateItems, evaluateProperties); + } catch (Exception ex) { + CheckDisconnected (); + LoggingService.LogError ("RunTarget failed", ex); + MSBuildTargetResult err = new MSBuildTargetResult (file, false, "", "", file, 1, 1, 1, 1, "Unknown MSBuild failure. Please try building the project again", ""); + MSBuildResult res = new MSBuildResult (new [] { err }); + return res; + } } - + + public string[] ResolveAssemblyReferences (ProjectConfigurationInfo[] configurations) + { + string[] refs = null; + var id = configurations [0].Configuration + "|" + configurations [0].Platform; + + lock (referenceCache) { + if (!referenceCache.TryGetValue (id, out refs)) { + MSBuildResult result; + try { + result = builder.Run ( + configurations, null, MSBuildVerbosity.Normal, + new[] { "ResolveAssemblyReferences" }, new [] { "ReferencePath" }, null + ); + } catch (Exception ex) { + CheckDisconnected (); + LoggingService.LogError ("ResolveAssemblyReferences failed", ex); + return new string[0]; + } + + List<MSBuildEvaluatedItem> items; + if (result.Items.TryGetValue ("ReferencePath", out items) && items != null) { + refs = items.Select (i => i.ItemSpec).ToArray (); + } else + refs = new string[0]; + + referenceCache [id] = refs; + } + } + return refs; + } + public void Refresh () { - builder.Refresh (); + lock (referenceCache) + referenceCache.Clear (); + try { + builder.Refresh (); + } catch (Exception ex) { + LoggingService.LogError ("MSBuild refresh failed", ex); + CheckDisconnected (); + } } public void RefreshWithContent (string projectContent) { - builder.RefreshWithContent (projectContent); + lock (referenceCache) + referenceCache.Clear (); + try { + builder.RefreshWithContent (projectContent); + } catch (Exception ex) { + LoggingService.LogError ("MSBuild refresh failed", ex); + CheckDisconnected (); + } } public void Dispose () diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnData.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnData.cs deleted file mode 100644 index 9f602a5dff..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnData.cs +++ /dev/null @@ -1,141 +0,0 @@ -// -// SlnData.cs -// -// Author: -// Ankit Jain <jankit@novell.com> -// -// Copyright (C) 2006 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using MonoDevelop.Projects; - -using System; -using System.Collections.Generic; - -namespace MonoDevelop.Projects.Formats.MSBuild -{ - class SlnData - { - string headerComment = "# MonoDevelop"; - Dictionary<SolutionConfiguration, string> configStrings; - List<string> globalExtra; // unused GlobalSections - Dictionary<string, List<string>> sectionExtras; - string[] extra; //used by solution folders.. - List<string> unknownProjects; - Dictionary<string, SolutionEntityItem> projectsByGuidTable; - - public void UpdateVersion (MSBuildFileFormat format) - { - VersionString = format.SlnVersion; - headerComment = "# " + format.ProductDescription; - } - - // Eg. "# Visual C# Express 2008" - public string HeaderComment { - get { return headerComment; } - set { headerComment = value; } - } - - // Eg. 9.00 or 10.00 - public string VersionString { get; set; } - - public Version VisualStudioVersion { get; set; } - - public Version MinimumVisualStudioVersion { get; set; } - - public Dictionary<SolutionConfiguration, string> ConfigStrings { - get { - if (configStrings == null) - configStrings = new Dictionary<SolutionConfiguration, string> (); - return configStrings; - } - } - - public List<string> GlobalExtra { - get { return globalExtra; } - set { globalExtra = value; } - } - - public string[] Extra { - get { return extra; } - set { extra = value; } - } - - public List<string> UnknownProjects { - get { - if (unknownProjects == null) - unknownProjects = new List<string> (); - return unknownProjects; - } - } - - //Extra lines per section which need to be preserved - //eg. lines in ProjectConfigurationPlatforms for projects - //that we couldn't load - public Dictionary<string, List<string>> SectionExtras { - get { - if (sectionExtras == null) - sectionExtras = new Dictionary<string, List<string>> (); - return sectionExtras; - } - } - - public Dictionary<string, SolutionEntityItem> ItemsByGuid { - get { - if (projectsByGuidTable == null) - projectsByGuidTable = new Dictionary<string, SolutionEntityItem> (); - return projectsByGuidTable; - } - } - - } - - class ItemSlnData - { - List<string> configLines; - - public List<string> ConfigLines { - get { - if (configLines == null) - configLines = new List<string> (); - return configLines; - } - } - - public static ItemSlnData ForItem (SolutionItem item) - { - ItemSlnData data = (ItemSlnData) item.ExtendedProperties [typeof(ItemSlnData)]; - if (data == null) { - data = new ItemSlnData (); - item.ExtendedProperties [typeof(ItemSlnData)] = data; - } - return data; - } - - public static void TransferData (SolutionItem source, SolutionItem target) - { - ItemSlnData data = (ItemSlnData) source.ExtendedProperties [typeof(ItemSlnData)]; - if (data != null) - target.ExtendedProperties [typeof(ItemSlnData)] = data; - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFile.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFile.cs new file mode 100644 index 0000000000..ba9c875b75 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFile.cs @@ -0,0 +1,581 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.IO; +using System.Collections; +using MonoDevelop.Core; + +namespace MonoDevelop.Projects.Formats.MSBuild +{ + public class SlnFile + { + SlnProjectCollection projects = new SlnProjectCollection (); + SlnSectionCollection sections = new SlnSectionCollection (); + SlnPropertySet metadata = new SlnPropertySet (true); + + public string FormatVersion { get; set; } + public string ProductDescription { get; set; } + + public string VisualStudioVersion { + get { return metadata.GetValue ("VisualStudioVersion"); } + set { metadata.SetValue ("VisualStudioVersion", value); } + } + + public string MinimumVisualStudioVersion { + get { return metadata.GetValue ("MinimumVisualStudioVersion"); } + set { metadata.SetValue ("MinimumVisualStudioVersion", value); } + } + + public SlnFile () + { + } + + /// <summary> + /// The directory to be used as base for converting absolute paths to relative + /// </summary> + public FilePath BaseDirectory { + get; + set; + } + + public SlnPropertySet SolutionConfigurationsSection { + get { return sections.GetOrCreateSection ("SolutionConfigurationPlatforms", "preSolution").Properties; } + } + + public SlnPropertySetCollection ProjectConfigurationsSection { + get { return sections.GetOrCreateSection ("ProjectConfigurationPlatforms", "postSolution").NestedPropertySets; } + } + + public SlnSectionCollection Sections { + get { return sections; } + } + + public SlnProjectCollection Projects { + get { return projects; } + } + + public void Read (string file) + { + using (var sr = new StreamReader (file)) + Read (sr); + } + + public void Read (TextReader reader) + { + string line; + int curLineNum = 0; + bool globalFound = false; + bool productRead = false; + + while ((line = reader.ReadLine ()) != null) { + curLineNum++; + line = line.Trim (); + if (line.StartsWith ("Microsoft Visual Studio Solution File")) { + int i = line.LastIndexOf (' '); + if (i == -1) + throw new InvalidSolutionFormatException (curLineNum); + FormatVersion = line.Substring (i + 1); + } + if (line.StartsWith ("# ")) { + if (!productRead) { + productRead = true; + ProductDescription = line.Substring (2); + } + } else if (line.StartsWith ("Project")) { + SlnProject p = new SlnProject (); + p.Read (reader, line, ref curLineNum); + projects.Add (p); + } else if (line == "Global") { + if (globalFound) + throw new InvalidSolutionFormatException (curLineNum, "Global section specified more than once"); + globalFound = true; + while ((line = reader.ReadLine ()) != null) { + curLineNum++; + line = line.Trim (); + if (line == "EndGlobal") { + break; + } else if (line.StartsWith ("GlobalSection")) { + var sec = new SlnSection (); + sec.Read (reader, line, ref curLineNum); + sections.Add (sec); + } else + throw new InvalidSolutionFormatException (curLineNum); + } + if (line == null) + throw new InvalidSolutionFormatException (curLineNum, "Global section not closed"); + } else if (line.IndexOf ('=') != -1) { + metadata.ReadLine (line, curLineNum); + } + } + if (FormatVersion == null) + throw new InvalidSolutionFormatException (curLineNum, "File header is missing"); + } + + public void Write (string file) + { + using (var sw = new StreamWriter (file)) + Write (sw); + } + + public void Write (TextWriter writer) + { + writer.NewLine = "\r\n"; + writer.WriteLine ("\r\nMicrosoft Visual Studio Solution File, Format Version " + FormatVersion); + writer.WriteLine ("# " + ProductDescription); + + metadata.Write (writer); + + foreach (var p in projects) + p.Write (writer); + + writer.WriteLine ("Global"); + foreach (SlnSection s in sections) + s.Write (writer, "GlobalSection"); + writer.WriteLine ("EndGlobal"); + } + } + + public class SlnProject + { + SlnSectionCollection sections = new SlnSectionCollection (); + + public string Id { get; set; } + public string TypeGuid { get; set; } + public string Name { get; set; } + public string FilePath { get; set; } + public int Line { get; private set; } + internal bool Processed { get; set; } + + public SlnSectionCollection Sections { + get { return sections; } + } + + internal void Read (TextReader reader, string line, ref int curLineNum) + { + Line = curLineNum; + + int n = 0; + FindNext (curLineNum, line, ref n, '('); + n++; + FindNext (curLineNum, line, ref n, '"'); + int n2 = n + 1; + FindNext (curLineNum, line, ref n2, '"'); + TypeGuid = line.Substring (n + 1, n2 - n - 1); + + n = n2 + 1; + FindNext (curLineNum, line, ref n, ')'); + FindNext (curLineNum, line, ref n, '='); + + FindNext (curLineNum, line, ref n, '"'); + n2 = n + 1; + FindNext (curLineNum, line, ref n2, '"'); + Name = line.Substring (n + 1, n2 - n - 1); + + n = n2 + 1; + FindNext (curLineNum, line, ref n, ','); + FindNext (curLineNum, line, ref n, '"'); + n2 = n + 1; + FindNext (curLineNum, line, ref n2, '"'); + FilePath = line.Substring (n + 1, n2 - n - 1); + + n = n2 + 1; + FindNext (curLineNum, line, ref n, ','); + FindNext (curLineNum, line, ref n, '"'); + n2 = n + 1; + FindNext (curLineNum, line, ref n2, '"'); + Id = line.Substring (n + 1, n2 - n - 1); + + while ((line = reader.ReadLine ()) != null) { + curLineNum++; + line = line.Trim (); + if (line == "EndProject") { + return; + } + if (line.StartsWith ("ProjectSection")) { + if (sections == null) + sections = new SlnSectionCollection (); + var sec = new SlnSection (); + sections.Add (sec); + sec.Read (reader, line, ref curLineNum); + } + } + + throw new InvalidSolutionFormatException (curLineNum, "Project section not closed"); + } + + void FindNext (int ln, string line, ref int i, char c) + { + i = line.IndexOf (c, i); + if (i == -1) + throw new InvalidSolutionFormatException (ln); + } + + public void Write (TextWriter writer) + { + writer.Write ("Project(\""); + writer.Write (TypeGuid); + writer.Write ("\") = \""); + writer.Write (Name); + writer.Write ("\", \""); + writer.Write (FilePath); + writer.Write ("\", \""); + writer.Write (Id); + writer.WriteLine ("\""); + if (sections != null) { + foreach (SlnSection s in sections) + s.Write (writer, "ProjectSection"); + } + writer.WriteLine ("EndProject"); + } + } + + public class SlnSection + { + SlnPropertySetCollection nestedPropertySets; + SlnPropertySet properties; + List<string> sectionLines; + int baseIndex; + + public string Id { get; set; } + public int Line { get; private set; } + internal bool Processed { get; set; } + + public SlnPropertySet Properties { + get { + if (properties == null) { + properties = new SlnPropertySet (); + if (sectionLines != null) { + foreach (var line in sectionLines) + properties.ReadLine (line, Line); + sectionLines = null; + } + } + return properties; + } + } + + public SlnPropertySetCollection NestedPropertySets { + get { + if (nestedPropertySets == null) { + nestedPropertySets = new SlnPropertySetCollection (); + if (sectionLines != null) + LoadPropertySets (); + } + return nestedPropertySets; + } + } + + public string SectionType { get; set; } + + internal void Read (TextReader reader, string line, ref int curLineNum) + { + Line = curLineNum; + int k = line.IndexOf ('('); + if (k == -1) + throw new InvalidSolutionFormatException (curLineNum, "Section id missing"); + var tag = line.Substring (0, k).Trim (); + var k2 = line.IndexOf (')', k); + if (k2 == -1) + throw new InvalidSolutionFormatException (curLineNum); + Id = line.Substring (k + 1, k2 - k - 1); + + k = line.IndexOf ('=', k2); + SectionType = line.Substring (k + 1).Trim (); + + var endTag = "End" + tag; + + sectionLines = new List<string> (); + baseIndex = ++curLineNum; + while ((line = reader.ReadLine()) != null) { + curLineNum++; + line = line.Trim (); + if (line == endTag) + break; + sectionLines.Add (line); + } + if (line == null) + throw new InvalidSolutionFormatException (curLineNum, "Closing section tag not found"); + } + + void LoadPropertySets () + { + if (sectionLines != null) { + SlnPropertySet curSet = null; + for (int n = 0; n < sectionLines.Count; n++) { + var line = sectionLines [n]; + var i = line.IndexOf ('.'); + if (i == -1) + throw new InvalidSolutionFormatException (baseIndex + i); + var id = line.Substring (0, i); + if (curSet == null || id != curSet.Id) { + curSet = new SlnPropertySet (id); + nestedPropertySets.Add (curSet); + } + curSet.ReadLine (line.Substring (i + 1), baseIndex + i); + } + sectionLines = null; + } + } + + internal void Write (TextWriter writer, string sectionTag) + { + writer.Write ("\t"); + writer.Write (sectionTag); + writer.Write ('('); + writer.Write (Id); + writer.Write (") = "); + writer.WriteLine (SectionType); + if (sectionLines != null) { + foreach (var l in sectionLines) + writer.WriteLine ("\t\t" + l); + } else if (properties != null) + properties.Write (writer); + else if (nestedPropertySets != null) { + foreach (var ps in nestedPropertySets) + ps.Write (writer); + } + writer.WriteLine ("\tEnd" + sectionTag); + } + } + + public class SlnPropertySet: IDictionary<string,string> + { + OrderedDictionary values = new OrderedDictionary (); + bool isMetadata; + + internal bool Processed { get; set; } + public int Line { get; private set; } + + public SlnPropertySet () + { + } + + public SlnPropertySet (string id) + { + Id = id; + } + + internal SlnPropertySet (bool isMetadata) + { + this.isMetadata = isMetadata; + } + + internal void ReadLine (string line, int currentLine) + { + if (Line == 0) + Line = currentLine; + line = line.Trim (); + int k = line.IndexOf ('='); + if (k != -1) { + var name = line.Substring (0, k).Trim (); + var val = line.Substring (k + 1).Trim (); + values.Add (name, val); + } else { + values.Add (line, null); + } + } + + internal void Write (TextWriter writer) + { + foreach (DictionaryEntry e in values) { + if (!isMetadata) + writer.Write ("\t\t"); + if (Id != null) + writer.Write (Id + "."); + writer.WriteLine (e.Key + " = " + e.Value); + } + } + + public string Id { get; private set; } + + public string GetValue (string key) + { + return (string) values [key]; + } + + public void SetValue (string key, string value) + { + values [key] = value; + } + + public void Add (string key, string value) + { + SetValue (key, value); + } + + public bool ContainsKey (string key) + { + return values.Contains (key); + } + + public bool Remove (string key) + { + var wasThere = values.Contains (key); + values.Remove (key); + return wasThere; + } + + public bool TryGetValue (string key, out string value) + { + value = (string) values [key]; + return value != null; + } + + public string this [string index] { + get { + return (string) values [index]; + } + set { + values [index] = value; + } + } + + public ICollection<string> Values { + get { + return values.Values.Cast<string>().ToList (); + } + } + + public ICollection<string> Keys { + get { return values.Keys.Cast<string> ().ToList (); } + } + + public void Add (KeyValuePair<string, string> item) + { + SetValue (item.Key, item.Value); + } + + public void Clear () + { + values.Clear (); + } + + internal void ClearExcept (HashSet<string> keys) + { + foreach (var k in values.Keys.Cast<string>().Except (keys).ToArray ()) + values.Remove (k); + } + + public bool Contains (KeyValuePair<string, string> item) + { + var val = GetValue (item.Key); + return val == item.Value; + } + + public void CopyTo (KeyValuePair<string, string>[] array, int arrayIndex) + { + foreach (DictionaryEntry de in values) + array [arrayIndex++] = new KeyValuePair<string, string> ((string)de.Key, (string)de.Value); + } + + public bool Remove (KeyValuePair<string, string> item) + { + if (Contains (item)) { + Remove (item.Key); + return true; + } else + return false; + } + + public int Count { + get { + return values.Count; + } + } + + public bool IsReadOnly { + get { + return false; + } + } + + public IEnumerator<KeyValuePair<string, string>> GetEnumerator () + { + foreach (DictionaryEntry de in values) + yield return new KeyValuePair<string,string> ((string)de.Key, (string)de.Value); + } + + IEnumerator IEnumerable.GetEnumerator () + { + foreach (DictionaryEntry de in values) + yield return new KeyValuePair<string,string> ((string)de.Key, (string)de.Value); + } + } + + public class SlnProjectCollection: Collection<SlnProject> + { + public SlnProject GetProject (string id) + { + return this.FirstOrDefault (s => s.Id == id); + } + + public SlnProject GetOrCreateProject (string id) + { + var p = this.FirstOrDefault (s => s.Id.Equals (id, StringComparison.OrdinalIgnoreCase)); + if (p == null) { + p = new SlnProject { Id = id }; + Add (p); + } + return p; + } + } + + public class SlnSectionCollection: Collection<SlnSection> + { + public SlnSection GetSection (string id) + { + return this.FirstOrDefault (s => s.Id == id); + } + + public SlnSection GetOrCreateSection (string id, string sectionType) + { + var sec = this.FirstOrDefault (s => s.Id == id); + if (sec == null) { + sec = new SlnSection { Id = id }; + sec.SectionType = sectionType; + Add (sec); + } + return sec; + } + + public void RemoveSection (string id) + { + var s = GetSection (id); + if (s != null) + Remove (s); + } + } + + public class SlnPropertySetCollection: Collection<SlnPropertySet> + { + public SlnPropertySet GetPropertySet (string id, bool ignoreCase = false) + { + var sc = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; + return this.FirstOrDefault (s => s.Id.Equals (id, sc)); + } + + public SlnPropertySet GetOrCreatePropertySet (string id, bool ignoreCase = false) + { + var ps = GetPropertySet (id, ignoreCase); + if (ps == null) { + ps = new SlnPropertySet (id); + Add (ps); + } + return ps; + } + } + + class InvalidSolutionFormatException: Exception + { + public InvalidSolutionFormatException (int line): base ("Invalid format in line " + line) + { + } + + public InvalidSolutionFormatException (int line, string msg): base ("Invalid format in line " + line + ": " + msg) + { + } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs index 27baad33c5..f1f4fb5522 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs @@ -27,10 +27,7 @@ // using System; -using System.Collections; using System.Collections.Generic; -using System.Collections.Specialized; -using System.Globalization; using System.IO; using System.Text; using System.Text.RegularExpressions; @@ -41,11 +38,19 @@ using MonoDevelop.Projects.Extensions; using MonoDevelop.Core; using System.Reflection; using System.Linq; +using System.Threading.Tasks; namespace MonoDevelop.Projects.Formats.MSBuild { - public class SlnFileFormat + class SlnFileFormat { + MSBuildFileFormat format; + + public SlnFileFormat (MSBuildFileFormat format) + { + this.format = format; + } + public string GetValidFormatName (object obj, string fileName, MSBuildFileFormat format) { return Path.ChangeExtension (fileName, ".sln"); @@ -71,372 +76,299 @@ namespace MonoDevelop.Projects.Formats.MSBuild return null; } - public void WriteFile (string file, object obj, MSBuildFileFormat format, bool saveProjects, IProgressMonitor monitor) + public Task WriteFile (string file, object obj, bool saveProjects, ProgressMonitor monitor) { - Solution sol = (Solution) obj; + return Task.Factory.StartNew (delegate { + Solution sol = (Solution)obj; - string tmpfilename = String.Empty; - try { - monitor.BeginTask (GettextCatalog.GetString ("Saving solution: {0}", file), 1); + string tmpfilename = String.Empty; try { - if (File.Exists (file)) - tmpfilename = Path.GetTempFileName (); - } catch (IOException) { - } + monitor.BeginTask (GettextCatalog.GetString ("Saving solution: {0}", file), 1); + try { + if (File.Exists (file)) + tmpfilename = Path.GetTempFileName (); + } catch (IOException) { + } - string baseDir = Path.GetDirectoryName (file); - if (tmpfilename == String.Empty) { - WriteFileInternal (file, sol, baseDir, format, saveProjects, monitor); - } else { - WriteFileInternal (tmpfilename, sol, baseDir, format, saveProjects, monitor); - File.Delete (file); - File.Move (tmpfilename, file); + if (tmpfilename == String.Empty) { + WriteFileInternal (file, file, sol, saveProjects, monitor); + } else { + WriteFileInternal (tmpfilename, file, sol, saveProjects, monitor); + File.Delete (file); + File.Move (tmpfilename, file); + } + } catch (Exception ex) { + monitor.ReportError (GettextCatalog.GetString ("Could not save solution: {0}", file), ex); + LoggingService.LogError (GettextCatalog.GetString ("Could not save solution: {0}", file), ex); + + if (!String.IsNullOrEmpty (tmpfilename)) + File.Delete (tmpfilename); + throw; + } finally { + monitor.EndTask (); } - } catch (Exception ex) { - monitor.ReportError (GettextCatalog.GetString ("Could not save solution: {0}", file), ex); - LoggingService.LogError (GettextCatalog.GetString ("Could not save solution: {0}", file), ex); - - if (!String.IsNullOrEmpty (tmpfilename)) - File.Delete (tmpfilename); - throw; - } finally { - monitor.EndTask (); - } + }); } - void WriteFileInternal (string file, Solution solution, string baseDir, MSBuildFileFormat format, bool saveProjects, IProgressMonitor monitor) + void WriteFileInternal (string file, string sourceFile, Solution solution, bool saveProjects, ProgressMonitor monitor) { - SolutionFolder c = solution.RootFolder; - - using (StreamWriter sw = new StreamWriter (file, false, Encoding.UTF8)) { - sw.NewLine = "\r\n"; - - SlnData slnData = GetSlnData (c); - if (slnData == null) { - // If a non-msbuild project is being converted by just - // changing the fileformat, then create the SlnData for it - slnData = new SlnData (); - c.ExtendedProperties [typeof (SlnFileFormat)] = slnData; + string baseDir = Path.GetDirectoryName (sourceFile); + + if (saveProjects) { + var items = solution.GetAllSolutionItems ().ToArray (); + monitor.BeginTask (items.Length + 1); + foreach (var item in items) { + try { + monitor.BeginStep (); + item.SavingSolution = true; + item.Save (monitor); + } finally { + item.SavingSolution = false; + } } + } else { + monitor.BeginTask (1); + monitor.BeginStep (); + } - slnData.UpdateVersion (format); - - sw.WriteLine (); - - //Write Header - sw.WriteLine ("Microsoft Visual Studio Solution File, Format Version " + slnData.VersionString); - sw.WriteLine (slnData.HeaderComment); - if (slnData.VisualStudioVersion != null) - sw.WriteLine ("VisualStudioVersion = {0}", slnData.VisualStudioVersion); - if (slnData.MinimumVisualStudioVersion != null) - sw.WriteLine ("MinimumVisualStudioVersion = {0}", slnData.MinimumVisualStudioVersion); - - //Write the projects - monitor.BeginTask (GettextCatalog.GetString ("Saving projects"), 1); - WriteProjects (c, baseDir, sw, saveProjects, monitor); - monitor.EndTask (); + SlnFile sln = new SlnFile (); + sln.BaseDirectory = baseDir; + if (File.Exists (sourceFile)) { + try { + sln.Read (sourceFile); + } catch (Exception ex) { + LoggingService.LogError ("Existing solution can't be updated since it can't be read", ex); + } + } - //Write the lines for unknownProjects - foreach (string l in slnData.UnknownProjects) - sw.WriteLine (l); + sln.FormatVersion = format.SlnVersion; + sln.ProductDescription = format.ProductDescription; - //Write the Globals - sw.WriteLine ("Global"); + solution.WriteSolution (monitor, sln); - //Write SolutionConfigurationPlatforms - //FIXME: SolutionConfigurations? - sw.WriteLine ("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution"); + sln.Write (file); + monitor.EndTask (); + } - foreach (SolutionConfiguration config in solution.Configurations) - sw.WriteLine ("\t\t{0} = {0}", ToSlnConfigurationId (config)); + internal void WriteFileInternal (SlnFile sln, Solution solution, ProgressMonitor monitor) + { + SolutionFolder c = solution.RootFolder; - sw.WriteLine ("\tEndGlobalSection"); + // Delete data for projects that have been removed from the solution + + var currentProjects = new HashSet<string> (solution.GetAllItems<SolutionFolderItem> ().Select (it => it.ItemId)); + var removedProjects = new HashSet<string> (); + if (solution.LoadedProjects != null) + removedProjects.UnionWith (solution.LoadedProjects.Except (currentProjects)); + var unknownProjects = new HashSet<string> (sln.Projects.Select (p => p.Id).Except (removedProjects).Except (currentProjects)); + + foreach (var p in removedProjects) { + var ps = sln.Projects.GetProject (p); + if (ps != null) + sln.Projects.Remove (ps); + var pc = sln.ProjectConfigurationsSection.GetPropertySet (p, true); + if (pc != null) + sln.ProjectConfigurationsSection.Remove (pc); + } + var secNested = sln.Sections.GetSection ("NestedProjects"); + if (secNested != null) { + foreach (var np in secNested.Properties.ToArray ()) { + if (removedProjects.Contains (np.Key) || removedProjects.Contains (np.Value)) + secNested.Properties.Remove (np.Key); + } + } + solution.LoadedProjects = currentProjects; - //Write ProjectConfigurationPlatforms - sw.WriteLine ("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"); + //Write the projects + using (monitor.BeginTask (GettextCatalog.GetString ("Saving projects"), 1)) { + monitor.BeginStep (); + WriteProjects (c, sln, monitor, unknownProjects); + } - List<string> list = new List<string> (); - WriteProjectConfigurations (solution, list); + //FIXME: SolutionConfigurations? - list.Sort (StringComparer.Create (CultureInfo.InvariantCulture, true)); - foreach (string s in list) - sw.WriteLine (s); + var pset = sln.SolutionConfigurationsSection; + foreach (SolutionConfiguration config in solution.Configurations) { + var cid = ToSlnConfigurationId (config); + pset.SetValue (cid, cid); + } - //Write lines for projects we couldn't load - if (slnData.SectionExtras.ContainsKey ("ProjectConfigurationPlatforms")) { - foreach (string s in slnData.SectionExtras ["ProjectConfigurationPlatforms"]) - sw.WriteLine ("\t\t{0}", s); - } + WriteProjectConfigurations (solution, sln); - sw.WriteLine ("\tEndGlobalSection"); - - //Write Nested Projects - ICollection<SolutionFolder> folders = solution.RootFolder.GetAllItems<SolutionFolder> (); - if (folders.Count > 1) { - // If folders ==1, that's the root folder - sw.WriteLine ("\tGlobalSection(NestedProjects) = preSolution"); - foreach (SolutionFolder folder in folders) { - if (folder.IsRoot) - continue; - WriteNestedProjects (folder, solution.RootFolder, sw); - } - sw.WriteLine ("\tEndGlobalSection"); + //Write Nested Projects + ICollection<SolutionFolder> folders = solution.RootFolder.GetAllItems<SolutionFolder> ().ToList (); + if (folders.Count > 1) { + // If folders ==1, that's the root folder + var sec = sln.Sections.GetOrCreateSection ("NestedProjects", "preSolution"); + foreach (SolutionFolder folder in folders) { + if (folder.IsRoot) + continue; + WriteNestedProjects (folder, solution.RootFolder, sec); } - - //Write custom properties - MSBuildSerializer ser = new MSBuildSerializer (solution.FileName); - DataItem data = (DataItem) ser.Serialize (solution, typeof(Solution)); + // Remove items which don't have a parent folder + var toRemove = solution.GetAllItems<SolutionFolderItem> ().Where (it => it.ParentFolder == solution.RootFolder); + foreach (var it in toRemove) + sec.Properties.Remove (it.ItemId); + } + + //Write custom properties + MSBuildSerializer ser = new MSBuildSerializer (solution.FileName); + DataItem data = (DataItem) ser.Serialize (solution, typeof(Solution)); + if (data.HasItemData) { + var sec = sln.Sections.GetOrCreateSection ("MonoDevelopProperties", "preSolution"); + WriteDataItem (sec.Properties, data); + } else + sln.Sections.RemoveSection ("MonoDevelopProperties"); + + // Write custom properties for configurations + foreach (SolutionConfiguration conf in solution.Configurations) { + data = (DataItem) ser.Serialize (conf); + string secId = "MonoDevelopProperties." + conf.Id; if (data.HasItemData) { - sw.WriteLine ("\tGlobalSection(MonoDevelopProperties) = preSolution"); - WriteDataItem (sw, data); - sw.WriteLine ("\tEndGlobalSection"); - } - - // Write custom properties for configurations - foreach (SolutionConfiguration conf in solution.Configurations) { - data = (DataItem) ser.Serialize (conf); - if (data.HasItemData) { - sw.WriteLine ("\tGlobalSection(MonoDevelopProperties." + conf.Id + ") = preSolution"); - WriteDataItem (sw, data); - sw.WriteLine ("\tEndGlobalSection"); - } - } - - //Write 'others' - if (slnData.GlobalExtra != null) { - foreach (string s in slnData.GlobalExtra) - sw.WriteLine (s); + var sec = sln.Sections.GetOrCreateSection (secId, "preSolution"); + WriteDataItem (sec.Properties, data); + } else { + sln.Sections.RemoveSection (secId); } - - sw.WriteLine ("EndGlobal"); } } - void WriteProjects (SolutionFolder folder, string baseDirectory, StreamWriter writer, bool saveProjects, IProgressMonitor monitor) + void WriteProjects (SolutionFolder folder, SlnFile sln, ProgressMonitor monitor, HashSet<string> unknownProjects) { - monitor.BeginStepTask (GettextCatalog.GetString ("Saving projects"), folder.Items.Count, 1); - foreach (SolutionItem ce in folder.Items) + monitor.BeginTask (folder.Items.Count); + foreach (SolutionFolderItem ce in folder.Items) { - string[] l = null; - if (ce is SolutionEntityItem) { + monitor.BeginStep (); + if (ce is SolutionItem) { - SolutionEntityItem item = (SolutionEntityItem) ce; - MSBuildHandler handler = MSBuildProjectService.GetItemHandler (item); - - if (saveProjects) { - try { - handler.SavingSolution = true; - item.Save (monitor); - } finally { - handler.SavingSolution = false; - } - } + SolutionItem item = (SolutionItem) ce; - l = handler.SlnProjectContent; + var proj = sln.Projects.GetOrCreateProject (ce.ItemId); + proj.TypeGuid = item.TypeGuid; + proj.Name = item.Name; + proj.FilePath = FileService.NormalizeRelativePath (FileService.AbsoluteToRelativePath (sln.BaseDirectory, item.FileName)).Replace ('/', '\\'); - writer.WriteLine (@"Project(""{0}"") = ""{1}"", ""{2}"", ""{3}""", - handler.TypeGuid, - item.Name, - FileService.NormalizeRelativePath (FileService.AbsoluteToRelativePath ( - baseDirectory, item.FileName)).Replace ('/', '\\'), - ce.ItemId); - DataItem data = handler.WriteSlnData (); + DataItem data = item.WriteSlnData (); if (data != null && data.HasItemData) { - writer.WriteLine ("\tProjectSection(MonoDevelopProperties) = preProject"); - WriteDataItem (writer, data); - writer.WriteLine ("\tEndProjectSection"); - } + var sec = proj.Sections.GetOrCreateSection ("MonoDevelopProperties", "preProject"); + WriteDataItem (sec.Properties, data); + } else + proj.Sections.RemoveSection ("MonoDevelopProperties"); + if (item.ItemDependencies.Count > 0) { - writer.WriteLine ("\tProjectSection(ProjectDependencies) = postProject"); + var sec = proj.Sections.GetOrCreateSection ("ProjectDependencies", "postProject"); + sec.Properties.ClearExcept (unknownProjects); foreach (var dep in item.ItemDependencies) - writer.WriteLine ("\t\t{0} = {0}", dep.ItemId); - if (handler.UnresolvedProjectDependencies != null) { - foreach (var dep in handler.UnresolvedProjectDependencies) - writer.WriteLine ("\t\t{0} = {0}", dep); - } - writer.WriteLine ("\tEndProjectSection"); - } + sec.Properties.SetValue (dep.ItemId, dep.ItemId); + } else + proj.Sections.RemoveSection ("ProjectDependencies"); } else if (ce is SolutionFolder) { - //Solution - SlnData slnData = GetSlnData (ce); - if (slnData == null) { - // Solution folder - slnData = new SlnData (); - ce.ExtendedProperties [typeof (SlnFileFormat)] = slnData; - } + var proj = sln.Projects.GetOrCreateProject (ce.ItemId); + proj.TypeGuid = MSBuildProjectService.FolderTypeGuid; + proj.Name = ce.Name; + proj.FilePath = ce.Name; - l = slnData.Extra; - - writer.WriteLine (@"Project(""{0}"") = ""{1}"", ""{2}"", ""{3}""", - MSBuildProjectService.FolderTypeGuid, - ce.Name, - ce.Name, - ce.ItemId); - // Folder files - WriteFolderFiles (writer, (SolutionFolder) ce); + WriteFolderFiles (proj, (SolutionFolder) ce); //Write custom properties MSBuildSerializer ser = new MSBuildSerializer (folder.ParentSolution.FileName); DataItem data = (DataItem) ser.Serialize (ce, typeof(SolutionFolder)); if (data.HasItemData) { - writer.WriteLine ("\tProjectSection(MonoDevelopProperties) = preProject"); - WriteDataItem (writer, data); - writer.WriteLine ("\tEndProjectSection"); + var sec = proj.Sections.GetOrCreateSection ("MonoDevelopProperties", "preProject"); + WriteDataItem (sec.Properties, data); } } - - if (l != null) { - foreach (string s in l) - writer.WriteLine (s); - } - - writer.WriteLine ("EndProject"); if (ce is SolutionFolder) - WriteProjects (ce as SolutionFolder, baseDirectory, writer, saveProjects, monitor); - monitor.Step (1); + WriteProjects (ce as SolutionFolder, sln, monitor, unknownProjects); } monitor.EndTask (); } - void WriteFolderFiles (StreamWriter writer, SolutionFolder folder) + void WriteFolderFiles (SlnProject proj, SolutionFolder folder) { if (folder.Files.Count > 0) { - writer.WriteLine ("\tProjectSection(SolutionItems) = preProject"); + var sec = proj.Sections.GetOrCreateSection ("SolutionItems", "preProject"); + sec.Properties.Clear (); foreach (FilePath f in folder.Files) { string relFile = MSBuildProjectService.ToMSBuildPathRelative (folder.ParentSolution.ItemDirectory, f); - writer.WriteLine ("\t\t" + relFile + " = " + relFile); + sec.Properties.SetValue (relFile, relFile); } - writer.WriteLine ("\tEndProjectSection"); - } + } else + proj.Sections.RemoveSection ("SolutionItems"); } - void WriteProjectConfigurations (Solution sol, List<string> list) + void WriteProjectConfigurations (Solution sol, SlnFile sln) { - foreach (SolutionConfiguration cc in sol.Configurations) { + var col = sln.ProjectConfigurationsSection; + + foreach (var item in sol.GetAllSolutionItems ()) { + // Don't save configurations for shared projects + if (!item.SupportsConfigurations ()) + continue; - foreach (SolutionConfigurationEntry cce in cc.Configurations) { - SolutionEntityItem p = cce.Item; + // <ProjectGuid>...</ProjectGuid> in some Visual Studio generated F# project files + // are missing "{"..."}" in their guid. This is not generally a problem since it + // is a valid GUID format. However the solution file format requires that these are present. + string itemGuid = item.ItemId; + if (!itemGuid.StartsWith ("{") && !itemGuid.EndsWith ("}")) + itemGuid = "{" + itemGuid + "}"; - // Don't save configurations for shared projects - if (!p.SupportsBuild () && !(p is UnloadedSolutionItem)) + var pset = col.GetOrCreatePropertySet (itemGuid, ignoreCase:true); + pset.Clear (); + + foreach (SolutionConfiguration cc in sol.Configurations) { + var cce = cc.GetEntryForItem (item); + if (cce == null) continue; - - // <ProjectGuid>...</ProjectGuid> in some Visual Studio generated F# project files - // are missing "{"..."}" in their guid. This is not generally a problem since it - // is a valid GUID format. However the solution file format requires that these are present. - string itemGuid = p.ItemId; - if (!itemGuid.StartsWith("{") && !itemGuid.EndsWith("}")) - itemGuid = "{" + itemGuid + "}"; + var configId = ToSlnConfigurationId (cc); + var itemConfigId = ToSlnConfigurationId (cce.ItemConfiguration); - list.Add (String.Format ( - "\t\t{0}.{1}.ActiveCfg = {2}", itemGuid, ToSlnConfigurationId (cc), ToSlnConfigurationId (cce.ItemConfiguration))); + pset.SetValue (configId + ".ActiveCfg", itemConfigId); if (cce.Build) - list.Add (String.Format ( - "\t\t{0}.{1}.Build.0 = {2}", itemGuid, ToSlnConfigurationId (cc), ToSlnConfigurationId (cce.ItemConfiguration))); - + pset.SetValue (configId + ".Build.0", itemConfigId); + if (cce.Deploy) - list.Add (String.Format ( - "\t\t{0}.{1}.Deploy.0 = {2}", itemGuid, ToSlnConfigurationId (cc), ToSlnConfigurationId (cce.ItemConfiguration))); + pset.SetValue (configId + ".Deploy.0", itemConfigId); } } - } - void WriteNestedProjects (SolutionFolder folder, SolutionFolder root, StreamWriter writer) + void WriteNestedProjects (SolutionFolder folder, SolutionFolder root, SlnSection sec) { - foreach (SolutionItem ce in folder.Items) - writer.WriteLine (@"{0}{1} = {2}", "\t\t", ce.ItemId, folder.ItemId); + foreach (SolutionFolderItem ce in folder.Items) + sec.Properties.SetValue (ce.ItemId, folder.ItemId); } - DataItem GetSolutionItemData (List<string> lines) + List<string> ReadSolutionItemDependencies (SlnProject proj) { - // Find a project section of type MonoDevelopProperties - int start, end; - if (!FindSection (lines, "MonoDevelopProperties", true, out start, out end)) - return null; - - // Deserialize the object - DataItem it = ReadDataItem (start, end - start + 1, lines); - - // Remove the lines, since they have already been preocessed - lines.RemoveRange (start, end - start + 1); - return it; - } - - List<string> ReadSolutionItemDependencies (List<string> lines) - { - // Find a project section of type MonoDevelopProperties - int start, end; - if (!FindSection (lines, "ProjectDependencies", false, out start, out end)) + // Find a project section of type ProjectDependencies + var sec = proj.Sections.GetSection ("ProjectDependencies"); + if (sec == null) return null; - var ids = new List<string> (); - for (int n=start + 1; n < end; n++) { - string line = lines [n]; - int i = line.IndexOf ('='); - if (i != -1) - ids.Add (line.Substring (0, i).Trim ()); - } - - // Remove the lines, since they have already been preocessed - lines.RemoveRange (start, end - start + 1); - return ids; + return sec.Properties.Keys.ToList (); } - List<string> ReadFolderFiles (List<string> lines) + IEnumerable<string> ReadFolderFiles (SlnProject proj) { // Find a solution item section of type SolutionItems + var sec = proj.Sections.GetSection ("SolutionItems"); + if (sec == null) + return new string[0]; - List<string> list = new List<string> (); - int start, end; - if (!FindSection (lines, "SolutionItems", true, out start, out end)) - return list; - - for (int n=start + 1; n < end; n++) { - string file = lines [n]; - int i = file.IndexOf ('='); - if (i == -1) - continue; - file = file.Substring (0, i).Trim (' ','\t'); - if (file.Length > 0) - list.Add (file); - } - - // Remove the lines, since they have already been preocessed - lines.RemoveRange (start, end - start + 1); - return list; + return sec.Properties.Keys.ToList (); } - - bool FindSection (List<string> lines, string name, bool preProject, out int start, out int end) - { - start = -1; - end = -1; - string prePost = preProject ? "preProject" : "postProject"; - var sectionLine = "ProjectSection(" + name + ")=" + prePost; - - for (int n=0; n<lines.Count && start == -1; n++) { - string line = lines [n].Replace ("\t","").Replace (" ", ""); - if (line == sectionLine) - start = n; - } - if (start == -1) - return false; - - for (int n=start+1; n<lines.Count && end == -1; n++) { - string line = lines [n].Replace ("\t","").Replace (" ", ""); - if (line == "EndProjectSection") - end = n; - } - return end != -1; - } - - void DeserializeSolutionItem (Solution sln, SolutionItem item, List<string> lines) + void DeserializeSolutionItem (Solution sln, SolutionFolderItem item, SlnProject proj) { // Deserialize the object - DataItem it = GetSolutionItemData (lines); + var sec = proj.Sections.GetSection ("MonoDevelopProperties"); + if (sec == null) + return; + + DataItem it = ReadDataItem (sec); if (it == null) return; @@ -445,14 +377,15 @@ namespace MonoDevelop.Projects.Formats.MSBuild ser.Deserialize (item, it); } - void WriteDataItem (StreamWriter sw, DataItem item) + void WriteDataItem (SlnPropertySet pset, DataItem item) { + pset.Clear (); int id = 0; foreach (DataNode val in item.ItemData) - WriteDataNode (sw, "", val, ref id); + WriteDataNode (pset, "", val, ref id); } - void WriteDataNode (StreamWriter sw, string prefix, DataNode node, ref int id) + void WriteDataNode (SlnPropertySet pset, string prefix, DataNode node, ref int id) { string name = node.Name; string newPrefix = prefix.Length > 0 ? prefix + "." + name: name; @@ -460,15 +393,15 @@ namespace MonoDevelop.Projects.Formats.MSBuild if (node is DataValue) { DataValue val = (DataValue) node; string value = EncodeString (val.Value); - sw.WriteLine ("\t\t" + newPrefix + " = " + value); + pset.SetValue (newPrefix, value); } else { DataItem it = (DataItem) node; - sw.WriteLine ("\t\t" + newPrefix + " = $" + id); + pset.SetValue (newPrefix, "$" + id); newPrefix = "$" + id; id ++; foreach (DataNode cn in it.ItemData) - WriteDataNode (sw, newPrefix, cn, ref id); + WriteDataNode (pset, newPrefix, cn, ref id); } } @@ -533,16 +466,14 @@ namespace MonoDevelop.Projects.Formats.MSBuild return val; } - DataItem ReadDataItem (Section sec, List<string> lines) - { - return ReadDataItem (sec.Start, sec.Count, lines); - } - - DataItem ReadDataItem (int start, int count, List<string> lines) + DataItem ReadDataItem (SlnSection sec) { DataItem it = new DataItem (); - int lineNum = start + 1; - int lastLine = start + count - 2; + + var lines = sec.Properties.ToArray (); + + int lineNum = 0; + int lastLine = lines.Length - 1; while (lineNum <= lastLine) { if (!ReadDataNode (it, lines, lastLine, "", ref lineNum)) lineNum++; @@ -550,38 +481,26 @@ namespace MonoDevelop.Projects.Formats.MSBuild return it; } - bool ReadDataNode (DataItem item, List<string> lines, int lastLine, string prefix, ref int lineNum) + bool ReadDataNode (DataItem item, KeyValuePair<string,string>[] lines, int lastLine, string prefix, ref int lineNum) { - string s = lines [lineNum].Trim (' ','\t'); - - if (s.Length == 0) { - lineNum++; - return true; - } + var s = lines [lineNum]; // Check if the line belongs to the current item if (prefix.Length > 0) { - if (!s.StartsWith (prefix + ".")) + if (!s.Key.StartsWith (prefix + ".")) return false; - s = s.Substring (prefix.Length + 1); } else { - if (s.StartsWith ("$")) + if (s.Key.StartsWith ("$")) return false; } - int i = s.IndexOf ('='); - if (i == -1) { - lineNum++; - return true; - } - - string name = s.Substring (0, i).Trim (' ','\t'); + string name = s.Key; if (name.Length == 0) { lineNum++; return true; } - string value = s.Substring (i+1).Trim (' ','\t'); + string value = s.Value; if (value.StartsWith ("$")) { // New item DataItem child = new DataItem (); @@ -629,7 +548,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild } //Reader - public object ReadFile (string fileName, MSBuildFileFormat format, IProgressMonitor monitor) + public async Task<object> ReadFile (string fileName, ProgressMonitor monitor) { if (fileName == null || monitor == null) return null; @@ -639,10 +558,10 @@ namespace MonoDevelop.Projects.Formats.MSBuild ProjectExtensionUtil.BeginLoadOperation (); sol = new Solution (); monitor.BeginTask (string.Format (GettextCatalog.GetString ("Loading solution: {0}"), fileName), 1); - var projectLoadMonitor = monitor as IProjectLoadProgressMonitor; + var projectLoadMonitor = monitor as ProjectLoadProgressMonitor; if (projectLoadMonitor != null) projectLoadMonitor.CurrentSolution = sol; - LoadSolution (sol, fileName, format, monitor); + await Task.Factory.StartNew (() => LoadSolution (sol, fileName, monitor)); } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("Could not load solution: {0}", fileName), ex); throw; @@ -653,129 +572,63 @@ namespace MonoDevelop.Projects.Formats.MSBuild return sol; } - //ExtendedProperties - // Per config - // Platform : Eg. Any CPU - // SolutionConfigurationPlatforms - // - SolutionFolder LoadSolution (Solution sol, string fileName, MSBuildFileFormat format, IProgressMonitor monitor) + SolutionFolder LoadSolution (Solution sol, string fileName, ProgressMonitor monitor) { - string headerComment; - string version = GetSlnFileVersion (fileName, out headerComment); - - ListDictionary globals = null; - SolutionFolder folder = null; - SlnData data = null; - List<Section> projectSections = null; - List<string> lines = null; - FileFormat projectFormat = Services.ProjectService.FileFormats.GetFileFormat (format); monitor.BeginTask (GettextCatalog.GetString ("Loading solution: {0}", fileName), 1); - //Parse the .sln file - using (StreamReader reader = new StreamReader(fileName)) { - sol.FileName = fileName; - sol.ConvertToFormat (projectFormat, false); - folder = sol.RootFolder; - sol.Version = "0.1"; //FIXME: - data = new SlnData (); - folder.ExtendedProperties [typeof (SlnFileFormat)] = data; - data.VersionString = version; - data.HeaderComment = headerComment; - - string s = null; - projectSections = new List<Section> (); - lines = new List<string> (); - globals = new ListDictionary (); - //Parse - while (reader.Peek () >= 0) { - s = GetNextLine (reader, lines).Trim (); - - if (String.Compare (s, "Global", StringComparison.OrdinalIgnoreCase) == 0) { - ParseGlobal (reader, lines, globals); - continue; - } - - if (s.StartsWith ("Project", StringComparison.Ordinal)) { - Section sec = new Section (); - projectSections.Add (sec); - sec.Start = lines.Count - 1; + var sln = new SlnFile (); + sln.Read (fileName); - int e = ReadUntil ("EndProject", reader, lines); - sec.Count = (e < 0) ? 1 : (e - sec.Start + 1); + sol.FileName = fileName; + sol.ConvertToFormat (projectFormat, false); - continue; - } + sol.ReadSolution (monitor, sln); + return sol.RootFolder; + } - if (s.StartsWith ("VisualStudioVersion = ", StringComparison.Ordinal)) { - Version v; - if (Version.TryParse (s.Substring ("VisualStudioVersion = ".Length), out v)) - data.VisualStudioVersion = v; - else - monitor.Log.WriteLine ("Ignoring unparseable VisualStudioVersion value in sln file"); - } + internal void LoadSolution (Solution sol, SlnFile sln, ProgressMonitor monitor) + { + var version = sln.FormatVersion; - if (s.StartsWith ("MinimumVisualStudioVersion = ", StringComparison.Ordinal)) { - Version v; - if (Version.TryParse (s.Substring ("MinimumVisualStudioVersion = ".Length), out v)) - data.MinimumVisualStudioVersion = v; - else - monitor.Log.WriteLine ("Ignoring unparseable MinimumVisualStudioVersion value in sln file"); - } - } - } + //Parse the .sln file + var folder = sol.RootFolder; + sol.Version = "0.1"; //FIXME: - monitor.BeginTask("Loading projects ..", projectSections.Count + 1); - Dictionary<string, SolutionItem> items = new Dictionary<string, SolutionItem> (); - List<SolutionItem> sortedList = new List<SolutionItem> (); - foreach (Section sec in projectSections) { + monitor.BeginTask("Loading projects ..", sln.Projects.Count + 1); + Dictionary<string, SolutionFolderItem> items = new Dictionary<string, SolutionFolderItem> (); + List<SolutionFolderItem> sortedList = new List<SolutionFolderItem> (); + foreach (SlnProject sec in sln.Projects) { monitor.Step (1); - Match match = ProjectRegex.Match (lines [sec.Start]); - if (!match.Success) { - LoggingService.LogDebug (GettextCatalog.GetString ( - "Invalid Project definition on line number #{0} in file '{1}'. Ignoring.", - sec.Start + 1, - fileName)); - - continue; - } - try { // Valid guid? - new Guid (match.Groups [1].Value); + new Guid (sec.TypeGuid); } catch (FormatException) { //Use default guid as projectGuid LoggingService.LogDebug (GettextCatalog.GetString ( "Invalid Project type guid '{0}' on line #{1}. Ignoring.", - match.Groups [1].Value, - sec.Start + 1)); + sec.Id, + sec.Line)); continue; } - string projTypeGuid = match.Groups [1].Value.ToUpper (); - string projectName = match.Groups [2].Value; - string projectPath = match.Groups [3].Value; - string projectGuid = match.Groups [4].Value.ToUpper (); - List<string> projLines; + string projTypeGuid = sec.TypeGuid.ToUpper (); + string projectName = sec.Name; + string projectPath = sec.FilePath; + string projectGuid = sec.Id; if (projTypeGuid == MSBuildProjectService.FolderTypeGuid) { //Solution folder SolutionFolder sfolder = new SolutionFolder (); sfolder.Name = projectName; - MSBuildProjectService.InitializeItemHandler (sfolder); - MSBuildProjectService.SetId (sfolder, projectGuid); + sfolder.ItemId = projectGuid; - projLines = lines.GetRange (sec.Start + 1, sec.Count - 2); - DeserializeSolutionItem (sol, sfolder, projLines); + DeserializeSolutionItem (sol, sfolder, sec); - foreach (string f in ReadFolderFiles (projLines)) - sfolder.Files.Add (MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (fileName), f)); + foreach (string f in ReadFolderFiles (sec)) + sfolder.Files.Add (MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (sol.FileName), f)); - SlnData slnData = new SlnData (); - slnData.Extra = projLines.ToArray (); - sfolder.ExtendedProperties [typeof (SlnFileFormat)] = slnData; - items.Add (projectGuid, sfolder); sortedList.Add (sfolder); @@ -785,42 +638,38 @@ namespace MonoDevelop.Projects.Formats.MSBuild if (projectPath.StartsWith("http://")) { monitor.ReportWarning (GettextCatalog.GetString ( "{0}({1}): Projects with non-local source (http://...) not supported. '{2}'.", - fileName, sec.Start + 1, projectPath)); - data.UnknownProjects.AddRange (lines.GetRange (sec.Start, sec.Count)); + sol.FileName, sec.Line, projectPath)); continue; } - string path = MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (fileName), projectPath); + string path = MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (sol.FileName), projectPath); if (String.IsNullOrEmpty (path)) { monitor.ReportWarning (GettextCatalog.GetString ( - "Invalid project path found in {0} : {1}", fileName, projectPath)); + "Invalid project path found in {0} : {1}", sol.FileName, projectPath)); LoggingService.LogWarning (GettextCatalog.GetString ( - "Invalid project path found in {0} : {1}", fileName, projectPath)); + "Invalid project path found in {0} : {1}", sol.FileName, projectPath)); continue; } projectPath = Path.GetFullPath (path); - SolutionEntityItem item = null; + SolutionItem item = null; try { if (sol.IsSolutionItemEnabled (projectPath)) { - item = ProjectExtensionUtil.LoadSolutionItem (monitor, projectPath, delegate { + var t = ProjectExtensionUtil.LoadSolutionItem (monitor, projectPath, delegate { return MSBuildProjectService.LoadItem (monitor, projectPath, format, projTypeGuid, projectGuid); }); + t.Wait (); + item = t.Result; if (item == null) { throw new UnknownSolutionItemTypeException (projTypeGuid); } } else { - var uitem = new UnloadedSolutionItem () { + item = new UnloadedSolutionItem () { FileName = projectPath }; - var h = new MSBuildHandler (projTypeGuid, projectGuid) { - Item = uitem, - }; - uitem.SetItemHandler (h); - item = uitem; } } catch (Exception e) { @@ -837,7 +686,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild var relPath = new FilePath (path).ToRelative (sol.BaseDirectory); if (!string.IsNullOrEmpty (name)) { var guids = name.Split (';'); - var projectInfo = MSBuildProjectService.GetUnknownProjectTypeInfo (guids, fileName); + var projectInfo = MSBuildProjectService.GetUnknownProjectTypeInfo (guids, sol.FileName); if (projectInfo != null) { loadAsProject = projectInfo.LoadFiles; LoggingService.LogWarning (string.Format ("Could not load {0} project '{1}'. {2}", projectInfo.Name, relPath, projectInfo.GetInstructions ())); @@ -861,218 +710,143 @@ namespace MonoDevelop.Projects.Formats.MSBuild "Error while trying to load the project '{0}': {1}", projectPath, e.Message)); } - SolutionEntityItem uitem; + SolutionItem uitem; if (loadAsProject) { uitem = new UnknownProject () { FileName = projectPath, - LoadError = e.Message, + UnsupportedProjectMessage = e.Message, }; } else { uitem = new UnknownSolutionItem () { FileName = projectPath, - LoadError = e.Message, + UnsupportedProjectMessage = e.Message, }; } - - var h = new MSBuildHandler (projTypeGuid, projectGuid) { - Item = uitem, - }; - uitem.SetItemHandler (h); item = uitem; } - MSBuildHandler handler = (MSBuildHandler) item.ItemHandler; - projLines = lines.GetRange (sec.Start + 1, sec.Count - 2); - DataItem it = GetSolutionItemData (projLines); + item.UnresolvedProjectDependencies = ReadSolutionItemDependencies (sec); - handler.UnresolvedProjectDependencies = ReadSolutionItemDependencies (projLines); - handler.SlnProjectContent = projLines.ToArray (); - handler.ReadSlnData (it); + // Deserialize the object + var ssec = sec.Sections.GetSection ("MonoDevelopProperties"); + if (ssec != null) { + DataItem it = ReadDataItem (ssec); + item.ReadSlnData (it); + } if (!items.ContainsKey (projectGuid)) { items.Add (projectGuid, item); sortedList.Add (item); - data.ItemsByGuid [projectGuid] = item; } else { monitor.ReportError (GettextCatalog.GetString ("Invalid solution file. There are two projects with the same GUID. The project {0} will be ignored.", projectPath), null); } } monitor.EndTask (); - if (globals != null && globals.Contains ("NestedProjects")) { - LoadNestedProjects (globals ["NestedProjects"] as Section, lines, items, monitor); - globals.Remove ("NestedProjects"); - } + sol.LoadedProjects = new HashSet<string> (items.Keys); + + var nested = sln.Sections.GetSection ("NestedProjects"); + if (nested != null) + LoadNestedProjects (nested, items, monitor); // Resolve project dependencies - foreach (var it in items.OfType<SolutionEntityItem> ()) { - MSBuildHandler handler = (MSBuildHandler) it.ItemHandler; - if (handler.UnresolvedProjectDependencies != null) { - foreach (var id in handler.UnresolvedProjectDependencies.ToArray ()) { - SolutionItem dep; - if (items.TryGetValue (id, out dep) && dep is SolutionEntityItem) { - handler.UnresolvedProjectDependencies.Remove (id); - it.ItemDependencies.Add ((SolutionEntityItem)dep); + foreach (var it in items.Values.OfType<SolutionItem> ()) { + if (it.UnresolvedProjectDependencies != null) { + foreach (var id in it.UnresolvedProjectDependencies.ToArray ()) { + SolutionFolderItem dep; + if (items.TryGetValue (id, out dep) && dep is SolutionItem) { + it.UnresolvedProjectDependencies.Remove (id); + it.ItemDependencies.Add ((SolutionItem)dep); } } - if (handler.UnresolvedProjectDependencies.Count == 0) - handler.UnresolvedProjectDependencies = null; + if (it.UnresolvedProjectDependencies.Count == 0) + it.UnresolvedProjectDependencies = null; } } //Add top level folders and projects to the main folder - foreach (SolutionItem ce in sortedList) { + foreach (SolutionFolderItem ce in sortedList) { if (ce.ParentFolder == null) folder.Items.Add (ce); } //FIXME: This can be just SolutionConfiguration also! - if (globals != null) { - if (globals.Contains ("SolutionConfigurationPlatforms")) { - LoadSolutionConfigurations (globals ["SolutionConfigurationPlatforms"] as Section, lines, - sol, monitor); - globals.Remove ("SolutionConfigurationPlatforms"); - } + LoadSolutionConfigurations (sln.SolutionConfigurationsSection, sol, monitor); - if (globals.Contains ("ProjectConfigurationPlatforms")) { - LoadProjectConfigurationMappings (globals ["ProjectConfigurationPlatforms"] as Section, lines, - sol, monitor); - globals.Remove ("ProjectConfigurationPlatforms"); - } + LoadProjectConfigurationMappings (sln.ProjectConfigurationsSection, sol, items, monitor); - if (globals.Contains ("MonoDevelopProperties")) { - LoadMonoDevelopProperties (globals ["MonoDevelopProperties"] as Section, lines, sol, monitor); - globals.Remove ("MonoDevelopProperties"); - } - - ArrayList toRemove = new ArrayList (); - foreach (DictionaryEntry e in globals) { - string name = (string) e.Key; - if (name.StartsWith ("MonoDevelopProperties.")) { - int i = name.IndexOf ('.'); - LoadMonoDevelopConfigurationProperties (name.Substring (i+1), (Section)e.Value, lines, sol, monitor); - toRemove.Add (e.Key); - } + LoadMonoDevelopProperties (sln.Sections.GetSection ("MonoDevelopProperties"), sol, monitor); + + foreach (var e in sln.Sections) { + string name = e.Id; + if (name.StartsWith ("MonoDevelopProperties.")) { + int i = name.IndexOf ('.'); + LoadMonoDevelopConfigurationProperties (name.Substring (i+1), e, sol, monitor); } - foreach (object key in toRemove) - globals.Remove (key); } - //Save the global sections that we dont use - List<string> globalLines = new List<string> (); - foreach (Section sec in globals.Values) - globalLines.InsertRange (globalLines.Count, lines.GetRange (sec.Start, sec.Count)); - - data.GlobalExtra = globalLines; monitor.EndTask (); - - // When reloading a project, keep the solution data and item id - sol.SolutionItemAdded += delegate(object sender, SolutionItemChangeEventArgs e) { - if (e.Reloading) { - ItemSlnData.TransferData (e.ReplacedItem, e.SolutionItem); - var ih = e.SolutionItem.ItemHandler as MSBuildHandler; - if (ih != null) - ih.ItemId = e.ReplacedItem.ItemId; - } - }; - - return folder; } - void ParseGlobal (StreamReader reader, List<string> lines, ListDictionary dict) + void LoadProjectConfigurationMappings (SlnPropertySetCollection sets, Solution sln, Dictionary<string, SolutionFolderItem> items, ProgressMonitor monitor) { - //Process GlobalSection-s - while (reader.Peek () >= 0) { - string s = GetNextLine (reader, lines).Trim (); - if (s.Length == 0) - //Skip blank lines - continue; - - Match m = GlobalSectionRegex.Match (s); - if (!m.Success) { - if (String.Compare (s, "EndGlobal", true) == 0) - return; - - continue; - } - - Section sec = new Section (m.Groups [1].Value, m.Groups [2].Value, lines.Count - 1, 1); - dict [sec.Key] = sec; - - sec.Count = ReadUntil ("EndGlobalSection", reader, lines) - sec.Start + 1; - //FIXME: sec.Count == -1 : No EndGlobalSection found, ignore entry? - } - } - - void LoadProjectConfigurationMappings (Section sec, List<string> lines, Solution sln, IProgressMonitor monitor) - { - if (sec == null || String.Compare (sec.Val, "postSolution", true) != 0) + if (sets == null) return; Dictionary<string, SolutionConfigurationEntry> cache = new Dictionary<string, SolutionConfigurationEntry> (); Dictionary<string, string> ignoredProjects = new Dictionary<string, string> (); - SlnData slnData = GetSlnData (sln.RootFolder); - - List<string> extras = new List<string> (); - for (int i = 0; i < sec.Count - 2; i ++) { - int lineNum = i + sec.Start + 1; - string s = lines [lineNum].Trim (); - extras.Add (s); - - //Format: - // {projectGuid}.SolutionConfigName|SolutionPlatform.ActiveCfg = ProjConfigName|ProjPlatform - // {projectGuid}.SolutionConfigName|SolutionPlatform.Build.0 = ProjConfigName|ProjPlatform - // {projectGuid}.SolutionConfigName|SolutionPlatform.Deploy.0 = ProjConfigName|ProjPlatform + foreach (var pset in sets) { + + var projGuid = pset.Id; + + if (!items.ContainsKey (projGuid)) { + if (ignoredProjects.ContainsKey (projGuid)) + // already warned + continue; - string [] parts = s.Split (new char [] {'='}, 2); - if (parts.Length < 2) { - LoggingService.LogDebug ("{0} ({1}) : Invalid format. Ignoring", sln.FileName, lineNum + 1); + LoggingService.LogWarning (GettextCatalog.GetString ("{0} ({1}) : Project with guid = '{2}' not found or not loaded. Ignoring", + sln.FileName, pset.Line + 1, projGuid)); + ignoredProjects [projGuid] = projGuid; continue; } - string action; - string projConfig = parts [1].Trim (); - - string left = parts [0].Trim (); - if (left.EndsWith (".ActiveCfg")) { - action = "ActiveCfg"; - left = left.Substring (0, left.Length - 10); - } else if (left.EndsWith (".Build.0")) { - action = "Build.0"; - left = left.Substring (0, left.Length - 8); - } else if (left.EndsWith (".Deploy.0")) { - action = "Deploy.0"; - left = left.Substring (0, left.Length - 9); - } else { - LoggingService.LogWarning (GettextCatalog.GetString ("{0} ({1}) : Unknown action. Only ActiveCfg, Build.0 and Deploy.0 supported.", - sln.FileName, lineNum + 1)); + SolutionFolderItem it; + if (!items.TryGetValue (projGuid, out it)) continue; - } - string [] t = left.Split (new char [] {'.'}, 2); - if (t.Length < 2) { - LoggingService.LogDebug ("{0} ({1}) : Invalid format of the left side. Ignoring", - sln.FileName, lineNum + 1); + SolutionItem item = it as SolutionItem; + + if (item == null || !item.SupportsConfigurations ()) continue; - } - string projGuid = t [0].ToUpper (); - string slnConfig = t [1]; + //Format: + // {projectGuid}.SolutionConfigName|SolutionPlatform.ActiveCfg = ProjConfigName|ProjPlatform + // {projectGuid}.SolutionConfigName|SolutionPlatform.Build.0 = ProjConfigName|ProjPlatform + // {projectGuid}.SolutionConfigName|SolutionPlatform.Deploy.0 = ProjConfigName|ProjPlatform - if (!slnData.ItemsByGuid.ContainsKey (projGuid)) { - if (ignoredProjects.ContainsKey (projGuid)) - // already warned + foreach (var prop in pset) { + string action; + string projConfig = prop.Value; + + string left = prop.Key; + if (left.EndsWith (".ActiveCfg")) { + action = "ActiveCfg"; + left = left.Substring (0, left.Length - 10); + } else if (left.EndsWith (".Build.0")) { + action = "Build.0"; + left = left.Substring (0, left.Length - 8); + } else if (left.EndsWith (".Deploy.0")) { + action = "Deploy.0"; + left = left.Substring (0, left.Length - 9); + } else { + LoggingService.LogWarning (GettextCatalog.GetString ("{0} ({1}) : Unknown action. Only ActiveCfg, Build.0 and Deploy.0 supported.", + sln.FileName, pset.Line)); continue; + } - LoggingService.LogWarning (GettextCatalog.GetString ("{0} ({1}) : Project with guid = '{2}' not found or not loaded. Ignoring", - sln.FileName, lineNum + 1, projGuid)); - ignoredProjects [projGuid] = projGuid; - continue; - } + string slnConfig = left; - SolutionEntityItem item; - if (slnData.ItemsByGuid.TryGetValue (projGuid, out item) && (item.SupportsBuild () || item is UnloadedSolutionItem)) { string key = projGuid + "." + slnConfig; SolutionConfigurationEntry combineConfigEntry = null; if (cache.ContainsKey (key)) { @@ -1092,6 +866,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild * if Build (true/false) for the project will * will depend on presence/absence of Build.0 entry */ + if (action == "ActiveCfg") { combineConfigEntry.ItemConfiguration = FromSlnConfigurationId (projConfig); } else if (action == "Build.0") { @@ -1100,15 +875,12 @@ namespace MonoDevelop.Projects.Formats.MSBuild combineConfigEntry.Deploy = true; } } - extras.RemoveAt (extras.Count - 1); } - - slnData.SectionExtras ["ProjectConfigurationPlatforms"] = extras; } /* Gets the CombineConfigurationEntry corresponding to the @entry in its parentCombine's * CombineConfiguration. Creates the required bits if not present */ - SolutionConfigurationEntry GetConfigEntry (Solution sol, SolutionEntityItem item, string configName) + SolutionConfigurationEntry GetConfigEntry (Solution sol, SolutionItem item, string configName) { configName = FromSlnConfigurationId (configName); @@ -1124,21 +896,13 @@ namespace MonoDevelop.Projects.Formats.MSBuild return solutionConfig.AddItem (item); } - void LoadSolutionConfigurations (Section sec, List<string> lines, Solution solution, IProgressMonitor monitor) + void LoadSolutionConfigurations (SlnPropertySet sec, Solution solution, ProgressMonitor monitor) { - if (sec == null || String.Compare (sec.Val, "preSolution", true) != 0) + if (sec == null) return; - for (int i = 0; i < sec.Count - 2; i ++) { - //FIXME: expects both key and val to be on the same line - int lineNum = i + sec.Start + 1; - string s = lines [lineNum].Trim (); - if (s.Length == 0) - //Skip blank lines - continue; + foreach (var pair in sec) { - KeyValuePair<string, string> pair = SplitKeyValue (s); - string configId = FromSlnConfigurationId (pair.Key); SolutionConfiguration config = solution.Configurations [configId]; @@ -1154,37 +918,37 @@ namespace MonoDevelop.Projects.Formats.MSBuild return new SolutionConfiguration (fullId); } - void LoadMonoDevelopProperties (Section sec, List<string> lines, Solution sln, IProgressMonitor monitor) + void LoadMonoDevelopProperties (SlnSection sec, Solution sln, ProgressMonitor monitor) { - DataItem it = ReadDataItem (sec, lines); + if (sec == null) + return; + DataItem it = ReadDataItem (sec); MSBuildSerializer ser = new MSBuildSerializer (sln.FileName); ser.SerializationContext.BaseFile = sln.FileName; ser.Deserialize (sln, it); } - void LoadMonoDevelopConfigurationProperties (string configName, Section sec, List<string> lines, Solution sln, IProgressMonitor monitor) + void LoadMonoDevelopConfigurationProperties (string configName, SlnSection sec, Solution sln, ProgressMonitor monitor) { SolutionConfiguration config = sln.Configurations [configName]; if (config == null) return; - DataItem it = ReadDataItem (sec, lines); + DataItem it = ReadDataItem (sec); MSBuildSerializer ser = new MSBuildSerializer (sln.FileName); ser.Deserialize (config, it); } - void LoadNestedProjects (Section sec, List<string> lines, - IDictionary<string, SolutionItem> entries, IProgressMonitor monitor) + void LoadNestedProjects (SlnSection sec, IDictionary<string, SolutionFolderItem> entries, ProgressMonitor monitor) { - if (sec == null || String.Compare (sec.Val, "preSolution", true) != 0) + if (sec == null || String.Compare (sec.SectionType, "preSolution", StringComparison.OrdinalIgnoreCase) != 0) return; - for (int i = 0; i < sec.Count - 2; i ++) { + foreach (var kvp in sec.Properties) { // Guids should be upper case for VS compatibility - KeyValuePair<string, string> pair = SplitKeyValue (lines [i + sec.Start + 1].Trim ()); - pair = new KeyValuePair<string, string> (pair.Key.ToUpper (), pair.Value.ToUpper ()); + var pair = new KeyValuePair<string, string> (kvp.Key.ToUpper (), kvp.Value.ToUpper ()); - SolutionItem folderItem; - SolutionItem item; + SolutionFolderItem folderItem; + SolutionFolderItem item; if (!entries.TryGetValue (pair.Value, out folderItem)) { //Container not found @@ -1232,17 +996,6 @@ namespace MonoDevelop.Projects.Formats.MSBuild } - KeyValuePair<string, string> SplitKeyValue (string s) - { - string [] pair = s.Split (new char [] {'='}, 2); - string key = pair [0].Trim (); - string val = String.Empty; - if (pair.Length == 2) - val = pair [1].Trim (); - - return new KeyValuePair<string, string> (key, val); - } - // Utility function to determine the sln file version string GetSlnFileVersion(string strInSlnFile, out string headerComment) { @@ -1276,32 +1029,6 @@ namespace MonoDevelop.Projects.Formats.MSBuild return strVersion; } - static SlnData GetSlnData (SolutionItem c) - { - if (c.ExtendedProperties.Contains (typeof (SlnFileFormat))) - return c.ExtendedProperties [typeof (SlnFileFormat)] as SlnData; - return null; - } - - // static regexes - static Regex projectRegex = null; - internal static Regex ProjectRegex { - get { - if (projectRegex == null) - projectRegex = new Regex(@"Project\(""(\{[^}]*\})""\) = ""(.*)"", ""(.*)"", ""(\{[^{]*\})"""); - return projectRegex; - } - } - - static Regex globalSectionRegex = null; - static Regex GlobalSectionRegex { - get { - if (globalSectionRegex == null) - globalSectionRegex = new Regex (@"GlobalSection\s*\(([^)]*)\)\s*=\s*(\w*)"); - return globalSectionRegex; - } - } - static Regex slnVersionRegex = null; internal static Regex SlnVersionRegex { get { diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/UnknownSolutionItemTypeException.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/UnknownSolutionItemTypeException.cs new file mode 100644 index 0000000000..ce2af4ae34 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/UnknownSolutionItemTypeException.cs @@ -0,0 +1,64 @@ +// +// UnknownSolutionItemTypeException.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Xml; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using MonoDevelop.Core; +using MonoDevelop.Projects; +using MonoDevelop.Core.Serialization; +using MonoDevelop.Core.Assemblies; +using MonoDevelop.Projects.Formats.MD1; +using MonoDevelop.Projects.Extensions; +using Mono.Addins; +using System.Linq; +using MonoDevelop.Core.Instrumentation; +using MonoDevelop.Core.ProgressMonitoring; +using System.Threading.Tasks; + +namespace MonoDevelop.Projects.Formats.MSBuild +{ + + class UnknownSolutionItemTypeException : InvalidOperationException + { + public UnknownSolutionItemTypeException () + : base ("Unknown solution item type") + { + } + + public UnknownSolutionItemTypeException (string name) + : base ("Unknown solution item type: " + name) + { + this.TypeName = name; + } + + public string TypeName { get; private set; } + } + +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/DotNetNamingPolicy.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/DotNetNamingPolicy.cs index 882004de7c..045e042aa3 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/DotNetNamingPolicy.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/DotNetNamingPolicy.cs @@ -62,10 +62,10 @@ namespace MonoDevelop.Projects.Policies internal static ResourceNamePolicy GetDefaultResourceNamePolicy (object ob) { FileFormat format = null; - if (ob is SolutionEntityItem) - format = ((SolutionEntityItem)ob).FileFormat; - else if (ob is SolutionItem) - format = ((SolutionItem)ob).ParentSolution.FileFormat; + if (ob is SolutionItem) + format = ((SolutionItem)ob).FileFormat; + else if (ob is SolutionFolderItem) + format = ((SolutionFolderItem)ob).ParentSolution.FileFormat; else if (ob is Solution) format = ((Solution)ob).FileFormat; diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyBag.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyBag.cs index 074bcc8d0d..4d8ce0d6be 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyBag.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyBag.cs @@ -42,7 +42,7 @@ namespace MonoDevelop.Projects.Policies [DataItem ("Policies")] public class PolicyBag: PolicyContainer, ICustomDataItem { - public PolicyBag (SolutionItem owner) + public PolicyBag (SolutionFolderItem owner) { this.Owner = owner; } @@ -51,7 +51,7 @@ namespace MonoDevelop.Projects.Policies { } - public SolutionItem Owner { get; internal set; } + public SolutionFolderItem Owner { get; internal set; } public override bool IsRoot { get { return Owner == null || Owner.ParentFolder == null; } @@ -107,7 +107,7 @@ namespace MonoDevelop.Projects.Policies { SolutionFolder solFol = Owner as SolutionFolder; if (solFol != null) - foreach (SolutionItem item in solFol.Items) + foreach (SolutionFolderItem item in solFol.Items) if (!item.Policies.DirectHas (args.PolicyType, args.Scope)) item.Policies.OnPolicyChanged (args.PolicyType, args.Scope); } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProject.cs index 2a98dae3cb..f3fd6487ff 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProject.cs @@ -1,4 +1,4 @@ -// +// // SharedProject.cs // // Author: @@ -31,35 +31,130 @@ using MonoDevelop.Core; using System.IO; using System.Xml; using MonoDevelop.Projects.Policies; +using System.Threading.Tasks; +using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.Projects.SharedAssetsProjects { + [RegisterProjectType ("{D954291E-2A0B-460D-934E-DC6B0785DB48}", Extension="shproj", Alias="SharedAssetsProject")] public class SharedAssetsProject: Project, IDotNetFileContainer { Solution currentSolution; IDotNetLanguageBinding languageBinding; string languageName; + string projitemsFile; public SharedAssetsProject () { + Initialize (this); } - public SharedAssetsProject (string language) + public SharedAssetsProject (string language): this () { languageName = language; } - public SharedAssetsProject (ProjectCreateInformation projectCreateInfo, XmlElement projectOptions) + public SharedAssetsProject (ProjectCreateInformation projectCreateInfo, XmlElement projectOptions): this () { languageName = projectOptions.GetAttribute ("language"); DefaultNamespace = projectCreateInfo.ProjectName; } - internal protected override List<FilePath> OnGetItemFiles (bool includeReferencedFiles) + protected override void OnReadProject (ProgressMonitor monitor, MSBuildProject msproject) + { + base.OnReadProject (monitor, msproject); + + var doc = msproject.Document; + projitemsFile = null; + foreach (var no in doc.DocumentElement.ChildNodes) { + var im = no as XmlElement; + if (im != null && im.LocalName == "Import" && im.GetAttribute ("Label") == "Shared") { + projitemsFile = im.GetAttribute ("Project"); + break; + } + } + if (projitemsFile == null) + return; + + // TODO: load the type from msbuild + LanguageName = "C#"; + + projitemsFile = Path.Combine (Path.GetDirectoryName (msproject.FileName), projitemsFile); + + MSBuildProject p = new MSBuildProject (); + p.Load (projitemsFile); + + var cp = p.PropertyGroups.FirstOrDefault (g => g.Label == "Configuration"); + if (cp != null) + DefaultNamespace = cp.GetValue ("Import_RootNamespace"); + + LoadProjectItems (p, ProjectItemFlags.None); + } + + protected override void OnWriteProject (ProgressMonitor monitor, MonoDevelop.Projects.Formats.MSBuild.MSBuildProject msproject) + { + base.OnWriteProject (monitor, msproject); + + MSBuildProject projitemsProject = new MSBuildProject (); + + var newProject = FileName == null || !File.Exists (FileName); + if (newProject) { + var grp = msproject.GetGlobalPropertyGroup (); + if (grp == null) + grp = msproject.AddNewPropertyGroup (false); + grp.SetValue ("ProjectGuid", ItemId, preserveExistingCase:true); + var import = msproject.AddNewImport (@"$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"); + import.Condition = @"Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"; + msproject.AddNewImport (@"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props"); + msproject.AddNewImport (@"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props"); + import = msproject.AddNewImport (Path.ChangeExtension (FileName.FileName, ".projitems")); + import.Label = "Shared"; + msproject.AddNewImport (@"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets"); + } else { + msproject.Load (FileName); + } + + // having no ToolsVersion is equivalent to 2.0, roundtrip that correctly + if (ToolsVersion != "2.0") + msproject.ToolsVersion = ToolsVersion; + else if (string.IsNullOrEmpty (msproject.ToolsVersion)) + msproject.ToolsVersion = null; + else + msproject.ToolsVersion = "2.0"; + + if (projitemsFile == null) + projitemsFile = Path.ChangeExtension (FileName, ".projitems"); + if (File.Exists (projitemsFile)) { + projitemsProject.Load (projitemsFile); + } else { + IMSBuildPropertySet grp = projitemsProject.AddNewPropertyGroup (true); + grp.SetValue ("MSBuildAllProjects", "$(MSBuildAllProjects);$(MSBuildThisFileFullPath)"); + grp.SetValue ("HasSharedItems", true); + grp.SetValue ("SharedGUID", ItemId, preserveExistingCase:true); + } + + IMSBuildPropertySet configGrp = projitemsProject.PropertyGroups.FirstOrDefault (g => g.Label == "Configuration"); + if (configGrp == null) { + configGrp = projitemsProject.AddNewPropertyGroup (true); + configGrp.Label = "Configuration"; + } + configGrp.SetValue ("Import_RootNamespace", DefaultNamespace); + + SaveProjectItems (monitor, new MSBuildFileFormatVS12 (), projitemsProject, "$(MSBuildThisFileDirectory)"); + + // Remove all items of this project, since items are saved in the projitems file + + foreach (var it in msproject.GetAllItems ().ToArray ()) + msproject.RemoveItem (it); + + projitemsProject.Save (projitemsFile); + } + + protected override IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles) { - var list = base.OnGetItemFiles (includeReferencedFiles); + var list = base.OnGetItemFiles (includeReferencedFiles).ToList (); if (!string.IsNullOrEmpty (FileName)) - list.Add (FileName.ChangeExtension (".projitems")); + list.Add (ProjItemsPath); return list; } @@ -70,10 +165,19 @@ namespace MonoDevelop.Projects.SharedAssetsProjects public string DefaultNamespace { get; set; } - public override IEnumerable<string> GetProjectTypes () + public FilePath ProjItemsPath { + get { + return projitemsFile != null ? (FilePath) projitemsFile : FileName.ChangeExtension (".projitems"); + } + set { + projitemsFile = value; + } + } + + protected override void OnGetProjectTypes (HashSet<string> types) { - yield return "SharedAssets"; - yield return "DotNet"; + types.Add ("SharedAssets"); + types.Add ("DotNet"); } public override string[] SupportedLanguages { @@ -95,17 +199,22 @@ namespace MonoDevelop.Projects.SharedAssetsProjects return LanguageBinding.IsSourceCodeFile (fileName); } - protected override BuildResult OnBuild (MonoDevelop.Core.IProgressMonitor monitor, ConfigurationSelector configuration) + protected override Task<BuildResult> OnBuild (MonoDevelop.Core.ProgressMonitor monitor, ConfigurationSelector configuration) + { + return Task.FromResult (BuildResult.Success); + } + + protected override bool OnGetSupportsTarget (string target) { - return new BuildResult (); + return false; } - internal protected override bool OnGetSupportsTarget (string target) + protected override bool OnGetSupportsExecute () { return false; } - internal protected override bool OnGetSupportsExecute () + protected override bool OnGetSupportsBuild () { return false; } @@ -143,7 +252,7 @@ namespace MonoDevelop.Projects.SharedAssetsProjects // Maybe there is a project that is already referencing this one. It may happen when creating a solution // from a template - foreach (var p in ParentSolution.GetAllSolutionItems<DotNetProject> ()) + foreach (var p in ParentSolution.GetAllItems<DotNetProject> ()) ProcessProject (p); } @@ -191,6 +300,14 @@ namespace MonoDevelop.Projects.SharedAssetsProjects void ProcessProject (DotNetProject p) { + // When the projitems file name doesn't match the shproj file name, the reference we add to the referencing projects + // uses the projitems name, not the shproj name. Here we detect such case and re-add the references using the correct name + var referencesToFix = p.References.Where (r => r.GetItemsProjectPath () == ProjItemsPath && r.Reference != Name).ToList (); + foreach (var r in referencesToFix) { + p.References.Remove (r); + p.References.Add (new ProjectReference (this)); + } + foreach (var pref in p.References.Where (r => r.ReferenceType == ReferenceType.Project && r.Reference == Name)) ProcessNewReference (pref); } @@ -198,7 +315,7 @@ namespace MonoDevelop.Projects.SharedAssetsProjects void ProcessNewReference (ProjectReference pref) { pref.Flags = ProjectItemFlags.DontPersist; - pref.SetItemsProjectPath (Path.ChangeExtension (FileName, ".projitems")); + pref.SetItemsProjectPath (ProjItemsPath); foreach (var f in Files) { if (pref.OwnerProject.Files.GetFile (f.FilePath) == null) { var cf = (ProjectFile)f.Clone (); @@ -268,7 +385,7 @@ namespace MonoDevelop.Projects.SharedAssetsProjects if (ParentSolution == null) return new DotNetProject[0]; - return ParentSolution.GetAllSolutionItems<DotNetProject> ().Where (p => p.References.Any (r => r.GetItemsProjectPath () != null)); + return ParentSolution.GetAllItems<DotNetProject> ().Where (p => p.References.Any (r => r.GetItemsProjectPath () != null)); } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProjectMSBuildExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProjectMSBuildExtension.cs index 1da660c7a1..645d7b282a 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProjectMSBuildExtension.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProjectMSBuildExtension.cs @@ -32,53 +32,45 @@ using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.Projects.SharedAssetsProjects { - class SharedAssetsProjectMSBuildExtension: MSBuildExtension + [RegisterProjectModelExtension] + class SharedAssetsProjectMSBuildExtension: DotNetProjectExtension { - public override void LoadProject (IProgressMonitor monitor, SolutionEntityItem item, MSBuildProject msproject) + internal protected override void OnReadProject (ProgressMonitor monitor, MSBuildProject msproject) { - base.LoadProject (monitor, item, msproject); - - var dnp = item as DotNetProject; - if (dnp == null) - return; + base.OnReadProject (monitor, msproject); // Convert .projitems imports into project references foreach (var sp in msproject.Imports.Where (im => im.Label == "Shared" && im.Project.EndsWith (".projitems"))) { var projitemsFile = sp.Project; if (!string.IsNullOrEmpty (projitemsFile)) { - projitemsFile = MSBuildProjectService.FromMSBuildPath (item.ItemDirectory, projitemsFile); + projitemsFile = MSBuildProjectService.FromMSBuildPath (Project.ItemDirectory, projitemsFile); projitemsFile = Path.Combine (Path.GetDirectoryName (msproject.FileName), projitemsFile); if (File.Exists (projitemsFile)) { - MSBuildSerializer iser = Handler.CreateSerializer (); - iser.SerializationContext.BaseFile = projitemsFile; - iser.SerializationContext.ProgressMonitor = monitor; MSBuildProject p = new MSBuildProject (); p.Load (projitemsFile); - Handler.LoadProjectItems (p, iser, ProjectItemFlags.Hidden | ProjectItemFlags.DontPersist); + Project.LoadProjectItems (p, ProjectItemFlags.Hidden | ProjectItemFlags.DontPersist); var r = new ProjectReference (ReferenceType.Project, Path.GetFileNameWithoutExtension (projitemsFile)); r.Flags = ProjectItemFlags.DontPersist; r.SetItemsProjectPath (projitemsFile); - dnp.References.Add (r); + Project.References.Add (r); } } } } - public override void SaveProject (IProgressMonitor monitor, SolutionEntityItem item, MSBuildProject project) + internal protected override void OnWriteProject (ProgressMonitor monitor, MSBuildProject project) { - base.SaveProject (monitor, item, project); - var dnp = item as DotNetProject; - if (dnp == null) - return; + base.OnWriteProject (monitor, project); + HashSet<string> validProjitems = new HashSet<string> (); - foreach (var r in dnp.References.Where (rp => rp.ReferenceType == ReferenceType.Project)) { + foreach (var r in Project.References.Where (rp => rp.ReferenceType == ReferenceType.Project)) { var ip = r.GetItemsProjectPath (); if (!string.IsNullOrEmpty (ip)) { - ip = MSBuildProjectService.ToMSBuildPath (item.ItemDirectory, ip); + ip = MSBuildProjectService.ToMSBuildPath (Project.ItemDirectory, ip); validProjitems.Add (ip); if (!project.Imports.Any (im => im.Project == ip)) { - var im = project.AddNewImport (ip, project.Imports.FirstOrDefault (i => i.Label != "Shared")); + var im = project.AddNewImport (ip, beforeImport:project.Imports.FirstOrDefault (i => i.Label != "Shared")); im.Label = "Shared"; im.Condition = "Exists('" + ip + "')"; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProjectMSBuildHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProjectMSBuildHandler.cs deleted file mode 100644 index d64df4f8e0..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProjectMSBuildHandler.cs +++ /dev/null @@ -1,139 +0,0 @@ -// -// SharedProjectMSBuildHandler.cs -// -// Author: -// Lluis Sanchez <lluis@xamarin.com> -// -// Copyright (c) 2014 Xamarin Inc -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Linq; -using System.Xml; -using System.IO; -using MonoDevelop.Core; -using System.Collections.Generic; -using MonoDevelop.Projects.Formats.MSBuild; - -namespace MonoDevelop.Projects.SharedAssetsProjects -{ - class SharedAssetsProjectMSBuildHandler: MSBuildProjectHandler - { - string projitemsFile; - - public SharedAssetsProjectMSBuildHandler () - { - } - - protected override void LoadProject (IProgressMonitor monitor, MSBuildProject msproject) - { - var doc = msproject.Document; - projitemsFile = null; - foreach (var no in doc.DocumentElement.ChildNodes) { - var im = no as XmlElement; - if (im != null && im.LocalName == "Import" && im.GetAttribute ("Label") == "Shared") { - projitemsFile = im.GetAttribute ("Project"); - break; - } - } - if (projitemsFile == null) - return; - - // TODO: load the type from msbuild - ((SharedAssetsProject)EntityItem).LanguageName = "C#"; - - projitemsFile = Path.Combine (Path.GetDirectoryName (msproject.FileName), projitemsFile); - - MSBuildProject p = new MSBuildProject (); - p.Load (projitemsFile); - - MSBuildSerializer ser = CreateSerializer (); - ser.SerializationContext.BaseFile = EntityItem.FileName; - ser.SerializationContext.ProgressMonitor = monitor; - - Item.SetItemHandler (this); - - var cp = p.PropertyGroups.FirstOrDefault (g => g.Label == "Configuration"); - if (cp != null) - ((SharedAssetsProject)EntityItem).DefaultNamespace = cp.GetPropertyValue ("Import_RootNamespace"); - - LoadProjectItems (p, ser, ProjectItemFlags.None); - } - - protected override MSBuildProject SaveProject (IProgressMonitor monitor) - { - MSBuildSerializer ser = CreateSerializer (); - ser.SerializationContext.BaseFile = EntityItem.FileName; - ser.SerializationContext.ProgressMonitor = monitor; - - MSBuildProject projitemsProject = new MSBuildProject (); - MSBuildProject msproject = new MSBuildProject (); - - var newProject = EntityItem.FileName == null || !File.Exists (EntityItem.FileName); - if (newProject) { - var grp = msproject.GetGlobalPropertyGroup (); - if (grp == null) - grp = msproject.AddNewPropertyGroup (false); - grp.SetPropertyValue ("ProjectGuid", EntityItem.ItemId, false); - var import = msproject.AddNewImport (@"$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"); - import.Condition = @"Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"; - msproject.AddNewImport (@"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props"); - msproject.AddNewImport (@"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props"); - import = msproject.AddNewImport (Path.ChangeExtension (EntityItem.FileName.FileName, ".projitems")); - import.Label = "Shared"; - msproject.AddNewImport (@"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets"); - } else { - msproject.Load (EntityItem.FileName); - } - - // having no ToolsVersion is equivalent to 2.0, roundtrip that correctly - if (ToolsVersion != "2.0") - msproject.ToolsVersion = ToolsVersion; - else if (string.IsNullOrEmpty (msproject.ToolsVersion)) - msproject.ToolsVersion = null; - else - msproject.ToolsVersion = "2.0"; - - if (projitemsFile == null) - projitemsFile = Path.ChangeExtension (EntityItem.FileName, ".projitems"); - if (File.Exists (projitemsFile)) { - projitemsProject.Load (projitemsFile); - } else { - var grp = projitemsProject.AddNewPropertyGroup (true); - grp.SetPropertyValue ("MSBuildAllProjects", "$(MSBuildAllProjects);$(MSBuildThisFileFullPath)", false); - grp.SetPropertyValue ("HasSharedItems", "true", false); - grp.SetPropertyValue ("SharedGUID", EntityItem.ItemId, false); - } - - var configGrp = projitemsProject.PropertyGroups.FirstOrDefault (g => g.Label == "Configuration"); - if (configGrp == null) { - configGrp = projitemsProject.AddNewPropertyGroup (true); - configGrp.Label = "Configuration"; - } - configGrp.SetPropertyValue ("Import_RootNamespace", ((SharedAssetsProject)EntityItem).DefaultNamespace, false); - - SaveProjectItems (monitor, new MSBuildFileFormatVS12 (), ser, projitemsProject, "$(MSBuildThisFileDirectory)"); - - projitemsProject.Save (projitemsFile); - - return msproject; - } - } -} - diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Text/TextEncoding.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Text/TextEncoding.cs index b1126af426..464366de6a 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Text/TextEncoding.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Text/TextEncoding.cs @@ -121,7 +121,7 @@ namespace MonoDevelop.Projects.Text PropertyService.SaveProperties (); } } - + public static TextEncoding GetEncoding (string id) { foreach (TextEncoding e in SupportedEncodings) { @@ -130,6 +130,15 @@ namespace MonoDevelop.Projects.Text } return null; } + + public static TextEncoding GetEncoding (int codePage) + { + foreach (TextEncoding e in SupportedEncodings) { + if (e.CodePage == codePage) + return e; + } + return null; + } public static string DefaultEncoding { get { return "UTF-8"; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/BuildEventHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/BuildEventHandler.cs index ef76135af7..596d7ee072 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/BuildEventHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/BuildEventHandler.cs @@ -35,10 +35,10 @@ namespace MonoDevelop.Projects public class BuildEventArgs: EventArgs { - IProgressMonitor monitor; + ProgressMonitor monitor; bool success; - public BuildEventArgs (IProgressMonitor monitor, bool success) + public BuildEventArgs (ProgressMonitor monitor, bool success) { this.monitor = monitor; this.success = success; @@ -48,7 +48,7 @@ namespace MonoDevelop.Projects this.FailedBuildCount = -1; } - public IProgressMonitor ProgressMonitor { + public ProgressMonitor ProgressMonitor { get { return monitor; } } @@ -72,7 +72,7 @@ namespace MonoDevelop.Projects get; set; } - public SolutionItem SolutionItem { + public SolutionFolderItem SolutionItem { get; set; } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/BuildResult.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/BuildResult.cs index 543ec390c1..9bfa798cba 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/BuildResult.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/BuildResult.cs @@ -43,6 +43,7 @@ namespace MonoDevelop.Projects string compilerOutput; List<BuildError> errors = new List<BuildError> (); IBuildTarget sourceTarget; + static BuildResult success = new BuildResult (); public BuildResult() { @@ -65,6 +66,18 @@ namespace MonoDevelop.Projects } } } + + public bool HasErrors { + get { return ErrorCount > 0; } + } + + public bool HasWarnings { + get { return WarningCount > 0; } + } + + public static BuildResult Success { + get { return success; } + } public ReadOnlyCollection<BuildError> Errors { get { return errors.AsReadOnly (); } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/BuildTool.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/BuildTool.cs index 43b3b5cfd6..46479efbc9 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/BuildTool.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/BuildTool.cs @@ -34,6 +34,7 @@ using Mono.Addins; using MonoDevelop.Core.ProgressMonitoring; using MonoDevelop.Core; using MonoDevelop.Core.Assemblies; +using System.Threading.Tasks; namespace MonoDevelop.Projects { @@ -48,6 +49,13 @@ namespace MonoDevelop.Projects public int Run (string[] arguments) { + var t = RunAsync (arguments); + t.Wait (); + return t.Result; + } + + public async Task<int> RunAsync (string[] arguments) + { Console.WriteLine (BrandingService.BrandApplicationName ("MonoDevelop Build Tool")); foreach (string s in arguments) ReadArgument (s); @@ -93,7 +101,7 @@ namespace MonoDevelop.Projects } } - IProgressMonitor monitor = new ConsoleProjectLoadProgressMonitor (new ConsoleProgressMonitor ()); + ProgressMonitor monitor = new ConsoleProjectLoadProgressMonitor (new ConsoleProgressMonitor ()); TargetRuntime targetRuntime = null; TargetRuntime defaultRuntime = Runtime.SystemAssemblyService.DefaultRuntime; @@ -106,11 +114,16 @@ namespace MonoDevelop.Projects IBuildTarget item; if (solFile != null) - item = Services.ProjectService.ReadWorkspaceItem (monitor, solFile); + item = await Services.ProjectService.ReadWorkspaceItem (monitor, solFile) as IBuildTarget; else - item = Services.ProjectService.ReadSolutionItem (monitor, itemFile); + item = await Services.ProjectService.ReadSolutionItem (monitor, itemFile); - using (var readItem = item) { + if (item == null) { + Console.WriteLine ("The file '" + file + "' can't be built"); + return 1; + } + + using (var readItem = (WorkspaceObject)item) { if (project != null) { Solution solution = item as Solution; item = null; @@ -130,21 +143,25 @@ namespace MonoDevelop.Projects monitor = new ConsoleProgressMonitor (); BuildResult res = null; - if (item is SolutionEntityItem && ((SolutionEntityItem)item).ParentSolution == null) { + if (item is SolutionItem && ((SolutionItem)item).ParentSolution == null) { ConfigurationSelector configuration = new ItemConfigurationSelector (config); - res = item.RunTarget (monitor, command, configuration); + if (command == ProjectService.BuildTarget) + res = await item.Build (monitor, configuration); + else if (command == ProjectService.CleanTarget) + res = await item.Clean (monitor, configuration); } else { ConfigurationSelector configuration = new SolutionConfigurationSelector (config); - SolutionEntityItem solutionEntityItem = item as SolutionEntityItem; + SolutionItem solutionEntityItem = item as SolutionItem; if (solutionEntityItem != null) { if (command == ProjectService.BuildTarget) - res = solutionEntityItem.Build (monitor, configuration, true); + res = await solutionEntityItem.Build (monitor, configuration, true); else if (command == ProjectService.CleanTarget) - solutionEntityItem.Clean (monitor, configuration); - else - res = item.RunTarget (monitor, command, configuration); + await solutionEntityItem.Clean (monitor, configuration); + else if (solutionEntityItem is Project) + res = await ((Project)item).RunTarget (monitor, command, configuration); } else { - res = item.RunTarget (monitor, command, configuration); + Console.WriteLine ("The project '" + project + "' can't be built"); + return 1; } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ChainedExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ChainedExtension.cs new file mode 100644 index 0000000000..48af259aba --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ChainedExtension.cs @@ -0,0 +1,94 @@ +// +// ChainedExtension.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Reflection; +using System.Linq; +using System.Collections.Generic; + +namespace MonoDevelop.Projects +{ + public class ChainedExtension: IDisposable + { + ChainedExtension nextInChain; + + internal protected static T FindNextImplementation<T> (ChainedExtension next) where T:class + { + if (next == null) + return null; + + var nextT = next as T; + if (nextT == null) + return FindNextImplementation<T> (next.nextInChain); + + foreach (var m in typeof(T).GetMembers (BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { + MethodInfo method = m as MethodInfo; + if (method == null) { + var prop = m as PropertyInfo; + if (prop != null) { + method = prop.GetGetMethod (); + if (method == null) + method = prop.GetSetMethod (); + } + } + if (method != null && method.IsVirtual && method.Name != "InitializeChain") { + var tm = next.GetType ().GetMethod (method.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, method.GetParameters ().Select (p=>p.ParameterType).ToArray (), null); + if (tm == null) + continue; + if (tm.DeclaringType != typeof(T)) + return nextT; + } + } + + return FindNextImplementation<T> (next.nextInChain); + } + + internal void Init (ChainedExtension next) + { + nextInChain = next; + InitializeChain (next); + } + + internal protected virtual void InitializeChain (ChainedExtension next) + { + } + + internal ChainedExtension Next { + get { return nextInChain; } + } + + internal void DisposeChain () + { + Dispose (); + if (nextInChain != null) + nextInChain.DisposeChain (); + } + + public virtual void Dispose () + { + } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CleanEventHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CleanEventHandler.cs index 5d0dc54264..430a43b3fe 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CleanEventHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CleanEventHandler.cs @@ -33,14 +33,14 @@ namespace MonoDevelop.Projects public class CleanEventArgs : EventArgs { - IProgressMonitor monitor; + ProgressMonitor monitor; - public CleanEventArgs (IProgressMonitor monitor) + public CleanEventArgs (ProgressMonitor monitor) { this.monitor = monitor; } - public IProgressMonitor Monitor { + public ProgressMonitor Monitor { get { return monitor; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CombineEntryRenamedEventArgs.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CombineEntryRenamedEventArgs.cs index 41f95e07ad..c7efbcef93 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CombineEntryRenamedEventArgs.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CombineEntryRenamedEventArgs.cs @@ -37,7 +37,7 @@ namespace MonoDevelop.Projects string oldName; string newName; - public SolutionItemRenamedEventArgs (SolutionItem node, string oldName, string newName) + public SolutionItemRenamedEventArgs (SolutionFolderItem node, string oldName, string newName) : base (node) { this.oldName = oldName; diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CompiledAssemblyProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CompiledAssemblyProject.cs index 481bcd9ecf..bbaa65182f 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CompiledAssemblyProject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CompiledAssemblyProject.cs @@ -34,6 +34,9 @@ using MonoDevelop.Core.ProgressMonitoring; using System.Collections.Generic; using Mono.Cecil.Mdb; using Mono.Cecil.Cil; +using System.Threading.Tasks; +using MonoDevelop.Core.Serialization; +using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.Projects { @@ -46,9 +49,9 @@ namespace MonoDevelop.Projects AddNewConfiguration ("Default"); } - public override IEnumerable<string> GetProjectTypes () + protected override void OnGetProjectTypes (HashSet<string> types) { - yield return "CompiledAssembly"; + types.Add ("CompiledAssembly"); } public override IconId StockIcon { @@ -137,17 +140,12 @@ namespace MonoDevelop.Projects return string.Join (Path.DirectorySeparatorChar.ToString (), s1, 0, n); } - protected override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration) + protected override Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { - return new BuildResult (); + return Task.FromResult (BuildResult.Success); } - internal protected override bool OnGetNeedsBuilding (ConfigurationSelector configuration) - { - return false; - } - - internal protected override void OnExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + protected async override Task OnExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { ProjectConfiguration conf = (ProjectConfiguration) GetConfiguration (configuration); monitor.Log.WriteLine (GettextCatalog.GetString ("Running {0} ...", FileName)); @@ -156,8 +154,6 @@ namespace MonoDevelop.Projects ? context.ExternalConsoleFactory.CreateConsole (!conf.PauseConsoleOutput) : context.ConsoleFactory.CreateConsole (!conf.PauseConsoleOutput); - AggregatedOperationMonitor aggregatedOperationMonitor = new AggregatedOperationMonitor (monitor); - try { try { ExecutionCommand executionCommand = CreateExecutionCommand (configuration, conf); @@ -167,14 +163,16 @@ namespace MonoDevelop.Projects return; } - IProcessAsyncOperation asyncOp = context.ExecutionHandler.Execute (executionCommand, console); - aggregatedOperationMonitor.AddOperation (asyncOp); - asyncOp.WaitForCompleted (); + ProcessAsyncOperation asyncOp = context.ExecutionHandler.Execute (executionCommand, console); + var stopper = monitor.CancellationToken.Register (asyncOp.Cancel); + + await asyncOp.Task; + + stopper.Dispose (); monitor.Log.WriteLine (GettextCatalog.GetString ("The application exited with code: {0}", asyncOp.ExitCode)); } finally { console.Dispose (); - aggregatedOperationMonitor.Dispose (); } } catch (Exception ex) { LoggingService.LogError (string.Format ("Cannot execute \"{0}\"", FileName), ex); @@ -182,7 +180,7 @@ namespace MonoDevelop.Projects } } - internal protected override bool OnGetCanExecute (ExecutionContext context, ConfigurationSelector configuration) + protected override bool OnGetCanExecute (ExecutionContext context, ConfigurationSelector configuration) { ProjectConfiguration config = (ProjectConfiguration) GetConfiguration (configuration); if (config == null) @@ -201,6 +199,32 @@ namespace MonoDevelop.Projects cmd.EnvironmentVariables = new Dictionary<string, string> (configuration.EnvironmentVariables); return cmd; } + + public override bool HasSlnData { + get { + return true; + } + } + + public override DataItem WriteSlnData () + { + DataSerializer ser = new DataSerializer (MSBuildProjectService.DataContext); + ser.SerializationContext.BaseFile = FileName; + ser.SerializationContext.DirectorySeparatorChar = '\\'; + DataItem data = (DataItem) ser.Serialize (this, typeof(CompiledAssemblyProject)); + return data; + } + + public override void ReadSlnData (DataItem item) + { + // Remove the default configuration, since new ones will be loaded + Configurations.Clear (); + + DataSerializer ser = new DataSerializer (MSBuildProjectService.DataContext); + ser.SerializationContext.BaseFile = FileName; + ser.SerializationContext.DirectorySeparatorChar = '\\'; + ser.Deserialize (this, item); + } } public class CompiledAssemblyExtension: ProjectServiceExtension @@ -212,22 +236,17 @@ namespace MonoDevelop.Projects return base.IsSolutionItemFile (fileName); } - protected override SolutionEntityItem LoadSolutionItem (IProgressMonitor monitor, string fileName) + protected override Task<SolutionItem> LoadSolutionItem (ProgressMonitor monitor, string fileName) { if (fileName.ToLower().EndsWith (".exe") || fileName.ToLower().EndsWith (".dll")) { - CompiledAssemblyProject p = new CompiledAssemblyProject (); - p.LoadFrom (fileName); - return p; + return Task<SolutionItem>.Factory.StartNew (delegate { + CompiledAssemblyProject p = new CompiledAssemblyProject (); + p.LoadFrom (fileName); + return p; + }); } return base.LoadSolutionItem (monitor, fileName); } - - public override void Save (IProgressMonitor monitor, SolutionEntityItem item) - { -// if (item is CompiledAssemblyProject) -// return; - base.Save (monitor, item); - } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ConfigurationEventHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ConfigurationEventHandler.cs index fdec84f720..61d537dd5f 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ConfigurationEventHandler.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ConfigurationEventHandler.cs @@ -38,7 +38,7 @@ namespace MonoDevelop.Projects { ItemConfiguration configuration; - public ConfigurationEventArgs (SolutionEntityItem entry, ItemConfiguration configuration): base (entry) + public ConfigurationEventArgs (SolutionItem entry, ItemConfiguration configuration): base (entry) { this.configuration = configuration; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CustomCommand.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CustomCommand.cs index 115edb369f..f74b6f51e8 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CustomCommand.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CustomCommand.cs @@ -35,6 +35,8 @@ using MonoDevelop.Core.Execution; using MonoDevelop.Core.StringParsing; using System.Collections.Generic; using MonoDevelop.Core.ProgressMonitoring; +using System.Threading.Tasks; +using System.Threading; namespace MonoDevelop.Projects { @@ -98,7 +100,7 @@ namespace MonoDevelop.Projects set { pauseExternalConsole = value; } } - public string GetCommandFile (IWorkspaceObject entry, ConfigurationSelector configuration) + public string GetCommandFile (WorkspaceObject entry, ConfigurationSelector configuration) { string exe, args; StringTagModel tagSource = GetTagModel (entry, configuration); @@ -106,7 +108,7 @@ namespace MonoDevelop.Projects return exe; } - public string GetCommandArgs (IWorkspaceObject entry, ConfigurationSelector configuration) + public string GetCommandArgs (WorkspaceObject entry, ConfigurationSelector configuration) { string exe, args; StringTagModel tagSource = GetTagModel (entry, configuration); @@ -114,7 +116,7 @@ namespace MonoDevelop.Projects return args; } - public FilePath GetCommandWorkingDir (IWorkspaceObject entry, ConfigurationSelector configuration) + public FilePath GetCommandWorkingDir (WorkspaceObject entry, ConfigurationSelector configuration) { StringTagModel tagSource = GetTagModel (entry, configuration); if (string.IsNullOrEmpty (workingdir)) @@ -135,10 +137,10 @@ namespace MonoDevelop.Projects return cmd; } - StringTagModel GetTagModel (IWorkspaceObject entry, ConfigurationSelector configuration) + StringTagModel GetTagModel (WorkspaceObject entry, ConfigurationSelector configuration) { - if (entry is SolutionItem) - return ((SolutionItem)entry).GetStringTagModel (configuration); + if (entry is SolutionFolderItem) + return ((SolutionFolderItem)entry).GetStringTagModel (configuration); else if (entry is WorkspaceItem) return ((WorkspaceItem)entry).GetStringTagModel (); else @@ -172,7 +174,7 @@ namespace MonoDevelop.Projects args = StringParserService.Parse (args, tagSource); } - public ProcessExecutionCommand CreateExecutionCommand (IWorkspaceObject entry, ConfigurationSelector configuration) + public ProcessExecutionCommand CreateExecutionCommand (WorkspaceObject entry, ConfigurationSelector configuration) { string exe, args; StringTagModel tagSource = GetTagModel (entry, configuration); @@ -207,12 +209,12 @@ namespace MonoDevelop.Projects return cmd; } - public void Execute (IProgressMonitor monitor, IWorkspaceObject entry, ConfigurationSelector configuration) + public Task<bool> Execute (ProgressMonitor monitor, WorkspaceObject entry, ConfigurationSelector configuration) { - Execute (monitor, entry, null, configuration); + return Execute (monitor, entry, null, configuration); } - public bool CanExecute (IWorkspaceObject entry, ExecutionContext context, ConfigurationSelector configuration) + public bool CanExecute (WorkspaceObject entry, ExecutionContext context, ConfigurationSelector configuration) { if (string.IsNullOrEmpty (command)) return false; @@ -224,7 +226,7 @@ namespace MonoDevelop.Projects return context.ExecutionHandler.CanExecute (cmd); } - public void Execute (IProgressMonitor monitor, IWorkspaceObject entry, ExecutionContext context, + public async Task<bool> Execute (ProgressMonitor monitor, WorkspaceObject entry, ExecutionContext context, ConfigurationSelector configuration) { ProcessExecutionCommand cmd = CreateExecutionCommand (entry, configuration); @@ -233,12 +235,12 @@ namespace MonoDevelop.Projects if (!Directory.Exists (cmd.WorkingDirectory)) { monitor.ReportError (GettextCatalog.GetString ("Custom command working directory does not exist"), null); - return; + return false; } - AggregatedOperationMonitor aggMon = null; - IProcessAsyncOperation oper = null; + ProcessAsyncOperation oper = null; IConsole console = null; + var result = true; try { if (context != null) { @@ -254,35 +256,33 @@ namespace MonoDevelop.Projects cmd.WorkingDirectory, console, null); } else { oper = Runtime.ProcessService.StartProcess (cmd.Command, cmd.Arguments, - cmd.WorkingDirectory, monitor.Log, monitor.Log, null, false); + cmd.WorkingDirectory, monitor.Log, monitor.Log, null, false).ProcessAsyncOperation; } } - aggMon = new AggregatedOperationMonitor (monitor, oper); - oper.WaitForCompleted (); - if (!oper.Success) { + + var stopper = monitor.CancellationToken.Register (oper.Cancel); + + await oper.Task; + + stopper.Dispose (); + + if (oper.ExitCode != 0) { monitor.ReportError ("Custom command failed (exit code: " + oper.ExitCode + ")", null); } } catch (Win32Exception w32ex) { monitor.ReportError (GettextCatalog.GetString ("Failed to execute custom command '{0}': {1}", cmd.Command, w32ex.Message), null); - return; + return false; } catch (Exception ex) { LoggingService.LogError ("Command execution failed", ex); throw new UserException (GettextCatalog.GetString ("Command execution failed: {0}", ex.Message)); } finally { - if (oper == null || !oper.Success) { - monitor.AsyncOperation.Cancel (); - } - if (oper != null) { - oper.Dispose (); - } + result = oper != null && oper.ExitCode == 0; if (console != null) { console.Dispose (); } - if (aggMon != null) { - aggMon.Dispose (); - } } + return result; } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CustomCommandCollection.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CustomCommandCollection.cs index 797ee6da64..ee37994054 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CustomCommandCollection.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CustomCommandCollection.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; using MonoDevelop.Core; +using System.Threading.Tasks; namespace MonoDevelop.Projects { @@ -48,19 +49,20 @@ namespace MonoDevelop.Projects Add (cmd.Clone ()); } - public void ExecuteCommand (IProgressMonitor monitor, IWorkspaceObject entry, CustomCommandType type, ConfigurationSelector configuration) + public Task<bool> ExecuteCommand (ProgressMonitor monitor, WorkspaceObject entry, CustomCommandType type, ConfigurationSelector configuration) { - ExecuteCommand (monitor, entry, type, null, configuration); + return ExecuteCommand (monitor, entry, type, null, configuration); } - public void ExecuteCommand (IProgressMonitor monitor, IWorkspaceObject entry, CustomCommandType type, ExecutionContext context, ConfigurationSelector configuration) + public async Task<bool> ExecuteCommand (ProgressMonitor monitor, WorkspaceObject entry, CustomCommandType type, ExecutionContext context, ConfigurationSelector configuration) { foreach (CustomCommand cmd in this) { - if (cmd.Type == type) - cmd.Execute (monitor, entry, context, configuration); - if (monitor.IsCancelRequested) - break; + if (cmd.Type == type) { + if (!await cmd.Execute (monitor, entry, context, configuration)) + return false; + } } + return true; } public bool HasCommands (CustomCommandType type) @@ -71,7 +73,7 @@ namespace MonoDevelop.Projects return false; } - public bool CanExecute (IWorkspaceObject entry, CustomCommandType type, ExecutionContext context, ConfigurationSelector configuration) + public bool CanExecute (WorkspaceObject entry, CustomCommandType type, ExecutionContext context, ConfigurationSelector configuration) { // Note: if this gets changed to return true if *any* of the commands can execute, then // ExecuteCommand() needs to be fixed to only execute commands that can be executed. diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CustomCommandExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CustomCommandExtension.cs deleted file mode 100644 index fc0a9bf77b..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CustomCommandExtension.cs +++ /dev/null @@ -1,101 +0,0 @@ -// CustomCommandExtension.cs -// -// Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2007 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// - - -using System; -using MonoDevelop.Core; -using System.CodeDom.Compiler; -using MonoDevelop.Core.Execution; - -namespace MonoDevelop.Projects -{ - internal class CustomCommandExtension: ProjectServiceExtension - { - protected override BuildResult Build (IProgressMonitor monitor, SolutionEntityItem entry, ConfigurationSelector configuration) - { - SolutionItemConfiguration conf = entry.GetConfiguration (configuration) as SolutionItemConfiguration; - if (conf != null) { - if (conf.CustomCommands.CanExecute (entry, CustomCommandType.BeforeBuild, null, configuration)) - conf.CustomCommands.ExecuteCommand (monitor, entry, CustomCommandType.BeforeBuild, configuration); - - if (monitor.IsCancelRequested) - return new BuildResult (new CompilerResults (null), ""); - } - - BuildResult res = base.Build (monitor, entry, configuration); - - if (conf != null && !monitor.IsCancelRequested && !res.Failed) { - if (conf.CustomCommands.CanExecute (entry, CustomCommandType.AfterBuild, null, configuration)) - conf.CustomCommands.ExecuteCommand (monitor, entry, CustomCommandType.AfterBuild, configuration); - } - - return res; - } - - protected override void Clean (IProgressMonitor monitor, SolutionEntityItem entry, ConfigurationSelector configuration) - { - SolutionItemConfiguration conf = entry.GetConfiguration (configuration) as SolutionItemConfiguration; - if (conf != null) { - if (conf.CustomCommands.CanExecute (entry, CustomCommandType.BeforeClean, null, configuration)) - conf.CustomCommands.ExecuteCommand (monitor, entry, CustomCommandType.BeforeClean, configuration); - - if (monitor.IsCancelRequested) - return; - } - - base.Clean (monitor, entry, configuration); - - if (conf != null && !monitor.IsCancelRequested) { - if (conf.CustomCommands.CanExecute (entry, CustomCommandType.AfterClean, null, configuration)) - conf.CustomCommands.ExecuteCommand (monitor, entry, CustomCommandType.AfterClean, configuration); - } - } - - protected override void Execute (IProgressMonitor monitor, SolutionEntityItem entry, ExecutionContext context, ConfigurationSelector configuration) - { - SolutionItemConfiguration conf = entry.GetConfiguration (configuration) as SolutionItemConfiguration; - if (conf != null) { - ExecutionContext localContext = new ExecutionContext (Runtime.ProcessService.DefaultExecutionHandler, context.ConsoleFactory, context.ExecutionTarget); - - if (conf.CustomCommands.CanExecute (entry, CustomCommandType.BeforeExecute, localContext, configuration)) - conf.CustomCommands.ExecuteCommand (monitor, entry, CustomCommandType.BeforeExecute, localContext, configuration); - - if (monitor.IsCancelRequested) - return; - } - - base.Execute (monitor, entry, context, configuration); - - if (conf != null && !monitor.IsCancelRequested) { - ExecutionContext localContext = new ExecutionContext (Runtime.ProcessService.DefaultExecutionHandler, context.ConsoleFactory, context.ExecutionTarget); - - if (conf.CustomCommands.CanExecute (entry, CustomCommandType.AfterExecute, localContext, configuration)) - conf.CustomCommands.ExecuteCommand (monitor, entry, CustomCommandType.AfterExecute, localContext, configuration); - } - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetAssemblyProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetAssemblyProject.cs deleted file mode 100644 index cba01e80c1..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetAssemblyProject.cs +++ /dev/null @@ -1,108 +0,0 @@ -// -// DotNetAssemblyProject.cs -// -// Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Xml; -using MonoDevelop.Core; -using MonoDevelop.Core.Assemblies; - -namespace MonoDevelop.Projects -{ - [ProjectModelDataItem ("DotNetProject")] - public class DotNetAssemblyProject: DotNetProject - { - public DotNetAssemblyProject () - { - } - - public DotNetAssemblyProject (string languageName) : base (languageName) - { - } - - public DotNetAssemblyProject (string languageName, ProjectCreateInformation projectCreateInfo, XmlElement projectOptions): - base (languageName, projectCreateInfo, projectOptions) - { - } - - public override System.Collections.Generic.IEnumerable<string> GetProjectTypes () - { - yield return "DotNetAssembly"; - foreach (var pt in base.GetProjectTypes ()) - yield return pt; - } - - public override bool SupportsFramework (TargetFramework framework) - { - // DotNetAssemblyProject can only generate assemblies for the regular framework. - // Special frameworks such as Moonlight or MonoTouch must subclass DotNetProject directly. - if (!framework.CanReferenceAssembliesTargetingFramework (TargetFrameworkMoniker.NET_1_1)) - return false; - - return base.SupportsFramework (framework); - } - - public override TargetFrameworkMoniker GetDefaultTargetFrameworkForFormat (FileFormat format) - { - switch (format.Id) { - case "MSBuild05": - return TargetFrameworkMoniker.NET_2_0; - case "MSBuild08": - return TargetFrameworkMoniker.NET_2_0; - case "MSBuild10": - case "MSBuild12": - return TargetFrameworkMoniker.NET_4_0; - } - return Services.ProjectService.DefaultTargetFramework.Id; - } - - protected override string GetDefaultTargetPlatform (ProjectCreateInformation projectCreateInfo) - { - if (CompileTarget == CompileTarget.Library) - return string.Empty; - - // Guess a good default platform for the project - if (projectCreateInfo.ParentFolder != null && projectCreateInfo.ParentFolder.ParentSolution != null) { - ItemConfiguration conf = projectCreateInfo.ParentFolder.ParentSolution.GetConfiguration (projectCreateInfo.ActiveConfiguration); - if (conf != null) - return conf.Platform; - else { - string curName, curPlatform, bestPlatform = null; - string sconf = projectCreateInfo.ActiveConfiguration.ToString (); - ItemConfiguration.ParseConfigurationId (sconf, out curName, out curPlatform); - foreach (ItemConfiguration ic in projectCreateInfo.ParentFolder.ParentSolution.Configurations) { - if (ic.Platform == curPlatform) - return curPlatform; - if (ic.Name == curName) - bestPlatform = ic.Platform; - } - if (bestPlatform != null) - return bestPlatform; - } - } - return Services.ProjectService.DefaultPlatformTarget; - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ConfigurationParameters.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetCompilerParameters.cs index 9ff5f46356..c45f57b51c 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ConfigurationParameters.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetCompilerParameters.cs @@ -31,9 +31,7 @@ using System.Linq; namespace MonoDevelop.Projects { - ///<summary>This should really be called DotNetCompilerParameters</summary> - [DataItem (FallbackType=typeof(UnknownCompilationParameters))] - public abstract class ConfigurationParameters: ProjectParameters + public abstract class DotNetCompilerParameters: ProjectParameters { DotNetProjectConfiguration configuration; @@ -58,9 +56,9 @@ namespace MonoDevelop.Projects return GetDefineSymbols ().Any (s => s == symbol); } - public new ConfigurationParameters Clone () + public new DotNetCompilerParameters Clone () { - return (ConfigurationParameters) base.Clone (); + return (DotNetCompilerParameters) base.Clone (); } public DotNetProjectConfiguration ParentConfiguration { @@ -71,11 +69,7 @@ namespace MonoDevelop.Projects ParentProject = configuration.ParentItem; } } - } - public abstract class DotNetConfigurationParameters : ConfigurationParameters - { - public abstract bool NoStdLib { get; set; } + public virtual bool NoStdLib { get; set; } } - } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs index d6a7a8c7f0..e2148a39ac 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs @@ -2,7 +2,7 @@ // // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2009 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy @@ -44,53 +44,67 @@ using MonoDevelop.Projects.Extensions; using MonoDevelop.Projects.Formats.MSBuild; using MonoDevelop.Core.Assemblies; using System.Globalization; +using System.Threading.Tasks; +using Mono.Addins; namespace MonoDevelop.Projects { - [DataInclude(typeof(DotNetProjectConfiguration))] - [ProjectModelDataItem ("AbstractDotNetProject")] - public abstract class DotNetProject : Project, IAssemblyProject, IDotNetFileContainer + public class DotNetProject : Project, IAssemblyProject, IDotNetFileContainer { bool usePartialTypes = true; - ProjectParameters languageParameters; DirectoryAssemblyContext privateAssemblyContext; ComposedAssemblyContext composedAssemblyContext; IAssemblyContext currentRuntimeContext; - [ItemProperty("OutputType")] CompileTarget compileTarget; IDotNetLanguageBinding languageBinding; protected ProjectReferenceCollection projectReferences; - [ItemProperty("RootNamespace", DefaultValue = "")] protected string defaultNamespace = String.Empty; - - public DotNetProject () + + protected DotNetProject () { - Runtime.SystemAssemblyService.DefaultRuntimeChanged += RuntimeSystemAssemblyServiceDefaultRuntimeChanged; + Initialize (this); + } + + protected DotNetProject (string languageName, params string[] flavorIds): base (flavorIds) + { + this.languageName = languageName; + Initialize (this); + } + + protected override void OnInitialize () + { + UseMSBuildEngineByDefault = true; + RequireMSBuildEngine = false; projectReferences = new ProjectReferenceCollection (); Items.Bind (projectReferences); - if (IsLibraryBasedProjectType) - CompileTarget = CompileTarget.Library; FileService.FileRemoved += OnFileRemoved; + Runtime.SystemAssemblyService.DefaultRuntimeChanged += RuntimeSystemAssemblyServiceDefaultRuntimeChanged; + + base.OnInitialize (); + + if (languageName == null) + languageName = MSBuildProjectService.GetLanguageFromGuid (TypeGuid); } - public DotNetProject (string languageName) : this() + protected override void OnExtensionChainInitialized () { - // Language name must be set before the item handler is assigned - this.languageName = languageName; - this.languageBinding = FindLanguage (languageName); - - if (this.languageBinding != null) - this.StockIcon = this.languageBinding.ProjectStockIcon; + base.OnExtensionChainInitialized (); this.usePartialTypes = SupportsPartialTypes; + + if (LanguageBinding != null) + this.StockIcon = LanguageBinding.ProjectStockIcon; + + if (IsLibraryBasedProjectType) + CompileTarget = CompileTarget.Library; } - public DotNetProject (string languageName, ProjectCreateInformation projectCreateInfo, XmlElement projectOptions) : this(languageName) + public override void InitializeNew (ProjectCreateInformation projectCreateInfo, XmlElement projectOptions) { if ((projectOptions != null) && (projectOptions.Attributes ["Target"] != null)) CompileTarget = (CompileTarget)Enum.Parse (typeof(CompileTarget), projectOptions.Attributes ["Target"].Value); @@ -98,8 +112,7 @@ namespace MonoDevelop.Projects CompileTarget = CompileTarget.Library; if (this.LanguageBinding != null) { - LanguageParameters = languageBinding.CreateProjectParameters (projectOptions); - + bool externalConsole = false; string platform = null; @@ -117,22 +130,22 @@ namespace MonoDevelop.Projects } string platformSuffix = string.IsNullOrEmpty (platform) ? string.Empty : "|" + platform; DotNetProjectConfiguration configDebug = CreateConfiguration ("Debug" + platformSuffix) as DotNetProjectConfiguration; - configDebug.CompilationParameters = languageBinding.CreateCompilationParameters (projectOptions); + configDebug.CompilationParameters = LanguageBinding.CreateCompilationParameters (projectOptions); configDebug.DebugMode = true; configDebug.ExternalConsole = externalConsole; configDebug.PauseConsoleOutput = externalConsole; Configurations.Add (configDebug); DotNetProjectConfiguration configRelease = CreateConfiguration ("Release" + platformSuffix) as DotNetProjectConfiguration; - + if (projectOptions != null) { XmlElement releaseProjectOptions = (XmlElement)projectOptions.CloneNode (true); releaseProjectOptions.SetAttribute ("Release", "True"); - configRelease.CompilationParameters = languageBinding.CreateCompilationParameters (releaseProjectOptions); + configRelease.CompilationParameters = LanguageBinding.CreateCompilationParameters (releaseProjectOptions); } else { - configRelease.CompilationParameters = languageBinding.CreateCompilationParameters (null); + configRelease.CompilationParameters = LanguageBinding.CreateCompilationParameters (null); } - + configRelease.CompilationParameters.RemoveDefineSymbol ("DEBUG"); configRelease.DebugMode = false; configRelease.ExternalConsole = externalConsole; @@ -184,9 +197,32 @@ namespace MonoDevelop.Projects return Runtime.SystemAssemblyService.GetTargetFramework (moniker); } - public override IEnumerable<string> GetProjectTypes () + protected override void OnGetProjectTypes (HashSet<string> types) + { + types.Add ("DotNet"); + types.Add ("DotNetAssembly"); + } + + DotNetProjectExtension projectExtension; + DotNetProjectExtension ProjectExtension { + get { + if (projectExtension == null) + projectExtension = ExtensionChain.GetExtension<DotNetProjectExtension> (); + return projectExtension; + } + } + + protected override IEnumerable<WorkspaceObjectExtension> CreateDefaultExtensions () + { + return base.CreateDefaultExtensions ().Concat (Enumerable.Repeat (new DefaultDotNetProjectExtension (), 1)); + } + + protected override ProjectItem OnCreateProjectItem (IMSBuildItemEvaluated item) { - yield return "DotNet"; + if (item.Name == "Reference" || item.Name == "ProjectReference") + return new ProjectReference (); + + return base.OnCreateProjectItem (item); } private string languageName; @@ -195,22 +231,53 @@ namespace MonoDevelop.Projects } public override string[] SupportedLanguages { - get { return new string[] {"",languageName}; } + get { return ProjectExtension.SupportedLanguages; } } public virtual bool IsLibraryBasedProjectType { - get { return false; } + get { return ProjectExtension.IsLibraryBasedProjectType; } + } + + public bool IsPortableLibrary { + get { return GetService<PortableDotNetProjectFlavor> () != null; } } public virtual bool GeneratesDebugInfoFile { - get { return true; } + get { return ProjectExtension.GeneratesDebugInfoFile; } } - - protected virtual string GetDefaultTargetPlatform (ProjectCreateInformation projectCreateInfo) + + protected string GetDefaultTargetPlatform (ProjectCreateInformation projectCreateInfo) { - return string.Empty; + return ProjectExtension.OnGetDefaultTargetPlatform (projectCreateInfo); } - + + protected virtual string OnGetDefaultTargetPlatform (ProjectCreateInformation projectCreateInfo) + { + if (CompileTarget == CompileTarget.Library) + return string.Empty; + + // Guess a good default platform for the project + if (projectCreateInfo.ParentFolder != null && projectCreateInfo.ParentFolder.ParentSolution != null) { + ItemConfiguration conf = projectCreateInfo.ParentFolder.ParentSolution.GetConfiguration (projectCreateInfo.ActiveConfiguration); + if (conf != null) + return conf.Platform; + else { + string curName, curPlatform, bestPlatform = null; + string sconf = projectCreateInfo.ActiveConfiguration.ToString (); + ItemConfiguration.ParseConfigurationId (sconf, out curName, out curPlatform); + foreach (ItemConfiguration ic in projectCreateInfo.ParentFolder.ParentSolution.Configurations) { + if (ic.Platform == curPlatform) + return curPlatform; + if (ic.Name == curName) + bestPlatform = ic.Platform; + } + if (bestPlatform != null) + return bestPlatform; + } + } + return Services.ProjectService.DefaultPlatformTarget; + } + public ProjectReferenceCollection References { get { return projectReferences; } } @@ -229,6 +296,10 @@ namespace MonoDevelop.Projects public virtual bool CanReferenceProject (DotNetProject targetProject, out string reason) { + return ProjectExtension.OnGetCanReferenceProject (targetProject, out reason); + } + bool CheckCanReferenceProject (DotNetProject targetProject, out string reason) + { if (!TargetFramework.CanReferenceAssembliesTargetingFramework (targetProject.TargetFramework)) { reason = GettextCatalog.GetString ("Incompatible target framework: {0}", targetProject.TargetFramework.Id); return false; @@ -264,20 +335,6 @@ namespace MonoDevelop.Projects } } - [ItemProperty("LanguageParameters")] - public ProjectParameters LanguageParameters { - get { - if (languageParameters == null && LanguageBinding != null) - LanguageParameters = LanguageBinding.CreateProjectParameters (null); - return languageParameters; - } - internal set { - languageParameters = value; - if (languageParameters != null) - languageParameters.ParentProject = this; - } - } - /// <summary> /// Default namespace setting. May be empty, use GetDefaultNamespace to get a usable value. /// </summary> @@ -288,7 +345,7 @@ namespace MonoDevelop.Projects NotifyModified ("DefaultNamespace"); } } - + /// <summary> /// Given a namespace, removes from it the implicit namespace of the project, /// if there is one. This depends on the target language. For example, in VB.NET @@ -296,7 +353,7 @@ namespace MonoDevelop.Projects /// </summary> public string StripImplicitNamespace (string ns) { - if ((LanguageParameters is DotNetProjectParameters) && ((DotNetProjectParameters)LanguageParameters).DefaultNamespaceIsImplicit) { + if (DefaultNamespaceIsImplicit) { if (DefaultNamespace.Length > 0 && ns.StartsWith (DefaultNamespace + ".")) return ns.Substring (DefaultNamespace.Length + 1); else if (DefaultNamespace == ns) @@ -305,23 +362,26 @@ namespace MonoDevelop.Projects return ns; } + public bool DefaultNamespaceIsImplicit { get; set; } + IResourceHandler resourceHandler; public IResourceHandler ResourceHandler { get { if (resourceHandler == null) { DotNetNamingPolicy pol = Policies.Get<DotNetNamingPolicy> (); - if (pol.ResourceNamePolicy == ResourceNamePolicy.FileFormatDefault) - resourceHandler = ItemHandler as IResourceHandler; - else if (pol.ResourceNamePolicy == ResourceNamePolicy.MSBuild) - resourceHandler = MSBuildProjectService.GetResourceHandlerForItem (this); - if (resourceHandler == null) + if (pol.ResourceNamePolicy == ResourceNamePolicy.FileFormatDefault || pol.ResourceNamePolicy == ResourceNamePolicy.MSBuild) { + resourceHandler = GetService<IResourceHandler> (); + if (resourceHandler == null) + resourceHandler = MSBuildResourceHandler.Instance; + } + else resourceHandler = DefaultResourceHandler.Instance; } return resourceHandler; } } - + TargetFramework targetFramework; public TargetFramework TargetFramework { @@ -350,18 +410,23 @@ namespace MonoDevelop.Projects public TargetRuntime TargetRuntime { get { return Runtime.SystemAssemblyService.DefaultRuntime; } } - + /// <summary> /// Gets the target framework for new projects /// </summary> /// <returns> /// The default target framework identifier. /// </returns> - public virtual TargetFrameworkMoniker GetDefaultTargetFrameworkId () + public TargetFrameworkMoniker GetDefaultTargetFrameworkId () + { + return ProjectExtension.OnGetDefaultTargetFrameworkId (); + } + + protected virtual TargetFrameworkMoniker OnGetDefaultTargetFrameworkId () { return Services.ProjectService.DefaultTargetFramework.Id; } - + /// <summary> /// Returns the default framework for a given format /// </summary> @@ -375,11 +440,25 @@ namespace MonoDevelop.Projects /// This method is used to determine what's the correct target framework for a project /// deserialized using a specific format. /// </remarks> - public virtual TargetFrameworkMoniker GetDefaultTargetFrameworkForFormat (FileFormat format) + public TargetFrameworkMoniker GetDefaultTargetFrameworkForFormat (FileFormat format) + { + return ProjectExtension.OnGetDefaultTargetFrameworkForFormat (format); + } + + protected virtual TargetFrameworkMoniker OnGetDefaultTargetFrameworkForFormat (FileFormat format) { + switch (format.Id) { + case "MSBuild05": + return TargetFrameworkMoniker.NET_2_0; + case "MSBuild08": + return TargetFrameworkMoniker.NET_2_0; + case "MSBuild10": + case "MSBuild12": + return TargetFrameworkMoniker.NET_4_0; + } return GetDefaultTargetFrameworkId (); } - + public IAssemblyContext AssemblyContext { get { if (composedAssemblyContext == null) { @@ -400,8 +479,17 @@ namespace MonoDevelop.Projects } } - public virtual bool SupportsFramework (TargetFramework framework) + public bool SupportsFramework (TargetFramework framework) + { + return ProjectExtension.OnGetSupportsFramework (framework); + } + + protected virtual bool OnSupportsFramework (TargetFramework framework) { + // DotNetAssemblyProject can only generate assemblies for the regular framework. + // Special frameworks such as Moonlight or MonoTouch must override SupportsFramework. + if (!framework.CanReferenceAssembliesTargetingFramework (TargetFrameworkMoniker.NET_1_1)) + return false; if (LanguageBinding == null) return false; ClrVersion[] versions = LanguageBinding.GetSupportedClrVersions (); @@ -414,7 +502,6 @@ namespace MonoDevelop.Projects return false; } - [ItemProperty(DefaultValue = true)] public bool UsePartialTypes { get { return usePartialTypes; } set { usePartialTypes = value; } @@ -426,16 +513,16 @@ namespace MonoDevelop.Projects composedAssemblyContext.Dispose (); // composedAssemblyContext = null; } - + // languageParameters = null; // privateAssemblyContext = null; // currentRuntimeContext = null; // languageBinding = null; // projectReferences = null; - + Runtime.SystemAssemblyService.DefaultRuntimeChanged -= RuntimeSystemAssemblyServiceDefaultRuntimeChanged; FileService.FileRemoved -= OnFileRemoved; - + base.Dispose (); } @@ -477,7 +564,7 @@ namespace MonoDevelop.Projects // cached and won't take into account unsubscriptions until the next dispatch if (Disposed) return; - + base.OnFileChanged (source, e); foreach (FileEventInfo ei in e) CheckReferenceChange (ei.FileName); @@ -501,24 +588,24 @@ namespace MonoDevelop.Projects this.References.Add (prNew); } } - + internal protected override void PopulateOutputFileList (List<FilePath> list, ConfigurationSelector configuration) { base.PopulateOutputFileList (list, configuration); DotNetProjectConfiguration conf = GetConfiguration (configuration) as DotNetProjectConfiguration; - + // Debug info file - + if (conf.DebugMode) { string mdbFile = TargetRuntime.GetAssemblyDebugInfoFile (conf.CompiledOutputName); list.Add (mdbFile); } - + // Generated satellite resource files - + FilePath outputDir = conf.OutputDirectory; string satelliteAsmName = Path.GetFileNameWithoutExtension (conf.CompiledOutputName) + ".resources.dll"; - + HashSet<string> cultures = new HashSet<string> (); foreach (ProjectFile finfo in Files) { if (finfo.Subtype == Subtype.Directory || finfo.BuildAction != BuildAction.EmbeddedResource) @@ -532,7 +619,7 @@ namespace MonoDevelop.Projects } } } - + [ThreadStatic] static int supportReferDistance; [ThreadStatic] @@ -561,13 +648,13 @@ namespace MonoDevelop.Projects //rename the app.config file list.Remove ("app.config"); list.Remove ("App.config"); - + ProjectFile appConfig = Files.FirstOrDefault (f => f.FilePath.FileName.Equals ("app.config", StringComparison.CurrentCultureIgnoreCase)); if (appConfig != null) { string output = GetOutputFileName (configuration).FileName; list.Add (appConfig.FilePath, true, output + ".config"); } - + //collect all the "local copy" references and their attendant files foreach (ProjectReference projectReference in References) { if (!projectReference.LocalCopy || !projectReference.CanSetLocalCopy) @@ -614,7 +701,7 @@ namespace MonoDevelop.Projects } } } - + //Given a filename like foo.it.resx, get 'it', if its //a valid culture //Note: hand-written as this can get called lotsa times @@ -664,14 +751,14 @@ namespace MonoDevelop.Projects return cultureNamesTable; } } - + IEnumerable<string> GetAssemblyRefsRec (string fileName, HashSet<string> visited) { // Recursivelly finds assemblies referenced by the given assembly - + if (!visited.Add (fileName)) yield break; - + if (!File.Exists (fileName)) { string ext = Path.GetExtension (fileName).ToLower (); if (ext == ".dll" || ext == ".exe") @@ -683,7 +770,7 @@ namespace MonoDevelop.Projects else yield break; } - + yield return fileName; foreach (var reference in SystemAssemblyService.GetAssemblyReferences (fileName)) { @@ -705,9 +792,9 @@ namespace MonoDevelop.Projects return newReferenceInformation; } - public override IEnumerable<SolutionItem> GetReferencedItems (ConfigurationSelector configuration) + protected override IEnumerable<SolutionItem> OnGetReferencedItems (ConfigurationSelector configuration) { - List<SolutionItem> items = new List<SolutionItem> (base.GetReferencedItems (configuration)); + var items = new List<SolutionItem> (base.OnGetReferencedItems (configuration)); if (ParentSolution == null) return items; @@ -745,23 +832,24 @@ namespace MonoDevelop.Projects /// </param> public IEnumerable<string> GetReferencedAssemblies (ConfigurationSelector configuration, bool includeProjectReferences) { - return Services.ProjectService.GetExtensionChain (this).GetReferencedAssemblies (this, configuration, includeProjectReferences); + return ProjectExtension.OnGetReferencedAssemblies (configuration, includeProjectReferences); } internal protected virtual IEnumerable<string> OnGetReferencedAssemblies (ConfigurationSelector configuration, bool includeProjectReferences) { - IAssemblyReferenceHandler handler = this.ItemHandler as IAssemblyReferenceHandler; - if (handler != null) { + if (CheckUseMSBuildEngine (configuration)) { if (includeProjectReferences) { foreach (ProjectReference pref in References.Where (pr => pr.ReferenceType == ReferenceType.Project)) { foreach (string asm in pref.GetReferencedFileNames (configuration)) yield return asm; } } - foreach (string file in handler.GetAssemblyReferences (configuration)) - yield return file; - } - else { + // Get the references list from the msbuild project + RemoteProjectBuilder builder = GetProjectBuilder (); + var configs = GetConfigurations (configuration); + foreach (var r in builder.ResolveAssemblyReferences (configs)) + yield return r; + } else { foreach (ProjectReference pref in References) { if (includeProjectReferences || pref.ReferenceType != ReferenceType.Project) { foreach (string asm in pref.GetReferencedFileNames (configuration)) @@ -772,12 +860,8 @@ namespace MonoDevelop.Projects var config = (DotNetProjectConfiguration)GetConfiguration (configuration); bool noStdLib = false; - if (config != null) { - var parameters = config.CompilationParameters as DotNetConfigurationParameters; - if (parameters != null) { - noStdLib = parameters.NoStdLib; - } - } + if (config != null) + noStdLib = config.CompilationParameters.NoStdLib; // System.Core is an implicit reference if (!noStdLib) { @@ -787,13 +871,13 @@ namespace MonoDevelop.Projects } } - protected internal override void OnSave (IProgressMonitor monitor) + protected internal override Task OnSave (ProgressMonitor monitor) { // Make sure the fx version is sorted out before saving - // to avoid changes in project references while saving + // to avoid changes in project references while saving if (targetFramework == null) targetFramework = Runtime.SystemAssemblyService.GetTargetFramework (GetDefaultTargetFrameworkForFormat (FileFormat)); - base.OnSave (monitor); + return base.OnSave (monitor); } IDotNetLanguageBinding FindLanguage (string name) @@ -839,7 +923,7 @@ namespace MonoDevelop.Projects { if (base.CheckNeedsBuild (configuration)) return true; - + // base.CheckNeedsBuild() checks Project references, but not Assembly, Package, or Custom. DateTime mtime = GetLastBuildTime (configuration); foreach (ProjectReference pref in References) { @@ -875,11 +959,11 @@ namespace MonoDevelop.Projects && String.Compare (Path.GetExtension (file.FilePath), ".resx", StringComparison.OrdinalIgnoreCase) == 0 && MD1DotNetProjectHandler.IsResgenRequired (file.FilePath, config.IntermediateOutputDirectory.Combine (file.ResourceId))); } - + protected internal override DateTime OnGetLastBuildTime (ConfigurationSelector configuration) { var outputBuildTime = base.OnGetLastBuildTime (configuration); - + //if the debug file is newer than the output file, use that as the build time var conf = (DotNetProjectConfiguration) GetConfiguration (configuration); if (GeneratesDebugInfoFile && conf != null && conf.DebugMode) { @@ -896,7 +980,7 @@ namespace MonoDevelop.Projects } return outputBuildTime; } - + public IList<string> GetUserAssemblyPaths (ConfigurationSelector configuration) { if (ParentSolution == null) @@ -908,7 +992,12 @@ namespace MonoDevelop.Projects .Where (d => !string.IsNullOrEmpty (d)).ToList (); } - protected virtual ExecutionCommand CreateExecutionCommand (ConfigurationSelector configSel, DotNetProjectConfiguration configuration) + public ExecutionCommand CreateExecutionCommand (ConfigurationSelector configSel, DotNetProjectConfiguration configuration) + { + return ProjectExtension.OnCreateExecutionCommand (configSel, configuration); + } + + internal protected virtual ExecutionCommand OnCreateExecutionCommand (ConfigurationSelector configSel, DotNetProjectConfiguration configuration) { DotNetExecutionCommand cmd = new DotNetExecutionCommand (configuration.CompiledOutputName); cmd.Arguments = configuration.CommandLineParameters; @@ -919,7 +1008,7 @@ namespace MonoDevelop.Projects return cmd; } - protected internal override bool OnGetCanExecute (ExecutionContext context, ConfigurationSelector configuration) + protected override bool OnGetCanExecute (ExecutionContext context, ConfigurationSelector configuration) { DotNetProjectConfiguration config = (DotNetProjectConfiguration) GetConfiguration (configuration); if (config == null) @@ -931,10 +1020,11 @@ namespace MonoDevelop.Projects return (compileTarget == CompileTarget.Exe || compileTarget == CompileTarget.WinExe) && context.ExecutionHandler.CanExecute (cmd); } - protected internal override List<FilePath> OnGetItemFiles (bool includeReferencedFiles) + protected override IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles) { - List<FilePath> col = base.OnGetItemFiles (includeReferencedFiles); + var baseFiles = base.OnGetItemFiles (includeReferencedFiles); if (includeReferencedFiles) { + List<FilePath> col = new List<FilePath> (); foreach (ProjectReference pref in References) { if (pref.ReferenceType == ReferenceType.Assembly) { foreach (var f in pref.GetReferencedFileNames (DefaultConfiguration.Selector)) @@ -945,10 +1035,20 @@ namespace MonoDevelop.Projects if (c.SignAssembly) col.Add (c.AssemblyKeyFile); } + baseFiles = baseFiles.Concat (col); } - return col; + return baseFiles; + } + + internal Task<BuildResult> Compile (ProgressMonitor monitor, BuildData buildData) + { + return ProjectExtension.OnCompile (monitor, buildData); } + protected virtual Task<BuildResult> OnCompile (ProgressMonitor monitor, BuildData buildData) + { + return MD1DotNetProjectHandler.Compile (monitor, this, buildData); + } public override bool IsCompileable (string fileName) { @@ -979,7 +1079,7 @@ namespace MonoDevelop.Projects string defaultNmspc = !string.IsNullOrEmpty (defaultNamespace) ? defaultNamespace : SanitisePotentialNamespace (project.Name) ?? "Application"; - + if (string.IsNullOrEmpty (fileName)) { return defaultNmspc; } @@ -1088,22 +1188,6 @@ namespace MonoDevelop.Projects return BuildAction.DotNetCommonActions; } - internal override void SetItemHandler (ISolutionItemHandler handler) - { - if (ProjectExtensionUtil.GetItemHandler (this) == null) { - // Initial assignment of the item handler - base.SetItemHandler (handler); - return; - } - IResourceHandler rh = ResourceHandler; - - base.SetItemHandler (handler); - resourceHandler = null; - // A change in the file format may imply a change in the resource naming policy. - // Make sure that the resource Id don't change. - MigrateResourceIds (rh, ResourceHandler); - } - protected override void OnEndLoad () { // The resource handler policy may have changed after loading, so reset any @@ -1112,7 +1196,7 @@ namespace MonoDevelop.Projects // Just after loading, the resource Ids are using the file format's policy. // They have to be converted to the new policy - IResourceHandler handler = ItemHandler as IResourceHandler; + IResourceHandler handler = GetService<IResourceHandler> (); if (handler != null) MigrateResourceIds (handler, ResourceHandler); @@ -1172,13 +1256,13 @@ namespace MonoDevelop.Projects internal void NotifyReferenceRemovedFromProject (ProjectReference reference) { NotifyModified ("References"); - OnReferenceRemovedFromProject (new ProjectReferenceEventArgs (this, reference)); + ProjectExtension.OnReferenceRemovedFromProject (new ProjectReferenceEventArgs (this, reference)); } internal void NotifyReferenceAddedToProject (ProjectReference reference) { NotifyModified ("References"); - OnReferenceAddedToProject (new ProjectReferenceEventArgs (this, reference)); + ProjectExtension.OnReferenceAddedToProject (new ProjectReferenceEventArgs (this, reference)); } protected virtual void OnReferenceRemovedFromProject (ProjectReferenceEventArgs e) @@ -1205,7 +1289,7 @@ namespace MonoDevelop.Projects CheckReferenceChange (ei.FileName); } - protected override void DoExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + protected async override Task DoExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { DotNetProjectConfiguration dotNetProjectConfig = GetConfiguration (configuration) as DotNetProjectConfiguration; monitor.Log.WriteLine (GettextCatalog.GetString ("Running {0} ...", dotNetProjectConfig.CompiledOutputName)); @@ -1213,8 +1297,6 @@ namespace MonoDevelop.Projects IConsole console = dotNetProjectConfig.ExternalConsole ? context.ExternalConsoleFactory.CreateConsole (!dotNetProjectConfig.PauseConsoleOutput) : context.ConsoleFactory.CreateConsole (!dotNetProjectConfig.PauseConsoleOutput); - - AggregatedOperationMonitor aggregatedOperationMonitor = new AggregatedOperationMonitor (monitor); try { try { @@ -1227,14 +1309,16 @@ namespace MonoDevelop.Projects return; } - IProcessAsyncOperation asyncOp = context.ExecutionHandler.Execute (executionCommand, console); - aggregatedOperationMonitor.AddOperation (asyncOp); - asyncOp.WaitForCompleted (); + ProcessAsyncOperation asyncOp = context.ExecutionHandler.Execute (executionCommand, console); + var stopper = monitor.CancellationToken.Register (asyncOp.Cancel); + + await asyncOp.Task; + + stopper.Dispose (); monitor.Log.WriteLine (GettextCatalog.GetString ("The application exited with code: {0}", asyncOp.ExitCode)); } finally { console.Dispose (); - aggregatedOperationMonitor.Dispose (); } } catch (Exception ex) { LoggingService.LogError (string.Format ("Cannot execute \"{0}\"", dotNetProjectConfig.CompiledOutputName), ex); @@ -1242,32 +1326,158 @@ namespace MonoDevelop.Projects } } - public void AddImportIfMissing (string name, string condition) + + protected override void OnReadProjectHeader (ProgressMonitor monitor, MSBuildProject msproject) { - importsAdded.Add (new DotNetProjectImport (name, condition)); + base.OnReadProjectHeader (monitor, msproject); + + compileTarget = msproject.EvaluatedProperties.GetValue<CompileTarget> ("OutputType"); + defaultNamespace = msproject.EvaluatedProperties.GetValue ("RootNamespace", string.Empty); + usePartialTypes = msproject.EvaluatedProperties.GetValue ("UsePartialTypes", true); + + string frameworkIdentifier = msproject.EvaluatedProperties.GetValue ("TargetFrameworkIdentifier"); + string frameworkVersion = msproject.EvaluatedProperties.GetValue ("TargetFrameworkVersion"); + string frameworkProfile = msproject.EvaluatedProperties.GetValue ("TargetFrameworkProfile"); + + //determine the default target framework from the project type's default + //overridden by the components in the project + var def = GetDefaultTargetFrameworkForFormat (GetFileFormat (GetToolsFormat ())); + var targetFx = new TargetFrameworkMoniker ( + string.IsNullOrEmpty (frameworkIdentifier)? def.Identifier : frameworkIdentifier, + string.IsNullOrEmpty (frameworkVersion)? def.Version : frameworkVersion, + string.IsNullOrEmpty (frameworkProfile)? def.Profile : frameworkProfile); + + + string fx = ExtendedProperties ["InternalTargetFrameworkVersion"] as string; + if (!string.IsNullOrEmpty (fx)) { + targetFx = TargetFrameworkMoniker.Parse (fx); + ExtendedProperties.Remove ("InternalTargetFrameworkVersion"); + } + + TargetFramework = Runtime.SystemAssemblyService.GetTargetFramework (targetFx); } - public void RemoveImport (string name) + protected override void OnWriteProjectHeader (ProgressMonitor monitor, MSBuildProject msproject) { - importsRemoved.Add (new DotNetProjectImport (name)); + base.OnWriteProjectHeader (monitor, msproject); + + IMSBuildPropertySet globalGroup = msproject.GetGlobalPropertyGroup (); + + globalGroup.SetValue ("OutputType", compileTarget); + globalGroup.SetValue ("RootNamespace", defaultNamespace, string.Empty); + globalGroup.SetValue ("UsePartialTypes", usePartialTypes, true); } - List <DotNetProjectImport> importsAdded = new List<DotNetProjectImport> (); + protected override void OnWriteProject (ProgressMonitor monitor, MSBuildProject msproject) + { + base.OnWriteProject (monitor, msproject); + + var toolsFormat = GetToolsFormat (); + var moniker = TargetFramework.Id; + bool supportsMultipleFrameworks = toolsFormat.SupportsMonikers || toolsFormat.SupportedFrameworks.Length > 0; + var def = GetDefaultTargetFrameworkForFormat (GetFileFormat (toolsFormat)); + + IMSBuildPropertySet globalGroup = msproject.GetGlobalPropertyGroup (); - internal IList<DotNetProjectImport> ImportsAdded { - get { return importsAdded; } + // If the format only supports one fx version, or the version is the default, there is no need to store it. + // However, is there is already a value set, do not remove it. + if (supportsMultipleFrameworks) { + globalGroup.SetValue ("TargetFrameworkVersion", "v" + moniker.Version, "v" + def.Version, true); + } + + if (toolsFormat.SupportsMonikers) { + globalGroup.SetValue ("TargetFrameworkIdentifier", moniker.Identifier, def.Identifier, true); + globalGroup.SetValue ("TargetFrameworkProfile", moniker.Profile, def.Profile, true); + } } - List <DotNetProjectImport> importsRemoved = new List<DotNetProjectImport> (); + protected override void OnWriteConfiguration (ProgressMonitor monitor, ProjectConfiguration config, IMSBuildPropertySet pset) + { + base.OnWriteConfiguration (monitor, config, pset); + if (pset.Project.IsNewProject) + pset.SetValue ("ErrorReport", "prompt"); + + } - internal IList<DotNetProjectImport> ImportsRemoved { - get { return importsRemoved; } + FileFormat GetFileFormat (MSBuildFileFormat fmt) + { + return new FileFormat (fmt, fmt.Id, fmt.Name); } - public void ImportsSaved () + internal class DefaultDotNetProjectExtension: DotNetProjectExtension { - importsAdded.Clear (); - importsRemoved.Clear (); + internal protected override bool IsLibraryBasedProjectType { + get { + return false; + } + } + + internal protected override bool GeneratesDebugInfoFile { + get { + return true; + } + } + + internal protected override bool SupportsPartialTypes { + get { + return Project.SupportsPartialTypes; + } + } + + + internal protected override bool OnGetCanReferenceProject (DotNetProject targetProject, out string reason) + { + return Project.CheckCanReferenceProject (targetProject, out reason); + } + + internal protected override string OnGetDefaultTargetPlatform (ProjectCreateInformation projectCreateInfo) + { + return Project.OnGetDefaultTargetPlatform (projectCreateInfo); + } + + internal protected override IEnumerable<string> OnGetReferencedAssemblies (ConfigurationSelector configuration, bool includeProjectReferences) + { + return Project.OnGetReferencedAssemblies (configuration, includeProjectReferences); + } + + internal protected override ExecutionCommand OnCreateExecutionCommand (ConfigurationSelector configSel, DotNetProjectConfiguration configuration) + { + return Project.OnCreateExecutionCommand (configSel, configuration); + } + + internal protected override void OnReferenceRemovedFromProject (ProjectReferenceEventArgs e) + { + Project.OnReferenceRemovedFromProject (e); + } + + internal protected override void OnReferenceAddedToProject (ProjectReferenceEventArgs e) + { + Project.OnReferenceAddedToProject (e); + } + + internal protected override Task<BuildResult> OnCompile (ProgressMonitor monitor, BuildData buildData) + { + return Project.OnCompile (monitor, buildData); + } + + #region Framework management + + internal protected override TargetFrameworkMoniker OnGetDefaultTargetFrameworkId () + { + return Project.OnGetDefaultTargetFrameworkId (); + } + + internal protected override TargetFrameworkMoniker OnGetDefaultTargetFrameworkForFormat (FileFormat format) + { + return Project.OnGetDefaultTargetFrameworkForFormat (format); + } + + internal protected override bool OnGetSupportsFramework (TargetFramework framework) + { + return Project.OnSupportsFramework (framework); + } + + #endregion } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectBinding.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectBinding.cs deleted file mode 100644 index e2e26591cb..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectBinding.cs +++ /dev/null @@ -1,76 +0,0 @@ -// -// DotNetProjectBinding.cs -// -// Author: -// Lluis Sanchez Gual -// -// Copyright (C) 2005 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.IO; -using System.Xml; -using MonoDevelop.Core.Serialization; -using MonoDevelop.Core; - -namespace MonoDevelop.Projects -{ - public class DotNetProjectBinding : IProjectBinding - { - public virtual string Name { - get { return "DotNet"; } - } - - public Project CreateProject (ProjectCreateInformation info, XmlElement projectOptions) - { - string lang = projectOptions.GetAttribute ("language"); - return CreateProject (lang, info, projectOptions); - } - - protected virtual DotNetProject CreateProject (string languageName, ProjectCreateInformation info, XmlElement projectOptions) - { - return new DotNetAssemblyProject (languageName, info, projectOptions); - } - - public Project CreateSingleFileProject (string file) - { - IDotNetLanguageBinding binding = LanguageBindingService.GetBindingPerFileName (file) as IDotNetLanguageBinding; - if (binding != null) { - ProjectCreateInformation info = new ProjectCreateInformation (); - info.ProjectName = Path.GetFileNameWithoutExtension (file); - info.SolutionPath = Path.GetDirectoryName (file); - info.ProjectBasePath = Path.GetDirectoryName (file); - Project project = CreateProject (binding.Language, info, null); - project.Files.Add (new ProjectFile (file)); - return project; - } - return null; - } - - public bool CanCreateSingleFileProject (string file) - { - IDotNetLanguageBinding binding = LanguageBindingService.GetBindingPerFileName (file) as IDotNetLanguageBinding; - return binding != null; - } - - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectConfiguration.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectConfiguration.cs index ed6bb65fa5..5d359650c8 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectConfiguration.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectConfiguration.cs @@ -35,6 +35,7 @@ using MonoDevelop.Core.Serialization; using MonoDevelop.Core.Assemblies; using MonoDevelop.Core.StringParsing; using System.Collections.Generic; +using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.Projects { @@ -47,14 +48,10 @@ namespace MonoDevelop.Projects public class DotNetProjectConfiguration: ProjectConfiguration { - [MonoDevelop.Projects.Formats.MSBuild.MergeToProject] - [ItemProperty ("AssemblyName")] string assembly; - - ConfigurationParameters compilationParameters; - string sourcePath; - + DotNetCompilerParameters compilationParameters; + public DotNetProjectConfiguration () { } @@ -63,32 +60,49 @@ namespace MonoDevelop.Projects { } - [MonoDevelop.Projects.Formats.MSBuild.MergeToProject] - [ItemProperty("SignAssembly", DefaultValue = false)] + internal protected override void Read (IMSBuildPropertySet pset, MSBuildFileFormat format) + { + base.Read (pset, format); + + assembly = pset.GetValue ("AssemblyName"); + signAssembly = pset.GetValue<bool> ("SignAssembly"); + delaySign = pset.GetValue<bool> ("DelaySign"); + assemblyKeyFile = pset.GetPathValue ("AssemblyOriginatorKeyFile"); + if (string.IsNullOrEmpty (assemblyKeyFile)) + assemblyKeyFile = pset.GetPathValue ("AssemblyKeyFile"); + if (compilationParameters != null) + ((IMSBuildDataObject)compilationParameters).Read (pset, format); + } + + internal protected override void Write (IMSBuildPropertySet pset, MSBuildFileFormat format) + { + base.Write (pset, format); + pset.SetValue ("AssemblyName", assembly, mergeToMainGroup: true); + pset.SetValue ("SignAssembly", signAssembly, defaultValue:false, mergeToMainGroup: true); + pset.SetValue ("DelaySign", delaySign, defaultValue:false, mergeToMainGroup:true); + pset.SetValue ("AssemblyOriginatorKeyFile", assemblyKeyFile, mergeToMainGroup:true); + if (compilationParameters != null) + ((IMSBuildDataObject)compilationParameters).Write (pset, format); + } + private bool signAssembly = false; public bool SignAssembly { get { return signAssembly; } set { signAssembly = value; } } - [MonoDevelop.Projects.Formats.MSBuild.MergeToProject] - [ItemProperty("DelaySign", DefaultValue = false)] private bool delaySign = false; public bool DelaySign { get { return delaySign; } set { delaySign = value; } } - [MonoDevelop.Projects.Formats.MSBuild.MergeToProject] - [ProjectPathItemProperty("AssemblyKeyFile", ReadOnly=true)] internal string OldAssemblyKeyFile { set { assemblyKeyFile = value; } } - [MonoDevelop.Projects.Formats.MSBuild.MergeToProject] - [ProjectPathItemProperty("AssemblyOriginatorKeyFile", DefaultValue = "")] - private string assemblyKeyFile = ""; - public string AssemblyKeyFile { + private FilePath assemblyKeyFile = FilePath.Empty; + public FilePath AssemblyKeyFile { get { return assemblyKeyFile; } set { assemblyKeyFile = value; } } @@ -149,8 +163,7 @@ namespace MonoDevelop.Projects } } - [ItemProperty ("CodeGeneration")] - public ConfigurationParameters CompilationParameters { + public DotNetCompilerParameters CompilationParameters { get { return compilationParameters; } set { compilationParameters = value; @@ -159,16 +172,6 @@ namespace MonoDevelop.Projects } } - public ProjectParameters ProjectParameters { - get { - DotNetProject dnp = ParentItem as DotNetProject; - if (dnp != null) - return dnp.LanguageParameters; - else - return null; - } - } - public FilePath CompiledOutputName { get { FilePath fullPath = OutputDirectory.Combine (OutputAssembly); @@ -206,7 +209,7 @@ namespace MonoDevelop.Projects } } - public class UnknownCompilationParameters: ConfigurationParameters, IExtendedDataItem + public class UnknownCompilationParameters: DotNetCompilerParameters, IExtendedDataItem { readonly Hashtable table = new Hashtable (); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectExtension.cs new file mode 100644 index 0000000000..09f2a6b871 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectExtension.cs @@ -0,0 +1,132 @@ +// +// DotNetProjectExtension.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using MonoDevelop.Core.Assemblies; +using MonoDevelop.Core.Execution; +using MonoDevelop.Core; +using System.Threading.Tasks; + +namespace MonoDevelop.Projects +{ + public class DotNetProjectExtension: ProjectExtension + { + #region Project properties + + DotNetProjectExtension next; + + internal protected override void InitializeChain (ChainedExtension next) + { + base.InitializeChain (next); + this.next = FindNextImplementation<DotNetProjectExtension> (next); + } + + internal protected override bool SupportsObject (WorkspaceObject item) + { + return base.SupportsObject (item) && (item is DotNetProject); + } + + new public DotNetProject Project { + get { return (DotNetProject)base.Item; } + } + + + internal protected virtual bool IsLibraryBasedProjectType { + get { + return next.IsLibraryBasedProjectType; + } + } + + internal protected virtual bool GeneratesDebugInfoFile { + get { + return next.GeneratesDebugInfoFile; + } + } + + internal protected virtual bool SupportsPartialTypes { + get { + return next.SupportsPartialTypes; + } + } + + #endregion + + internal protected virtual bool OnGetCanReferenceProject (DotNetProject targetProject, out string reason) + { + return next.OnGetCanReferenceProject (targetProject, out reason); + } + + internal protected virtual string OnGetDefaultTargetPlatform (ProjectCreateInformation projectCreateInfo) + { + return next.OnGetDefaultTargetPlatform (projectCreateInfo); + } + + internal protected virtual IEnumerable<string> OnGetReferencedAssemblies (ConfigurationSelector configuration, bool includeProjectReferences) + { + return next.OnGetReferencedAssemblies (configuration, includeProjectReferences); + } + + internal protected virtual ExecutionCommand OnCreateExecutionCommand (ConfigurationSelector configSel, DotNetProjectConfiguration configuration) + { + return next.OnCreateExecutionCommand (configSel, configuration); + } + + internal protected virtual void OnReferenceRemovedFromProject (ProjectReferenceEventArgs e) + { + next.OnReferenceRemovedFromProject (e); + } + + internal protected virtual void OnReferenceAddedToProject (ProjectReferenceEventArgs e) + { + next.OnReferenceAddedToProject (e); + } + + #region Framework management + + internal protected virtual TargetFrameworkMoniker OnGetDefaultTargetFrameworkId () + { + return next.OnGetDefaultTargetFrameworkId (); + } + + internal protected virtual TargetFrameworkMoniker OnGetDefaultTargetFrameworkForFormat (FileFormat format) + { + return next.OnGetDefaultTargetFrameworkForFormat (format); + } + + internal protected virtual bool OnGetSupportsFramework (TargetFramework framework) + { + return next.OnGetSupportsFramework (framework); + } + + internal protected virtual Task<BuildResult> OnCompile (ProgressMonitor monitor, BuildData buildData) + { + return next.OnCompile (monitor, buildData); + } + + #endregion + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ExtensionChain.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ExtensionChain.cs new file mode 100644 index 0000000000..9916adc7bd --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ExtensionChain.cs @@ -0,0 +1,69 @@ +// +// ExtensionChain.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; + +namespace MonoDevelop.Projects +{ + public class ExtensionChain + { + ChainedExtension first; + Dictionary<Type,ChainedExtension> chains = new Dictionary<Type, ChainedExtension> (); + + public static ExtensionChain Create<T> (T[] extensions) where T:ChainedExtension + { + for (int n = extensions.Length - 2; n >= 0; n--) + extensions [n].Init (extensions [n + 1]); + return new ExtensionChain { + first = extensions[0] + }; + } + + public T GetExtension<T> () where T:ChainedExtension + { + ChainedExtension e; + if (!chains.TryGetValue (typeof(T), out e)) { + chains [typeof(T)] = e = ChainedExtension.FindNextImplementation<T> (first); + } + return (T)e; + } + + public IEnumerable<ChainedExtension> GetAllExtensions () + { + var e = first; + while (e != null) { + yield return e; + e = e.Next; + } + } + + public void Dispose () + { + first.DisposeChain (); + } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/GenericProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/GenericProject.cs index 9e14d17bb6..7e324914a0 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/GenericProject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/GenericProject.cs @@ -49,9 +49,9 @@ namespace MonoDevelop.Projects return conf; } - public override IEnumerable<string> GetProjectTypes () + protected override void OnGetProjectTypes (HashSet<string> types) { - yield return "GenericProject"; + types.Add ("GenericProject"); } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/GenericProjectBinding.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/GenericProjectBinding.cs deleted file mode 100644 index a0adbabee8..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/GenericProjectBinding.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// MakefileProjectBinding.cs -// -// Author: -// Lluis Sanchez Gual -// -// Copyright (C) 2007 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.IO; -using System.Xml; -using MonoDevelop.Core.Serialization; -using MonoDevelop.Core; -using MonoDevelop.Projects; - -namespace MonoDevelop.Projects -{ - public class GenericProjectBinding : IProjectBinding - { - public virtual string Name { - get { return "GenericProject"; } - } - - public Project CreateProject (ProjectCreateInformation info, XmlElement projectOptions) - { - return new GenericProject (info, projectOptions); - } - - public Project CreateSingleFileProject (string file) - { - return null; - } - - public bool CanCreateSingleFileProject (string file) - { - return false; - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IBuildTarget.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IBuildTarget.cs index 46f53edd81..bc882c60d3 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IBuildTarget.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IBuildTarget.cs @@ -29,19 +29,17 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using MonoDevelop.Core; +using System.Threading.Tasks; namespace MonoDevelop.Projects { - public interface IBuildTarget: IWorkspaceObject + public interface IBuildTarget { - BuildResult RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration); - bool SupportsTarget (string target); - void Execute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration); + Task<BuildResult> Build (ProgressMonitor monitor, ConfigurationSelector configuration, bool buildReferencedTargets = false); + Task<BuildResult> Clean (ProgressMonitor monitor, ConfigurationSelector configuration); + Task Execute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration); bool CanExecute (ExecutionContext context, ConfigurationSelector configuration); bool NeedsBuilding (ConfigurationSelector configuration); - void SetNeedsBuilding (bool needsBuilding, ConfigurationSelector configuration); - -// ReadOnlyCollection<string> GetConfigurations (); -// event EventHandler ConfigurationsChanged; + string Name { get; } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IDotNetLanguageBinding.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IDotNetLanguageBinding.cs index 618219d4a3..9b30606afb 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IDotNetLanguageBinding.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IDotNetLanguageBinding.cs @@ -38,10 +38,9 @@ namespace MonoDevelop.Projects get; } - ConfigurationParameters CreateCompilationParameters (XmlElement projectOptions); - ProjectParameters CreateProjectParameters (XmlElement projectOptions); + DotNetCompilerParameters CreateCompilationParameters (XmlElement projectOptions); - BuildResult Compile (ProjectItemCollection items, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, IProgressMonitor monitor); + BuildResult Compile (ProjectItemCollection items, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, ProgressMonitor monitor); ClrVersion[] GetSupportedClrVersions (); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectParameters.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IMSBuildDataObject.cs index 013b99f441..2c94b3c395 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectParameters.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IMSBuildDataObject.cs @@ -1,21 +1,21 @@ -// -// DotNetProjectParameters.cs -// +// +// IProjectConfigurationData.cs +// // Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,18 +23,15 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - using System; +using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.Projects { - /// <summary> - /// This is the base class for project parameter classes. - /// </summary> - public class DotNetProjectParameters: ProjectParameters + public interface IMSBuildDataObject { - public virtual bool DefaultNamespaceIsImplicit { - get { return false; } - } + void Read (IMSBuildPropertySet pset, MSBuildFileFormat format); + void Write (IMSBuildPropertySet pset, MSBuildFileFormat format); } } + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SimpleProjectItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IProject.cs index 633e82f83d..286b4abe95 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SimpleProjectItem.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IProject.cs @@ -1,21 +1,21 @@ -// -// SimpleProjectItem.cs -// +// +// IProject.cs +// // Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,15 +23,12 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - using System; -using MonoDevelop.Core.Serialization; namespace MonoDevelop.Projects { - public class SimpleProjectItem: ProjectItem + public interface IProject2 { - [ItemProperty ("Include")] - public string Include { get; set; } } } + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IProjectBinding.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IProjectBinding.cs deleted file mode 100644 index 5c0ce972f9..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IProjectBinding.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// IProjectBinding.cs -// -// Author: -// Lluis Sanchez Gual - -// -// Copyright (C) 2005 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - - -using System; -using System.Collections; -using System.Xml; - -namespace MonoDevelop.Projects -{ - public interface IProjectBinding - { - /// <remarks> - /// Returns the project type name - /// </remarks> - string Name { get; } - - /// <remarks> - /// Creates a Project out of the given ProjetCreateInformation object. - /// Each project binding must provide a representation of the project - /// it 'controls'. - /// </remarks> - Project CreateProject (ProjectCreateInformation info, XmlElement projectOptions); - - /// <remarks> - /// Creates a Project for a single source file. If the file is not - /// valid for this project type, it must return null. - /// </remarks> - Project CreateSingleFileProject (string sourceFile); - - bool CanCreateSingleFileProject (string sourceFile); - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IPropertySet.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IPropertySet.cs new file mode 100644 index 0000000000..56ccd1f3c8 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/IPropertySet.cs @@ -0,0 +1,49 @@ +// +// IPropertySet.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Xml; +using MonoDevelop.Core; +using System.Xml.Linq; + +namespace MonoDevelop.Projects +{ + public interface IPropertySet + { + + void SetValue (string name, string value, string defaultValue = null, bool preserveExistingCase = false, bool mergeToMainGroup = false, string condition = null, bool persist = true); + void SetValue (string name, XmlElement elem, bool mergeToMainGroup = false, string condition = null, bool persist = true); + void SetValue (string name, XElement elem, bool mergeToMainGroup = false, string condition = null, bool persist = true); + void SetValue (string name, FilePath value, FilePath defaultValue = default(FilePath), bool relativeToProject = true, bool mergeToMainGroup = false, string condition = null, bool persist = true); + void SetValue (string name, bool value, bool? defaultValue = false, bool mergeToMainGroup = false, string condition = null, bool persist = true); + + string GetValue (string name, string defaultValue = null); + XElement GetXmlValue (string name); + FilePath GetPathValue (string name, FilePath defaultValue = default(FilePath), bool relativeToProject = true); + bool GetBoolValue (string name, bool defaultValue = false); + + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ItemConfiguration.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ItemConfiguration.cs index 32e1e1316e..8956f4feef 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ItemConfiguration.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ItemConfiguration.cs @@ -32,6 +32,7 @@ using System.Collections.ObjectModel; using MonoDevelop.Projects; using MonoDevelop.Core.Serialization; using MonoDevelop.Core; +using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.Projects { @@ -107,7 +108,7 @@ namespace MonoDevelop.Projects public CustomCommandCollection CustomCommands { get { return customCommands; } } - + public object Clone() { ItemConfiguration conf = (ItemConfiguration) Activator.CreateInstance (GetType ()); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/LanguageBindingService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/LanguageBindingService.cs index f2823eeeb3..61b04d8b89 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/LanguageBindingService.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/LanguageBindingService.cs @@ -48,9 +48,6 @@ namespace MonoDevelop.Projects object par = dotNetBinding.CreateCompilationParameters (null); if (par != null) Services.ProjectService.DataContext.IncludeType (par.GetType ()); - par = dotNetBinding.CreateProjectParameters (null); - if (par != null) - Services.ProjectService.DataContext.IncludeType (par.GetType ()); } break; case ExtensionChange.Remove: diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/PortableDotNetProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/PortableDotNetProjectFlavor.cs index 7903a6152a..4a30eee279 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/PortableDotNetProject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/PortableDotNetProjectFlavor.cs @@ -1,20 +1,21 @@ -// -// PortableDotNetProject.cs -// -// Author: Jeffrey Stedfast <jeff@xamarin.com> -// -// Copyright (c) 2012 Xamarin Inc. -// +// +// PortableDotNetProjectFlavor.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,57 +23,39 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - using System; -using System.Xml; -using MonoDevelop.Core; +using System.Collections.Generic; using MonoDevelop.Core.Assemblies; using System.Linq; -using System.Collections.Generic; namespace MonoDevelop.Projects { - public class PortableDotNetProject : DotNetProject + public class PortableDotNetProjectFlavor: DotNetProjectExtension { - public PortableDotNetProject () - { - } - - public PortableDotNetProject (string languageName) : base (languageName) - { - } - - public PortableDotNetProject (string languageName, ProjectCreateInformation projectCreateInfo, XmlElement projectOptions) - : base (languageName, projectCreateInfo, projectOptions) + internal protected override void OnGetProjectTypes (HashSet<string> types) { + types.Add ("PortableDotNet"); } - public override IEnumerable<string> GetProjectTypes () - { - yield return "PortableDotNet"; - foreach (var t in base.GetProjectTypes ()) - yield return t; - } - - public override bool SupportsFormat (FileFormat format) + internal protected override bool OnGetSupportsFormat (FileFormat format) { int version; - + if (!format.Id.StartsWith ("MSBuild", StringComparison.Ordinal)) return false; - + if (!int.TryParse (format.Id.Substring ("MSBuild".Length), out version)) return false; - + return version >= 10; } - - public override bool SupportsFramework (TargetFramework framework) + + internal protected override bool OnGetSupportsFramework (TargetFramework framework) { return framework.Id.Identifier == TargetFrameworkMoniker.ID_PORTABLE; } - - public override TargetFrameworkMoniker GetDefaultTargetFrameworkForFormat (FileFormat format) + + internal protected override TargetFrameworkMoniker OnGetDefaultTargetFrameworkForFormat (FileFormat format) { // Note: This value is used only when serializing the TargetFramework to the .csproj file. // Any component of the TargetFramework that is different from this base TargetFramework @@ -82,19 +65,20 @@ namespace MonoDevelop.Projects // TargetFrameworkVersion and TargetFrameworkProfile values will be serialized. return new TargetFrameworkMoniker (".NETPortable", "1.0"); } - - public override TargetFrameworkMoniker GetDefaultTargetFrameworkId () + + internal protected override TargetFrameworkMoniker OnGetDefaultTargetFrameworkId () { // Profile78 includes .NET 4.5+, Windows Phone 8, and Xamarin.iOS/Android, so make that our default. // Note: see also: PortableLibrary.xpt.xml return new TargetFrameworkMoniker (".NETPortable", "4.5", "Profile78"); } - protected internal override IEnumerable<string> OnGetReferencedAssemblies (ConfigurationSelector configuration, bool includeProjectReferences) + internal protected override IEnumerable<string> OnGetReferencedAssemblies (ConfigurationSelector configuration, bool includeProjectReferences) { var res = base.OnGetReferencedAssemblies (configuration, includeProjectReferences); - var asms = TargetRuntime.AssemblyContext.GetAssemblies (TargetFramework).Where (a => a.Package.IsFrameworkPackage).Select (a => a.Location); + var asms = Project.TargetRuntime.AssemblyContext.GetAssemblies (Project.TargetFramework).Where (a => a.Package.IsFrameworkPackage).Select (a => a.Location); return res.Concat (asms).Distinct (); } } } + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs index b3bf2233e3..ce145e9c78 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs @@ -37,6 +37,14 @@ using MonoDevelop; using MonoDevelop.Core; using MonoDevelop.Core.Serialization; using MonoDevelop.Projects; +using System.Threading.Tasks; +using MonoDevelop.Projects.Formats.MSBuild; +using System.Xml; +using MonoDevelop.Core.Instrumentation; +using MonoDevelop.Core.Assemblies; +using MonoDevelop.Projects.Extensions; +using System.Threading; +using Mono.Addins; namespace MonoDevelop.Projects @@ -48,27 +56,200 @@ namespace MonoDevelop.Projects /// This is the base class for MonoDevelop projects. A project is a solution item which has a list of /// source code files and which can be built to generate an output. /// </remarks> - [DataInclude(typeof(ProjectFile))] - [ProjectModelDataItem(FallbackType = typeof(UnknownProject))] - public abstract class Project : SolutionEntityItem + public class Project : SolutionItem { + string[] flavorGuids = new string[0]; string[] buildActions; + MSBuildProject sourceProject; + + string productVersion; + string schemaVersion; + bool modifiedInMemory; + + List<string> defaultImports = new List<string> (); protected Project () { FileService.FileChanged += OnFileChanged; + Runtime.SystemAssemblyService.DefaultRuntimeChanged += OnDefaultRuntimeChanged; files = new ProjectFileCollection (); Items.Bind (files); DependencyResolutionEnabled = true; } - + + protected Project (params string[] flavorGuids): this() + { + this.flavorGuids = flavorGuids; + } + + protected Project (string[] flavorIds, MSBuildProject sourceProject): this(flavorIds) + { + } + + protected Project (ProjectCreateInformation projectCreateInfo, XmlElement projectOptions): this() + { + var ids = projectOptions != null ? projectOptions.GetAttribute ("flavorIds") : null; + if (!string.IsNullOrEmpty (ids)) { + this.flavorGuids = ids.Split (new [] {';'}, StringSplitOptions.RemoveEmptyEntries); + } + } + + internal class CreationContext + { + static object theLock = new object (); + public MSBuildProject Project { get; set; } + public string TypeGuid { get; set; } + + internal static void LockContext (MSBuildProject p, string typeGuid) + { + Monitor.Enter (theLock); + Current = new CreationContext (); + Current.Project = p; + Current.TypeGuid = typeGuid; + } + + internal static void UnlockContext () + { + Current = null; + Monitor.Exit (theLock); + } + + public static CreationContext Current { get; private set; } + } + + protected override void OnInitialize () + { + base.OnInitialize (); + + if (CreationContext.Current != null) { + + if (IsExtensionChainCreated) + throw new InvalidOperationException ("Extension chain already created for this object"); + + TypeGuid = CreationContext.Current.TypeGuid; + this.sourceProject = CreationContext.Current.Project; + + IMSBuildPropertySet globalGroup = sourceProject.GetGlobalPropertyGroup (); + string projectTypeGuids = globalGroup.GetValue ("ProjectTypeGuids"); + + if (projectTypeGuids != null) { + var subtypeGuids = new List<string> (); + foreach (string guid in projectTypeGuids.Split (';')) { + string sguid = guid.Trim (); + if (sguid.Length > 0 && string.Compare (sguid, CreationContext.Current.TypeGuid, StringComparison.OrdinalIgnoreCase) != 0) + subtypeGuids.Add (guid); + } + flavorGuids = subtypeGuids.ToArray (); + } + } + } + + protected override void OnExtensionChainInitialized () + { + base.OnExtensionChainInitialized (); + if (CreationContext.Current != null) + FileName = CreationContext.Current.Project.FileName; + } + + void OnDefaultRuntimeChanged (object o, EventArgs args) + { + // If the default runtime changes, the project builder for this project may change + // so it has to be created again. + CleanupProjectBuilder (); + } + + public IEnumerable<string> FlavorGuids { + get { return flavorGuids; } + } + + public List<string> DefaultImports { + get { return defaultImports; } + } + + public string ToolsVersion { get; private set; } + + internal bool CheckAllFlavorsSupported () + { + return FlavorGuids.All (g => ProjectExtension.SupportsFlavor (g)); + } + + ProjectExtension projectExtension; + ProjectExtension ProjectExtension { + get { + if (projectExtension == null) + projectExtension = ExtensionChain.GetExtension<ProjectExtension> (); + return projectExtension; + } + } + + /// <summary>Whether to use the MSBuild engine by default.</summary> + internal bool UseMSBuildEngineByDefault { get; set; } + + /// <summary>Forces the MSBuild engine to be used.</summary> + internal bool RequireMSBuildEngine { get; set; } + + protected override void OnModified (SolutionItemModifiedEventArgs args) + { + if (!Loading) + modifiedInMemory = true; + base.OnModified (args); + } + + protected override Task OnLoad (ProgressMonitor monitor) + { + MSBuildProject p = sourceProject; + sourceProject = null; + + return Task.Factory.StartNew (delegate { + if (p == null) + p = MSBuildProject.LoadAsync (FileName).Result; + IMSBuildPropertySet globalGroup = p.GetGlobalPropertyGroup (); + // Avoid crash if there is not global group + if (globalGroup == null) + p.AddNewPropertyGroup (false); + + try { + ProjectExtensionUtil.BeginLoadOperation (); + ReadProject (monitor, p); + } finally { + ProjectExtensionUtil.EndLoadOperation (); + } + }); + } + + internal protected override Task OnSave (ProgressMonitor monitor) + { + modifiedInMemory = false; + + return Task.Factory.StartNew (delegate { + var msproject = WriteProject (monitor); + if (msproject == null) + return; + + // Don't save the file to disk if the content did not change + msproject.Save (FileName); + + if (projectBuilder != null) + projectBuilder.Refresh (); + }); + } + + protected override IEnumerable<WorkspaceObjectExtension> CreateDefaultExtensions () + { + return base.CreateDefaultExtensions ().Concat (Enumerable.Repeat (new DefaultMSBuildProjectExtension (), 1)); + } + + internal protected override IEnumerable<string> GetItemTypeGuids () + { + return base.GetItemTypeGuids ().Concat (flavorGuids); + } + /// <summary> /// Description of the project. /// </summary> - [ItemProperty("Description", DefaultValue = "")] private string description = ""; public string Description { - get { return description; } + get { return description ?? ""; } set { description = value; NotifyModified ("Description"); @@ -86,7 +267,7 @@ namespace MonoDevelop.Projects /// </param> public virtual bool IsCompileable (string fileName) { - return false; + return ProjectExtension.OnGetIsCompileable (fileName); } /// <summary> @@ -97,7 +278,6 @@ namespace MonoDevelop.Projects } private ProjectFileCollection files; - [ProjectPathItemProperty ("BaseIntermediateOutputPath")] FilePath baseIntermediateOutputPath; public virtual FilePath BaseIntermediateOutputPath { @@ -129,7 +309,31 @@ namespace MonoDevelop.Projects /// <summary> /// Gets the project type and its base types. /// </summary> - public abstract IEnumerable<string> GetProjectTypes (); + public IEnumerable<string> GetProjectTypes () + { + var types = new HashSet<string> (); + ProjectExtension.OnGetProjectTypes (types); + return types; + } + + protected virtual void OnGetProjectTypes (HashSet<string> types) + { + } + + public bool HasFlavor<T> () + { + return GetService (typeof(T)) != null; + } + + public T GetFlavor<T> () where T:ProjectExtension + { + return (T) GetService (typeof(T)); + } + + internal IEnumerable<ProjectExtension> GetFlavors () + { + return ExtensionChain.GetAllExtensions ().OfType<ProjectExtension> (); + } /// <summary> /// Gets or sets the icon of the project. @@ -138,10 +342,15 @@ namespace MonoDevelop.Projects /// The stock icon. /// </value> public virtual IconId StockIcon { - get { return stockIcon; } + get { + if (stockIcon != null) + return stockIcon.Value; + else + return ProjectExtension.StockIcon; + } set { this.stockIcon = value; NotifyModified ("StockIcon"); } } - IconId stockIcon = "md-project"; + IconId? stockIcon; /// <summary> /// List of languages that this project supports @@ -150,7 +359,7 @@ namespace MonoDevelop.Projects /// The identifiers of the supported languages. /// </value> public virtual string[] SupportedLanguages { - get { return new String[] { "" }; } + get { return ProjectExtension.SupportedLanguages; } } /// <summary> @@ -164,9 +373,60 @@ namespace MonoDevelop.Projects /// </param> public virtual string GetDefaultBuildAction (string fileName) { - return IsCompileable (fileName) ? BuildAction.Compile : BuildAction.None; + return ProjectExtension.OnGetDefaultBuildAction (fileName); } - + + public string GetDefaultResourceId (ProjectFile projectFile) + { + return ProjectExtension.OnGetDefaultResourceId (projectFile); + } + + protected virtual string OnGetDefaultResourceId (ProjectFile projectFile) + { + return MSBuildResourceHandler.Instance.GetDefaultResourceId (projectFile); + } + + internal ProjectItem CreateProjectItem (IMSBuildItemEvaluated item) + { + return ProjectExtension.OnCreateProjectItem (item); + } + + protected virtual ProjectItem OnCreateProjectItem (IMSBuildItemEvaluated item) + { + if (item.Name == "Folder") + return new ProjectFile (); + + // Unknown item. Must be a file. + if (!string.IsNullOrEmpty (item.Include) && !UnsupportedItems.Contains (item.Name) && IsValidFile (item.Include)) + return new ProjectFile (); + + return new UnknownProjectItem (item.Name, item.Include); + } + + bool IsValidFile (string path) + { + // If it is an absolute uri, it's not a valid file + try { + if (Uri.IsWellFormedUriString (path, UriKind.Absolute)) { + var f = new Uri (path); + return f.Scheme == "file"; + } + } catch { + // Old mono versions may crash in IsWellFormedUriString if the path + // is not an uri. + } + return true; + } + + // Items generated by VS but which MD is not using and should be ignored + + internal static readonly IList<string> UnsupportedItems = new string[] { + "BootstrapperFile", "AppDesigner", "WebReferences", "WebReferenceUrl", "Service", + "ProjectReference", "Reference", // Reference elements are included here because they are special-cased for DotNetProject, and they are unsupported in other types of projects + "InternalsVisibleTo", + "InternalsVisibleToTest" + }; + /// <summary> /// Gets a project file. /// </summary> @@ -255,7 +515,7 @@ namespace MonoDevelop.Projects /// </summary> protected virtual IEnumerable<string> GetStandardBuildActions () { - return BuildAction.StandardActions; + return ProjectExtension.OnGetStandardBuildActions (); } /// <summary> @@ -263,25 +523,244 @@ namespace MonoDevelop.Projects /// </summary> protected virtual IList<string> GetCommonBuildActions () { - return BuildAction.StandardActions; + return ProjectExtension.OnGetCommonBuildActions (); } - public static Project LoadProject (string filename, IProgressMonitor monitor) + public override void Dispose () { - Project prj = Services.ProjectService.ReadSolutionItem (monitor, filename) as Project; - if (prj == null) - throw new InvalidOperationException ("Invalid project file: " + filename); + FileService.FileChanged -= OnFileChanged; + Runtime.SystemAssemblyService.DefaultRuntimeChanged -= OnDefaultRuntimeChanged; + CleanupProjectBuilder (); + base.Dispose (); + } - return prj; + /// <summary> + /// Runs a build or execution target. + /// </summary> + /// <returns> + /// The result of the operation + /// </returns> + /// <param name='monitor'> + /// A progress monitor + /// </param> + /// <param name='target'> + /// Name of the target + /// </param> + /// <param name='configuration'> + /// Configuration to use to run the target + /// </param> + public Task<BuildResult> RunTarget (ProgressMonitor monitor, string target, ConfigurationSelector configuration) + { + return ProjectExtension.OnRunTarget (monitor, target, configuration); } + public bool SupportsTarget (string target) + { + return !IsUnsupportedProject && ProjectExtension.OnGetSupportsTarget (target); + } - public override void Dispose () + protected virtual bool OnGetSupportsTarget (string target) { - FileService.FileChanged -= OnFileChanged; - base.Dispose (); + return target == "Build" || target == "Clean"; } - + + /// <summary> + /// Runs a build or execution target. + /// </summary> + /// <returns> + /// The result of the operation + /// </returns> + /// <param name='monitor'> + /// A progress monitor + /// </param> + /// <param name='target'> + /// Name of the target + /// </param> + /// <param name='configuration'> + /// Configuration to use to run the target + /// </param> + /// <remarks> + /// Subclasses can override this method to provide a custom implementation of project operations such as + /// build or clean. The default implementation delegates the execution to the more specific OnBuild + /// and OnClean methods, or to the item handler for other targets. + /// </remarks> + internal async protected virtual Task<BuildResult> OnRunTarget (ProgressMonitor monitor, string target, ConfigurationSelector configuration) + { + if (target == ProjectService.BuildTarget) + return await RunBuildTarget (monitor, configuration); + else if (target == ProjectService.CleanTarget) + return await RunCleanTarget (monitor, configuration); + return await RunMSBuildTarget (monitor, target, configuration) ?? new BuildResult (); + } + + + async Task<BuildResult> DoRunTarget (ProgressMonitor monitor, string target, ConfigurationSelector configuration) + { + if (target == ProjectService.BuildTarget) { + SolutionItemConfiguration conf = GetConfiguration (configuration); + if (conf != null && conf.CustomCommands.HasCommands (CustomCommandType.Build)) { + if (!await conf.CustomCommands.ExecuteCommand (monitor, this, CustomCommandType.Build, configuration)) { + var r = new BuildResult (); + r.AddError (GettextCatalog.GetString ("Custom command execution failed")); + return r; + } + return BuildResult.Success; + } + } else if (target == ProjectService.CleanTarget) { + SolutionItemConfiguration config = GetConfiguration (configuration); + if (config != null && config.CustomCommands.HasCommands (CustomCommandType.Clean)) { + if (!await config.CustomCommands.ExecuteCommand (monitor, this, CustomCommandType.Clean, configuration)) { + var r = new BuildResult (); + r.AddError (GettextCatalog.GetString ("Custom command execution failed")); + return r; + } + return BuildResult.Success; + } + } + return await OnRunTarget (monitor, target, configuration); + } + + async Task<BuildResult> RunMSBuildTarget (ProgressMonitor monitor, string target, ConfigurationSelector configuration) + { + if (CheckUseMSBuildEngine (configuration)) { + LogWriter logWriter = new LogWriter (monitor.Log); + RemoteProjectBuilder builder = GetProjectBuilder (); + var configs = GetConfigurations (configuration); + + MSBuildResult result = null; + await Task.Factory.StartNew (delegate { + result = builder.Run (configs, logWriter, MSBuildProjectService.DefaultMSBuildVerbosity, new[] { target }, null, null); + System.Runtime.Remoting.RemotingServices.Disconnect (logWriter); + }); + + var br = new BuildResult (); + foreach (var err in result.Errors) { + FilePath file = null; + if (err.File != null) + file = Path.Combine (Path.GetDirectoryName (err.ProjectFile), err.File); + + if (err.IsWarning) + br.AddWarning (file, err.LineNumber, err.ColumnNumber, err.Code, err.Message); + else + br.AddError (file, err.LineNumber, err.ColumnNumber, err.Code, err.Message); + } + return br; + } + else { + CleanupProjectBuilder (); + if (this is DotNetProject) { + var handler = new MonoDevelop.Projects.Formats.MD1.MD1DotNetProjectHandler ((DotNetProject)this); + return await handler.RunTarget (monitor, target, configuration); + } + } + return null; + } + + internal ProjectConfigurationInfo[] GetConfigurations (ConfigurationSelector configuration) + { + // Returns a list of project/configuration information for the provided item and all its references + List<ProjectConfigurationInfo> configs = new List<ProjectConfigurationInfo> (); + var c = GetConfiguration (configuration); + configs.Add (new ProjectConfigurationInfo () { + ProjectFile = FileName, + Configuration = c.Name, + Platform = GetExplicitPlatform (c) + }); + foreach (var refProject in GetReferencedItems (configuration).OfType<Project> ()) { + var refConfig = refProject.GetConfiguration (configuration); + if (refConfig != null) { + configs.Add (new ProjectConfigurationInfo () { + ProjectFile = refProject.FileName, + Configuration = refConfig.Name, + Platform = GetExplicitPlatform (refConfig) + }); + } + } + return configs.ToArray (); + } + + //for some reason, MD internally handles "AnyCPU" as "", but we need to be explicit when + //passing it to the build engine + static string GetExplicitPlatform (SolutionItemConfiguration configObject) + { + if (string.IsNullOrEmpty (configObject.Platform)) { + return "AnyCPU"; + } + return configObject.Platform; + } + + #region Project builder management + + RemoteProjectBuilder projectBuilder; + string lastBuildToolsVersion; + string lastBuildRuntime; + string lastFileName; + string lastSlnFileName; + object builderLock = new object (); + + internal RemoteProjectBuilder GetProjectBuilder () + { + //FIXME: we can't really have per-project runtimes, has to be per-solution + TargetRuntime runtime = null; + var ap = this as IAssemblyProject; + runtime = ap != null ? ap.TargetRuntime : Runtime.SystemAssemblyService.CurrentRuntime; + + var sln = ParentSolution; + var slnFile = sln != null ? sln.FileName : null; + + lock (builderLock) { + if (projectBuilder == null || lastBuildToolsVersion != ToolsVersion || lastBuildRuntime != runtime.Id || lastFileName != FileName || lastSlnFileName != slnFile) { + if (projectBuilder != null) { + projectBuilder.Dispose (); + projectBuilder = null; + } + projectBuilder = MSBuildProjectService.GetProjectBuilder (runtime, ToolsVersion, FileName, slnFile); + projectBuilder.Disconnected += delegate { + CleanupProjectBuilder (); + }; + lastBuildToolsVersion = ToolsVersion; + lastBuildRuntime = runtime.Id; + lastFileName = FileName; + lastSlnFileName = slnFile; + } else if (modifiedInMemory) { + modifiedInMemory = false; + // TODO NPM +// var p = SaveProject (new NullProgressMonitor ()); +// projectBuilder.RefreshWithContent (p.SaveToString ()); + } + } + return projectBuilder; + } + + void CleanupProjectBuilder () + { + if (projectBuilder != null) { + projectBuilder.Dispose (); + projectBuilder = null; + } + } + + #endregion + + /// <summary>Whether to use the MSBuild engine for the specified item.</summary> + internal bool CheckUseMSBuildEngine (ConfigurationSelector sel, bool checkReferences = true) + { + // if the item mandates MSBuild, always use it + if (RequireMSBuildEngine) + return true; + // if the user has set the option, use the setting + if (UseMSBuildEngine.HasValue) + return UseMSBuildEngine.Value; + + // If the item type defaults to using MSBuild, only use MSBuild if its direct references also use MSBuild. + // This prevents a not-uncommon common error referencing non-MSBuild projects from MSBuild projects + // NOTE: This adds about 11ms to the load/build/etc times of the MonoDevelop solution. Doing it recursively + // adds well over a second. + return UseMSBuildEngineByDefault && ( + !checkReferences || GetReferencedItems (sel).OfType<Project>().All (i => i.CheckUseMSBuildEngine (sel, false)) + ); + } + /// <summary> /// Adds a file to the project /// </summary> @@ -394,11 +873,15 @@ namespace MonoDevelop.Projects //so in order to avoid doing them twice when using the msbuild engine, we special-case them bool UsingMSBuildEngine (ConfigurationSelector sel) { - var msbuildHandler = ItemHandler as MonoDevelop.Projects.Formats.MSBuild.MSBuildProjectHandler; - return msbuildHandler != null && msbuildHandler.UseMSBuildEngineForItem (this, sel); + return CheckUseMSBuildEngine (sel); } - protected override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration) + protected override Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return RunTarget (monitor, "Build", configuration); + } + + async Task<BuildResult> RunBuildTarget (ProgressMonitor monitor, ConfigurationSelector configuration) { // create output directory, if not exists ProjectConfiguration conf = GetConfiguration (configuration) as ProjectConfiguration; @@ -411,7 +894,7 @@ namespace MonoDevelop.Projects StringParserService.Properties["Project"] = Name; if (UsingMSBuildEngine (configuration)) { - return DoBuild (monitor, configuration); + return await DoBuild (monitor, configuration); } string outputDir = conf.OutputDirectory; @@ -429,7 +912,7 @@ namespace MonoDevelop.Projects monitor.Log.WriteLine ("Performing main compilation..."); - BuildResult res = DoBuild (monitor, configuration); + BuildResult res = await DoBuild (monitor, configuration); if (res != null) { string errorString = GettextCatalog.GetPluralString ("{0} error", "{0} errors", res.ErrorCount, res.ErrorCount); @@ -454,7 +937,7 @@ namespace MonoDevelop.Projects /// Copies all support files to the output directory of the given configuration. Support files /// include: assembly references with the Local Copy flag, data files with the Copy to Output option, etc. /// </remarks> - public void CopySupportFiles (IProgressMonitor monitor, ConfigurationSelector configuration) + public void CopySupportFiles (ProgressMonitor monitor, ConfigurationSelector configuration) { ProjectConfiguration config = (ProjectConfiguration) GetConfiguration (configuration); @@ -505,7 +988,7 @@ namespace MonoDevelop.Projects /// Deletes all support files from the output directory of the given configuration. Support files /// include: assembly references with the Local Copy flag, data files with the Copy to Output option, etc. /// </remarks> - public void DeleteSupportFiles (IProgressMonitor monitor, ConfigurationSelector configuration) + public async Task DeleteSupportFiles (ProgressMonitor monitor, ConfigurationSelector configuration) { ProjectConfiguration config = (ProjectConfiguration) GetConfiguration (configuration); @@ -517,7 +1000,7 @@ namespace MonoDevelop.Projects continue; try { - dest.Delete (); + await dest.DeleteAsync (); } catch (IOException ex) { monitor.ReportError (GettextCatalog.GetString ("Error deleting support file '{0}'.", dest), ex); } @@ -559,13 +1042,17 @@ namespace MonoDevelop.Projects /// </remarks> internal protected virtual void PopulateSupportFileList (FileCopySet list, ConfigurationSelector configuration) { + ProjectExtension.OnPopulateSupportFileList (list, configuration); + } + void DoPopulateSupportFileList (FileCopySet list, ConfigurationSelector configuration) + { foreach (ProjectFile pf in Files) { if (pf.CopyToOutputDirectory == FileCopyMode.None) continue; list.Add (pf.FilePath, pf.CopyToOutputDirectory == FileCopyMode.PreserveNewest, pf.ProjectVirtualPath); } } - + /// <summary> /// Gets a list of files generated when building this project /// </summary> @@ -601,6 +1088,10 @@ namespace MonoDevelop.Projects /// </remarks> internal protected virtual void PopulateOutputFileList (List<FilePath> list, ConfigurationSelector configuration) { + ProjectExtension.OnPopulateOutputFileList (list, configuration); + } + void DoPopulateOutputFileList (List<FilePath> list, ConfigurationSelector configuration) + { string file = GetOutputFileName (configuration); if (file != null) list.Add (file); @@ -622,55 +1113,64 @@ namespace MonoDevelop.Projects /// This method is invoked to build the project. Support files such as files with the Copy to Output flag will /// be copied before calling this method. /// </remarks> - protected virtual BuildResult DoBuild (IProgressMonitor monitor, ConfigurationSelector configuration) + protected async virtual Task<BuildResult> DoBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { - BuildResult res = ItemHandler.RunTarget (monitor, "Build", configuration); + BuildResult res = await RunMSBuildTarget (monitor, "Build", configuration); return res ?? new BuildResult (); } - protected override void OnClean (IProgressMonitor monitor, ConfigurationSelector configuration) + protected override Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return RunTarget (monitor, "Clean", configuration); + } + + async Task<BuildResult> RunCleanTarget (ProgressMonitor monitor, ConfigurationSelector configuration) { ProjectConfiguration config = GetConfiguration (configuration) as ProjectConfiguration; if (config == null) { monitor.ReportError (GettextCatalog.GetString ("Configuration '{0}' not found in project '{1}'", configuration, Name), null); - return; + return BuildResult.Success; } if (UsingMSBuildEngine (configuration)) { - DoClean (monitor, config.Selector); - return; + return await DoClean (monitor, config.Selector); } monitor.Log.WriteLine ("Removing output files..."); - - // Delete generated files - foreach (FilePath file in GetOutputFiles (configuration)) { - if (File.Exists (file)) { - file.Delete (); - if (file.ParentDirectory.CanonicalPath != config.OutputDirectory.CanonicalPath && Directory.GetFiles (file.ParentDirectory).Length == 0) - file.ParentDirectory.Delete (); + + var filesToDelete = GetOutputFiles (configuration).ToArray (); + + await Task.Factory.StartNew (delegate { + // Delete generated files + foreach (FilePath file in filesToDelete) { + if (File.Exists (file)) { + file.Delete (); + if (file.ParentDirectory.CanonicalPath != config.OutputDirectory.CanonicalPath && Directory.GetFiles (file.ParentDirectory).Length == 0) + file.ParentDirectory.Delete (); + } } - } + }); - DeleteSupportFiles (monitor, configuration); + await DeleteSupportFiles (monitor, configuration); - DoClean (monitor, config.Selector); + var res = await DoClean (monitor, config.Selector); monitor.Log.WriteLine (GettextCatalog.GetString ("Clean complete")); + return res; } - protected virtual void DoClean (IProgressMonitor monitor, ConfigurationSelector configuration) + protected virtual Task<BuildResult> DoClean (ProgressMonitor monitor, ConfigurationSelector configuration) { - ItemHandler.RunTarget (monitor, "Clean", configuration); + return RunMSBuildTarget (monitor, "Clean", configuration); } - protected internal override void OnExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + protected async override Task OnExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { ProjectConfiguration config = GetConfiguration (configuration) as ProjectConfiguration; if (config == null) { monitor.ReportError (GettextCatalog.GetString ("Configuration '{0}' not found in project '{1}'", configuration, Name), null); return; } - DoExecute (monitor, context, configuration); + await DoExecute (monitor, context, configuration); } /// <summary> @@ -685,8 +1185,9 @@ namespace MonoDevelop.Projects /// <param name='configuration'> /// Configuration to execute. /// </param> - protected virtual void DoExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + protected virtual Task DoExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { + return new Task (delegate {}); } /// <summary> @@ -700,14 +1201,21 @@ namespace MonoDevelop.Projects /// </param> public virtual FilePath GetOutputFileName (ConfigurationSelector configuration) { - return FilePath.Null; + return ProjectExtension.OnGetOutputFileName (configuration); } - protected internal override bool OnGetNeedsBuilding (ConfigurationSelector configuration) + internal protected override bool OnGetNeedsBuilding (ConfigurationSelector configuration) { return CheckNeedsBuild (configuration); } + protected override void OnSetNeedsBuilding (ConfigurationSelector configuration) + { + var of = GetOutputFileName (configuration); + if (File.Exists (of)) + File.Delete (of); + } + /// <summary> /// Checks if the project needs to be built /// </summary> @@ -734,7 +1242,7 @@ namespace MonoDevelop.Projects } } - foreach (SolutionItem pref in GetReferencedItems (configuration)) { + foreach (SolutionFolderItem pref in GetReferencedItems (configuration)) { if (pref.GetLastBuildTime (configuration) > tim) return true; } @@ -778,16 +1286,19 @@ namespace MonoDevelop.Projects } } - protected internal override List<FilePath> OnGetItemFiles (bool includeReferencedFiles) + protected override IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles) { - List<FilePath> col = base.OnGetItemFiles (includeReferencedFiles); + var baseFiles = base.OnGetItemFiles (includeReferencedFiles); + if (includeReferencedFiles) { + List<FilePath> col = new List<FilePath> (); foreach (ProjectFile pf in Files) { if (pf.Subtype != Subtype.Directory) col.Add (pf.FilePath); } + baseFiles = baseFiles.Concat (col); } - return col; + return baseFiles; } protected internal override void OnItemsAdded (IEnumerable<ProjectItem> objs) @@ -908,6 +1419,775 @@ namespace MonoDevelop.Projects } } + internal void ReadProject (ProgressMonitor monitor, MSBuildProject msproject) + { + OnReadProjectHeader (monitor, msproject); + ProjectExtension.OnReadProject (monitor, msproject); + NeedsReload = false; + } + + bool newProject; + + internal MSBuildProject WriteProject (ProgressMonitor monitor) + { + MSBuildProject msproject = new MSBuildProject (); + newProject = FileName == null || !File.Exists (FileName); + if (newProject) { + if (SupportsBuild ()) + msproject.DefaultTargets = "Build"; + msproject.FileName = FileName; + } else { + msproject.Load (FileName); + } + + OnWriteProjectHeader (monitor, msproject); + ProjectExtension.OnWriteProject (monitor, msproject); + + return msproject; + } + + class ConfigData + { + public ConfigData (string conf, string plt, IMSBuildPropertySet grp) + { + Config = conf; + Platform = plt; + Group = grp; + } + + public bool FullySpecified { + get { return Config != Unspecified && Platform != Unspecified; } + } + + public string Config; + public string Platform; + public IMSBuildPropertySet Group; + public bool Exists; + public bool IsNew; // The group did not exist in the original file + } + + const string Unspecified = null; + ITimeTracker timer; + + protected virtual void OnReadProjectHeader (ProgressMonitor monitor, MSBuildProject msproject) + { + timer = Counters.ReadMSBuildProject.BeginTiming (); + + ToolsVersion = msproject.ToolsVersion; + if (string.IsNullOrEmpty (ToolsVersion)) + ToolsVersion = "2.0"; + + IMSBuildPropertySet globalGroup = msproject.GetGlobalPropertyGroup (); + // Avoid crash if there is not global group + if (globalGroup == null) + globalGroup = msproject.AddNewPropertyGroup (false); + + productVersion = globalGroup.GetValue ("ProductVersion"); + schemaVersion = globalGroup.GetValue ("SchemaVersion"); + + // Get the project ID + + string itemGuid = globalGroup.GetValue ("ProjectGuid"); + if (itemGuid == null) + throw new UserException ("Project file doesn't have a valid ProjectGuid"); + + // Workaround for a VS issue. VS doesn't include the curly braces in the ProjectGuid + // of shared projects. + if (!itemGuid.StartsWith ("{", StringComparison.Ordinal)) + itemGuid = "{" + itemGuid + "}"; + + ItemId = itemGuid.ToUpper (); + + // Get the project GUIDs + + string projectTypeGuids = globalGroup.GetValue ("ProjectTypeGuids"); + + var subtypeGuids = new List<string> (); + if (projectTypeGuids != null) { + foreach (string guid in projectTypeGuids.Split (';')) { + string sguid = guid.Trim (); + if (sguid.Length > 0 && string.Compare (sguid, TypeGuid, StringComparison.OrdinalIgnoreCase) != 0) + subtypeGuids.Add (guid); + } + } + flavorGuids = subtypeGuids.ToArray (); + + if (!CheckAllFlavorsSupported ()) { + var guids = new [] { TypeGuid }; + var projectInfo = MSBuildProjectService.GetUnknownProjectTypeInfo (guids.Concat (flavorGuids).ToArray (), FileName); + IsUnsupportedProject = true; + if (projectInfo != null) + UnsupportedProjectMessage = projectInfo.GetInstructions (); + } + + // Common properties + + Description = msproject.EvaluatedProperties.GetValue ("Description", ""); + baseIntermediateOutputPath = msproject.EvaluatedProperties.GetPathValue ("BaseIntermediateOutputPath", defaultValue:BaseDirectory.Combine ("obj"), relativeToProject:true); + + RemoveDuplicateItems (msproject); + } + + protected virtual void OnReadProject (ProgressMonitor monitor, MSBuildProject msproject) + { + timer.Trace ("Read project items"); + LoadProjectItems (msproject, ProjectItemFlags.None); + + timer.Trace ("Read configurations"); + + List<ConfigData> configData = GetConfigData (msproject, false); + List<ConfigData> partialConfigurations = new List<ConfigData> (); + HashSet<string> handledConfigurations = new HashSet<string> (); + var configurations = new HashSet<string> (); + var platforms = new HashSet<string> (); + + IMSBuildPropertySet globalGroup = msproject.GetGlobalPropertyGroup (); + configData.Insert (0, new ConfigData (Unspecified, Unspecified, globalGroup)); + + // Load configurations, skipping the dummy config at index 0. + for (int i = 1; i < configData.Count; i++) { + ConfigData cgrp = configData[i]; + string platform = cgrp.Platform; + string conf = cgrp.Config; + + if (platform != Unspecified) + platforms.Add (platform); + + if (conf != Unspecified) + configurations.Add (conf); + + if (conf == Unspecified || platform == Unspecified) { + // skip partial configurations for now... + partialConfigurations.Add (cgrp); + continue; + } + + string key = conf + "|" + platform; + if (handledConfigurations.Contains (key)) + continue; + + LoadConfiguration (monitor, configData, conf, platform); + + handledConfigurations.Add (key); + } + + // Now we can load any partial configurations by combining them with known configs or platforms. + if (partialConfigurations.Count > 0) { + if (platforms.Count == 0) + platforms.Add (string.Empty); // AnyCpu + + foreach (ConfigData cgrp in partialConfigurations) { + if (cgrp.Config != Unspecified && cgrp.Platform == Unspecified) { + string conf = cgrp.Config; + + foreach (var platform in platforms) { + string key = conf + "|" + platform; + + if (handledConfigurations.Contains (key)) + continue; + + LoadConfiguration (monitor, configData, conf, platform); + + handledConfigurations.Add (key); + } + } else if (cgrp.Config == Unspecified && cgrp.Platform != Unspecified) { + string platform = cgrp.Platform; + + foreach (var conf in configurations) { + string key = conf + "|" + platform; + + if (handledConfigurations.Contains (key)) + continue; + + LoadConfiguration (monitor, configData, conf, platform); + + handledConfigurations.Add (key); + } + } + } + } + + // Read extended properties + + timer.Trace ("Read extended properties"); + } + + List<ConfigData> GetConfigData (MSBuildProject msproject, bool includeGlobalGroups) + { + List<ConfigData> configData = new List<ConfigData> (); + foreach (MSBuildPropertyGroup cgrp in msproject.PropertyGroups) { + string conf, platform; + if (ParseConfigCondition (cgrp.Condition, out conf, out platform) || includeGlobalGroups) + configData.Add (new ConfigData (conf, platform, cgrp)); + } + return configData; + } + + bool ParseConfigCondition (string cond, out string config, out string platform) + { + config = platform = Unspecified; + int i = cond.IndexOf ("==", StringComparison.Ordinal); + if (i == -1) + return false; + if (cond.Substring (0, i).Trim () == "'$(Configuration)|$(Platform)'") { + if (!ExtractConfigName (cond.Substring (i + 2), out cond)) + return false; + i = cond.IndexOf ('|'); + if (i != -1) { + config = cond.Substring (0, i); + platform = cond.Substring (i+1); + } else { + // Invalid configuration + return false; + } + if (platform == "AnyCPU") + platform = string.Empty; + return true; + } + else if (cond.Substring (0, i).Trim () == "'$(Configuration)'") { + if (!ExtractConfigName (cond.Substring (i + 2), out config)) + return false; + platform = Unspecified; + return true; + } + else if (cond.Substring (0, i).Trim () == "'$(Platform)'") { + config = Unspecified; + if (!ExtractConfigName (cond.Substring (i + 2), out platform)) + return false; + if (platform == "AnyCPU") + platform = string.Empty; + return true; + } + return false; + } + + bool ExtractConfigName (string name, out string config) + { + config = name.Trim (' '); + if (config.Length <= 2) + return false; + if (config [0] != '\'' || config [config.Length - 1] != '\'') + return false; + config = config.Substring (1, config.Length - 2); + return config.IndexOf ('\'') == -1; + } + + void LoadConfiguration (ProgressMonitor monitor, List<ConfigData> configData, string conf, string platform) + { + IMSBuildPropertySet grp = GetMergedConfiguration (configData, conf, platform, null); + ProjectConfiguration config = (ProjectConfiguration) CreateConfiguration (conf); + + config.Platform = platform; + projectExtension.OnReadConfiguration (monitor, config, grp); + Configurations.Add (config); + } + + protected virtual void OnReadConfiguration (ProgressMonitor monitor, ProjectConfiguration config, IMSBuildPropertySet grp) + { + config.Read (grp, GetToolsFormat ()); + } + + void RemoveDuplicateItems (MSBuildProject msproject) + { + timer.Trace ("Checking for duplicate items"); + + var uniqueIncludes = new Dictionary<string,object> (); + var toRemove = new List<MSBuildItem> (); + foreach (MSBuildItem bi in msproject.GetAllItems ()) { + object existing; + string key = bi.Name + "<" + bi.Include; + if (!uniqueIncludes.TryGetValue (key, out existing)) { + uniqueIncludes[key] = bi; + continue; + } + var exBi = existing as MSBuildItem; + if (exBi != null) { + if (exBi.Condition != bi.Condition || exBi.Element.InnerXml != bi.Element.InnerXml) { + uniqueIncludes[key] = new List<MSBuildItem> { exBi, bi }; + } else { + toRemove.Add (bi); + } + continue; + } + + var exList = (List<MSBuildItem>)existing; + bool found = false; + foreach (var m in (exList)) { + if (m.Condition == bi.Condition && m.Element.InnerXml == bi.Element.InnerXml) { + found = true; + break; + } + } + if (!found) { + exList.Add (bi); + } else { + toRemove.Add (bi); + } + } + if (toRemove.Count == 0) + return; + + timer.Trace ("Removing duplicate items"); + + foreach (var t in toRemove) + msproject.RemoveItem (t); + } + + IMSBuildPropertySet GetMergedConfiguration (List<ConfigData> configData, string conf, string platform, IMSBuildPropertySet propGroupLimit) + { + IMSBuildPropertySet merged = null; + + foreach (ConfigData grp in configData) { + if (grp.Group == propGroupLimit) + break; + if ((grp.Config == conf || grp.Config == Unspecified || conf == Unspecified) && (grp.Platform == platform || grp.Platform == Unspecified || platform == Unspecified)) { + if (merged == null) + merged = grp.Group; + else if (merged is MSBuildPropertyGroupMerged) + ((MSBuildPropertyGroupMerged)merged).Add (grp.Group); + else { + MSBuildPropertyGroupMerged m = new MSBuildPropertyGroupMerged (merged.Project, GetToolsFormat()); + m.Add (merged); + m.Add (grp.Group); + merged = m; + } + } + } + return merged; + } + + //HACK: the solution's format is irrelevant to MSBuild projects, what matters is the ToolsVersion + // but other parts of the MD API expect a FileFormat + internal MSBuildFileFormat GetToolsFormat () + { + switch (ToolsVersion) { + case "2.0": + return new MSBuildFileFormatVS05 (); + case "3.5": + return new MSBuildFileFormatVS08 (); + case "4.0": + if (SolutionFormat != null && SolutionFormat.Id == "MSBuild10") + return SolutionFormat; + return new MSBuildFileFormatVS12 (); + case "12.0": + return new MSBuildFileFormatVS12 (); + default: + throw new Exception ("Unknown ToolsVersion '" + ToolsVersion + "'"); + } + } + + internal void LoadProjectItems (MSBuildProject msproject, ProjectItemFlags flags) + { + foreach (var buildItem in msproject.GetAllItems ()) { + ProjectItem it = ReadItem (buildItem); + if (it == null) + continue; + it.Flags = flags; + if (it is ProjectFile) { + var file = (ProjectFile)it; + if (file.Name.IndexOf ('*') > -1) { + // Thanks to IsOriginatedFromWildcard, these expanded items will not be saved back to disk. + foreach (var expandedItem in ResolveWildcardItems (file)) + Items.Add (expandedItem); + // Add to wildcard items (so it can be re-saved) instead of Items (where tools will + // try to compile and display these nonstandard items + WildcardItems.Add (it); + continue; + } + } + Items.Add (it); + } + } + + internal override void SetSolutionFormat (MSBuildFileFormat format, bool converting) + { + base.SetSolutionFormat (format, converting); + + // when converting formats, set ToolsVersion, ProductVersion, SchemaVersion to default values written by VS + // this happens on creation too + // else we leave them alone and just roundtrip them + if (converting) { + ToolsVersion = format.DefaultToolsVersion; + productVersion = format.DefaultProductVersion; + schemaVersion = format.DefaultSchemaVersion; + } + } + + internal ProjectItem ReadItem (IMSBuildItemEvaluated buildItem) + { + var item = CreateProjectItem (buildItem); + item.Read (this, buildItem); + return item; + } + + const string RecursiveDirectoryWildcard = "**"; + static readonly char[] directorySeparators = new [] { + Path.DirectorySeparatorChar, + Path.AltDirectorySeparatorChar + }; + + static string GetWildcardDirectoryName (string path) + { + int indexOfLast = path.LastIndexOfAny (directorySeparators); + if (indexOfLast < 0) + return String.Empty; + return path.Substring (0, indexOfLast); + } + + static string GetWildcardFileName (string path) + { + int indexOfLast = path.LastIndexOfAny (directorySeparators); + if (indexOfLast < 0) + return path; + if (indexOfLast == path.Length) + return String.Empty; + return path.Substring (indexOfLast + 1, path.Length - (indexOfLast + 1)); + } + + + static IEnumerable<string> ExpandWildcardFilePath (string filePath) + { + if (String.IsNullOrWhiteSpace (filePath)) + throw new ArgumentException ("Not a wildcard path"); + + string dir = GetWildcardDirectoryName (filePath); + string file = GetWildcardFileName (filePath); + + if (String.IsNullOrEmpty (dir) || String.IsNullOrEmpty (file)) + return null; + + SearchOption searchOption = SearchOption.TopDirectoryOnly; + if (dir.EndsWith (RecursiveDirectoryWildcard, StringComparison.Ordinal)) { + dir = dir.Substring (0, dir.Length - RecursiveDirectoryWildcard.Length); + searchOption = SearchOption.AllDirectories; + } + + if (!Directory.Exists (dir)) + return null; + + return Directory.GetFiles (dir, file, searchOption); + } + + static IEnumerable<ProjectFile> ResolveWildcardItems (ProjectFile wildcardFile) + { + var paths = ExpandWildcardFilePath (wildcardFile.Name); + if (paths == null) + yield break; + foreach (var resolvedFilePath in paths) { + var projectFile = (ProjectFile)wildcardFile.Clone (); + projectFile.Name = resolvedFilePath; + projectFile.Flags |= ProjectItemFlags.DontPersist; + yield return projectFile; + } + } + + struct MergedPropertyValue + { + public readonly string XmlValue; + public readonly bool PreserveExistingCase; + public readonly bool IsDefault; + + public MergedPropertyValue (string xmlValue, bool preserveExistingCase, bool isDefault) + { + this.XmlValue = xmlValue; + this.PreserveExistingCase = preserveExistingCase; + this.IsDefault = isDefault; + } + } + + protected virtual void OnWriteProjectHeader (ProgressMonitor monitor, MSBuildProject msproject) + { + IMSBuildPropertySet globalGroup = msproject.GetGlobalPropertyGroup (); + if (globalGroup == null) + globalGroup = msproject.AddNewPropertyGroup (false); + + if (Configurations.Count > 0) { + ItemConfiguration conf = Configurations.FirstOrDefault<ItemConfiguration> (c => c.Name == "Debug"); + if (conf == null) conf = Configurations [0]; + globalGroup.SetValue ("Configuration", conf.Name, condition:" '$(Configuration)' == '' "); + + string platform = conf.Platform.Length == 0 ? "AnyCPU" : conf.Platform; + globalGroup.SetValue ("Platform", platform, condition:" '$(Platform)' == '' "); + } + + if (TypeGuid == MSBuildProjectService.GenericItemGuid) { + DataType dt = MSBuildProjectService.DataContext.GetConfigurationDataType (GetType ()); + globalGroup.SetValue ("ItemType", dt.Name); + } + + globalGroup.SetValue ("ProductVersion", productVersion); + globalGroup.SetValue ("SchemaVersion", schemaVersion); + + globalGroup.SetValue ("ProjectGuid", ItemId); + + if (flavorGuids.Length > 0) { + string gg = string.Join (";", flavorGuids); + gg += ";" + TypeGuid; + globalGroup.SetValue ("ProjectTypeGuids", gg.ToUpper (), preserveExistingCase:true); + } else { + globalGroup.RemoveProperty ("ProjectTypeGuids"); + } + + // having no ToolsVersion is equivalent to 2.0, roundtrip that correctly + if (ToolsVersion != "2.0") + msproject.ToolsVersion = ToolsVersion; + else if (string.IsNullOrEmpty (msproject.ToolsVersion)) + msproject.ToolsVersion = null; + else + msproject.ToolsVersion = "2.0"; + + msproject.GetGlobalPropertyGroup ().SetValue ("Description", Description, ""); + msproject.GetGlobalPropertyGroup ().SetValue ("BaseIntermediateOutputPath", BaseIntermediateOutputPath, defaultValue:BaseDirectory.Combine ("obj"), relativeToProject:true); + } + + protected virtual void OnWriteProject (ProgressMonitor monitor, MSBuildProject msproject) + { + var toolsFormat = GetToolsFormat (); + + IMSBuildPropertySet globalGroup = msproject.GetGlobalPropertyGroup (); + + // Configurations + + if (Configurations.Count > 0) { + List<ConfigData> configData = GetConfigData (msproject, true); + + // Write configuration data, creating new property groups if necessary + + foreach (ProjectConfiguration conf in Configurations) { + ConfigData cdata = FindPropertyGroup (configData, conf); + if (cdata == null) { + MSBuildPropertyGroup pg = msproject.AddNewPropertyGroup (true); + pg.IgnoreDefaultValues = true; + pg.Condition = BuildConfigCondition (conf.Name, conf.Platform); + cdata = new ConfigData (conf.Name, conf.Platform, pg); + cdata.IsNew = true; + configData.Add (cdata); + } + ((MSBuildPropertyGroup)cdata.Group).IgnoreDefaultValues = true; + cdata.Exists = true; + ProjectExtension.OnWriteConfiguration (monitor, conf, cdata.Group); + } + + // Find the properties in all configurations that have the MergeToProject flag set + var mergeToProjectProperties = new HashSet<MergedProperty> (GetMergeToProjectProperties (configData)); + var mergeToProjectPropertyNames = new HashSet<string> (mergeToProjectProperties.Select (p => p.Name)); + var mergeToProjectPropertyValues = new Dictionary<string,MergedPropertyValue> (); + + foreach (ProjectConfiguration conf in Configurations) { + ConfigData cdata = FindPropertyGroup (configData, conf); + var propGroup = (MSBuildPropertyGroup) cdata.Group; + + IMSBuildPropertySet baseGroup = GetMergedConfiguration (configData, conf.Name, conf.Platform, propGroup); + + CollectMergetoprojectProperties (propGroup, mergeToProjectProperties, mergeToProjectPropertyValues); + + propGroup.UnMerge (baseGroup, mergeToProjectPropertyNames); + propGroup.IgnoreDefaultValues = false; + } + + // Move properties with common values from configurations to the main + // property group + foreach (KeyValuePair<string,MergedPropertyValue> prop in mergeToProjectPropertyValues) { + if (!prop.Value.IsDefault) + globalGroup.SetValue (prop.Key, prop.Value.XmlValue, preserveExistingCase: prop.Value.PreserveExistingCase); + else + globalGroup.RemoveProperty (prop.Key); + } + foreach (string prop in mergeToProjectPropertyNames) { + if (!mergeToProjectPropertyValues.ContainsKey (prop)) + globalGroup.RemoveProperty (prop); + } + foreach (SolutionItemConfiguration conf in Configurations) { + var propGroup = FindPropertyGroup (configData, conf).Group; + foreach (string mp in mergeToProjectPropertyValues.Keys) + propGroup.RemoveProperty (mp); + } + + // Remove groups corresponding to configurations that have been removed + // or groups which don't have any property and did not already exist + foreach (ConfigData cd in configData) { + if ((!cd.Exists && cd.FullySpecified) || (cd.IsNew && !cd.Group.Properties.Any ())) + msproject.RemoveGroup ((MSBuildPropertyGroup)cd.Group); + } + } + SaveProjectItems (monitor, toolsFormat, msproject); + + if (msproject.IsNewProject) { + foreach (var im in DefaultImports) + msproject.AddNewImport (im); + } + + foreach (var im in importsAdded) { + if (msproject.GetImport (im.Name, im.Condition) == null) + msproject.AddNewImport (im.Name, im.Condition); + } + foreach (var im in importsRemoved) { + var i = msproject.GetImport (im.Name, im.Condition); + if (i != null) + msproject.RemoveImport (i); + } + } + + void WriteConfiguration (ProgressMonitor monitor, List<ConfigData> configData, string conf, string platform) + { + IMSBuildPropertySet grp = GetMergedConfiguration (configData, conf, platform, null); + ProjectConfiguration config = (ProjectConfiguration) CreateConfiguration (conf); + + config.Platform = platform; + config.Read (grp, GetToolsFormat ()); + Configurations.Add (config); + projectExtension.OnReadConfiguration (monitor, config, grp); + } + + protected virtual void OnWriteConfiguration (ProgressMonitor monitor, ProjectConfiguration config, IMSBuildPropertySet pset) + { + config.Write (pset, SolutionFormat); + } + + IEnumerable<MergedProperty> GetMergeToProjectProperties (List<ConfigData> configData) + { + Dictionary<string,MergedProperty> mergeProps = new Dictionary<string, MergedProperty> (); + foreach (var cd in configData.Where (d => d.FullySpecified)) { + foreach (var prop in cd.Group.Properties) { + if (!prop.MergeToMainGroup) { + mergeProps [prop.Name] = null; + } else if (!mergeProps.ContainsKey (prop.Name)) + mergeProps [prop.Name] = prop.CreateMergedProperty (); + } + } + return mergeProps.Values.Where (p => p != null); + } + + void CollectMergetoprojectProperties (IMSBuildPropertySet pgroup, HashSet<MergedProperty> properties, Dictionary<string,MergedPropertyValue> mergeToProjectProperties) + { + // This method checks every property in pgroup which has the MergeToProject flag. + // If the value of this property is the same as the one stored in mergeToProjectProperties + // it means that the property can be merged to the main project property group (so far). + + foreach (var pinfo in new List<MergedProperty> (properties)) { + MSBuildProperty prop = pgroup.GetProperty (pinfo.Name); + + MergedPropertyValue mvalue; + if (!mergeToProjectProperties.TryGetValue (pinfo.Name, out mvalue)) { + if (prop != null) { + // This is the first time the value is checked. Just assign it. + mergeToProjectProperties.Add (pinfo.Name, new MergedPropertyValue (prop.Value, pinfo.PreserveExistingCase, pinfo.IsDefault)); + continue; + } + // If there is no value, it can't be merged + } + else if (prop != null && string.Equals (prop.Value, mvalue.XmlValue, mvalue.PreserveExistingCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) + // Same value. It can be merged. + continue; + + // The property can't be merged because different configurations have different + // values for it. Remove it from the list. + properties.Remove (pinfo); + mergeToProjectProperties.Remove (pinfo.Name); + } + } + + struct ItemInfo { + public MSBuildItem Item; + public bool Added; + } + + internal void SaveProjectItems (ProgressMonitor monitor, MSBuildFileFormat toolsFormat, MSBuildProject msproject, string pathPrefix = null) + { + // Remove old items + Dictionary<string, ItemInfo> oldItems = new Dictionary<string, ItemInfo> (); + foreach (MSBuildItem item in msproject.GetAllItems ()) + oldItems [item.Name + "<" + item.UnevaluatedInclude + "<" + item.Condition] = new ItemInfo () { + Item = item + }; + // Add the new items + foreach (ProjectItem ob in Items.Concat (WildcardItems).Where (it => !it.Flags.HasFlag (ProjectItemFlags.DontPersist))) + SaveProjectItem (monitor, toolsFormat, msproject, ob, oldItems, pathPrefix); + foreach (ItemInfo itemInfo in oldItems.Values) { + if (!itemInfo.Added) + msproject.RemoveItem (itemInfo.Item); + } + } + + void SaveProjectItem (ProgressMonitor monitor, MSBuildFileFormat fmt, MSBuildProject msproject, ProjectItem item, Dictionary<string,ItemInfo> oldItems, string pathPrefix = null) + { + var include = item.UnevaluatedInclude ?? item.Include; + if (pathPrefix != null && !include.StartsWith (pathPrefix)) + include = pathPrefix + include; + + MSBuildItem buildItem = AddOrGetBuildItem (msproject, oldItems, item.ItemName, include, item.Condition); + item.Write (fmt, buildItem); + if (pathPrefix != null) + buildItem.Include = include; + } + + MSBuildItem AddOrGetBuildItem (MSBuildProject msproject, Dictionary<string,ItemInfo> oldItems, string name, string include, string condition) + { + ItemInfo itemInfo; + string key = name + "<" + include + "<" + condition; + if (oldItems.TryGetValue (key, out itemInfo)) { + if (!itemInfo.Added) { + itemInfo.Added = true; + oldItems [key] = itemInfo; + } + return itemInfo.Item; + } else { + return msproject.AddNewItem (name, include); + } + } + + ConfigData FindPropertyGroup (List<ConfigData> configData, SolutionItemConfiguration config) + { + foreach (ConfigData data in configData) { + if (data.Config == config.Name && data.Platform == config.Platform) + return data; + } + return null; + } + + string BuildConfigCondition (string config, string platform) + { + if (platform.Length == 0) + platform = "AnyCPU"; + return " '$(Configuration)|$(Platform)' == '" + config + "|" + platform + "' "; + } + + bool IsMergeToProjectProperty (ItemProperty prop) + { + foreach (object at in prop.CustomAttributes) { + if (at is MergeToProjectAttribute) + return true; + } + return false; + } + + public void AddImportIfMissing (string name, string condition) + { + importsAdded.Add (new DotNetProjectImport (name, condition)); + } + + public void RemoveImport (string name) + { + importsRemoved.Add (new DotNetProjectImport (name)); + } + + List <DotNetProjectImport> importsAdded = new List<DotNetProjectImport> (); + + internal IList<DotNetProjectImport> ImportsAdded { + get { return importsAdded; } + } + + List <DotNetProjectImport> importsRemoved = new List<DotNetProjectImport> (); + + internal IList<DotNetProjectImport> ImportsRemoved { + get { return importsRemoved; } + } + + void ImportsSaved () + { + importsAdded.Clear (); + importsRemoved.Clear (); + } internal void NotifyFileRenamedInProject (ProjectFileRenamedEventArgs args) { NotifyModified ("Files"); @@ -919,6 +2199,10 @@ namespace MonoDevelop.Projects /// </summary> protected virtual void OnFileRemovedFromProject (ProjectFileEventArgs e) { + ProjectExtension.OnFileRemovedFromProject (e); + } + void DoOnFileRemovedFromProject (ProjectFileEventArgs e) + { buildActions = null; if (FileRemovedFromProject != null) { FileRemovedFromProject (this, e); @@ -930,38 +2214,54 @@ namespace MonoDevelop.Projects /// </summary> protected virtual void OnFileAddedToProject (ProjectFileEventArgs e) { + ProjectExtension.OnFileAddedToProject (e); + } + void DoOnFileAddedToProject (ProjectFileEventArgs e) + { buildActions = null; if (FileAddedToProject != null) { FileAddedToProject (this, e); } } - + /// <summary> /// Raises the FileChangedInProject event. /// </summary> protected virtual void OnFileChangedInProject (ProjectFileEventArgs e) { + ProjectExtension.OnFileChangedInProject (e); + } + void DoOnFileChangedInProject (ProjectFileEventArgs e) + { if (FileChangedInProject != null) { FileChangedInProject (this, e); } } - + /// <summary> /// Raises the FilePropertyChangedInProject event. /// </summary> protected virtual void OnFilePropertyChangedInProject (ProjectFileEventArgs e) { + ProjectExtension.OnFilePropertyChangedInProject (e); + } + void DoOnFilePropertyChangedInProject (ProjectFileEventArgs e) + { buildActions = null; if (FilePropertyChangedInProject != null) { FilePropertyChangedInProject (this, e); } } - + /// <summary> /// Raises the FileRenamedInProject event. /// </summary> protected virtual void OnFileRenamedInProject (ProjectFileRenamedEventArgs e) { + ProjectExtension.OnFileRenamedInProject (e); + } + void DoOnFileRenamedInProject (ProjectFileRenamedEventArgs e) + { if (FileRenamedInProject != null) { FileRenamedInProject (this, e); } @@ -991,6 +2291,126 @@ namespace MonoDevelop.Projects /// Occurs when a file of this project has been renamed /// </summary> public event ProjectFileRenamedEventHandler FileRenamedInProject; + + + class DefaultMSBuildProjectExtension: ProjectExtension + { + internal protected override bool SupportsFlavor (string guid) + { + return false; + } + + internal protected override bool OnGetIsCompileable (string fileName) + { + return false; + } + + internal protected override void OnGetProjectTypes (HashSet<string> types) + { + Project.OnGetProjectTypes (types); + } + + internal protected override Task<BuildResult> OnRunTarget (ProgressMonitor monitor, string target, ConfigurationSelector configuration) + { + return Project.DoRunTarget (monitor, target, configuration); + } + + internal protected override bool OnGetSupportsTarget (string target) + { + return Project.OnGetSupportsTarget (target); + } + + internal protected override string OnGetDefaultBuildAction (string fileName) + { + return Project.IsCompileable (fileName) ? BuildAction.Compile : BuildAction.None; + } + + internal protected override string OnGetDefaultResourceId (ProjectFile projectFile) + { + return Project.OnGetDefaultResourceId (projectFile); + } + + internal protected override IEnumerable<string> OnGetStandardBuildActions () + { + return BuildAction.StandardActions; + } + + internal protected override IList<string> OnGetCommonBuildActions () + { + return BuildAction.StandardActions; + } + + internal protected override ProjectItem OnCreateProjectItem (IMSBuildItemEvaluated item) + { + return Project.OnCreateProjectItem (item); + } + + internal protected override void OnPopulateSupportFileList (FileCopySet list, ConfigurationSelector configuration) + { + Project.DoPopulateSupportFileList (list, configuration); + } + + internal protected override void OnPopulateOutputFileList (List<FilePath> list, ConfigurationSelector configuration) + { + Project.DoPopulateOutputFileList (list, configuration); + } + + internal protected override FilePath OnGetOutputFileName (ConfigurationSelector configuration) + { + return FilePath.Null; + } + + internal protected override string[] SupportedLanguages { + get { + return new String[] { "" }; + } + } + + internal protected override void OnFileRemovedFromProject (ProjectFileEventArgs e) + { + Project.DoOnFileRemovedFromProject (e); + } + + internal protected override void OnFileAddedToProject (ProjectFileEventArgs e) + { + Project.DoOnFileAddedToProject (e); + } + + internal protected override void OnFileChangedInProject (ProjectFileEventArgs e) + { + Project.DoOnFileChangedInProject (e); + } + + internal protected override void OnFilePropertyChangedInProject (ProjectFileEventArgs e) + { + Project.DoOnFilePropertyChangedInProject (e); + } + + internal protected override void OnFileRenamedInProject (ProjectFileRenamedEventArgs e) + { + Project.DoOnFileRenamedInProject (e); + } + + internal protected override void OnReadProject (ProgressMonitor monitor, MSBuildProject msproject) + { + Project.OnReadProject (monitor, msproject); + } + + internal protected override void OnWriteProject (ProgressMonitor monitor, MSBuildProject msproject) + { + Project.OnWriteProject (monitor, msproject); + } + + internal protected override void OnReadConfiguration (ProgressMonitor monitor, ProjectConfiguration config, IMSBuildPropertySet grp) + { + Project.OnReadConfiguration (monitor, config, grp); + } + + internal protected override void OnWriteConfiguration (ProgressMonitor monitor, ProjectConfiguration config, IMSBuildPropertySet grp) + { + Project.OnWriteConfiguration (monitor, config, grp); + } + } } public delegate void ProjectEventHandler (Object sender, ProjectEventArgs e); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectConfiguration.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectConfiguration.cs index 1db4404892..7a4420c57c 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectConfiguration.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectConfiguration.cs @@ -32,10 +32,12 @@ using System.IO; using MonoDevelop.Core.Serialization; using System.Collections.Generic; using MonoDevelop.Core.StringParsing; +using System.Xml.Linq; +using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.Projects { - public class ProjectConfiguration : SolutionItemConfiguration + public class ProjectConfiguration : SolutionItemConfiguration, IMSBuildDataObject { public ProjectConfiguration () @@ -46,8 +48,64 @@ namespace MonoDevelop.Projects { } - [ProjectPathItemProperty("IntermediateOutputPath")] - private FilePath intermediateOutputDirectory; + #region IProjectConfigurationData implementation + + void IMSBuildDataObject.Read (IMSBuildPropertySet pset, MSBuildFileFormat format) + { + Read (pset, format); + } + + void IMSBuildDataObject.Write (IMSBuildPropertySet pset, MSBuildFileFormat format) + { + Write (pset, format); + } + + #endregion + + internal protected virtual void Read (IMSBuildPropertySet pset, MSBuildFileFormat format) + { + intermediateOutputDirectory = pset.GetPathValue ("IntermediateOutputPath"); + outputDirectory = pset.GetPathValue ("OutputPath", defaultValue:"." + Path.DirectorySeparatorChar); + debugMode = pset.GetValue<bool> ("DebugSymbols"); + pauseConsoleOutput = pset.GetValue ("ConsolePause", true); + externalConsole = pset.GetValue<bool> ("ExternalConsole"); + commandLineParameters = pset.GetValue ("Commandlineparameters", ""); + runWithWarnings = pset.GetValue ("RunWithWarnings", true); + + var svars = pset.GetValue ("EnvironmentVariables"); + if (svars != null) { + XElement vars = XElement.Parse (svars); + foreach (var val in vars.Elements ("Variable")) { + var name = (string)val.Attribute ("name"); + if (name != null) + environmentVariables [name] = (string)val.Attribute ("value"); + } + } + } + + internal protected virtual void Write (IMSBuildPropertySet pset, MSBuildFileFormat format) + { + pset.SetValue ("IntermediateOutputPath", intermediateOutputDirectory, defaultValue:FilePath.Null); + pset.SetValue ("DebugSymbols", debugMode, false); + pset.SetValue ("OutputPath", outputDirectory); + pset.SetValue ("ConsolePause", pauseConsoleOutput, true); + pset.SetValue ("ExternalConsole", externalConsole, false); + pset.SetValue ("Commandlineparameters", commandLineParameters, ""); + pset.SetValue ("RunWithWarnings", runWithWarnings, true); + + if (environmentVariables.Count > 0) { + XElement e = new XElement ("EnvironmentVariables"); + foreach (var v in environmentVariables) { + var val = new XElement ("Variable"); + val.SetAttributeValue ("name", v.Key); + val.SetAttributeValue ("value", v.Value); + e.Add (val); + } + pset.SetValue ("EnvironmentVariables", e.ToString ()); + } + } + + FilePath intermediateOutputDirectory = FilePath.Empty; public virtual FilePath IntermediateOutputDirectory { get { @@ -66,46 +124,37 @@ namespace MonoDevelop.Projects } } - [ProjectPathItemProperty("OutputPath")] - private FilePath outputDirectory = "." + Path.DirectorySeparatorChar; + FilePath outputDirectory = "." + Path.DirectorySeparatorChar; public virtual FilePath OutputDirectory { get { return outputDirectory; } set { outputDirectory = value; } } - [ItemProperty("DebugSymbols", DefaultValue = false)] - private bool debugMode = false; + bool debugMode = false; public bool DebugMode { get { return debugMode; } set { debugMode = value; } } - [ItemProperty("ConsolePause", DefaultValue = true)] - private bool pauseConsoleOutput = true; + bool pauseConsoleOutput = true; public bool PauseConsoleOutput { get { return pauseConsoleOutput; } set { pauseConsoleOutput = value; } } - [ItemProperty("Externalconsole", DefaultValue = false)] - private bool externalConsole = false; + bool externalConsole = false; public bool ExternalConsole { get { return externalConsole; } set { externalConsole = value; } } - [ItemProperty("Commandlineparameters", DefaultValue = "")] - private string commandLineParameters = ""; + string commandLineParameters = ""; public string CommandLineParameters { get { return commandLineParameters; } set { commandLineParameters = value; } } - [ItemProperty("EnvironmentVariables", SkipEmpty = true)] - [ItemProperty("Variable", Scope = "item")] - [ItemProperty("name", Scope = "key")] - [ItemProperty("value", Scope = "value")] - private Dictionary<string, string> environmentVariables = new Dictionary<string, string> (); + Dictionary<string, string> environmentVariables = new Dictionary<string, string> (); public Dictionary<string, string> EnvironmentVariables { get { return environmentVariables; } } @@ -122,8 +171,7 @@ namespace MonoDevelop.Projects return vars; } - [ItemProperty("RunWithWarnings", DefaultValue = true)] - private bool runWithWarnings = true; + bool runWithWarnings = true; public virtual bool RunWithWarnings { get { return runWithWarnings; } set { runWithWarnings = value; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectConvertTool.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectConvertTool.cs index 6bedef9308..c849d3b8d0 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectConvertTool.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectConvertTool.cs @@ -177,7 +177,10 @@ namespace MonoDevelop.Projects destPath = Path.GetDirectoryName (projectFile); destPath = FileService.GetFullPath (destPath); - string ofile = Services.ProjectService.Export (monitor, projectFile, itemsToExport, destPath, format); + var t = Services.ProjectService.Export (monitor, projectFile, itemsToExport, destPath, format); + t.Wait (); + string ofile = t.Result; + if (ofile != null) { Console.WriteLine ("Saved file: " + ofile); return 0; diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectExtension.cs new file mode 100644 index 0000000000..a1dd21715c --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectExtension.cs @@ -0,0 +1,182 @@ +// +// MSBuildProjectExtension.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using MonoDevelop.Core; +using System.Threading.Tasks; +using MonoDevelop.Projects.Formats.MSBuild; +using Mono.Addins; +using System.Linq; + +namespace MonoDevelop.Projects +{ + public class ProjectExtension: SolutionItemExtension + { + ProjectExtension next; + + public Project Project { + get { return (Project) base.Item; } + } + + internal protected override void InitializeChain (ChainedExtension next) + { + base.InitializeChain (next); + this.next = FindNextImplementation<ProjectExtension> (next); + } + + internal protected override bool SupportsObject (WorkspaceObject item) + { + return item is Project && base.SupportsObject (item); + } + + internal protected virtual bool SupportsFlavor (string guid) + { + if (FlavorGuid != null && guid.Equals (FlavorGuid, StringComparison.OrdinalIgnoreCase)) + return true; + return next.SupportsFlavor (guid); + } + + internal protected virtual Task<BuildResult> OnRunTarget (ProgressMonitor monitor, string target, ConfigurationSelector configuration) + { + return next.OnRunTarget (monitor, target, configuration); + } + + internal protected virtual bool OnGetSupportsTarget (string target) + { + return next.OnGetSupportsTarget (target); + } + + internal protected virtual void OnGetProjectTypes (HashSet<string> types) + { + next.OnGetProjectTypes (types); + } + + internal protected virtual void OnReadProject (ProgressMonitor monitor, MSBuildProject msproject) + { + next.OnReadProject (monitor, msproject); + } + + internal protected virtual void OnReadConfiguration (ProgressMonitor monitor, ProjectConfiguration config, IMSBuildPropertySet pset) + { + next.OnReadConfiguration (monitor, config, pset); + } + + internal protected virtual void OnWriteProject (ProgressMonitor monitor, MSBuildProject msproject) + { + next.OnWriteProject (monitor, msproject); + } + + internal protected virtual void OnWriteConfiguration (ProgressMonitor monitor, ProjectConfiguration config, IMSBuildPropertySet pset) + { + next.OnWriteConfiguration (monitor, config, pset); + } + + #region Building + + internal protected virtual bool OnGetIsCompileable (string fileName) + { + return next.OnGetIsCompileable (fileName); + } + + internal protected virtual string OnGetDefaultBuildAction (string fileName) + { + return next.OnGetDefaultBuildAction (fileName); + } + + internal protected virtual string OnGetDefaultResourceId (ProjectFile projectFile) + { + return next.OnGetDefaultResourceId (projectFile); + } + + internal protected virtual IEnumerable<string> OnGetStandardBuildActions () + { + return next.OnGetStandardBuildActions (); + } + + internal protected virtual IList<string> OnGetCommonBuildActions () + { + return next.OnGetCommonBuildActions (); + } + + internal protected virtual ProjectItem OnCreateProjectItem (IMSBuildItemEvaluated item) + { + return next.OnCreateProjectItem (item); + } + + internal protected virtual void OnPopulateSupportFileList (FileCopySet list, ConfigurationSelector configuration) + { + next.OnPopulateSupportFileList (list, configuration); + } + + internal protected virtual void OnPopulateOutputFileList (List<FilePath> list, ConfigurationSelector configuration) + { + next.OnPopulateOutputFileList (list, configuration); + } + + internal protected virtual FilePath OnGetOutputFileName (ConfigurationSelector configuration) + { + return next.OnGetOutputFileName (configuration); + } + + internal protected virtual string[] SupportedLanguages { + get { + return next.SupportedLanguages; + } + } + + #endregion + + #region Events + + internal protected virtual void OnFileRemovedFromProject (ProjectFileEventArgs e) + { + next.OnFileRemovedFromProject (e); + } + + internal protected virtual void OnFileAddedToProject (ProjectFileEventArgs e) + { + next.OnFileAddedToProject (e); + } + + internal protected virtual void OnFileChangedInProject (ProjectFileEventArgs e) + { + next.OnFileChangedInProject (e); + } + + internal protected virtual void OnFilePropertyChangedInProject (ProjectFileEventArgs e) + { + next.OnFilePropertyChangedInProject (e); + } + + internal protected virtual void OnFileRenamedInProject (ProjectFileRenamedEventArgs e) + { + next.OnFileRenamedInProject (e); + } + + #endregion + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectFile.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectFile.cs index 77d9f63534..ad7d99b972 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectFile.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectFile.cs @@ -37,6 +37,7 @@ using MonoDevelop.Core; using MonoDevelop.Core.Serialization; using MonoDevelop.Projects; using MonoDevelop.Projects.Extensions; +using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.Projects { @@ -55,21 +56,98 @@ namespace MonoDevelop.Projects { } - public ProjectFile (string filename) + public ProjectFile (string filename): this (filename, MonoDevelop.Projects.BuildAction.Compile) { - this.filename = FileService.GetFullPath (filename); - subtype = Subtype.Code; - buildaction = MonoDevelop.Projects.BuildAction.Compile; } public ProjectFile (string filename, string buildAction) { this.filename = FileService.GetFullPath (filename); subtype = Subtype.Code; - buildaction = buildAction; + ItemName = buildaction = buildAction; + } + + public override string Include { + get { + if (project != null) { + string path = MSBuildProjectService.ToMSBuildPath (project.ItemDirectory, FilePath); + if (path.Length > 0) { + //directory paths must end with '/' + if ((Subtype == Subtype.Directory) && path [path.Length - 1] != '\\') + path = path + "\\"; + return path; + } + } + return base.Include; + } + protected set { + base.Include = value; + } + } + + internal protected override void Read (Project project, IMSBuildItemEvaluated buildItem) + { + base.Read (project, buildItem); + + if (buildItem.Name == "Folder") { + // Read folders + string path = MSBuildProjectService.FromMSBuildPath (project.ItemDirectory, buildItem.Include); + Name = Path.GetDirectoryName (path); + Subtype = Subtype.Directory; + return; + } + + Name = MSBuildProjectService.FromMSBuildPath (project.ItemDirectory, buildItem.Include); + BuildAction = buildItem.Name; + + DependsOn = buildItem.Metadata.GetPathValue ("DependentUpon", relativeToPath:FilePath.ParentDirectory); + + string copy = buildItem.Metadata.GetValue ("CopyToOutputDirectory"); + if (!string.IsNullOrEmpty (copy)) { + switch (copy) { + case "None": break; + case "Always": CopyToOutputDirectory = FileCopyMode.Always; break; + case "PreserveNewest": CopyToOutputDirectory = FileCopyMode.PreserveNewest; break; + default: + LoggingService.LogWarning ( + "Unrecognised value {0} for CopyToOutputDirectory MSBuild property", + copy); + break; + } + } + + Visible = buildItem.Metadata.GetValue ("Visible", true); + resourceId = buildItem.Metadata.GetValue ("LogicalName"); + contentType = buildItem.Metadata.GetValue ("SubType"); + generator = buildItem.Metadata.GetValue ("Generator"); + customToolNamespace = buildItem.Metadata.GetValue ("CustomToolNamespace"); + lastGenOutput = buildItem.Metadata.GetValue ("LastGenOutput"); + Link = buildItem.Metadata.GetPathValue ("Link", relativeToProject:false); } - [ItemProperty("subtype")] + internal protected override void Write (MSBuildFileFormat fmt, MSBuildItem buildItem) + { + base.Write (fmt, buildItem); + + buildItem.Metadata.SetValue ("DependentUpon", DependsOn, FilePath.Empty, relativeToPath:FilePath.ParentDirectory); + buildItem.Metadata.SetValue ("SubType", ContentType, ""); + buildItem.Metadata.SetValue ("Generator", Generator, ""); + buildItem.Metadata.SetValue ("CustomToolNamespace", CustomToolNamespace, ""); + buildItem.Metadata.SetValue ("LastGenOutput", LastGenOutput, ""); + buildItem.Metadata.SetValue ("Link", Link, FilePath.Empty, relativeToProject:false); + buildItem.Metadata.SetValue ("CopyToOutputDirectory", CopyToOutputDirectory.ToString (), "None"); + buildItem.Metadata.SetValue ("Visible", Visible, true); + + var resId = ResourceId; + + //For EmbeddedResource, emit LogicalName only when it does not match the default Id + if (BuildAction == MonoDevelop.Projects.BuildAction.EmbeddedResource && project.GetDefaultResourceId (this) == resId) + resId = ""; + + buildItem.Metadata.SetValue ("LogicalName", resId, ""); + } + + Subtype subtype; public Subtype Subtype { get { return subtype; } @@ -79,17 +157,6 @@ namespace MonoDevelop.Projects } } - [ItemProperty("data", DefaultValue = "")] - string data = ""; - public string Data { - get { return data; } - set { - data = value; - OnChanged ("Data"); - } - } - - public string Name { get { return filename; } @@ -117,8 +184,6 @@ namespace MonoDevelop.Projects } } - - [ItemProperty("buildaction")] string buildaction = MonoDevelop.Projects.BuildAction.None; public string BuildAction { get { return buildaction; } @@ -128,7 +193,6 @@ namespace MonoDevelop.Projects } } - [ItemProperty("resource_id", DefaultValue = "")] string resourceId = String.Empty; internal string GetResourceId (IResourceHandler resourceHandler) @@ -148,15 +212,6 @@ namespace MonoDevelop.Projects } /// <summary> - /// Set to true if this ProjectFile was created at load time by - /// a ProjectFile containing wildcards. If true, this instance - /// should not be saved to a csproj file. - /// </summary> - internal bool IsOriginatedFromWildcard { - get; set; - } - - /// <summary> /// The file should be treated as effectively having this relative path within the project. If the file is /// a link or outside the project root, this will not be the same as the physical file. /// </summary> @@ -179,17 +234,15 @@ namespace MonoDevelop.Projects get { return project; } } - [ItemProperty("SubType")] - string contentType = String.Empty; + string contentType; public string ContentType { - get { return contentType; } + get { return contentType ?? ""; } set { contentType = value; OnChanged ("ContentType"); } } - [ItemProperty("Visible", DefaultValue = true)] bool visible = true; /// <summary> @@ -205,14 +258,13 @@ namespace MonoDevelop.Projects } } - [ItemProperty("Generator", DefaultValue = "")] string generator; /// <summary> /// The ID of a custom code generator. /// </summary> public string Generator { - get { return generator; } + get { return generator ?? ""; } set { if (generator != value) { generator = value; @@ -221,14 +273,13 @@ namespace MonoDevelop.Projects } } - [ItemProperty("CustomToolNamespace", DefaultValue = "")] string customToolNamespace; /// <summary> /// Overrides the namespace in which the custom code generator should generate code. /// </summary> public string CustomToolNamespace { - get { return customToolNamespace; } + get { return customToolNamespace ?? ""; } set { if (customToolNamespace != value) { customToolNamespace = value; @@ -238,14 +289,13 @@ namespace MonoDevelop.Projects } - [ItemProperty("LastGenOutput", DefaultValue = "")] string lastGenOutput; /// <summary> /// The file most recently generated by the custom tool. Relative to this file's parent directory. /// </summary> public string LastGenOutput { - get { return lastGenOutput; } + get { return lastGenOutput ?? ""; } set { if (lastGenOutput != value) { lastGenOutput = value; @@ -254,8 +304,6 @@ namespace MonoDevelop.Projects } } - - [RelativeProjectPathItemProperty("Link", DefaultValue = "")] string link; /// <summary> @@ -263,7 +311,7 @@ namespace MonoDevelop.Projects /// within the project root. Use ProjectVirtualPath to read the effective virtual path for any file. /// </summary> public FilePath Link { - get { return link; } + get { return link ?? ""; } set { if (link != value) { if (value.IsAbsolute || value.ToString ().StartsWith ("..", StringComparison.Ordinal)) @@ -296,8 +344,7 @@ namespace MonoDevelop.Projects } } - [ItemProperty("copyToOutputDirectory", DefaultValue = FileCopyMode.None)] - FileCopyMode copyToOutputDirectory; + FileCopyMode copyToOutputDirectory = FileCopyMode.None; public FileCopyMode CopyToOutputDirectory { get { return copyToOutputDirectory; } set { @@ -311,7 +358,7 @@ namespace MonoDevelop.Projects #region File grouping string dependsOn; public string DependsOn { - get { return dependsOn; } + get { return dependsOn ?? ""; } set { if (dependsOn != value) { @@ -406,15 +453,18 @@ namespace MonoDevelop.Projects return resourceId; } set { - resourceId = value; - OnChanged ("ResourceId"); + if (resourceId != value) { + var oldVal = ResourceId; + resourceId = value; + if (ResourceId != oldVal) + OnChanged ("ResourceId"); + } } } internal void SetProject (Project project) { this.project = project; - if (project != null) OnVirtualPathChanged (FilePath.Null, ProjectVirtualPath); } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItem.cs index 8c5a7303fa..cb9934cd82 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItem.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItem.cs @@ -26,14 +26,16 @@ using System; using System.Collections; +using System.Collections.Generic; using MonoDevelop.Core.Serialization; +using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.Projects { public class ProjectItem: IExtendedDataItem { Hashtable extendedProperties; - + public IDictionary ExtendedProperties { get { if (extendedProperties == null) @@ -41,19 +43,42 @@ namespace MonoDevelop.Projects return extendedProperties; } } + + public void SetMetadata (string name, string value, bool isXml = false) + { + } + + public string GetMetadata (string name, string defaultValue = null) + { + return null; + } internal string Condition { get; set; } + public string ItemName { get; protected set; } + + public virtual string Include { get; protected set; } + + public string UnevaluatedInclude { get; protected set; } + public ProjectItemFlags Flags { get; set; } + + internal protected virtual void Read (Project project, IMSBuildItemEvaluated buildItem) + { + ItemName = buildItem.Name; + Include = buildItem.Include; + UnevaluatedInclude = buildItem.UnevaluatedInclude; + Condition = buildItem.Condition; + } + + internal protected virtual void Write (MSBuildFileFormat fmt, MSBuildItem buildItem) + { + buildItem.Condition = Condition; + } } public class UnknownProjectItem: ProjectItem { - public string ItemName { get; private set; } - - [ItemProperty ("Include")] - public string Include { get; private set; } - public UnknownProjectItem (string name, string include) { this.ItemName = name; diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItemCollection.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItemCollection.cs index cfdbd848dc..4a2badcff1 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItemCollection.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItemCollection.cs @@ -37,7 +37,7 @@ namespace MonoDevelop.Projects { } - internal ProjectItemCollection (SolutionEntityItem parent): base (parent) + internal ProjectItemCollection (SolutionItem parent): base (parent) { } } @@ -51,11 +51,11 @@ namespace MonoDevelop.Projects public class ProjectItemCollection<T>: ItemCollection<T>, IItemListHandler where T: ProjectItem { - SolutionEntityItem parent; + SolutionItem parent; IItemListHandler parentCollection; List<IItemListHandler> subCollections; - internal ProjectItemCollection (SolutionEntityItem parent) + internal ProjectItemCollection (SolutionItem parent) { this.parent = parent; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItemEventArgs.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItemEventArgs.cs index 50cbb2dd8e..806c633362 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItemEventArgs.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItemEventArgs.cs @@ -34,7 +34,7 @@ namespace MonoDevelop.Projects { } - public ProjectItemEventArgs (SolutionEntityItem solutionItem, ProjectItem item) + public ProjectItemEventArgs (SolutionItem solutionItem, ProjectItem item) { Add (new ProjectItemEventInfo (solutionItem, item)); } @@ -43,15 +43,15 @@ namespace MonoDevelop.Projects public class ProjectItemEventInfo { ProjectItem item; - SolutionEntityItem solutionItem; + SolutionItem solutionItem; - public ProjectItemEventInfo (SolutionEntityItem solutionItem, ProjectItem item) + public ProjectItemEventInfo (SolutionItem solutionItem, ProjectItem item) { this.item = item; this.solutionItem = solutionItem; } - public SolutionEntityItem SolutionItem { + public SolutionItem SolutionItem { get { return solutionItem; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectParameters.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectParameters.cs index 457111b18d..f78e021bc7 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectParameters.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectParameters.cs @@ -27,11 +27,12 @@ using System; using MonoDevelop.Core.Serialization; using MonoDevelop.Projects.Extensions; +using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.Projects { [DataItem (FallbackType=typeof(UnknownProjectParameters))] - public class ProjectParameters: ILoadController + public class ProjectParameters: ILoadController, IMSBuildDataObject { DotNetProject parentProject; @@ -69,5 +70,23 @@ namespace MonoDevelop.Projects protected virtual void OnEndLoad () { } + + void IMSBuildDataObject.Read (IMSBuildPropertySet pset, MSBuildFileFormat format) + { + Read (pset, format); + } + + void IMSBuildDataObject.Write (IMSBuildPropertySet pset, MSBuildFileFormat format) + { + Write (pset, format); + } + + protected virtual void Read (IMSBuildPropertySet pset, MSBuildFileFormat format) + { + } + + protected virtual void Write (IMSBuildPropertySet pset, MSBuildFileFormat format) + { + } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectReference.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectReference.cs index 74e56794d8..a30115c441 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectReference.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectReference.cs @@ -37,6 +37,7 @@ using System.ComponentModel; using MonoDevelop.Projects; using MonoDevelop.Core.Serialization; using MonoDevelop.Core.Assemblies; +using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.Projects { @@ -73,8 +74,11 @@ namespace MonoDevelop.Projects string package; SystemPackage cachedPackage; string customError; - string hintPath; - + FilePath hintPath; + + string originalMSBuildReferenceInclude; + string originalMSBuildReferenceHintPath; + public event EventHandler StatusChanged; [ItemProperty ("Package", DefaultValue="")] @@ -100,6 +104,19 @@ namespace MonoDevelop.Projects ownerProject = project; UpdatePackageReference (); } + + public sealed override string Include { + get { + if (referenceType == ReferenceType.Project && base.Include == null) { + Project refProj = OwnerProject != null && OwnerProject.ParentSolution != null ? OwnerProject.ParentSolution.FindProjectByName (Reference) : null; + if (refProj != null) + base.Include = MSBuildProjectService.ToMSBuildPath (OwnerProject.ItemDirectory, refProj.FileName); + else + base.Include = Reference; + } + return base.Include; + } + } public ProjectReference (ReferenceType referenceType, string reference): this (referenceType, reference, null) { @@ -107,20 +124,66 @@ namespace MonoDevelop.Projects public ProjectReference (ReferenceType referenceType, string reference, string hintPath) { + Init (referenceType, reference, hintPath); + } + + void Init (ReferenceType referenceType, string reference, string hintPath) + { if (referenceType == ReferenceType.Assembly) { specificVersion = false; if (hintPath == null) { hintPath = reference; reference = Path.GetFileNameWithoutExtension (reference); } + + if (Include == null) { + if (File.Exists (HintPath)) { + try { + var aname = System.Reflection.AssemblyName.GetAssemblyName (HintPath); + if (SpecificVersion) { + Include = aname.FullName; + } else { + Include = aname.Name; + } + } catch (Exception ex) { + string msg = string.Format ("Could not get full name for assembly '{0}'.", Reference); + LoggingService.LogError (msg, ex); + } + } + if (Include == null) + Include = Path.GetFileNameWithoutExtension (hintPath); + } + } + + switch (referenceType) { + case ReferenceType.Package: + case ReferenceType.Assembly: + ItemName = "Reference"; + break; + case ReferenceType.Project: + ItemName = "ProjectReference"; + break; } this.referenceType = referenceType; this.reference = reference; this.hintPath = hintPath; UpdatePackageReference (); + + if (referenceType == ReferenceType.Package && Include == null) { + Include = StoredReference; + SystemPackage pkg = Package; + if (pkg != null && pkg.IsFrameworkPackage) { + int i = Include.IndexOf (','); + if (i != -1) + Include = Include.Substring (0, i).Trim (); + } + } + + if (Include == null) + Include = reference; } - + public ProjectReference (Project referencedProject) { referenceType = ReferenceType.Project; @@ -138,7 +201,120 @@ namespace MonoDevelop.Projects package = asm.Package.Name; UpdatePackageReference (); } - + + internal protected override void Read (Project project, IMSBuildItemEvaluated buildItem) + { + base.Read (project, buildItem); + + if (buildItem.Name == "Reference") + ReadReference (project, buildItem); + else if (buildItem.Name == "ProjectReference") + ReadProjectReference (project, buildItem); + + LocalCopy = buildItem.Metadata.GetValue ("Private", DefaultLocalCopy); + } + + void ReadReference (Project project, IMSBuildItemEvaluated buildItem) + { + if (buildItem.Metadata.HasProperty ("HintPath")) { + FilePath path; + var p = buildItem.Metadata.GetProperty ("HintPath"); + if (p != null) + originalMSBuildReferenceHintPath = p.UnevaluatedValue; + if (!buildItem.Metadata.TryGetPathValue ("HintPath", out path)) { + var hp = buildItem.Metadata.GetValue ("HintPath"); + Init (ReferenceType.Assembly, hp, null); + SetInvalid (GettextCatalog.GetString ("Invalid file path")); + originalMSBuildReferenceInclude = buildItem.Include; + } else { + var type = File.Exists (path) ? ReferenceType.Assembly : ReferenceType.Package; + Init (type, buildItem.Include, path); + } + } else { + string asm = buildItem.Include; + // This is a workaround for a VS bug. Looks like it is writing this assembly incorrectly + if (asm == "System.configuration") + asm = "System.Configuration"; + else if (asm == "System.XML") + asm = "System.Xml"; + else if (asm == "system") + asm = "System"; + Init (ReferenceType.Package, asm, null); + } + + string specificVersion = buildItem.Metadata.GetValue ("SpecificVersion"); + if (string.IsNullOrWhiteSpace (specificVersion)) { + // If the SpecificVersion element isn't present, check if the Assembly Reference specifies a Version + SpecificVersion = ReferenceStringHasVersion (buildItem.Include); + } + else { + bool value; + // if we can't parse the value, default to false which is more permissive + SpecificVersion = bool.TryParse (specificVersion, out value) && value; + } + } + + void ReadProjectReference (Project project, IMSBuildItemEvaluated buildItem) + { + // Get the project name from the path, since the Name attribute may other stuff other than the name + string path = MSBuildProjectService.FromMSBuildPath (project.ItemDirectory, buildItem.Include); + string name = Path.GetFileNameWithoutExtension (path); + Init (ReferenceType.Project, name, null); + } + + internal protected override void Write (MSBuildFileFormat fmt, MSBuildItem buildItem) + { + // If the project is not supported, don't try to update any metadata of the property, + // just leave what was read + if (OwnerProject.IsUnsupportedProject) + return; + + base.Write (fmt, buildItem); + + if (ReferenceType == ReferenceType.Assembly) { + if (originalMSBuildReferenceHintPath != null) + buildItem.Metadata.SetValue ("HintPath", originalMSBuildReferenceHintPath, ""); + else + buildItem.Metadata.SetValue ("HintPath", HintPath); + + buildItem.Metadata.SetValue ("SpecificVersion", SpecificVersion || !ReferenceStringHasVersion (Include), true); + } + else if (ReferenceType == ReferenceType.Package) { + buildItem.Metadata.SetValue ("SpecificVersion", SpecificVersion || !ReferenceStringHasVersion (Include), true); + + //RequiredTargetFramework is undocumented, maybe only a hint for VS. Only seems to be used for .NETFramework + var dnp = OwnerProject as DotNetProject; + IList supportedFrameworks = fmt.SupportedFrameworks; + if (supportedFrameworks != null && dnp != null && Package != null + && dnp.TargetFramework.Id.Identifier == TargetFrameworkMoniker.ID_NET_FRAMEWORK + && Package.IsFrameworkPackage && supportedFrameworks.Contains (Package.TargetFramework) + && Package.TargetFramework.Version != "2.0" && supportedFrameworks.Count > 1) + { + TargetFramework fx = Runtime.SystemAssemblyService.GetTargetFramework (Package.TargetFramework); + buildItem.Metadata.SetValue ("RequiredTargetFramework", fx.Id.Version); + } else { + buildItem.Metadata.RemoveProperty ("RequiredTargetFramework"); + } + + buildItem.Metadata.SetValue ("HintPath", originalMSBuildReferenceHintPath, ""); + } + else if (ReferenceType == ReferenceType.Project) { + Project refProj = OwnerProject.ParentSolution.FindProjectByName (Reference); + if (refProj != null) { + buildItem.Metadata.SetValue ("Project", refProj.ItemId); + buildItem.Metadata.SetValue ("Name", refProj.Name); + } + } + + buildItem.Metadata.SetValue ("Private", LocalCopy, DefaultLocalCopy); + } + + bool ReferenceStringHasVersion (string asmName) + { + int commaPos = asmName.IndexOf (','); + return commaPos >= 0 && asmName.IndexOf ("Version", commaPos) >= 0; + } + protected void InitCustomReference (string reference) { Reference = reference; @@ -256,8 +432,7 @@ namespace MonoDevelop.Projects if (notFound) { if (ownerProject != null) { bool isDefaultRuntime = Runtime.SystemAssemblyService.DefaultRuntime == TargetRuntime; - var hintPath = ExtendedProperties ["_OriginalMSBuildReferenceHintPath"] as string; - bool probablyFrameworkAssembly = string.IsNullOrEmpty (hintPath); + bool probablyFrameworkAssembly = string.IsNullOrEmpty (originalMSBuildReferenceHintPath); if (TargetRuntime.IsInstalled (TargetFramework) || !probablyFrameworkAssembly) { if (isDefaultRuntime) @@ -307,7 +482,7 @@ namespace MonoDevelop.Projects } } - public string HintPath { + public FilePath HintPath { get { return hintPath; } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs index 64d8bc6e76..fa493fb8f7 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs @@ -26,28 +26,22 @@ using System; using System.Collections; -using System.Collections.Specialized; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Xml; -using System.CodeDom.Compiler; -using System.Threading; using MonoDevelop.Projects; using MonoDevelop.Core.Serialization; using MonoDevelop.Core; using Mono.Addins; -using MonoDevelop.Core.ProgressMonitoring; -using MonoDevelop.Core.Execution; using MonoDevelop.Core.Assemblies; using MonoDevelop.Core.Instrumentation; using MonoDevelop.Projects.Extensions; using Mono.Unix; -using MonoDevelop.Core.StringParsing; using System.Linq; using MonoDevelop.Projects.Formats.MSBuild; +using System.Threading.Tasks; namespace MonoDevelop.Projects { @@ -63,7 +57,7 @@ namespace MonoDevelop.Projects TargetFramework defaultTargetFramework; string defaultPlatformTarget = "x86"; - static readonly TargetFrameworkMoniker DefaultTargetFrameworkId = TargetFrameworkMoniker.NET_4_0; + static readonly TargetFrameworkMoniker DefaultTargetFrameworkId = TargetFrameworkMoniker.NET_4_5; public const string BuildTarget = "Build"; public const string CleanTarget = "Clean"; @@ -72,7 +66,9 @@ namespace MonoDevelop.Projects const string SerializableClassesExtensionPath = "/MonoDevelop/ProjectModel/SerializableClasses"; const string ExtendedPropertiesExtensionPath = "/MonoDevelop/ProjectModel/ExtendedProperties"; const string ProjectBindingsExtensionPath = "/MonoDevelop/ProjectModel/ProjectBindings"; - + + internal const string ProjectModelExtensionsPath = "/MonoDevelop/ProjectModel/ProjectModelExtensions"; + internal event EventHandler DataContextChanged; class ExtensionChainInfo @@ -101,7 +97,7 @@ namespace MonoDevelop.Projects get { return formatManager; } } - internal ProjectServiceExtension GetExtensionChain (IBuildTarget target) + internal ProjectServiceExtension GetExtensionChain (WorkspaceObject target) { ProjectServiceExtension chain; if (target != null) { @@ -147,18 +143,14 @@ namespace MonoDevelop.Projects ProjectServiceExtension CreateExtensionChain (ProjectServiceExtension[] extensions) { - var first = new CustomCommandExtension (); - - for (int n=0; n<extensions.Length - 1; n++) - extensions [n].Next = extensions [n + 1]; - if (extensions.Length > 0) { + for (int n=0; n<extensions.Length - 1; n++) + extensions [n].Next = extensions [n + 1]; extensions [extensions.Length - 1].Next = extensionChainTerminator; - first.Next = extensions [0]; + return extensions [0]; } else { - first.Next = extensionChainTerminator; + return extensionChainTerminator; } - return first; } public string DefaultPlatformTarget { @@ -191,16 +183,16 @@ namespace MonoDevelop.Projects return formats [0]; } - public SolutionEntityItem ReadSolutionItem (IProgressMonitor monitor, string file) + public async Task<SolutionItem> ReadSolutionItem (ProgressMonitor monitor, string file) { file = Path.GetFullPath (file); using (Counters.ReadSolutionItem.BeginTiming ("Read project " + file)) { file = GetTargetFile (file); - SolutionEntityItem loadedItem = GetExtensionChain (null).LoadSolutionItem (monitor, file, delegate { - FileFormat format; - SolutionEntityItem item = ReadFile (monitor, file, typeof(SolutionEntityItem), out format) as SolutionEntityItem; + SolutionItem loadedItem = await GetExtensionChain (null).LoadSolutionItem (monitor, file, async delegate { + var res = await ReadFile (monitor, file, typeof(SolutionItem)); + SolutionItem item = res.Item1 as SolutionItem; if (item != null) - item.FileFormat = format; + item.FileFormat = res.Item2; else throw new InvalidOperationException ("Invalid file format: " + file); return item; @@ -210,23 +202,23 @@ namespace MonoDevelop.Projects } } - public SolutionItem ReadSolutionItem (IProgressMonitor monitor, SolutionItemReference reference, params WorkspaceItem[] workspaces) + public async Task<SolutionFolderItem> ReadSolutionItem (ProgressMonitor monitor, SolutionItemReference reference, params WorkspaceItem[] workspaces) { if (reference.Id == null) { FilePath file = reference.Path.FullPath; foreach (WorkspaceItem workspace in workspaces) { - foreach (SolutionEntityItem eitem in workspace.GetAllSolutionItems<SolutionEntityItem> ()) + foreach (SolutionItem eitem in workspace.GetAllItems<Solution>().SelectMany (s => s.GetAllSolutionItems ())) if (file == eitem.FileName) return eitem; } - return ReadSolutionItem (monitor, reference.Path); + return await ReadSolutionItem (monitor, reference.Path); } else { Solution sol = null; if (workspaces.Length > 0) { FilePath file = reference.Path.FullPath; foreach (WorkspaceItem workspace in workspaces) { - foreach (Solution item in workspace.GetAllSolutions ()) { + foreach (Solution item in workspace.GetAllItems<Solution>()) { if (item.FileName.FullPath == file) { sol = item; break; @@ -237,7 +229,7 @@ namespace MonoDevelop.Projects } } if (sol == null) - sol = ReadWorkspaceItem (monitor, reference.Path) as Solution; + sol = await ReadWorkspaceItem (monitor, reference.Path) as Solution; if (reference.Id == ":root:") return sol.RootFolder; @@ -246,12 +238,12 @@ namespace MonoDevelop.Projects } } - public WorkspaceItem ReadWorkspaceItem (IProgressMonitor monitor, string file) + public async Task<WorkspaceItem> ReadWorkspaceItem (ProgressMonitor monitor, string file) { file = Path.GetFullPath (file); using (Counters.ReadWorkspaceItem.BeginTiming ("Read solution " + file)) { file = GetTargetFile (file); - WorkspaceItem item = GetExtensionChain (null).LoadWorkspaceItem (monitor, file) as WorkspaceItem; + WorkspaceItem item = await GetExtensionChain (null).LoadWorkspaceItem (monitor, file) as WorkspaceItem; if (item != null) item.NeedsReload = false; else @@ -260,54 +252,45 @@ namespace MonoDevelop.Projects } } - internal void InternalWriteSolutionItem (IProgressMonitor monitor, FilePath file, SolutionEntityItem item) - { - var newFile = WriteFile (monitor, file, item, null); - if (newFile != null) - item.FileName = newFile; - else - throw new InvalidOperationException ("FileFormat not provided for solution item '" + item.Name + "'"); - } - - internal WorkspaceItem InternalReadWorkspaceItem (string file, IProgressMonitor monitor) + internal async Task<WorkspaceItem> InternalReadWorkspaceItem (string file, ProgressMonitor monitor) { - FileFormat format; - WorkspaceItem item = ReadFile (monitor, file, typeof(WorkspaceItem), out format) as WorkspaceItem; + var res = await ReadFile (monitor, file, typeof(WorkspaceItem)); + WorkspaceItem item = res.Item1 as WorkspaceItem; if (item == null) throw new InvalidOperationException ("Invalid file format: " + file); if (!item.FormatSet) - item.ConvertToFormat (format, false); + await item.ConvertToFormat (res.Item2, false); return item; } - internal void InternalWriteWorkspaceItem (IProgressMonitor monitor, FilePath file, WorkspaceItem item) + internal async Task InternalWriteWorkspaceItem (ProgressMonitor monitor, FilePath file, WorkspaceItem item) { - var newFile = WriteFile (monitor, file, item, item.FileFormat); + var newFile = await WriteFile (monitor, file, item, item.FileFormat); if (newFile != null) item.FileName = newFile; else throw new InvalidOperationException ("FileFormat not provided for workspace item '" + item.Name + "'"); } - object ReadFile (IProgressMonitor monitor, string file, Type expectedType, out FileFormat format) + async Task<Tuple<object,FileFormat>> ReadFile (ProgressMonitor monitor, string file, Type expectedType) { FileFormat[] formats = formatManager.GetFileFormats (file, expectedType); if (formats.Length == 0) throw new InvalidOperationException ("Unknown file format: " + file); - format = formats [0]; - object obj = format.Format.ReadFile (file, expectedType, monitor); + var format = formats [0]; + object obj = await format.Format.ReadFile (file, expectedType, monitor); if (obj == null) throw new InvalidOperationException ("Invalid file format: " + file); - return obj; + return new Tuple<object,FileFormat> (obj, format); } - FilePath WriteFile (IProgressMonitor monitor, FilePath file, object item, FileFormat format) + async Task<FilePath> WriteFile (ProgressMonitor monitor, FilePath file, object item, FileFormat format) { if (format == null) { if (defaultFormat.CanWrite (item)) @@ -325,33 +308,33 @@ namespace MonoDevelop.Projects FileService.RequestFileEdit (file); - format.Format.WriteFile (file, item, monitor); + await format.Format.WriteFile (file, item, monitor); return file; } - public string Export (IProgressMonitor monitor, string rootSourceFile, string targetPath, FileFormat format) + public Task<string> Export (ProgressMonitor monitor, string rootSourceFile, string targetPath, FileFormat format) { rootSourceFile = GetTargetFile (rootSourceFile); return Export (monitor, rootSourceFile, null, targetPath, format); } - public string Export (IProgressMonitor monitor, string rootSourceFile, string[] includedChildIds, string targetPath, FileFormat format) + public async Task<string> Export (ProgressMonitor monitor, string rootSourceFile, string[] includedChildIds, string targetPath, FileFormat format) { IWorkspaceFileObject obj; if (IsWorkspaceItemFile (rootSourceFile)) { - obj = ReadWorkspaceItem (monitor, rootSourceFile) as Solution; + obj = await ReadWorkspaceItem (monitor, rootSourceFile) as Solution; } else { - obj = ReadSolutionItem (monitor, rootSourceFile); + obj = await ReadSolutionItem (monitor, rootSourceFile); if (obj == null) throw new InvalidOperationException ("File is not a solution or project."); } using (obj) { - return Export (monitor, obj, includedChildIds, targetPath, format); + return await Export (monitor, obj, includedChildIds, targetPath, format); } } - string Export (IProgressMonitor monitor, IWorkspaceFileObject obj, string[] includedChildIds, string targetPath, FileFormat format) + async Task<string> Export (ProgressMonitor monitor, IWorkspaceFileObject obj, string[] includedChildIds, string targetPath, FileFormat format) { string rootSourceFile = obj.FileName; string sourcePath = Path.GetFullPath (Path.GetDirectoryName (rootSourceFile)); @@ -363,17 +346,17 @@ namespace MonoDevelop.Projects string newFile = Path.Combine (targetPath, Path.GetFileName (rootSourceFile)); if (IsWorkspaceItemFile (rootSourceFile)) - obj = ReadWorkspaceItem (monitor, newFile); + obj = await ReadWorkspaceItem (monitor, newFile); else - obj = (SolutionEntityItem) ReadSolutionItem (monitor, newFile); + obj = (SolutionItem) await ReadSolutionItem (monitor, newFile); using (obj) { - List<FilePath> oldFiles = obj.GetItemFiles (true); + var oldFiles = obj.GetItemFiles (true).ToList (); ExcludeEntries (obj, includedChildIds); if (format != null) - obj.ConvertToFormat (format, true); - obj.Save (monitor);
- List<FilePath> newFiles = obj.GetItemFiles (true); + await obj.ConvertToFormat (format, true); + await obj.SaveAsync (monitor);
+ var newFiles = obj.GetItemFiles (true); foreach (FilePath f in newFiles) { if (!f.IsChildPathOf (targetPath)) { @@ -408,8 +391,8 @@ namespace MonoDevelop.Projects using (obj) { ExcludeEntries (obj, includedChildIds); if (format != null) - obj.ConvertToFormat (format, true); - obj.Save (monitor); + await obj.ConvertToFormat (format, true); + await obj.SaveAsync (monitor); return obj.FileName; } } @@ -425,14 +408,14 @@ namespace MonoDevelop.Projects foreach (string it in includedChildIds) childIds [it] = it; - foreach (SolutionItem item in sol.GetAllSolutionItems<SolutionItem> ()) { + foreach (SolutionFolderItem item in sol.GetAllItems<SolutionFolderItem> ()) { if (!childIds.ContainsKey (item.ItemId) && item.ParentFolder != null) item.ParentFolder.Items.Remove (item); } } }
- bool CopyFiles (IProgressMonitor monitor, IWorkspaceFileObject obj, IEnumerable<FilePath> files, FilePath targetBasePath, bool ignoreExternalFiles) + bool CopyFiles (ProgressMonitor monitor, IWorkspaceFileObject obj, IEnumerable<FilePath> files, FilePath targetBasePath, bool ignoreExternalFiles) {
FilePath baseDir = obj.BaseDirectory.FullPath;
foreach (FilePath file in files) { @@ -465,51 +448,28 @@ namespace MonoDevelop.Projects return true; } - public bool CanCreateSingleFileProject (string file) + public DotNetProject CreateDotNetProject (string language) { - foreach (ProjectBindingCodon projectBinding in projectBindings) { - if (projectBinding.ProjectBinding.CanCreateSingleFileProject (file)) - return true; - } - return false; + string typeGuid = MSBuildProjectService.GetLanguageGuid (language); + return (DotNetProject) MSBuildProjectService.CreateSolutionItem (typeGuid); } - - public Project CreateSingleFileProject (string file) - { - foreach (ProjectBindingCodon projectBinding in projectBindings) { - if (projectBinding.ProjectBinding.CanCreateSingleFileProject (file)) { - return projectBinding.ProjectBinding.CreateSingleFileProject (file); - } - } - return null; - } - - public Project CreateProject (string type, ProjectCreateInformation info, XmlElement projectOptions) + + public Project CreateProject (string typeAlias, ProjectCreateInformation info, XmlElement projectOptions) { - foreach (ProjectBindingCodon projectBinding in projectBindings) { - if (projectBinding.ProjectBinding.Name == type) { - Project project = projectBinding.ProjectBinding.CreateProject (info, projectOptions); - return project; - } - } - throw new InvalidOperationException ("Project type '" + type + "' not found"); + return MSBuildProjectService.CreateSolutionItem (typeAlias, info, projectOptions) as Project; } - public bool CanCreateProject (string type) + public bool CanCreateProject (string typeAlias, ProjectCreateInformation info, XmlElement projectOptions) { - foreach (ProjectBindingCodon projectBinding in projectBindings) { - if (projectBinding.ProjectBinding.Name == type) - return true; - } - return false; + return MSBuildProjectService.CanCreateSolutionItem (typeAlias, info, projectOptions); } //TODO: find solution that contains the project if possible - public Solution GetWrapperSolution (IProgressMonitor monitor, string filename) + public async Task<Solution> GetWrapperSolution (ProgressMonitor monitor, string filename) { // First of all, check if a solution with the same name already exists - FileFormat[] formats = Services.ProjectService.FileFormats.GetFileFormats (filename, typeof(SolutionEntityItem)); + FileFormat[] formats = Services.ProjectService.FileFormats.GetFileFormats (filename, typeof(SolutionItem)); if (formats.Length == 0) formats = new [] { DefaultFileFormat }; @@ -520,16 +480,16 @@ namespace MonoDevelop.Projects string solFileName = solutionFileFormat.GetValidFileName (tempSolution, filename); if (File.Exists (solFileName)) { - return (Solution) Services.ProjectService.ReadWorkspaceItem (monitor, solFileName); + return (Solution) await Services.ProjectService.ReadWorkspaceItem (monitor, solFileName); } else { // Create a temporary solution and add the project to the solution tempSolution.SetLocation (Path.GetDirectoryName (filename), Path.GetFileNameWithoutExtension (filename)); - SolutionEntityItem sitem = Services.ProjectService.ReadSolutionItem (monitor, filename); - tempSolution.ConvertToFormat (solutionFileFormat, false); + SolutionItem sitem = await Services.ProjectService.ReadSolutionItem (monitor, filename); + await tempSolution.ConvertToFormat (solutionFileFormat, false); tempSolution.RootFolder.Items.Add (sitem); tempSolution.CreateDefaultConfigurations (); - tempSolution.Save (monitor); + await tempSolution.SaveAsync (monitor); return tempSolution; } } @@ -552,7 +512,7 @@ namespace MonoDevelop.Projects internal bool IsSolutionItemFileInternal (string filename) { - return formatManager.GetFileFormats (filename, typeof(SolutionItem)).Length > 0; + return formatManager.GetFileFormats (filename, typeof(SolutionFolderItem)).Length > 0; } internal bool IsWorkspaceItemFileInternal (string filename) @@ -634,34 +594,6 @@ namespace MonoDevelop.Projects internal class DefaultProjectServiceExtension: ProjectServiceExtension { - Dictionary <SolutionItem,bool> needsBuildingCache; - - public override object GetService (SolutionItem item, Type type) - { - return item.OnGetService (type); - } - - public override object GetService (WorkspaceItem item, Type type) - { - return item.OnGetService (type); - } - - public override void Save (IProgressMonitor monitor, SolutionEntityItem entry) - { - FileService.RequestFileEdit (entry.GetItemFiles (false)); - entry.OnSave (monitor); - } - - public override void Save (IProgressMonitor monitor, WorkspaceItem entry) - { - entry.OnSave (monitor); - }
-
- public override List<FilePath> GetItemFiles (SolutionEntityItem entry, bool includeReferencedFiles) - { - return entry.OnGetItemFiles (includeReferencedFiles); - } - public override bool IsSolutionItemFile (string filename) { return Services.ProjectService.IsSolutionItemFileInternal (filename); @@ -672,152 +604,15 @@ namespace MonoDevelop.Projects return Services.ProjectService.IsWorkspaceItemFileInternal (filename); } - internal override SolutionEntityItem LoadSolutionItem (IProgressMonitor monitor, string fileName, ItemLoadCallback callback) + internal override Task<SolutionItem> LoadSolutionItem (ProgressMonitor monitor, string fileName, ItemLoadCallback callback) { return callback (monitor, fileName); } - public override WorkspaceItem LoadWorkspaceItem (IProgressMonitor monitor, string fileName) + public override Task<WorkspaceItem> LoadWorkspaceItem (ProgressMonitor monitor, string fileName) { return Services.ProjectService.InternalReadWorkspaceItem (fileName, monitor); } - - public override BuildResult RunTarget (IProgressMonitor monitor, IBuildTarget item, string target, ConfigurationSelector configuration) - { - BuildResult res; - if (item is WorkspaceItem) { - res = ((WorkspaceItem)item).OnRunTarget (monitor, target, configuration); - } - else if (item is SolutionItem) - res = ((SolutionItem)item).OnRunTarget (monitor, target, configuration); - else - throw new InvalidOperationException ("Unknown item type: " + item); - - if (res != null) - res.SourceTarget = item; - return res; - } - - public override bool SupportsTarget (IBuildTarget item, string target) - { - if (item is WorkspaceItem) - return ((WorkspaceItem)item).OnGetSupportsTarget (target); - else if (item is SolutionItem) - return ((SolutionItem)item).OnGetSupportsTarget (target); - else - throw new InvalidOperationException ("Unknown item type: " + item); - } - - public override bool SupportsExecute (IBuildTarget item) - { - if (item is WorkspaceItem) - return ((WorkspaceItem)item).OnGetSupportsExecute (); - else if (item is SolutionItem) - return ((SolutionItem)item).OnGetSupportsExecute (); - else - throw new InvalidOperationException ("Unknown item type: " + item); - } - - public override void Execute (IProgressMonitor monitor, IBuildTarget item, ExecutionContext context, ConfigurationSelector configuration) - { - if (item is SolutionEntityItem) { - SolutionEntityItem entry = (SolutionEntityItem) item; - SolutionItemConfiguration conf = entry.GetConfiguration (configuration) as SolutionItemConfiguration; - if (conf != null && conf.CustomCommands.HasCommands (CustomCommandType.Execute)) { - conf.CustomCommands.ExecuteCommand (monitor, entry, CustomCommandType.Execute, context, configuration); - return; - } - entry.OnExecute (monitor, context, configuration); - } - else if (item is WorkspaceItem) { - ((WorkspaceItem)item).OnExecute (monitor, context, configuration); - } - else if (item is SolutionItem) - ((SolutionItem)item).OnExecute (monitor, context, configuration); - else - throw new InvalidOperationException ("Unknown item type: " + item); - } - - public override bool CanExecute (IBuildTarget item, ExecutionContext context, ConfigurationSelector configuration) - { - if (item is SolutionEntityItem) { - SolutionEntityItem entry = (SolutionEntityItem) item; - SolutionItemConfiguration conf = entry.GetConfiguration (configuration) as SolutionItemConfiguration; - if (conf != null && conf.CustomCommands.HasCommands (CustomCommandType.Execute)) - return conf.CustomCommands.CanExecute (entry, CustomCommandType.Execute, context, configuration); - return entry.OnGetCanExecute (context, configuration); - } - else if (item is WorkspaceItem) { - return ((WorkspaceItem)item).OnGetCanExecute (context, configuration); - } - else if (item is SolutionItem) - return ((SolutionItem)item).OnGetCanExecute (context, configuration); - else - throw new InvalidOperationException ("Unknown item type: " + item); - } - - public override IEnumerable<ExecutionTarget> GetExecutionTargets (IBuildTarget item, ConfigurationSelector configuration) - { - if (item is WorkspaceItem) { - return ((WorkspaceItem)item).OnGetExecutionTargets (configuration); - } - else if (item is SolutionItem) - return ((SolutionItem)item).OnGetExecutionTargets (configuration); - else - throw new InvalidOperationException ("Unknown item type: " + item); - } - - public override bool GetNeedsBuilding (IBuildTarget item, ConfigurationSelector configuration) - { - if (item is SolutionItem) { - SolutionItem entry = (SolutionItem) item; - // This is a cache to avoid unneeded recursive calls to GetNeedsBuilding. - bool cleanCache = false; - if (needsBuildingCache == null) { - needsBuildingCache = new Dictionary <SolutionItem,bool> (); - cleanCache = true; - } else { - bool res; - if (needsBuildingCache.TryGetValue (entry, out res)) - return res; - } - - bool nb = entry.OnGetNeedsBuilding (configuration); - - needsBuildingCache [entry] = nb; - if (cleanCache) - needsBuildingCache = null; - return nb; - } - else if (item is WorkspaceItem) { - return ((WorkspaceItem)item).OnGetNeedsBuilding (configuration); - } - else - throw new InvalidOperationException ("Unknown item type: " + item); - } - - public override void SetNeedsBuilding (IBuildTarget item, bool val, ConfigurationSelector configuration) - { - if (item is SolutionItem) { - SolutionItem entry = (SolutionItem) item; - entry.OnSetNeedsBuilding (val, configuration); - } - else if (item is WorkspaceItem) { - ((WorkspaceItem)item).OnSetNeedsBuilding (val, configuration); - } - else - throw new InvalidOperationException ("Unknown item type: " + item); - } - - internal override BuildResult Compile(IProgressMonitor monitor, SolutionEntityItem item, BuildData buildData, ItemCompileCallback callback) - { - return callback (monitor, item, buildData); - } - - public override IEnumerable<string> GetReferencedAssemblies (DotNetProject project, ConfigurationSelector configuration, bool includeProjectReferences) - { - return project.OnGetReferencedAssemblies (configuration, includeProjectReferences); - } } internal static class Counters @@ -826,7 +621,7 @@ namespace MonoDevelop.Projects public static Counter ItemsLoaded = InstrumentationService.CreateCounter ("Projects loaded", "Project Model"); public static Counter SolutionsInMemory = InstrumentationService.CreateCounter ("Solutions in memory", "Project Model"); public static Counter SolutionsLoaded = InstrumentationService.CreateCounter ("Solutions loaded", "Project Model"); - public static TimerCounter ReadWorkspaceItem = InstrumentationService.CreateTimerCounter ("Workspace item read", "Project Model"); + public static TimerCounter ReadWorkspaceItem = InstrumentationService.CreateTimerCounter ("Workspace item read", "Project Model", id:"Core.ReadWorkspaceItem"); public static TimerCounter ReadSolutionItem = InstrumentationService.CreateTimerCounter ("Solution item read", "Project Model"); public static TimerCounter ReadMSBuildProject = InstrumentationService.CreateTimerCounter ("MSBuild project read", "Project Model"); public static TimerCounter WriteMSBuildProject = InstrumentationService.CreateTimerCounter ("MSBuild project written", "Project Model"); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectServiceExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectServiceExtension.cs index 476081baf6..08d368c82e 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectServiceExtension.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectServiceExtension.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using MonoDevelop.Core; using MonoDevelop.Projects.Extensions; using MonoDevelop.Core.Execution; +using System.Threading.Tasks; namespace MonoDevelop.Projects { @@ -39,9 +40,8 @@ namespace MonoDevelop.Projects internal ProjectServiceExtension Next; Stack<ItemLoadCallback> loadCallbackStack = new Stack<ItemLoadCallback> (); - Stack<ItemCompileCallback> compileCallbackStack = new Stack<ItemCompileCallback> (); - - internal ProjectServiceExtension GetNext (IBuildTarget item) + + internal ProjectServiceExtension GetNext (WorkspaceObject item) { if (Next.SupportsItem (item)) return Next; @@ -49,42 +49,11 @@ namespace MonoDevelop.Projects return Next.GetNext (item); } - public virtual bool SupportsItem (IBuildTarget item) + public virtual bool SupportsItem (WorkspaceObject item) { return true; } - public virtual object GetService (SolutionItem item, Type type) - { - if (type.IsInstanceOfType (this)) - return this; - else - return GetNext (item).GetService (item, type); - } - - public virtual object GetService (WorkspaceItem item, Type type) - { - if (type.IsInstanceOfType (this)) - return this; - else - return GetNext (item).GetService (item, type); - } - - public virtual void Save (IProgressMonitor monitor, SolutionEntityItem item) - { - GetNext (item).Save (monitor, item); - } - - public virtual void Save (IProgressMonitor monitor, WorkspaceItem item) - { - GetNext (item).Save (monitor, item); - }
-
- public virtual List<FilePath> GetItemFiles (SolutionEntityItem item, bool includeReferencedFiles) - { - return GetNext (item).GetItemFiles (item, includeReferencedFiles); - } - public virtual bool IsSolutionItemFile (string fileName) { return GetNext (UnknownItem.Instance).IsSolutionItemFile (fileName); @@ -95,307 +64,25 @@ namespace MonoDevelop.Projects return GetNext (UnknownItem.Instance).IsWorkspaceItemFile (fileName); } - internal virtual SolutionEntityItem LoadSolutionItem (IProgressMonitor monitor, string fileName, ItemLoadCallback callback) + internal async virtual Task<SolutionItem> LoadSolutionItem (ProgressMonitor monitor, string fileName, ItemLoadCallback callback) { loadCallbackStack.Push (callback); try { - SolutionEntityItem res = LoadSolutionItem (monitor, fileName); - return res; + return await LoadSolutionItem (monitor, fileName); } finally { loadCallbackStack.Pop (); } } - protected virtual SolutionEntityItem LoadSolutionItem (IProgressMonitor monitor, string fileName) + protected virtual Task<SolutionItem> LoadSolutionItem (ProgressMonitor monitor, string fileName) { return GetNext (UnknownItem.Instance).LoadSolutionItem (monitor, fileName, loadCallbackStack.Peek ()); } - public virtual WorkspaceItem LoadWorkspaceItem (IProgressMonitor monitor, string fileName) + public virtual Task<WorkspaceItem> LoadWorkspaceItem (ProgressMonitor monitor, string fileName) { return GetNext (UnknownItem.Instance).LoadWorkspaceItem (monitor, fileName); } - - public virtual BuildResult RunTarget (IProgressMonitor monitor, IBuildTarget item, string target, ConfigurationSelector configuration) - { - if (target == ProjectService.BuildTarget) - return Build (monitor, item, configuration); - else if (target == ProjectService.CleanTarget) { - Clean (monitor, item, configuration); - return null; - } - else - return GetNext (item).RunTarget (monitor, item, target, configuration); - } - - public virtual bool SupportsTarget (IBuildTarget item, string target) - { - if (item is SolutionEntityItem) - return SupportsTarget ((SolutionEntityItem)item, target); - else if (item is WorkspaceItem) - return SupportsTarget ((WorkspaceItem) item, target); - else - return GetNext (item).SupportsTarget (item, target); - } - - protected virtual bool SupportsTarget (SolutionEntityItem item, string target) - { - return GetNext (item).SupportsTarget ((IBuildTarget) item, target); - } - - protected virtual bool SupportsTarget (Solution solution, string target) - { - return GetNext (solution).SupportsTarget ((IBuildTarget) solution, target); - } - - protected virtual bool SupportsTarget (WorkspaceItem item, string target) - { - if (item is Solution) - return SupportsTarget ((Solution) item, target); - else - return GetNext (item).SupportsTarget ((IBuildTarget) item, target); - } - - public virtual bool SupportsExecute (IBuildTarget item) - { - if (item is SolutionEntityItem) - return SupportsExecute ((SolutionEntityItem)item); - else if (item is WorkspaceItem) - return SupportsExecute ((WorkspaceItem) item); - else - return GetNext (item).SupportsExecute (item); - } - - protected virtual bool SupportsExecute (SolutionEntityItem item) - { - return GetNext (item).SupportsExecute ((IBuildTarget) item); - } - - protected virtual bool SupportsExecute (Solution solution) - { - return GetNext (solution).SupportsExecute ((IBuildTarget) solution); - } - - protected virtual bool SupportsExecute (WorkspaceItem item) - { - if (item is Solution) - return SupportsExecute ((Solution) item); - else - return GetNext (item).SupportsExecute ((IBuildTarget) item); - } - - protected virtual void Clean (IProgressMonitor monitor, IBuildTarget item, ConfigurationSelector configuration) - { - if (item is SolutionEntityItem) - Clean (monitor, (SolutionEntityItem) item, configuration); - else if (item is WorkspaceItem) - Clean (monitor, (WorkspaceItem) item, configuration); - else - GetNext (item).RunTarget (monitor, item, ProjectService.CleanTarget, configuration); - } - - protected virtual void Clean (IProgressMonitor monitor, SolutionEntityItem item, ConfigurationSelector configuration) - { - GetNext (item).RunTarget (monitor, item, ProjectService.CleanTarget, configuration); - } - - protected virtual void Clean (IProgressMonitor monitor, Solution item, ConfigurationSelector configuration) - { - GetNext (item).RunTarget (monitor, item, ProjectService.CleanTarget, configuration); - } - - protected virtual void Clean (IProgressMonitor monitor, WorkspaceItem item, ConfigurationSelector configuration) - { - if (item is Solution) - Clean (monitor, (Solution) item, configuration); - else - GetNext (item).RunTarget (monitor, item, ProjectService.CleanTarget, configuration); - } - - protected virtual BuildResult Build (IProgressMonitor monitor, IBuildTarget item, ConfigurationSelector configuration) - { - if (item is SolutionEntityItem) - return Build (monitor, (SolutionEntityItem) item, configuration); - if (item is WorkspaceItem) - return Build (monitor, (WorkspaceItem) item, configuration); - return GetNext (item).RunTarget (monitor, item, ProjectService.BuildTarget, configuration); - } - - protected virtual BuildResult Build (IProgressMonitor monitor, SolutionEntityItem item, ConfigurationSelector configuration) - { - return GetNext (item).RunTarget (monitor, item, ProjectService.BuildTarget, configuration); - } - - protected virtual BuildResult Build (IProgressMonitor monitor, WorkspaceItem item, ConfigurationSelector configuration) - { - if (item is Solution) - return Build (monitor, (Solution) item, configuration); - return GetNext (item).RunTarget (monitor, item, ProjectService.BuildTarget, configuration); - } - - protected virtual BuildResult Build (IProgressMonitor monitor, Solution solution, ConfigurationSelector configuration) - { - return GetNext (solution).RunTarget (monitor, solution, ProjectService.BuildTarget, configuration); - } - - public virtual void Execute (IProgressMonitor monitor, IBuildTarget item, ExecutionContext context, ConfigurationSelector configuration) - { - if (item is SolutionEntityItem) - Execute (monitor, (SolutionEntityItem)item, context, configuration); - else if (item is WorkspaceItem) - Execute (monitor, (WorkspaceItem) item, context, configuration); - else - GetNext (item).Execute (monitor, item, context, configuration); - } - - protected virtual void Execute (IProgressMonitor monitor, SolutionEntityItem item, ExecutionContext context, ConfigurationSelector configuration) - { - GetNext (item).Execute (monitor, (IBuildTarget) item, context, configuration); - } - - protected virtual void Execute (IProgressMonitor monitor, Solution solution, ExecutionContext context, ConfigurationSelector configuration) - { - GetNext (solution).Execute (monitor, (IBuildTarget) solution, context, configuration); - } - - protected virtual void Execute (IProgressMonitor monitor, WorkspaceItem item, ExecutionContext context, ConfigurationSelector configuration) - { - if (item is Solution) - Execute (monitor, (Solution) item, context, configuration); - else - GetNext (item).Execute (monitor, (IBuildTarget) item, context, configuration); - } - - public virtual bool CanExecute (IBuildTarget item, ExecutionContext context, ConfigurationSelector configuration) - { - if (item is SolutionEntityItem) - return CanExecute ((SolutionEntityItem)item, context, configuration); - else if (item is WorkspaceItem) - return CanExecute ((WorkspaceItem) item, context, configuration); - else - return GetNext (item).CanExecute (item, context, configuration); - } - - protected virtual bool CanExecute (SolutionEntityItem item, ExecutionContext context, ConfigurationSelector configuration) - { - return GetNext (item).CanExecute ((IBuildTarget) item, context, configuration); - } - - protected virtual bool CanExecute (Solution solution, ExecutionContext context, ConfigurationSelector configuration) - { - return GetNext (solution).CanExecute ((IBuildTarget) solution, context, configuration); - } - - protected virtual bool CanExecute (WorkspaceItem item, ExecutionContext context, ConfigurationSelector configuration) - { - if (item is Solution) - return CanExecute ((Solution) item, context, configuration); - else - return GetNext (item).CanExecute ((IBuildTarget) item, context, configuration); - } - - public virtual IEnumerable<ExecutionTarget> GetExecutionTargets (IBuildTarget item, ConfigurationSelector configuration) - { - if (item is SolutionEntityItem) - return GetExecutionTargets ((SolutionEntityItem)item, configuration); - else if (item is WorkspaceItem) - return GetExecutionTargets ((WorkspaceItem) item, configuration); - else - return GetNext (item).GetExecutionTargets (item, configuration); - } - - protected virtual IEnumerable<ExecutionTarget> GetExecutionTargets (SolutionEntityItem item, ConfigurationSelector configuration) - { - return GetNext (item).GetExecutionTargets ((IBuildTarget) item, configuration); - } - - protected virtual IEnumerable<ExecutionTarget> GetExecutionTargets (Solution solution, ConfigurationSelector configuration) - { - return GetNext (solution).GetExecutionTargets ((IBuildTarget) solution, configuration); - } - - protected virtual IEnumerable<ExecutionTarget> GetExecutionTargets (WorkspaceItem item, ConfigurationSelector configuration) - { - if (item is Solution) - return GetExecutionTargets ((Solution) item, configuration); - else - return GetNext (item).GetExecutionTargets ((IBuildTarget) item, configuration); - } - - public virtual bool GetNeedsBuilding (IBuildTarget item, ConfigurationSelector configuration) - { - if (item is SolutionEntityItem) - return GetNeedsBuilding ((SolutionEntityItem) item, configuration); - if (item is WorkspaceItem) - return GetNeedsBuilding ((WorkspaceItem) item, configuration); - return GetNext (item).GetNeedsBuilding (item, configuration); - } - - protected virtual bool GetNeedsBuilding (SolutionEntityItem item, ConfigurationSelector configuration) - { - return GetNext (item).GetNeedsBuilding ((IBuildTarget) item, configuration); - } - - protected virtual bool GetNeedsBuilding (Solution item, ConfigurationSelector configuration) - { - return GetNext (item).GetNeedsBuilding ((IBuildTarget) item, configuration); - } - - protected virtual bool GetNeedsBuilding (WorkspaceItem item, ConfigurationSelector configuration) - { - if (item is Solution) - return GetNeedsBuilding ((Solution) item, configuration); - return GetNext (item).GetNeedsBuilding ((IBuildTarget) item, configuration); - } - - public virtual void SetNeedsBuilding (IBuildTarget item, bool val, ConfigurationSelector configuration) - { - if (item is SolutionEntityItem) - SetNeedsBuilding ((SolutionEntityItem) item, val, configuration); - else if (item is WorkspaceItem) - SetNeedsBuilding ((WorkspaceItem) item, val, configuration); - else - GetNext (item).SetNeedsBuilding (item, val, configuration); - } - - protected virtual void SetNeedsBuilding (SolutionEntityItem item, bool val, ConfigurationSelector configuration) - { - GetNext (item).SetNeedsBuilding ((IBuildTarget) item, val, configuration); - } - - protected virtual void SetNeedsBuilding (Solution item, bool val, ConfigurationSelector configuration) - { - GetNext (item).SetNeedsBuilding ((IBuildTarget) item, val, configuration); - } - - protected virtual void SetNeedsBuilding (WorkspaceItem item, bool val, ConfigurationSelector configuration) - { - if (item is Solution) - SetNeedsBuilding ((Solution) item, val, configuration); - else - GetNext (item).SetNeedsBuilding ((IBuildTarget) item, val, configuration); - } - - internal virtual BuildResult Compile (IProgressMonitor monitor, SolutionEntityItem item, BuildData buildData, ItemCompileCallback callback) - { - compileCallbackStack.Push (callback); - try { - BuildResult res = Compile (monitor, item, buildData); - return res; - } finally { - compileCallbackStack.Pop (); - } - } - - protected virtual BuildResult Compile (IProgressMonitor monitor, SolutionEntityItem item, BuildData buildData) - { - return GetNext (item).Compile (monitor, item, buildData, compileCallbackStack.Peek ()); - } - - public virtual IEnumerable<string> GetReferencedAssemblies (DotNetProject project, ConfigurationSelector configuration, bool includeProjectReferences) - { - return GetNext (project).GetReferencedAssemblies (project, configuration, includeProjectReferences); - } } public class BuildData @@ -405,16 +92,21 @@ namespace MonoDevelop.Projects public ConfigurationSelector ConfigurationSelector { get; internal set; } } - class UnknownItem: IBuildTarget + class UnknownItem: WorkspaceObject, IBuildTarget { public static UnknownItem Instance = new UnknownItem (); - - public BuildResult RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration) + + public Task<BuildResult> Build (ProgressMonitor monitor, ConfigurationSelector configuration, bool buildReferencedTargets = false) { - return new BuildResult (); + return Task.FromResult (BuildResult.Success); } - public void Execute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + public Task<BuildResult> Clean (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return Task.FromResult (BuildResult.Success); + } + + public Task Execute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { throw new System.NotImplementedException(); } @@ -424,45 +116,24 @@ namespace MonoDevelop.Projects return false; } - public bool SupportsTarget (string target) - { - return false; - } - public bool NeedsBuilding (ConfigurationSelector configuration) { return false; } - - public void SetNeedsBuilding (bool needsBuilding, ConfigurationSelector configuration) + + protected override string OnGetName () { + return "Unknown"; } - - public void Save (IProgressMonitor monitor) + + protected override string OnGetBaseDirectory () { + return FilePath.Empty; } - - public string Name { - get { return "Unknown"; } - set { } - } - - - public FilePath ItemDirectory { - get { return FilePath.Empty; } - } - - public FilePath BaseDirectory { - get { return FilePath.Empty; } - set { } - } - - public void Dispose () + + protected override string OnGetItemDirectory () { - } - - public System.Collections.IDictionary ExtendedProperties { - get { return null; } + return FilePath.Empty; } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProjectBinding.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/RegisterDotNetProject.cs index ca7f7527a1..1d237ac31f 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProjectBinding.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/RegisterDotNetProject.cs @@ -1,5 +1,5 @@ // -// SharedAssetsProjectBinding.cs +// RegisterDotNetProject.cs // // Author: // Lluis Sanchez Gual <lluis@xamarin.com> @@ -24,35 +24,22 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; +using Mono.Addins; -namespace MonoDevelop.Projects.SharedAssetsProjects +namespace MonoDevelop.Projects { - public class SharedAssetsProjectBinding: IProjectBinding + public class RegisterDotNetProjectTypeAttribute: RegisterProjectTypeAttribute { - #region IProjectBinding implementation - - public Project CreateProject (ProjectCreateInformation info, System.Xml.XmlElement projectOptions) - { - return new SharedAssetsProject (info, projectOptions); - } - - public Project CreateSingleFileProject (string sourceFile) + protected RegisterDotNetProjectTypeAttribute () { - throw new NotImplementedException (); } - public bool CanCreateSingleFileProject (string sourceFile) + public RegisterDotNetProjectTypeAttribute ([NodeAttribute ("guid")] string guid, [NodeAttribute("language")] string language): base (guid) { - return false; - } - - public string Name { - get { - return "SharedAssetsProject"; - } } - #endregion + [NodeAttribute ("language", Required=true)] + public string Language { get; set; } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/RegisterProjectAttribute.cs index adb9f0a0c4..e582055a24 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildExtension.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/RegisterProjectAttribute.cs @@ -1,5 +1,5 @@ // -// MSBuildExtension.cs +// MSBuildProjectTypeAttribute.cs // // Author: // Lluis Sanchez Gual <lluis@xamarin.com> @@ -25,24 +25,20 @@ // THE SOFTWARE. using System; using MonoDevelop.Core; +using System.Threading.Tasks; +using MonoDevelop.Projects.Formats.MSBuild; +using Mono.Addins; -namespace MonoDevelop.Projects.Formats.MSBuild +namespace MonoDevelop.Projects { - public class MSBuildExtension + public class RegisterProjectTypeAttribute: RegisterSolutionItemTypeAttribute { - public MSBuildProjectHandler Handler { get; set; } - - public virtual void LoadProject (IProgressMonitor monitor, SolutionEntityItem item, MSBuildProject project) - { - } - - public virtual void SaveProject (IProgressMonitor monitor, SolutionEntityItem item, MSBuildProject project) + protected RegisterProjectTypeAttribute () { } - public virtual object GetService (Type t) + public RegisterProjectTypeAttribute ([NodeAttribute ("guid")] string guid): base (guid) { - return null; } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/RegisterProjectFlavorAttribute.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/RegisterProjectFlavorAttribute.cs new file mode 100644 index 0000000000..023723f1db --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/RegisterProjectFlavorAttribute.cs @@ -0,0 +1,48 @@ +// +// ProjectFlavorTypeAttribute.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Linq; +using Mono.Addins; + +namespace MonoDevelop.Projects +{ + public class RegisterProjectFlavorAttribute: RegisterProjectModelExtensionAttribute + { + internal RegisterProjectFlavorAttribute () + { + } + + public RegisterProjectFlavorAttribute ([NodeAttribute ("guid")] string guid) + { + Guid = guid; + } + + [NodeAttribute ("guid", Description = "GUID of the extension. The extension will be loaded if the project has this GUID in the project type GUID list. " + + "If not specified, the extension will be applied to all projects.")] + public string Guid { get; set; } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/RegisterProjectModelExtensionAttribute.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/RegisterProjectModelExtensionAttribute.cs new file mode 100644 index 0000000000..9c47679650 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/RegisterProjectModelExtensionAttribute.cs @@ -0,0 +1,36 @@ +// +// RegisterProjectModelExtensionAttribute.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using Mono.Addins; + +namespace MonoDevelop.Projects +{ + public class RegisterProjectModelExtensionAttribute: CustomExtensionAttribute + { + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/RegisterSolutionItemTypeAttribute.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/RegisterSolutionItemTypeAttribute.cs new file mode 100644 index 0000000000..ccdc33ab8b --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/RegisterSolutionItemTypeAttribute.cs @@ -0,0 +1,62 @@ +// +// SolutionItemTypeAttribute.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Threading.Tasks; +using MonoDevelop.Core; +using Mono.Addins; +using MonoDevelop.Core.ProgressMonitoring; + +namespace MonoDevelop.Projects +{ + public class RegisterSolutionItemTypeAttribute: CustomExtensionAttribute + { + [NodeAttribute ("guid", Required=true)] + public string Guid { get; set; } + + [NodeAttribute ("extension")] + public string Extension { get; set; } + + [NodeAttribute ("import")] + public string Import { get; set; } + + [NodeAttribute ("alias")] + public string Alias { get; set; } + + public string TypeName { + get { return ((TypeExtensionNode)ExtensionNode).TypeName; } + } + + protected RegisterSolutionItemTypeAttribute () + { + } + + public RegisterSolutionItemTypeAttribute ([NodeAttribute ("guid")] string guid) + { + Guid = guid; + } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs index f0b7f171f2..97534bbc16 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs @@ -36,18 +36,21 @@ using MonoDevelop.Core; using MonoDevelop.Core.ProgressMonitoring; using MonoDevelop.Core.StringParsing; using MonoDevelop.Projects.Policies; +using MonoDevelop.Core.Execution; +using System.Threading.Tasks; +using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.Projects { [ProjectModelDataItem] - public class Solution: WorkspaceItem, IConfigurationTarget, IPolicyProvider + public class Solution: WorkspaceItem, IConfigurationTarget, IPolicyProvider, IBuildTarget { internal object MemoryProbe = Counters.SolutionsInMemory.CreateMemoryProbe (); SolutionFolder rootFolder; string defaultConfiguration; - SolutionEntityItem startupItem; - List<SolutionEntityItem> startupItems; + SolutionItem startupItem; + List<SolutionItem> startupItems; bool singleStartup = true; // Used for serialization only @@ -70,8 +73,24 @@ namespace MonoDevelop.Projects { Counters.SolutionsLoaded++; configurations = new SolutionConfigurationCollection (this); + Initialize (this); } - + + internal HashSet<string> LoadedProjects { + get; + set; + } + + SolutionExtension itemExtension; + + SolutionExtension SolutionExtension { + get { + if (itemExtension == null) + itemExtension = ExtensionChain.GetExtension<SolutionExtension> (); + return itemExtension; + } + } + public SolutionFolder RootFolder { get { if (rootFolder == null) { @@ -103,18 +122,13 @@ namespace MonoDevelop.Projects // Does not include solution folders public ReadOnlyCollection<SolutionItem> Items { get { - if (solutionItems == null) { - List<SolutionItem> list = new List<SolutionItem> (); - foreach (SolutionItem item in GetAllSolutionItems ()) - if (!(item is SolutionFolder)) - list.Add (item); - solutionItems = list.AsReadOnly (); - } + if (solutionItems == null) + solutionItems = GetAllSolutionItems ().ToList().AsReadOnly (); return solutionItems; } } - public SolutionEntityItem StartupItem { + public SolutionItem StartupItem { get { if (startItemFileName != null) { startupItem = FindSolutionItem (startItemFileName); @@ -122,8 +136,8 @@ namespace MonoDevelop.Projects singleStartup = true; } if (startupItem == null && singleStartup) { - ReadOnlyCollection<SolutionEntityItem> its = GetAllSolutionItems<SolutionEntityItem> (); - if (its.Count > 0) + var its = GetAllItems<SolutionItem> (); + if (its.Any ()) startupItem = its.FirstOrDefault (it => it.SupportsExecute ()); } return startupItem; @@ -161,12 +175,12 @@ namespace MonoDevelop.Projects } } - public List<SolutionEntityItem> MultiStartupItems { + public List<SolutionItem> MultiStartupItems { get { if (multiStartupItems != null) { - startupItems = new List<SolutionEntityItem> (); + startupItems = new List<SolutionItem> (); foreach (string file in multiStartupItems) { - SolutionEntityItem it = FindSolutionItem (file); + SolutionItem it = FindSolutionItem (file); if (it != null) startupItems.Add (it); } @@ -174,7 +188,7 @@ namespace MonoDevelop.Projects singleStartup = false; } else if (startupItems == null) - startupItems = new List<SolutionEntityItem> (); + startupItems = new List<SolutionItem> (); return startupItems; } } @@ -200,7 +214,7 @@ namespace MonoDevelop.Projects if (multiStartupItems != null) return multiStartupItems; List<string> files = new List<string> (); - foreach (SolutionEntityItem item in MultiStartupItems) + foreach (SolutionItem item in MultiStartupItems) files.Add (item.FileName); return files; } @@ -248,30 +262,30 @@ namespace MonoDevelop.Projects CleanItemProperties (UserProperties, RootFolder, "MonoDevelop.Ide.ItemProperties"); } - void CollectItemProperties (PropertyBag props, SolutionItem item, string path) + void CollectItemProperties (PropertyBag props, SolutionFolderItem item, string path) { if (!item.UserProperties.IsEmpty && item.ParentFolder != null) props.SetValue (path, item.UserProperties); SolutionFolder sf = item as SolutionFolder; if (sf != null) { - foreach (SolutionItem ci in sf.Items) + foreach (SolutionFolderItem ci in sf.Items) CollectItemProperties (props, ci, path + "." + ci.Name); } } - void CleanItemProperties (PropertyBag props, SolutionItem item, string path) + void CleanItemProperties (PropertyBag props, SolutionFolderItem item, string path) { props.RemoveValue (path); SolutionFolder sf = item as SolutionFolder; if (sf != null) { - foreach (SolutionItem ci in sf.Items) + foreach (SolutionFolderItem ci in sf.Items) CleanItemProperties (props, ci, path + "." + ci.Name); } } - void LoadItemProperties (PropertyBag props, SolutionItem item, string path) + void LoadItemProperties (PropertyBag props, SolutionFolderItem item, string path) { PropertyBag info = props.GetValue<PropertyBag> (path); if (info != null) { @@ -281,14 +295,14 @@ namespace MonoDevelop.Projects SolutionFolder sf = item as SolutionFolder; if (sf != null) { - foreach (SolutionItem ci in sf.Items) + foreach (SolutionFolderItem ci in sf.Items) LoadItemProperties (props, ci, path + "." + ci.Name); } } public void CreateDefaultConfigurations () { - foreach (SolutionEntityItem item in Items.Where (it => it.SupportsBuild ())) { + foreach (SolutionItem item in Items.Where (it => it.SupportsBuild ())) { foreach (ItemConfiguration conf in item.Configurations) { SolutionConfiguration sc = Configurations [conf.Id]; if (sc == null) { @@ -308,7 +322,7 @@ namespace MonoDevelop.Projects public SolutionConfiguration AddConfiguration (string name, bool createConfigForItems) { SolutionConfiguration conf = new SolutionConfiguration (name); - foreach (SolutionEntityItem item in Items.Where (it => it.SupportsBuild())) { + foreach (SolutionItem item in Items.Where (it => it.SupportsBuild())) { if (createConfigForItems && item.GetConfiguration (new ItemConfigurationSelector (name)) == null) { SolutionItemConfiguration newc = item.CreateConfiguration (name); if (item.DefaultConfiguration != null) @@ -334,15 +348,15 @@ namespace MonoDevelop.Projects return (SolutionConfiguration) configuration.GetConfiguration (this) ?? DefaultConfiguration; } - public SolutionItem GetSolutionItem (string itemId) + public SolutionFolderItem GetSolutionItem (string itemId) { - foreach (SolutionItem item in Items) + foreach (SolutionFolderItem item in Items) if (item.ItemId == itemId) return item; return null; } - public override SolutionEntityItem FindSolutionItem (string fileName) + public SolutionItem FindSolutionItem (string fileName) { return RootFolder.FindSolutionItem (fileName); } @@ -352,11 +366,16 @@ namespace MonoDevelop.Projects return RootFolder.FindProjectByName (name); } - public override ReadOnlyCollection<T> GetAllSolutionItems<T> () + public IEnumerable<SolutionItem> GetAllSolutionItems () { - return RootFolder.GetAllItems<T> (); + return GetAllItems<SolutionItem> (); } - + + public IEnumerable<Project> GetAllProjects () + { + return GetAllItems<Project> (); + } + public ReadOnlyCollection<T> GetAllSolutionItemsWithTopologicalSort<T> (ConfigurationSelector configuration) where T: SolutionItem { return RootFolder.GetAllItemsWithTopologicalSort<T> (configuration); @@ -378,17 +397,22 @@ namespace MonoDevelop.Projects return RootFolder.GetProjectsContainingFile (fileName); } - public override bool ContainsItem (IWorkspaceObject obj) + public override bool ContainsItem (WorkspaceObject obj) { if (base.ContainsItem (obj)) return true; - foreach (SolutionItem it in GetAllSolutionItems<SolutionItem> ()) { + foreach (SolutionFolderItem it in GetAllItems<SolutionFolderItem> ()) { if (it == obj) return true; } return false; } + + protected override IEnumerable<WorkspaceObject> OnGetChildren () + { + yield return RootFolder; + } public string Description { get { @@ -494,7 +518,7 @@ namespace MonoDevelop.Projects } set { version = value; - foreach (SolutionEntityItem item in GetAllSolutionItems<SolutionEntityItem> ()) { + foreach (SolutionItem item in GetAllItems<SolutionItem> ()) { if (item.SyncVersionWithSolution) item.Version = value; } @@ -515,7 +539,7 @@ namespace MonoDevelop.Projects return list == null || !list.Contains (solutionItemPath); } - public void SetSolutionItemEnabled (string solutionItemPath, bool enabled) + internal void SetSolutionItemEnabled (string solutionItemPath, bool enabled) { solutionItemPath = GetRelativeChildPath (Path.GetFullPath (solutionItemPath)); var list = UserProperties.GetValue<List<string>> ("DisabledProjects"); @@ -543,25 +567,91 @@ namespace MonoDevelop.Projects } } } - - protected override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration) + + + public Task<BuildResult> Clean (ProgressMonitor monitor, string configuration) + { + return Clean (monitor, (SolutionConfigurationSelector) configuration); + } + + public Task<BuildResult> Clean (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return SolutionExtension.Clean (monitor, configuration); + } + + public Task<BuildResult> Build (ProgressMonitor monitor, string configuration) + { + return SolutionExtension.Build (monitor, (SolutionConfigurationSelector) configuration); + } + + Task<BuildResult> IBuildTarget.Build (ProgressMonitor monitor, ConfigurationSelector configuration, bool buildReferencedTargets) + { + return Build (monitor, configuration); + } + + public Task<BuildResult> Build (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return SolutionExtension.Build (monitor, configuration); + } + + public bool NeedsBuilding (ConfigurationSelector configuration) + { + return SolutionExtension.NeedsBuilding (configuration); + } + + public Task Execute (ProgressMonitor monitor, ExecutionContext context, string configuration) + { + return Execute (monitor, context, (SolutionConfigurationSelector) configuration); + } + + public Task Execute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + { + return SolutionExtension.Execute (monitor, context, configuration); + } + + public bool CanExecute (ExecutionContext context, string configuration) + { + return CanExecute (context, (SolutionConfigurationSelector) configuration); + } + + public bool CanExecute (ExecutionContext context, ConfigurationSelector configuration) + { + return SolutionExtension.CanExecute (context, configuration); + } + + public IEnumerable<ExecutionTarget> GetExecutionTargets (string configuration) + { + return GetExecutionTargets ((SolutionConfigurationSelector) configuration); + } + + public IEnumerable<ExecutionTarget> GetExecutionTargets (ConfigurationSelector configuration) + { + return SolutionExtension.GetExecutionTargets (this, configuration); + } + + protected virtual Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { return RootFolder.Build (monitor, configuration); } - - protected override void OnClean (IProgressMonitor monitor, ConfigurationSelector configuration) + + protected virtual bool OnGetNeedsBuilding (ConfigurationSelector configuration) + { + return RootFolder.NeedsBuilding (configuration); + } + + protected virtual Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration) { - RootFolder.Clean (monitor, configuration); + return RootFolder.Clean (monitor, configuration); } - protected internal override bool OnGetCanExecute(ExecutionContext context, ConfigurationSelector configuration) + protected virtual bool OnGetCanExecute(ExecutionContext context, ConfigurationSelector configuration) { if (SingleStartup) { if (StartupItem == null) return false; return StartupItem.CanExecute (context, configuration); } else { - foreach (SolutionEntityItem it in MultiStartupItems) { + foreach (SolutionItem it in MultiStartupItems) { if (it.CanExecute (context, configuration)) return true; } @@ -569,44 +659,36 @@ namespace MonoDevelop.Projects } } - protected internal override void OnExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + protected async virtual Task OnExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { if (SingleStartup) { if (StartupItem == null) { monitor.ReportError (GettextCatalog.GetString ("Startup item not set"), null); return; } - StartupItem.Execute (monitor, context, configuration); + await StartupItem.Execute (monitor, context, configuration); } else { - List<IAsyncOperation> list = new List<IAsyncOperation> (); + var tasks = new List<Task> (); + var monitors = new List<AggregatedProgressMonitor> (); monitor.BeginTask ("Executing projects", 1); - SynchronizedProgressMonitor syncMonitor = new SynchronizedProgressMonitor (monitor); - - foreach (SolutionEntityItem it in MultiStartupItems) { + foreach (SolutionItem it in MultiStartupItems) { if (!it.CanExecute (context, configuration)) continue; AggregatedProgressMonitor mon = new AggregatedProgressMonitor (); - mon.AddSlaveMonitor (syncMonitor, MonitorAction.ReportError | MonitorAction.ReportWarning | MonitorAction.SlaveCancel); - list.Add (mon.AsyncOperation); - SolutionEntityItem cit = it; - - Thread t = new Thread (delegate () { - try { - using (mon) { - cit.Execute (mon, context, configuration); - } - } catch (Exception ex) { - LoggingService.LogError ("Project execution failed", ex); - } - }); - t.Name = "Project execution"; - t.IsBackground = true; - t.Start (); + mon.AddSlaveMonitor (monitor, MonitorAction.ReportError | MonitorAction.ReportWarning | MonitorAction.SlaveCancel); + monitors.Add (mon); + tasks.Add (it.Execute (mon, context, configuration)); } - foreach (IAsyncOperation op in list) - op.WaitForCompleted (); - + try { + await Task.WhenAll (tasks); + } catch (Exception ex) { + LoggingService.LogError ("Project execution failed", ex); + } finally { + foreach (var m in monitors) + m.Dispose (); + } + monitor.EndTask (); } } @@ -617,25 +699,25 @@ namespace MonoDevelop.Projects StartupItemChanged (this, e); } - public override void ConvertToFormat (FileFormat format, bool convertChildren) + public async override Task ConvertToFormat (FileFormat format, bool convertChildren) { - base.ConvertToFormat (format, convertChildren); - foreach (SolutionItem item in GetAllSolutionItems<SolutionItem> ()) - ConvertToSolutionFormat (item, convertChildren); + await base.ConvertToFormat (format, convertChildren); + foreach (SolutionFolderItem item in GetAllItems<SolutionFolderItem> ()) + await ConvertToSolutionFormat (item, convertChildren); } public override bool SupportsFormat (FileFormat format) { if (!base.SupportsFormat (format)) return false; - return GetAllSolutionItems<SolutionEntityItem> ().All (p => p.SupportsFormat (format)); + return GetAllItems<SolutionItem> ().All (p => p.SupportsFormat (format)); }
- public override List<FilePath> GetItemFiles (bool includeReferencedFiles) + protected override IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles) {
- List<FilePath> files = base.GetItemFiles (includeReferencedFiles); + List<FilePath> files = base.OnGetItemFiles (includeReferencedFiles).ToList (); if (includeReferencedFiles) { - foreach (SolutionEntityItem item in GetAllSolutionItems<SolutionEntityItem> ()) + foreach (SolutionItem item in GetAllItems<SolutionItem> ()) files.AddRange (item.GetItemFiles (true)); } return files; @@ -649,7 +731,7 @@ namespace MonoDevelop.Projects SolutionFolder sf = args.SolutionItem as SolutionFolder; if (sf != null) { - foreach (SolutionItem eitem in sf.GetAllItems<SolutionItem> ()) + foreach (SolutionFolderItem eitem in sf.GetAllItems<SolutionFolderItem> ()) SetupNewItem (eitem, null); } else { @@ -660,14 +742,14 @@ namespace MonoDevelop.Projects SolutionItemAdded (this, args); } - void SetupNewItem (SolutionItem item, SolutionItem replacedItem) + void SetupNewItem (SolutionFolderItem item, SolutionFolderItem replacedItem) { - ConvertToSolutionFormat (item, false); + ConvertToSolutionFormat (item, false).Wait (); - SolutionEntityItem eitem = item as SolutionEntityItem; + SolutionItem eitem = item as SolutionItem; if (eitem != null) { eitem.NeedsReload = false; - if (eitem.SupportsBuild () || replacedItem != null) { + if (eitem.SupportsConfigurations () || replacedItem != null) { if (replacedItem == null) { // Register the new entry in every solution configuration foreach (SolutionConfiguration conf in Configurations) @@ -678,11 +760,11 @@ namespace MonoDevelop.Projects } else { // Reuse the configuration information of the replaced item foreach (SolutionConfiguration conf in Configurations) - conf.ReplaceItem ((SolutionEntityItem)replacedItem, eitem); + conf.ReplaceItem ((SolutionItem)replacedItem, eitem); if (StartupItem == replacedItem) StartupItem = eitem; else { - int i = MultiStartupItems.IndexOf ((SolutionEntityItem)replacedItem); + int i = MultiStartupItems.IndexOf ((SolutionItem)replacedItem); if (i != -1) MultiStartupItems [i] = eitem; } @@ -691,11 +773,11 @@ namespace MonoDevelop.Projects } } - void ConvertToSolutionFormat (SolutionItem item, bool force) + async Task ConvertToSolutionFormat (SolutionFolderItem item, bool force) { - SolutionEntityItem eitem = item as SolutionEntityItem; + SolutionItem eitem = item as SolutionItem; if (force || !FileFormat.Format.SupportsMixedFormats || eitem == null || !eitem.IsSaved) { - this.FileFormat.Format.ConvertToFormat (item); + await this.FileFormat.Format.ConvertToFormat (item); if (eitem != null) eitem.InstallFormat (this.FileFormat); } @@ -707,11 +789,11 @@ namespace MonoDevelop.Projects SolutionFolder sf = args.SolutionItem as SolutionFolder; if (sf != null) { - foreach (SolutionEntityItem eitem in sf.GetAllItems<SolutionEntityItem> ()) + foreach (SolutionItem eitem in sf.GetAllItems<SolutionItem> ()) DetachItem (eitem, args.Reloading); } else { - SolutionEntityItem item = args.SolutionItem as SolutionEntityItem; + SolutionItem item = args.SolutionItem as SolutionItem; if (item != null) DetachItem (item, args.Reloading); } @@ -720,7 +802,7 @@ namespace MonoDevelop.Projects SolutionItemRemoved (this, args); } - void DetachItem (SolutionEntityItem item, bool reloading) + void DetachItem (SolutionItem item, bool reloading) { item.NeedsReload = false; if (!reloading) { @@ -744,7 +826,7 @@ namespace MonoDevelop.Projects if (projectToRemove == null) return; - foreach (DotNetProject project in GetAllSolutionItems <DotNetProject>()) { + foreach (DotNetProject project in GetAllItems <DotNetProject>()) { if (project == projectToRemove) continue; @@ -760,7 +842,27 @@ namespace MonoDevelop.Projects } } } + + internal void ReadSolution (ProgressMonitor monitor, SlnFile file) + { + SolutionExtension.OnReadSolution (monitor, file); + } + + protected virtual void OnReadSolution (ProgressMonitor monitor, SlnFile file) + { + ((MSBuildFileFormat)FileFormat.Format).SlnFileFormat.LoadSolution (this, file, monitor); + } + + internal void WriteSolution (ProgressMonitor monitor, SlnFile file) + { + SolutionExtension.OnWriteSolution (monitor, file); + } + protected virtual void OnWriteSolution (ProgressMonitor monitor, SlnFile file) + { + ((MSBuildFileFormat)FileFormat.Format).SlnFileFormat.WriteFileInternal (file, this, monitor); + } + internal void NotifyConfigurationsChanged () { OnConfigurationsChanged (); @@ -843,6 +945,54 @@ namespace MonoDevelop.Projects public event SolutionItemModifiedEventHandler EntryModified; public event SolutionItemEventHandler EntrySaved; public event EventHandler<SolutionItemEventArgs> ItemReloadRequired; + + protected override IEnumerable<WorkspaceObjectExtension> CreateDefaultExtensions () + { + return base.CreateDefaultExtensions ().Concat (Enumerable.Repeat (new DefaultSolutionExtension (), 1)); + } + + internal class DefaultSolutionExtension: SolutionExtension + { + internal protected override IEnumerable<FilePath> GetItemFiles (bool includeReferencedFiles) + { + return Solution.OnGetItemFiles (includeReferencedFiles); + } + + internal protected override Task<BuildResult> Build (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return Solution.OnBuild (monitor, configuration); + } + + internal protected override bool NeedsBuilding (ConfigurationSelector configuration) + { + return Solution.OnGetNeedsBuilding (configuration); + } + + internal protected override Task<BuildResult> Clean (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return Solution.OnClean (monitor, configuration); + } + + internal protected override Task Execute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + { + return Solution.OnExecute (monitor, context, configuration); + } + + internal protected override bool CanExecute (ExecutionContext context, ConfigurationSelector configuration) + { + return Solution.OnGetCanExecute (context, configuration); + } + + internal protected override void OnReadSolution (ProgressMonitor monitor, SlnFile file) + { + Solution.OnReadSolution (monitor, file); + } + + internal protected override void OnWriteSolution (ProgressMonitor monitor, SlnFile file) + { + Solution.OnWriteSolution (monitor, file); + } + } } [Mono.Addins.Extension] diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionConfiguration.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionConfiguration.cs index dfa4bc6832..717edf5f9b 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionConfiguration.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionConfiguration.cs @@ -73,7 +73,7 @@ namespace MonoDevelop.Projects get { return configurations.AsReadOnly (); } } - public bool BuildEnabledForItem (SolutionEntityItem item) + public bool BuildEnabledForItem (SolutionItem item) { foreach (SolutionConfigurationEntry entry in configurations) { if (entry.Item == item) @@ -82,7 +82,7 @@ namespace MonoDevelop.Projects return false; } - public string GetMappedConfiguration (SolutionEntityItem item) + public string GetMappedConfiguration (SolutionItem item) { foreach (SolutionConfigurationEntry entry in configurations) { if (entry.Item == item) @@ -91,7 +91,7 @@ namespace MonoDevelop.Projects return null; } - public SolutionConfigurationEntry GetEntryForItem (SolutionEntityItem item) + public SolutionConfigurationEntry GetEntryForItem (SolutionItem item) { foreach (SolutionConfigurationEntry entry in configurations) { if (entry.Item == item) @@ -100,13 +100,13 @@ namespace MonoDevelop.Projects return null; } - public SolutionConfigurationEntry AddItem (SolutionEntityItem item) + public SolutionConfigurationEntry AddItem (SolutionItem item) { string conf = FindMatchingConfiguration (item); return AddItem (item, conf != null, conf); } - string FindMatchingConfiguration (SolutionEntityItem item) + string FindMatchingConfiguration (SolutionItem item) { SolutionItemConfiguration startupConfiguration = null; @@ -153,7 +153,7 @@ namespace MonoDevelop.Projects return item.Configurations [0].Id; } - public SolutionConfigurationEntry AddItem (SolutionEntityItem item, bool build, string itemConfiguration) + public SolutionConfigurationEntry AddItem (SolutionItem item, bool build, string itemConfiguration) { if (itemConfiguration == null) itemConfiguration = Name; @@ -166,7 +166,7 @@ namespace MonoDevelop.Projects return conf; } - public void RemoveItem (SolutionEntityItem item) + public void RemoveItem (SolutionItem item) { for (int n=0; n<configurations.Count; n++) { if (configurations [n].Item == item) { @@ -176,7 +176,7 @@ namespace MonoDevelop.Projects } } - internal void ReplaceItem (SolutionEntityItem oldItem, SolutionEntityItem newItem) + internal void ReplaceItem (SolutionItem oldItem, SolutionItem newItem) { foreach (var e in configurations.Where (ce => ce.Item == oldItem)) e.Item = newItem; @@ -203,7 +203,7 @@ namespace MonoDevelop.Projects public class SolutionConfigurationEntry { - SolutionEntityItem item; + SolutionItem item; SolutionConfiguration parentConfig; [ItemProperty ("name")] @@ -227,7 +227,7 @@ namespace MonoDevelop.Projects this.deploy = other.deploy; } - internal SolutionConfigurationEntry (SolutionConfiguration parentConfig, SolutionEntityItem item) + internal SolutionConfigurationEntry (SolutionConfiguration parentConfig, SolutionItem item) { this.parentConfig = parentConfig; this.item = item; @@ -258,12 +258,12 @@ namespace MonoDevelop.Projects set { deploy = value; } } - public SolutionEntityItem Item { + public SolutionItem Item { get { if (item == null && parentConfig != null) { Solution sol = parentConfig.ParentSolution; if (sol != null) - item = sol.GetSolutionItem (itemId) as SolutionEntityItem; + item = sol.GetSolutionItem (itemId) as SolutionItem; } return item; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionConfigurationSelector.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionConfigurationSelector.cs index 04beb91589..531bd74947 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionConfigurationSelector.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionConfigurationSelector.cs @@ -48,9 +48,9 @@ namespace MonoDevelop.Projects public override ItemConfiguration GetConfiguration (IConfigurationTarget target) { ItemConfiguration sconf; - if (target is SolutionEntityItem) { + if (target is SolutionItem) { // Get the mapped configuration - SolutionEntityItem item = (SolutionEntityItem) target; + SolutionItem item = (SolutionItem) target; if (item.ParentSolution != null) { SolutionConfiguration config = item.ParentSolution.Configurations [Id]; if (config != null) { diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionEntityItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionEntityItem.cs deleted file mode 100644 index 0698a3fcf3..0000000000 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionEntityItem.cs +++ /dev/null @@ -1,584 +0,0 @@ -// SolutionEntityItem.cs -// -// Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2008 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// - -using System; -using System.Linq; -using System.Xml; -using System.IO; -using System.Collections; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.Collections.Generic; -using System.Reflection; -using System.Diagnostics; -using System.CodeDom.Compiler; - -using MonoDevelop.Core; -using MonoDevelop.Projects; -using MonoDevelop.Core.Serialization; -using MonoDevelop.Projects.Extensions; -using MonoDevelop.Core.StringParsing; - -namespace MonoDevelop.Projects -{ - [ProjectModelDataItem (FallbackType = typeof(UnknownSolutionItem))] - public abstract class SolutionEntityItem : SolutionItem, IConfigurationTarget, IWorkspaceFileObject - { - internal object MemoryProbe = Counters.ItemsInMemory.CreateMemoryProbe (); - - ProjectItemCollection items; - ProjectItemCollection wildcardItems; - ItemCollection<SolutionEntityItem> dependencies = new ItemCollection<SolutionEntityItem> (); - - SolutionItemEventArgs thisItemArgs; - - FileStatusTracker<SolutionItemEventArgs> fileStatusTracker; - - FilePath fileName; - string name; - - FileFormat fileFormat; - - SolutionItemConfiguration activeConfiguration; - SolutionItemConfigurationCollection configurations; - - public event EventHandler ConfigurationsChanged; - public event ConfigurationEventHandler DefaultConfigurationChanged; - public event ConfigurationEventHandler ConfigurationAdded; - public event ConfigurationEventHandler ConfigurationRemoved; - public event EventHandler<ProjectItemEventArgs> ProjectItemAdded; - public event EventHandler<ProjectItemEventArgs> ProjectItemRemoved; - - public SolutionEntityItem () - { - items = new ProjectItemCollection (this); - wildcardItems = new ProjectItemCollection (this); - thisItemArgs = new SolutionItemEventArgs (this); - configurations = new SolutionItemConfigurationCollection (this); - configurations.ConfigurationAdded += new ConfigurationEventHandler (OnConfigurationAddedToCollection); - configurations.ConfigurationRemoved += new ConfigurationEventHandler (OnConfigurationRemovedFromCollection); - Counters.ItemsLoaded++; - fileStatusTracker = new FileStatusTracker<SolutionItemEventArgs> (this, OnReloadRequired, new SolutionItemEventArgs (this)); - } - - public override void Dispose () - { - if (Disposed) - return; - - Counters.ItemsLoaded--; - - foreach (var item in items.Concat (wildcardItems)) { - IDisposable disp = item as IDisposable; - if (disp != null) - disp.Dispose (); - } - - // items = null; - // wildcardItems = null; - // thisItemArgs = null; - // fileStatusTracker = null; - // fileFormat = null; - // activeConfiguration = null; - // configurations = null; - - base.Dispose (); - } - - - internal override void SetItemHandler (ISolutionItemHandler handler) - { - string oldName = Name; - string oldFile = FileName; - - base.SetItemHandler (handler); - - // This will update the name if needed, when SyncFileName is true - Name = oldName; - if (!string.IsNullOrEmpty (oldFile)) - FileName = oldFile; - } - - [ItemProperty ("ReleaseVersion", DefaultValue="0.1")] - string releaseVersion = "0.1"; - - [ItemProperty ("SynchReleaseVersion", DefaultValue = true)] - bool syncReleaseVersion = true; - - public string Version { - get { - // If syncReleaseVersion is set, releaseVersion will already contain the solution's version - // That's because the version must be up to date even when loading the project individually - return releaseVersion; - } - set { - releaseVersion = value; - NotifyModified ("Version"); - } - } - - public bool SyncVersionWithSolution { - get { - return syncReleaseVersion; - } - set { - syncReleaseVersion = value; - if (syncReleaseVersion && ParentSolution != null) - Version = ParentSolution.Version; - NotifyModified ("SyncVersionWithSolution"); - } - } - - [ItemProperty ("name")] - public override string Name { - get { - return name ?? string.Empty; - } - set { - if (name == value) - return; - string oldName = name; - name = value; - if (!Loading && ItemHandler.SyncFileName) { - if (string.IsNullOrEmpty (fileName)) - FileName = value; - else { - string ext = fileName.Extension; - FileName = fileName.ParentDirectory.Combine (value) + ext; - } - } - OnNameChanged (new SolutionItemRenamedEventArgs (this, oldName, name)); - } - } - - public virtual FilePath FileName { - get { - return fileName; - } - set { - fileName = value; - if (FileFormat != null) - fileName = FileFormat.GetValidFileName (this, fileName); - if (ItemHandler.SyncFileName) - Name = fileName.FileNameWithoutExtension; - NotifyModified ("FileName"); - } - } - - public bool Enabled { - get { return ParentSolution != null ? ParentSolution.IsSolutionItemEnabled (FileName) : true; } - set { - if (ParentSolution != null) - ParentSolution.SetSolutionItemEnabled (FileName, value); - } - } - - public FileFormat FileFormat { - get { - if (ParentSolution != null) { - if (ParentSolution.FileFormat.Format.SupportsMixedFormats && fileFormat != null) - return fileFormat; - return ParentSolution.FileFormat; - } - if (fileFormat == null) - fileFormat = Services.ProjectService.GetDefaultFormat (this); - return fileFormat; - } - set { - if (ParentSolution != null && !ParentSolution.FileFormat.Format.SupportsMixedFormats) - throw new InvalidOperationException ("The file format can't be changed when the item belongs to a solution."); - InstallFormat (value); - fileFormat.Format.ConvertToFormat (this); - NeedsReload = false; - NotifyModified ("FileFormat"); - } - } - - public ProjectItemCollection Items { - get { return items; } - } - - internal ProjectItemCollection WildcardItems { - get { return wildcardItems; } - } - - /// <summary> - /// Projects that need to be built before building this one - /// </summary> - /// <value>The dependencies.</value> - public ItemCollection<SolutionEntityItem> ItemDependencies { - get { return dependencies; } - } - - public override IEnumerable<SolutionItem> GetReferencedItems (ConfigurationSelector configuration) - { - return base.GetReferencedItems (configuration).Concat (dependencies); - } - - void IWorkspaceFileObject.ConvertToFormat (FileFormat format, bool convertChildren) - { - this.FileFormat = format; - } - - public virtual bool SupportsFormat (FileFormat format) - { - return true; - } - - internal void InstallFormat (FileFormat format) - { - fileFormat = format; - if (fileName != FilePath.Null) - fileName = fileFormat.GetValidFileName (this, fileName); - } - - protected override void InitializeItemHandler () - { - Services.ProjectService.GetDefaultFormat (this).Format.ConvertToFormat (this); - } - - protected override FilePath GetDefaultBaseDirectory ( ) - { - return FileName.IsNullOrEmpty ? FilePath.Empty : FileName.ParentDirectory; - } - - public void Save (FilePath fileName, IProgressMonitor monitor) - { - FileName = fileName; - Save (monitor); - } - - public override void Save (IProgressMonitor monitor) - { - if (string.IsNullOrEmpty (FileName)) - throw new InvalidOperationException ("Project does not have a file name"); - - try { - fileStatusTracker.BeginSave (); - Services.ProjectService.GetExtensionChain (this).Save (monitor, this); - OnSaved (thisItemArgs); - } finally { - fileStatusTracker.EndSave (); - } - FileService.NotifyFileChanged (FileName); - } - - protected override void OnEndLoad () - { - base.OnEndLoad (); - fileStatusTracker.ResetLoadTimes (); - - if (syncReleaseVersion && ParentSolution != null) - releaseVersion = ParentSolution.Version; - } - - - internal bool IsSaved { - get { - return !string.IsNullOrEmpty (FileName) && File.Exists (FileName); - } - } - - public override bool NeedsReload { - get { return fileStatusTracker.NeedsReload; } - set { fileStatusTracker.NeedsReload = value; } - } - - public virtual bool ItemFilesChanged { - get { return fileStatusTracker.ItemFilesChanged; } - } - - internal protected override BuildResult OnRunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration) - { - if (target == ProjectService.BuildTarget) { - SolutionItemConfiguration conf = GetConfiguration (configuration) as SolutionItemConfiguration; - if (conf != null && conf.CustomCommands.HasCommands (CustomCommandType.Build)) { - conf.CustomCommands.ExecuteCommand (monitor, this, CustomCommandType.Build, configuration); - return new BuildResult (); - } - } else if (target == ProjectService.CleanTarget) { - SolutionItemConfiguration config = GetConfiguration (configuration) as SolutionItemConfiguration; - if (config != null && config.CustomCommands.HasCommands (CustomCommandType.Clean)) { - config.CustomCommands.ExecuteCommand (monitor, this, CustomCommandType.Clean, configuration); - return new BuildResult (); - } - } - return base.OnRunTarget (monitor, target, configuration); - } - - protected internal virtual void OnSave (IProgressMonitor monitor) - { - ItemHandler.Save (monitor); - } - - [Obsolete ("This method will be removed in future releases")] - public void SetNeedsBuilding (bool value) - { - // Nothing to be done - } - - public FilePath GetAbsoluteChildPath (FilePath relPath) - { - return relPath.ToAbsolute (BaseDirectory); - } - - public FilePath GetRelativeChildPath (FilePath absPath) - { - return absPath.ToRelative (BaseDirectory); - } - - public List<FilePath> GetItemFiles (bool includeReferencedFiles) - { - return Services.ProjectService.GetExtensionChain (this).GetItemFiles (this, includeReferencedFiles); - } - - internal protected virtual List<FilePath> OnGetItemFiles (bool includeReferencedFiles) - { - List<FilePath> col = FileFormat.Format.GetItemFiles (this); - if (!string.IsNullOrEmpty (FileName) && !col.Contains (FileName)) - col.Add (FileName); - return col; - } - - protected override void OnNameChanged (SolutionItemRenamedEventArgs e) - { - Solution solution = this.ParentSolution; - - if (solution != null) { - foreach (DotNetProject project in solution.GetAllSolutionItems<DotNetProject>()) { - if (project == this) - continue; - - project.RenameReferences (e.OldName, e.NewName); - } - } - fileStatusTracker.ResetLoadTimes (); - base.OnNameChanged (e); - } - - protected virtual void OnSaved (SolutionItemEventArgs args) - { - if (Saved != null) - Saved (this, args); - } - - public virtual string[] SupportedPlatforms { - get { - return new string [0]; - } - } - - public virtual SolutionItemConfiguration GetConfiguration (ConfigurationSelector configuration) - { - return (SolutionItemConfiguration) configuration.GetConfiguration (this) ?? DefaultConfiguration; - } - - ItemConfiguration IConfigurationTarget.DefaultConfiguration { - get { return DefaultConfiguration; } - set { DefaultConfiguration = (SolutionItemConfiguration) value; } - } - - public SolutionItemConfiguration DefaultConfiguration { - get { - if (activeConfiguration == null && configurations.Count > 0) { - return configurations[0]; - } - return activeConfiguration; - } - set { - if (activeConfiguration != value) { - activeConfiguration = value; - NotifyModified ("DefaultConfiguration"); - OnDefaultConfigurationChanged (new ConfigurationEventArgs (this, value)); - } - } - } - - public string DefaultConfigurationId { - get { - if (DefaultConfiguration != null) - return DefaultConfiguration.Id; - else - return null; - } - set { - DefaultConfiguration = GetConfiguration (new ItemConfigurationSelector (value)); - } - } - - public virtual ReadOnlyCollection<string> GetConfigurations () - { - List<string> configs = new List<string> (); - foreach (SolutionItemConfiguration conf in Configurations) - configs.Add (conf.Id); - return configs.AsReadOnly (); - } - - [ItemProperty ("Configurations")] - [ItemProperty ("Configuration", ValueType=typeof(SolutionItemConfiguration), Scope="*")] - public SolutionItemConfigurationCollection Configurations { - get { - return configurations; - } - } - - IItemConfigurationCollection IConfigurationTarget.Configurations { - get { - return Configurations; - } - } - - public SolutionItemConfiguration AddNewConfiguration (string name) - { - SolutionItemConfiguration config = CreateConfiguration (name); - Configurations.Add (config); - return config; - } - - ItemConfiguration IConfigurationTarget.CreateConfiguration (string name) - { - return CreateConfiguration (name); - } - - public virtual SolutionItemConfiguration CreateConfiguration (string name) - { - return new SolutionItemConfiguration (name); - } - - void OnConfigurationAddedToCollection (object ob, ConfigurationEventArgs args) - { - NotifyModified ("Configurations"); - OnConfigurationAdded (new ConfigurationEventArgs (this, args.Configuration)); - if (ConfigurationsChanged != null) - ConfigurationsChanged (this, EventArgs.Empty); - if (activeConfiguration == null) - DefaultConfigurationId = args.Configuration.Id; - } - - void OnConfigurationRemovedFromCollection (object ob, ConfigurationEventArgs args) - { - if (activeConfiguration == args.Configuration) { - if (Configurations.Count > 0) - DefaultConfiguration = Configurations [0]; - else - DefaultConfiguration = null; - } - NotifyModified ("Configurations"); - OnConfigurationRemoved (new ConfigurationEventArgs (this, args.Configuration)); - if (ConfigurationsChanged != null) - ConfigurationsChanged (this, EventArgs.Empty); - } - - public override StringTagModelDescription GetStringTagModelDescription (ConfigurationSelector conf) - { - StringTagModelDescription model = base.GetStringTagModelDescription (conf); - SolutionItemConfiguration config = GetConfiguration (conf); - if (config != null) - model.Add (config.GetType ()); - else - model.Add (typeof(SolutionItemConfiguration)); - return model; - } - - public override StringTagModel GetStringTagModel (ConfigurationSelector conf) - { - StringTagModel source = base.GetStringTagModel (conf); - SolutionItemConfiguration config = GetConfiguration (conf); - if (config != null) - source.Add (config); - return source; - } - - internal protected virtual void OnItemsAdded (IEnumerable<ProjectItem> objs) - { - NotifyModified ("Items"); - var args = new ProjectItemEventArgs (); - args.AddRange (objs.Select (pi => new ProjectItemEventInfo (this, pi))); - if (ProjectItemAdded != null) - ProjectItemAdded (this, args); - } - - internal protected virtual void OnItemsRemoved (IEnumerable<ProjectItem> objs) - { - NotifyModified ("Items"); - var args = new ProjectItemEventArgs (); - args.AddRange (objs.Select (pi => new ProjectItemEventInfo (this, pi))); - if (ProjectItemRemoved != null) - ProjectItemRemoved (this, args); - } - - protected virtual void OnDefaultConfigurationChanged (ConfigurationEventArgs args) - { - if (DefaultConfigurationChanged != null) - DefaultConfigurationChanged (this, args); - } - - protected virtual void OnConfigurationAdded (ConfigurationEventArgs args) - { - if (ConfigurationAdded != null) - ConfigurationAdded (this, args); - } - - protected virtual void OnConfigurationRemoved (ConfigurationEventArgs args) - { - if (ConfigurationRemoved != null) - ConfigurationRemoved (this, args); - } - - protected virtual void OnReloadRequired (SolutionItemEventArgs args) - { - fileStatusTracker.FireReloadRequired (args); - } - - public event SolutionItemEventHandler Saved; - -/* public event EventHandler<SolutionItemEventArgs> ReloadRequired { - add { fileStatusTracker.ReloadRequired += value; } - remove { fileStatusTracker.ReloadRequired -= value; } - } -*/ } - - [Mono.Addins.Extension] - class SolutionEntityItemTagProvider: StringTagProvider<SolutionEntityItem>, IStringTagProvider - { - public override IEnumerable<StringTagDescription> GetTags () - { - yield return new StringTagDescription ("ProjectFile", "Project File"); - } - - public override object GetTagValue (SolutionEntityItem item, string tag) - { - switch (tag) { - case "ITEMFILE": - case "PROJECTFILE": - case "PROJECTFILENAME": - return item.FileName; - } - throw new NotSupportedException (); - } - } -} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionExtension.cs new file mode 100644 index 0000000000..4da2bdf7d0 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionExtension.cs @@ -0,0 +1,89 @@ +// +// SolutionExtension.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using MonoDevelop.Core; +using MonoDevelop.Core.Execution; +using System.Collections.Generic; +using System.Threading.Tasks; +using MonoDevelop.Projects.Formats.MSBuild; + +namespace MonoDevelop.Projects +{ + public class SolutionExtension: WorkspaceItemExtension + { + SolutionExtension next; + + protected Solution Solution { + get { return (Solution) base.Item; } + } + + internal protected override bool SupportsItem (WorkspaceItem item) + { + return item is Solution; + } + + internal protected virtual Task<BuildResult> Build (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return next.Build (monitor, configuration); + } + + internal protected virtual Task<BuildResult> Clean (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return next.Clean (monitor, configuration); + } + + internal protected virtual Task Execute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + { + return next.Execute (monitor, context, configuration); + } + + internal protected virtual bool CanExecute (ExecutionContext context, ConfigurationSelector configuration) + { + return next.CanExecute (context, configuration); + } + + internal protected virtual IEnumerable<ExecutionTarget> GetExecutionTargets (Solution solution, ConfigurationSelector configuration) + { + return next.GetExecutionTargets (solution, configuration); + } + + internal protected virtual bool NeedsBuilding (ConfigurationSelector configuration) + { + return next.NeedsBuilding (configuration); + } + + internal protected virtual void OnReadSolution (ProgressMonitor monitor, SlnFile file) + { + next.OnReadSolution (monitor, file); + } + + internal protected virtual void OnWriteSolution (ProgressMonitor monitor, SlnFile file) + { + next.OnWriteSolution (monitor, file); + } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolder.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolder.cs index d4f9cb7e91..15942ba39c 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolder.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolder.cs @@ -45,11 +45,12 @@ using MonoDevelop.Core.ProgressMonitoring; using MonoDevelop.Projects; using MonoDevelop.Projects.Extensions; using MonoDevelop.Core.Serialization; +using System.Threading.Tasks; namespace MonoDevelop.Projects { [DataInclude (typeof(SolutionConfiguration))] - public class SolutionFolder : SolutionItem + public class SolutionFolder : SolutionFolderItem { SolutionFolderItemCollection items; SolutionFolderFileCollection files; @@ -67,6 +68,11 @@ namespace MonoDevelop.Projects } } + protected override IEnumerable<WorkspaceObject> OnGetChildren () + { + return Items; + } + internal SolutionFolderItemCollection GetItemsWithoutCreating () { return items; @@ -86,20 +92,17 @@ namespace MonoDevelop.Projects get { return ParentFolder == null; } } - public override string Name { - get { - if (ParentFolder == null && ParentSolution != null) - return ParentSolution.Name; - else - return name; - } - set { - if (value != name) { - string oldName = name; - name = value; - OnNameChanged (new SolutionItemRenamedEventArgs (this, oldName, name)); - } - } + protected override string OnGetName () + { + if (ParentFolder == null && ParentSolution != null) + return ParentSolution.Name; + else + return name; + } + + protected override void OnSetName (string value) + { + name = value; }
protected override FilePath GetDefaultBaseDirectory ( ) @@ -136,7 +139,7 @@ namespace MonoDevelop.Projects {
FilePath path = null; - foreach (SolutionItem it in Items) {
+ foreach (SolutionFolderItem it in Items) {
FilePath subdir; if (it is SolutionFolder) { SolutionFolder sf = (SolutionFolder) it; @@ -184,25 +187,19 @@ namespace MonoDevelop.Projects else return null; } - - internal override IDictionary InternalGetExtendedProperties { - get { - if (ParentSolution != null && ParentFolder == null) - return ParentSolution.ExtendedProperties; - else - return base.InternalGetExtendedProperties; - } - } - - protected override void InitializeItemHandler () + + protected override IDictionary OnGetExtendedProperties () { - SetItemHandler (new DummySolutionFolderHandler (this)); + if (ParentSolution != null && ParentFolder == null) + return ParentSolution.ExtendedProperties; + else + return base.OnGetExtendedProperties (); } - + public override void Dispose() { if (items != null) { - foreach (SolutionItem e in items) + foreach (SolutionFolderItem e in items) e.Dispose (); items = null; } @@ -210,30 +207,25 @@ namespace MonoDevelop.Projects base.Dispose (); } - public SolutionItem ReloadItem (IProgressMonitor monitor, SolutionItem sitem) + public async Task<SolutionFolderItem> ReloadItem (ProgressMonitor monitor, SolutionFolderItem sitem) { if (Items.IndexOf (sitem) == -1) throw new InvalidOperationException ("Solution item '" + sitem.Name + "' does not belong to folder '" + Name + "'"); - SolutionEntityItem item = sitem as SolutionEntityItem; + SolutionItem item = sitem as SolutionItem; if (item != null) { // Load the new item - SolutionEntityItem newItem; + SolutionItem newItem; try { if (ParentSolution.IsSolutionItemEnabled (item.FileName)) - newItem = Services.ProjectService.ReadSolutionItem (monitor, item.FileName); + newItem = await Services.ProjectService.ReadSolutionItem (monitor, item.FileName); else { UnknownSolutionItem e = new UnloadedSolutionItem () { FileName = item.FileName }; - var ch = item.GetItemHandler () as MonoDevelop.Projects.Formats.MSBuild.MSBuildHandler; - if (ch != null) { - var h = new MonoDevelop.Projects.Formats.MSBuild.MSBuildHandler (ch.TypeGuid, ch.ItemId) { - Item = e, - }; - e.SetItemHandler (h); - } + e.ItemId = item.ItemId; + e.TypeGuid = item.TypeGuid; newItem = e; } } catch (Exception ex) { @@ -249,7 +241,7 @@ namespace MonoDevelop.Projects newItem.Dispose (); // Find the replacement if it exists - return Items.OfType<SolutionEntityItem> ().FirstOrDefault (it => it.FileName == item.FileName); + return Items.OfType<SolutionItem> ().FirstOrDefault (it => it.FileName == item.FileName); } // Replace in the file list @@ -269,7 +261,7 @@ namespace MonoDevelop.Projects return sitem; } - internal void NotifyItemAdded (SolutionItem item, bool newToSolution) + internal void NotifyItemAdded (SolutionFolderItem item, bool newToSolution) { ConnectChildEntryEvents (item); @@ -277,7 +269,7 @@ namespace MonoDevelop.Projects OnItemAdded (new SolutionItemChangeEventArgs (item, ParentSolution, false), newToSolution); } - void ConnectChildEntryEvents (SolutionItem item) + void ConnectChildEntryEvents (SolutionFolderItem item) { if (item is Project) { Project project = item as Project; @@ -303,42 +295,36 @@ namespace MonoDevelop.Projects folder.ReferenceAddedToProject += NotifyReferenceAddedToProject; } - if (item is SolutionEntityItem) { - ((SolutionEntityItem)item).Saved += NotifyItemSaved; + if (item is SolutionItem) { + ((SolutionItem)item).Saved += NotifyItemSaved; // ((SolutionEntityItem)item).ReloadRequired += NotifyItemReloadRequired; } item.Modified += NotifyItemModified; } - public override void Save (IProgressMonitor monitor) - { - foreach (SolutionItem item in Items) - item.Save (monitor); - } - - public SolutionEntityItem AddItem (IProgressMonitor monitor, string filename) + public Task<SolutionItem> AddItem (ProgressMonitor monitor, string filename) { return AddItem (monitor, filename, false); } - public SolutionEntityItem AddItem (IProgressMonitor monitor, string filename, bool createSolutionConfigurations) + public async Task<SolutionItem> AddItem (ProgressMonitor monitor, string filename, bool createSolutionConfigurations) { - if (monitor == null) monitor = new NullProgressMonitor (); - SolutionEntityItem entry = Services.ProjectService.ReadSolutionItem (monitor, filename); + if (monitor == null) monitor = new ProgressMonitor (); + SolutionItem entry = await Services.ProjectService.ReadSolutionItem (monitor, filename); AddItem (entry, createSolutionConfigurations); return entry; } - public void AddItem (SolutionItem item) + public void AddItem (SolutionFolderItem item) { AddItem (item, false); } - public void AddItem (SolutionItem item, bool createSolutionConfigurations) + public void AddItem (SolutionFolderItem item, bool createSolutionConfigurations) { Items.Add (item); - SolutionEntityItem eitem = item as SolutionEntityItem; + SolutionItem eitem = item as SolutionItem; if (eitem != null && createSolutionConfigurations && eitem.SupportsBuild ()) { // Create new solution configurations for item configurations foreach (ItemConfiguration iconf in eitem.Configurations) { @@ -352,7 +338,7 @@ namespace MonoDevelop.Projects if (!found) { SolutionConfiguration sconf = new SolutionConfiguration (iconf.Id); // Add all items to the new configuration - foreach (var it in ParentSolution.GetAllSolutionItems<SolutionEntityItem> ()) + foreach (var it in ParentSolution.GetAllItems<SolutionItem> ()) sconf.AddItem (it); ParentSolution.Configurations.Add (sconf); } @@ -360,14 +346,14 @@ namespace MonoDevelop.Projects } } - internal void NotifyItemRemoved (SolutionItem item, bool removedFromSolution) + internal void NotifyItemRemoved (SolutionFolderItem item, bool removedFromSolution) { DisconnectChildEntryEvents (item); NotifyModified ("Items"); OnItemRemoved (new SolutionItemChangeEventArgs (item, ParentSolution, false), removedFromSolution); } - void DisconnectChildEntryEvents (SolutionItem entry) + void DisconnectChildEntryEvents (SolutionFolderItem entry) { if (entry is Project) { Project pce = entry as Project; @@ -393,35 +379,29 @@ namespace MonoDevelop.Projects cce.ReferenceAddedToProject -= NotifyReferenceAddedToProject; } - if (entry is SolutionEntityItem) { - ((SolutionEntityItem)entry).Saved -= NotifyItemSaved; + if (entry is SolutionItem) { + ((SolutionItem)entry).Saved -= NotifyItemSaved; // ((SolutionEntityItem)entry).ReloadRequired -= NotifyItemReloadRequired; } entry.Modified -= NotifyItemModified; } - protected internal override void OnExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + public void Execute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { } - - /// <remarks> - /// Returns a collection containing all entries in this folder and - /// undercombines - /// </remarks> - public ReadOnlyCollection<SolutionItem> GetAllItems () + + public bool CanExecute (ExecutionContext context, ConfigurationSelector configuration) { - return GetAllItems<SolutionItem> (); + return false; } - + /// <remarks> - /// Returns a collection containing all entries of the given type in this folder and + /// Returns a collection containing all entries in this folder and /// undercombines /// </remarks> - public ReadOnlyCollection<T> GetAllItems<T> () where T: SolutionItem + public IEnumerable<SolutionFolderItem> GetAllItems () { - List<T> list = new List<T> (); - GetAllItems<T> (list, this); - return list.AsReadOnly (); + return GetAllItems<SolutionFolderItem> (); } public ReadOnlyCollection<T> GetAllItemsWithTopologicalSort<T> (ConfigurationSelector configuration) where T: SolutionItem @@ -447,24 +427,24 @@ namespace MonoDevelop.Projects return SolutionItem.TopologicalSort<Project> (list, configuration); } - void GetAllItems<T> (List<T> list, SolutionItem item) where T: SolutionItem + void GetAllItems<T> (List<T> list, SolutionFolderItem item) where T: SolutionFolderItem { if (item is T) { list.Add ((T)item); } if (item is SolutionFolder) { - foreach (SolutionItem ce in ((SolutionFolder)item).Items) + foreach (SolutionFolderItem ce in ((SolutionFolder)item).Items) GetAllItems<T> (list, ce); } } public ReadOnlyCollection<SolutionItem> GetAllBuildableEntries (ConfigurationSelector configuration, bool topologicalSort, bool includeExternalReferences) { - List<SolutionItem> list = new List<SolutionItem> (); + var list = new List<SolutionItem> (); GetAllBuildableEntries (list, configuration, includeExternalReferences); if (topologicalSort) - return TopologicalSort<SolutionItem> (list, configuration); + return SolutionItem.TopologicalSort<SolutionItem> (list, configuration); else return list.AsReadOnly (); } @@ -482,22 +462,25 @@ namespace MonoDevelop.Projects if (conf == null) return; - foreach (SolutionItem item in Items) { + foreach (SolutionFolderItem item in Items) { if (item is SolutionFolder) ((SolutionFolder)item).GetAllBuildableEntries (list, configuration, includeExternalReferences); - else if ((item is SolutionEntityItem) && conf.BuildEnabledForItem ((SolutionEntityItem) item) && item.SupportsBuild ()) - GetAllBuildableReferences (list, item, configuration, includeExternalReferences); + else if ((item is SolutionItem) && conf.BuildEnabledForItem ((SolutionItem) item) && ((SolutionItem)item).SupportsBuild ()) + GetAllBuildableReferences (list, (SolutionItem)item, configuration, includeExternalReferences, false); } } - void GetAllBuildableReferences (List<SolutionItem> list, SolutionItem item, ConfigurationSelector configuration, bool includeExternalReferences) + void GetAllBuildableReferences (List<SolutionItem> list, SolutionItem item, ConfigurationSelector configuration, bool includeExternalReferences, bool isDirectReference) { if (list.Contains (item)) return; + // Skip unsupported projects which are not directly referenced by other (supported) projects + if (!isDirectReference && item.IsUnsupportedProject) + return; list.Add (item); if (includeExternalReferences) { - foreach (SolutionItem it in item.GetReferencedItems (configuration)) - GetAllBuildableReferences (list, it, configuration, includeExternalReferences); + foreach (var it in item.GetReferencedItems (configuration)) + GetAllBuildableReferences (list, it, configuration, includeExternalReferences, true); } } @@ -538,19 +521,19 @@ namespace MonoDevelop.Projects } } - public SolutionEntityItem FindSolutionItem (string fileName) + public SolutionItem FindSolutionItem (string fileName) { string path = Path.GetFullPath (fileName); - foreach (SolutionItem it in Items) { + foreach (SolutionFolderItem it in Items) { if (it is SolutionFolder) { - SolutionEntityItem r = ((SolutionFolder)it).FindSolutionItem (fileName); + SolutionItem r = ((SolutionFolder)it).FindSolutionItem (fileName); if (r != null) return r; } - else if (it is SolutionEntityItem) { - SolutionEntityItem se = (SolutionEntityItem) it; + else if (it is SolutionItem) { + SolutionItem se = (SolutionItem) it; if (!string.IsNullOrEmpty (se.FileName) && path == Path.GetFullPath (se.FileName)) - return (SolutionEntityItem) it; + return (SolutionItem) it; } } return null; @@ -558,7 +541,7 @@ namespace MonoDevelop.Projects public Project FindProjectByName (string name) { - foreach (SolutionItem it in Items) { + foreach (SolutionFolderItem it in Items) { if (it is SolutionFolder) { Project r = ((SolutionFolder)it).FindProjectByName (name); if (r != null) @@ -572,85 +555,42 @@ namespace MonoDevelop.Projects return null; } - protected internal override BuildResult OnRunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration) + public async Task<BuildResult> Clean (ProgressMonitor monitor, ConfigurationSelector configuration) { - if (target == ProjectService.BuildTarget) - return OnBuild (monitor, configuration); - else if (target == ProjectService.CleanTarget) { - OnClean (monitor, configuration); + if (ParentSolution == null) return new BuildResult (); - } - + SolutionConfiguration conf = ParentSolution.GetConfiguration (configuration); + if (conf == null) + return new BuildResult (); + + var res = new BuildResult { BuildCount = 0 }; + ReadOnlyCollection<SolutionItem> allProjects; - try { allProjects = GetAllBuildableEntries (configuration, true, true); } catch (CyclicDependencyException) { monitor.ReportError (GettextCatalog.GetString ("Cyclic dependencies are not supported."), null); return new BuildResult ("", 1, 1); } - - try { - monitor.BeginTask (GettextCatalog.GetString ("Building Solution: {0} ({1})", Name, configuration.ToString ()), allProjects.Count); - - BuildResult cres = new BuildResult (); - cres.BuildCount = 0; - HashSet<SolutionItem> failedItems = new HashSet<SolutionItem> (); - - foreach (SolutionItem item in allProjects) { - if (monitor.IsCancelRequested) - break; - if (!item.ContainsReferences (failedItems, configuration)) { - BuildResult res = item.RunTarget (monitor, target, configuration); - if (res != null) { - cres.Append (res); - if (res.ErrorCount > 0) - failedItems.Add (item); - } - } else - failedItems.Add (item); - monitor.Step (1); - } - return cres; - } finally { - monitor.EndTask (); - } - } - - protected override void OnClean (IProgressMonitor monitor, ConfigurationSelector configuration) - { - if (ParentSolution == null) - return; - SolutionConfiguration conf = ParentSolution.GetConfiguration (configuration); - if (conf == null) - return; - + monitor.BeginTask (GettextCatalog.GetString ("Cleaning Solution: {0} ({1})", Name, configuration.ToString ()), allProjects.Count); try { - monitor.BeginTask (GettextCatalog.GetString ("Cleaning Solution: {0} ({1})", Name, configuration.ToString ()), Items.Count); - - foreach (SolutionItem item in Items) { - if (item is SolutionFolder) - item.Clean (monitor, configuration); - else if (item is SolutionEntityItem) { - SolutionEntityItem si = (SolutionEntityItem) item; - // ce can be null if you add items to the root solution folder which - // causes them to be placed in an autogenerated 'Project Items' folder - SolutionConfigurationEntry ce = conf.GetEntryForItem (si); - if (ce != null && ce.Build) - si.Clean (monitor, ce.ItemConfigurationSelector); - } else { - item.Clean (monitor, configuration); - } + foreach (var si in allProjects) { + // ce can be null if you add items to the root solution folder which + // causes them to be placed in an autogenerated 'Project Items' folder + SolutionConfigurationEntry ce = conf.GetEntryForItem (si); + if (ce != null && ce.Build) + res.Append (await si.Clean (monitor, ce.ItemConfigurationSelector)); monitor.Step (1); } } finally { monitor.EndTask (); } + return res; } - protected override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration) + public async Task<BuildResult> Build (ProgressMonitor monitor, ConfigurationSelector configuration, bool buildReferencedTargets = false) { ReadOnlyCollection<SolutionItem> allProjects; @@ -671,11 +611,11 @@ namespace MonoDevelop.Projects HashSet<SolutionItem> failedItems = new HashSet<SolutionItem> (); foreach (SolutionItem item in toBuild) { - if (monitor.IsCancelRequested) + if (monitor.CancellationToken.IsCancellationRequested) break; if (!item.ContainsReferences (failedItems, configuration)) { - BuildResult res = item.Build (monitor, configuration, false); + BuildResult res = await item.Build (monitor, configuration, false); if (res != null) { cres.Append (res); if (res.ErrorCount > 0) @@ -691,12 +631,17 @@ namespace MonoDevelop.Projects } } + public bool NeedsBuilding (ConfigurationSelector configuration) + { + return Items.OfType<IBuildTarget>().Any (t => t.NeedsBuilding (configuration)); + } + protected internal override DateTime OnGetLastBuildTime (ConfigurationSelector configuration) { // Return the min value, since that the last time all items in the // folder were built DateTime tim = DateTime.MaxValue; - foreach (SolutionItem it in Items) { + foreach (SolutionFolderItem it in Items) { DateTime t = it.GetLastBuildTime (configuration); if (t < tim) tim = t; @@ -1020,12 +965,12 @@ namespace MonoDevelop.Projects get { return folder.Name; } } - public BuildResult RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration) + public Task<BuildResult> RunTarget (ProgressMonitor monitor, string target, ConfigurationSelector configuration) { throw new NotImplementedException (); } - public void Save (IProgressMonitor monitor) + public Task Save (ProgressMonitor monitor) { throw new NotImplementedException (); } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolderItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolderItem.cs new file mode 100644 index 0000000000..9dd7b25a7d --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolderItem.cs @@ -0,0 +1,549 @@ +// SolutionItem.cs +// +// Author: +// Lluis Sanchez Gual <lluis@novell.com> +// +// Copyright (c) 2008 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// + +using System; +using System.Collections; +using System.Xml; +using MonoDevelop.Core; +using MonoDevelop.Core.Serialization; +using MonoDevelop.Projects.Extensions;
+using MonoDevelop.Core.StringParsing; +using MonoDevelop.Projects.Policies; +using System.Collections.Generic; +using MonoDevelop.Projects.Formats.MSBuild; + +namespace MonoDevelop.Projects +{ + public abstract class SolutionFolderItem: WorkspaceObject, IExtendedDataItem, IPolicyProvider + { + SolutionFolder parentFolder; + Solution parentSolution; + SolutionFolder internalChildren; + + [ProjectPathItemProperty ("BaseDirectory", DefaultValue=null)] + string baseDirectory; + + [ItemProperty ("Policies", IsExternal = true, SkipEmpty = true)] + PolicyBag policies; + + [ItemProperty ("UseMSBuildEngine")] + public bool? UseMSBuildEngine { get; set; } + + PropertyBag userProperties; + + internal List<string> UnresolvedProjectDependencies { get; set; } + + [ItemProperty ("name")] + public new string Name { + get { + return base.Name; + } + set { + if (value != Name) { + var oldName = Name; + OnSetName (value); + OnNameChanged (new SolutionItemRenamedEventArgs (this, oldName, Name)); + } + } + } + + public string TypeGuid { + get; + set; + } + + protected abstract void OnSetName (string value); + + /// <summary> + /// Gets the solution to which this item belongs + /// </summary> + public Solution ParentSolution { + get { + if (parentFolder != null) + return parentFolder.ParentSolution; + return parentSolution; + } + internal set { + if (parentSolution != null && parentSolution != value) + NotifyUnboundFromSolution (true); + parentSolution = value; + NotifyBoundToSolution (true); + } + } + + /// <summary> + /// Gets or sets the base directory of this solution item + /// </summary> + /// <value> + /// The base directory. + /// </value> + /// <remarks> + /// The base directory is the directory where files belonging to this project + /// are placed. Notice that this directory may be different than the directory + /// where the project file is placed. + /// </remarks> + public new FilePath BaseDirectory { + get { + if (baseDirectory == null) {
+ FilePath dir = GetDefaultBaseDirectory (); + if (dir.IsNullOrEmpty) + dir = "."; + return dir.FullPath; + } + else + return baseDirectory; + } + set {
+ FilePath def = GetDefaultBaseDirectory (); + if (value != FilePath.Null && def != FilePath.Null && value.FullPath == def.FullPath) + baseDirectory = null; + else if (string.IsNullOrEmpty (value)) + baseDirectory = null; + else + baseDirectory = value.FullPath; + NotifyModified ("BaseDirectory"); + } + } + + protected override string OnGetBaseDirectory () + { + return BaseDirectory; + } + + protected override string OnGetItemDirectory () + { + FilePath dir = GetDefaultBaseDirectory (); + if (string.IsNullOrEmpty (dir)) + dir = "."; + return dir.FullPath; + } + + internal bool HasCustomBaseDirectory { + get { return baseDirectory != null; } + }
+ + /// <summary> + /// Gets the default base directory. + /// </summary> + /// <remarks> + /// The base directory is the directory where files belonging to this project + /// are placed. Notice that this directory may be different than the directory + /// where the project file is placed. + /// </remarks> + protected virtual FilePath GetDefaultBaseDirectory ( ) + { + return ParentSolution.BaseDirectory; + } + + /// <summary> + /// Gets the identifier of this solution item + /// </summary> + /// <remarks> + /// The identifier is unique inside the solution + /// </remarks> + public string ItemId { + get { + if (itemId == null) + itemId = "{" + Guid.NewGuid ().ToString ().ToUpper () + "}"; + return itemId; + } + set { + itemId = value; + } + } + + string itemId; + + /// <summary> + /// Gets policies. + /// </summary> + /// <remarks> + /// Returns a policy container which can be used to query policies specific for this + /// solution item. If a policy is not defined for this item, the inherited value will be returned. + /// </remarks> + public PolicyBag Policies { + get { + //newly created (i.e. not deserialised) SolutionItems may have a null PolicyBag + if (policies == null) + policies = new MonoDevelop.Projects.Policies.PolicyBag (); + //this is the easiest reliable place to associate a deserialised Policybag with its owner + policies.Owner = this; + return policies; + } + //setter so that a solution can deserialise the PropertyBag on its RootFolder + internal set { + policies = value; + } + } + + PolicyContainer IPolicyProvider.Policies { + get { + return Policies; + } + } + + /// <summary> + /// Gets solution item properties specific to the current user + /// </summary> + /// <remarks> + /// These properties are not stored in the project file, but in a separate file which is not to be shared + /// with other users. + /// User properties are only loaded when the project is loaded inside the IDE. + /// </remarks> + public PropertyBag UserProperties { + get { + if (userProperties == null) + userProperties = new PropertyBag (); + return userProperties; + } + } + + /// <summary> + /// Initializes the user properties of the item + /// </summary> + /// <param name='properties'> + /// Properties to be set + /// </param> + /// <exception cref='InvalidOperationException'> + /// The user properties have already been set + /// </exception> + /// <remarks> + /// This method is used by the IDE to initialize the user properties when a project is loaded. + /// </remarks> + public void LoadUserProperties (PropertyBag properties) + { + if (userProperties != null) + throw new InvalidOperationException ("User properties already loaded."); + userProperties = properties; + } + + /// <summary> + /// Gets the parent solution folder. + /// </summary> + public SolutionFolder ParentFolder { + get { + return parentFolder; + } + internal set { + if (parentFolder != null && parentFolder.ParentSolution != null && (value == null || value.ParentSolution != parentFolder.ParentSolution)) + NotifyUnboundFromSolution (false); + + parentFolder = value; + if (internalChildren != null) { + internalChildren.ParentFolder = value; + } + if (value != null && value.ParentSolution != null) { + NotifyBoundToSolution (false); + } + } + } + + // Normally, the ParentFolder setter fires OnBoundToSolution. However, when deserializing, child + // ParentFolder hierarchies can become connected before the ParentSolution becomes set. This method + // enables us to recursively fire the OnBoundToSolution call in those cases. + void NotifyBoundToSolution (bool includeInternalChildren) + { + var folder = this as SolutionFolder; + if (folder != null) { + var items = folder.GetItemsWithoutCreating (); + if (items != null) { + foreach (var item in items) { + item.NotifyBoundToSolution (true); + } + } + } + if (includeInternalChildren && internalChildren != null) { + internalChildren.NotifyBoundToSolution (true); + } + OnBoundToSolution (); + } + + void NotifyUnboundFromSolution (bool includeInternalChildren) + { + var folder = this as SolutionFolder; + if (folder != null) { + var items = folder.GetItemsWithoutCreating (); + if (items != null) { + foreach (var item in items) { + item.NotifyUnboundFromSolution (true); + } + } + } + if (includeInternalChildren && internalChildren != null) { + internalChildren.NotifyUnboundFromSolution (true); + } + OnUnboundFromSolution (); + } + + /// <summary> + /// Releases all resource used by the <see cref="MonoDevelop.Projects.SolutionItem"/> object. + /// </summary> + /// <remarks> + /// Call <see cref="Dispose"/> when you are finished using the <see cref="MonoDevelop.Projects.SolutionItem"/>. The + /// <see cref="Dispose"/> method leaves the <see cref="MonoDevelop.Projects.SolutionItem"/> in an unusable state. + /// After calling <see cref="Dispose"/>, you must release all references to the + /// <see cref="MonoDevelop.Projects.SolutionItem"/> so the garbage collector can reclaim the memory that the + /// <see cref="MonoDevelop.Projects.SolutionItem"/> was occupying. + /// </remarks> + public override void Dispose () + { + base.Dispose (); + + if (userProperties != null) { + ((IDisposable)userProperties).Dispose (); + userProperties = null; + } + + // parentFolder = null; + // parentSolution = null; + // internalChildren = null; + // policies = null; + } + + /// <summary> + /// Gets the time of the last build + /// </summary> + /// <returns> + /// The last build time. + /// </returns> + /// <param name='configuration'> + /// Configuration for which to get the last build time. + /// </param> + public DateTime GetLastBuildTime (ConfigurationSelector configuration) + { + return OnGetLastBuildTime (configuration); + } + + /// <summary> + /// Gets or sets a value indicating whether this <see cref="MonoDevelop.Projects.SolutionItem"/> needs to be reload due to changes in project or solution file + /// </summary> + /// <value> + /// <c>true</c> if needs reload; otherwise, <c>false</c>. + /// </value> + public virtual bool NeedsReload { + get { + if (ParentSolution != null) + return ParentSolution.NeedsReload; + else + return false; + } + set { + } + } + + /// <summary> + /// Registers an internal child item. + /// </summary> + /// <param name='item'> + /// An item + /// </param> + /// <remarks> + /// Some kind of projects may be composed of several child projects. + /// By registering those child projects using this method, the child + /// projects will be plugged into the parent solution infrastructure + /// (so for example, the ParentSolution property for those projects + /// will return the correct value) + /// </remarks> + protected void RegisterInternalChild (SolutionFolderItem item) + { + if (internalChildren == null) { + internalChildren = new SolutionFolder (); + internalChildren.ParentFolder = parentFolder; + } + internalChildren.Items.Add (item); + } + + /// <summary> + /// Unregisters an internal child item. + /// </summary> + /// <param name='item'> + /// The item + /// </param> + protected void UnregisterInternalChild (SolutionFolderItem item) + { + if (internalChildren != null) + internalChildren.Items.Remove (item); + } + + /// <summary> + /// Gets the string tag model description for this solution item + /// </summary> + /// <returns> + /// The string tag model description + /// </returns> + /// <param name='conf'> + /// Configuration for which to get the string tag model description + /// </param> + public virtual StringTagModelDescription GetStringTagModelDescription (ConfigurationSelector conf) + { + StringTagModelDescription model = new StringTagModelDescription (); + model.Add (GetType ()); + model.Add (typeof(Solution)); + return model; + } + + /// <summary> + /// Gets the string tag model for this solution item + /// </summary> + /// <returns> + /// The string tag model + /// </returns> + /// <param name='conf'> + /// Configuration for which to get the string tag model + /// </param> + public virtual StringTagModel GetStringTagModel (ConfigurationSelector conf) + { + StringTagModel source = new StringTagModel (); + source.Add (this); + if (ParentSolution != null) + source.Add (ParentSolution.GetStringTagModel ()); + return source; + } + + /// <summary> + /// Gets the author information for this solution item, inherited from the solution and global settings. + /// </summary> + public AuthorInformation AuthorInformation { + get { + if (ParentSolution != null) + return ParentSolution.AuthorInformation; + else + return AuthorInformation.Default; + } + } + + internal MSBuildFileFormat SolutionFormat { get; private set; } + + internal virtual void SetSolutionFormat (MSBuildFileFormat format, bool converting) + { + this.SolutionFormat = format; + } + + public virtual bool HasSlnData { + get { return false; } + } + + DataItem customSlnData; + + public virtual DataItem WriteSlnData () + { + return customSlnData; + } + + public virtual void ReadSlnData (DataItem item) + { + customSlnData = item; + } + + /// <summary> + /// Notifies that this solution item has been modified + /// </summary> + /// <param name='hint'> + /// Hint about which part of the solution item has been modified. This will typically be the property name. + /// </param> + public void NotifyModified (string hint) + { + OnModified (new SolutionItemModifiedEventArgs (this, hint)); + } + + /// <summary> + /// Raises the modified event. + /// </summary> + /// <param name='args'> + /// Arguments. + /// </param> + protected virtual void OnModified (SolutionItemModifiedEventArgs args) + { + if (Modified != null && !Disposed) + Modified (this, args); + } + + /// <summary> + /// Raises the name changed event. + /// </summary> + /// <param name='e'> + /// Arguments. + /// </param> + protected virtual void OnNameChanged (SolutionItemRenamedEventArgs e) + { + NotifyModified ("Name"); + if (NameChanged != null && !Disposed) + NameChanged (this, e); + } + + /// <summary> + /// Initializes the item handler. + /// </summary> + /// <remarks> + /// This method is called the first time an item handler is requested. + /// Subclasses should override this method use SetItemHandler to + /// assign a handler to this item. + /// </remarks> + protected virtual void InitializeItemHandler () + { + } + + /// <summary> + /// Gets the time of the last build + /// </summary> + /// <returns> + /// The last build time. + /// </returns> + /// <param name='configuration'> + /// Configuration for which to get the last build time. + /// </param> + internal protected virtual DateTime OnGetLastBuildTime (ConfigurationSelector configuration) + { + return DateTime.MinValue; + } + + /// <summary> + /// Called just after this item is bound to a solution + /// </summary> + protected virtual void OnBoundToSolution () + { + } + + /// <summary> + /// Called just before this item is removed from a solution (ParentSolution is still valid when this method is called) + /// </summary> + protected virtual void OnUnboundFromSolution () + { + } + + /// <summary> + /// Occurs when the name of the item changes + /// </summary> + public event SolutionItemRenamedEventHandler NameChanged; + + /// <summary> + /// Occurs when the item is modified. + /// </summary> + public event SolutionItemModifiedEventHandler Modified; + } + +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolderItemCollection.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolderItemCollection.cs index e6704c7a57..81b85305e1 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolderItemCollection.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolderItemCollection.cs @@ -30,7 +30,7 @@ using System.Collections.ObjectModel; namespace MonoDevelop.Projects { - public class SolutionFolderItemCollection: ItemCollection<SolutionItem> + public class SolutionFolderItemCollection: ItemCollection<SolutionFolderItem> { SolutionFolder parentFolder; @@ -43,14 +43,14 @@ namespace MonoDevelop.Projects this.parentFolder = parentFolder; } - internal void Replace (SolutionItem item, SolutionItem newItem) + internal void Replace (SolutionFolderItem item, SolutionFolderItem newItem) { int i = IndexOf (item); Items [i] = newItem; newItem.ParentFolder = parentFolder; } - protected override void OnItemAdded (SolutionItem item) + protected override void OnItemAdded (SolutionFolderItem item) { if (parentFolder != null) { // If the item belongs to another solution, remove it from there. @@ -74,7 +74,7 @@ namespace MonoDevelop.Projects } } - protected override void OnItemRemoved (SolutionItem item) + protected override void OnItemRemoved (SolutionFolderItem item) { if (parentFolder != null) { item.ParentFolder = null; @@ -82,12 +82,12 @@ namespace MonoDevelop.Projects } } - internal void InternalAdd (SolutionItem item) + internal void InternalAdd (SolutionFolderItem item) { Items.Add (item); } - internal void InternalRemove (SolutionItem item) + internal void InternalRemove (SolutionFolderItem item) { Items.Remove (item); } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs index 3dd753efab..4cf410e674 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs @@ -1,4 +1,4 @@ -// SolutionItem.cs +// SolutionEntityItem.cs // // Author: // Lluis Sanchez Gual <lluis@novell.com> @@ -26,419 +26,301 @@ // using System; +using System.Linq; +using System.Xml; +using System.IO; using System.Collections; -using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Xml; +using System.Collections.Specialized; +using System.Collections.Generic; +using System.Reflection; +using System.Diagnostics; using System.CodeDom.Compiler; + using MonoDevelop.Core; +using MonoDevelop.Projects; using MonoDevelop.Core.Serialization; -using MonoDevelop.Projects.Extensions;
-using MonoDevelop.Core.Collections; +using MonoDevelop.Projects.Extensions; using MonoDevelop.Core.StringParsing; -using MonoDevelop.Core.Instrumentation; -using MonoDevelop.Projects.Policies; using MonoDevelop.Core.Execution; +using Mono.Addins; +using MonoDevelop.Core.Instrumentation; +using MonoDevelop.Core.Collections; +using System.Threading.Tasks; +using MonoDevelop.Projects.Formats.MSBuild; namespace MonoDevelop.Projects { - public abstract class SolutionItem: IExtendedDataItem, IBuildTarget, ILoadController, IPolicyProvider + public abstract class SolutionItem : SolutionFolderItem, IWorkspaceFileObject, IConfigurationTarget, ILoadController, IBuildTarget { - SolutionFolder parentFolder; - Solution parentSolution; - ISolutionItemHandler handler; + internal object MemoryProbe = Counters.ItemsInMemory.CreateMemoryProbe (); + int loading; - SolutionFolder internalChildren; + ProjectItemCollection items; + ProjectItemCollection wildcardItems; + ItemCollection<SolutionItem> dependencies = new ItemCollection<SolutionItem> (); + + SolutionItemEventArgs thisItemArgs; - [ProjectPathItemProperty ("BaseDirectory", DefaultValue=null)] - string baseDirectory; + FileStatusTracker<SolutionItemEventArgs> fileStatusTracker; + + FilePath fileName; + string name; - Hashtable extendedProperties; + FileFormat fileFormat; - [ItemProperty ("Policies", IsExternal = true, SkipEmpty = true)] - MonoDevelop.Projects.Policies.PolicyBag policies; + SolutionItemConfiguration activeConfiguration; + SolutionItemConfigurationCollection configurations; - [ItemProperty ("UseMSBuildEngine")] - public bool? UseMSBuildEngine { get; set; } - - PropertyBag userProperties; + public event EventHandler ConfigurationsChanged; + public event ConfigurationEventHandler DefaultConfigurationChanged; + public event ConfigurationEventHandler ConfigurationAdded; + public event ConfigurationEventHandler ConfigurationRemoved; + public event EventHandler<ProjectItemEventArgs> ProjectItemAdded; + public event EventHandler<ProjectItemEventArgs> ProjectItemRemoved; + + // When set, it means this item is saved as part of a global solution save operation + internal bool SavingSolution { get; set; } - /// <summary> - /// Initializes a new instance of the <see cref="MonoDevelop.Projects.SolutionItem"/> class. - /// </summary> - public SolutionItem() + public SolutionItem () { + var fmt = Services.ProjectService.FileFormats.GetFileFormat (MSBuildProjectService.DefaultFormat); + TypeGuid = MSBuildProjectService.GetTypeGuidForItem (this); + + SetSolutionFormat ((MSBuildFileFormat)fmt.Format, true); ProjectExtensionUtil.LoadControl (this); + items = new ProjectItemCollection (this); + wildcardItems = new ProjectItemCollection (this); + thisItemArgs = new SolutionItemEventArgs (this); + configurations = new SolutionItemConfigurationCollection (this); + configurations.ConfigurationAdded += OnConfigurationAddedToCollection; + configurations.ConfigurationRemoved += OnConfigurationRemovedFromCollection; + Counters.ItemsLoaded++; + fileStatusTracker = new FileStatusTracker<SolutionItemEventArgs> (this, OnReloadRequired, new SolutionItemEventArgs (this)); } - - /// <summary> - /// Initializes a new instance of this item, using an xml element as template - /// </summary> - /// <param name='template'> - /// The template - /// </param> - public virtual void InitializeFromTemplate (XmlElement template) - { - } - - /// <summary> - /// Gets the handler for this solution item - /// </summary> - /// <value> - /// The solution item handler. - /// </value> - /// <exception cref='InvalidOperationException'> - /// Is thrown if there isn't a ISolutionItemHandler for this solution item - /// </exception> - protected internal ISolutionItemHandler ItemHandler { + + SolutionItemExtension itemExtension; + + SolutionItemExtension ItemExtension { get { - if (handler == null) { - InitializeItemHandler (); - if (handler == null) - throw new InvalidOperationException ("No handler found for solution item of type: " + GetType ()); - } - return handler; + if (itemExtension == null) + itemExtension = ExtensionChain.GetExtension<SolutionItemExtension> (); + return itemExtension; } } - - /// <summary> - /// Sets the handler for this solution item - /// </summary> - /// <param name='handler'> - /// A handler. - /// </param> - internal virtual void SetItemHandler (ISolutionItemHandler handler) + + protected override IEnumerable<WorkspaceObjectExtension> CreateDefaultExtensions () { - if (this.handler != null) - this.handler.Dispose (); - this.handler = handler; + foreach (var e in base.CreateDefaultExtensions ()) + yield return e; + yield return new DefaultMSBuildItemExtension (); } - - internal ISolutionItemHandler GetItemHandler () + + internal protected virtual IEnumerable<string> GetItemTypeGuids () { - // Used to get the handler without lazy loading it - return this.handler; + yield return TypeGuid; } - - /// <summary> - /// Gets the author information for this solution item, inherited from the solution and global settings. - /// </summary> - public AuthorInformation AuthorInformation { - get { - if (ParentSolution != null) - return ParentSolution.AuthorInformation; - else - return AuthorInformation.Default; - } - } - - /// <summary> - /// Gets a service instance of a given type - /// </summary> - /// <returns> - /// The service. - /// </returns> - /// <typeparam name='T'> - /// Type of the service - /// </typeparam> - /// <remarks> - /// This method looks for an imlpementation of a service of the given type. - /// </remarks> - public T GetService<T> () where T: class + + public override void Dispose () { - return (T) GetService (typeof(T)); + base.Dispose (); + Counters.ItemsLoaded--; + + foreach (var item in items.Concat (wildcardItems)) { + IDisposable disp = item as IDisposable; + if (disp != null) + disp.Dispose (); + } + + // items = null; + // wildcardItems = null; + // thisItemArgs = null; + // fileStatusTracker = null; + // fileFormat = null; + // activeConfiguration = null; + // configurations = null; } - /// <summary> - /// Gets a service instance of a given type - /// </summary> - /// <returns> - /// The service. - /// </returns> - /// <param name='t'> - /// Type of the service - /// </param> - /// <remarks> - /// This method looks for an imlpementation of a service of the given type. - /// </remarks> - public virtual object GetService (Type t) + void HandleSolutionItemAdded (object sender, SolutionItemChangeEventArgs e) { - return Services.ProjectService.GetExtensionChain (this).GetService (this, t); - } - - /// <summary> - /// Gets the solution to which this item belongs - /// </summary> - public Solution ParentSolution { - get { - if (parentFolder != null) - return parentFolder.ParentSolution; - return parentSolution; - } - internal set { - parentSolution = value; - NotifyBoundToSolution (true); + if (e.Reloading && dependencies.Count > 0 && (e.SolutionItem is SolutionItem) && (e.ReplacedItem is SolutionItem)) { + int i = dependencies.IndexOf ((SolutionItem)e.ReplacedItem); + if (i != -1) + dependencies [i] = (SolutionItem) e.SolutionItem; } } - /// <summary> - /// Gets a value indicating whether this item is currently being loaded from a file - /// </summary> - /// <remarks> - /// While an item is loading, some events such as project file change events may be fired. - /// This flag can be used to check if change events are caused by data being loaded. - /// </remarks> - public bool Loading { - get { return loading > 0; } - } - - /// <summary> - /// Saves the solution item - /// </summary> - /// <param name='monitor'> - /// A progress monitor. - /// </param> - public abstract void Save (IProgressMonitor monitor); - - /// <summary> - /// Name of the solution item - /// </summary> - public abstract string Name { get; set; } - - /// <summary> - /// Gets or sets the base directory of this solution item - /// </summary> - /// <value> - /// The base directory. - /// </value> - /// <remarks> - /// The base directory is the directory where files belonging to this project - /// are placed. Notice that this directory may be different than the directory - /// where the project file is placed. - /// </remarks> - public FilePath BaseDirectory { - get { - if (baseDirectory == null) {
- FilePath dir = GetDefaultBaseDirectory (); - if (dir.IsNullOrEmpty) - dir = "."; - return dir.FullPath; - } - else - return baseDirectory; - } - set {
- FilePath def = GetDefaultBaseDirectory (); - if (value != FilePath.Null && def != FilePath.Null && value.FullPath == def.FullPath) - baseDirectory = null; - else if (string.IsNullOrEmpty (value)) - baseDirectory = null; - else - baseDirectory = value.FullPath; - NotifyModified ("BaseDirectory"); - } + void HandleSolutionItemRemoved (object sender, SolutionItemChangeEventArgs e) + { + if (!e.Reloading && (e.SolutionItem is SolutionItem)) + dependencies.Remove ((SolutionItem)e.SolutionItem); } - - /// <summary> - /// Gets the directory where this solution item is placed - /// </summary> - public FilePath ItemDirectory { - get {
- FilePath dir = GetDefaultBaseDirectory (); - if (string.IsNullOrEmpty (dir)) - dir = "."; - return dir.FullPath; - } + + void ILoadController.BeginLoad () + { + loading++; + OnBeginLoad (); } - - internal bool HasCustomBaseDirectory { - get { return baseDirectory != null; } - }
- - /// <summary> - /// Gets the default base directory. - /// </summary> - /// <remarks> - /// The base directory is the directory where files belonging to this project - /// are placed. Notice that this directory may be different than the directory - /// where the project file is placed. - /// </remarks> - protected virtual FilePath GetDefaultBaseDirectory ( ) + + void ILoadController.EndLoad () { - return ParentSolution.BaseDirectory; + loading--; + OnEndLoad (); } /// <summary> - /// Gets the identifier of this solution item + /// Called when a load operation for this solution item has started /// </summary> - /// <remarks> - /// The identifier is unique inside the solution - /// </remarks> - public string ItemId { - get { return ItemHandler.ItemId; } + protected virtual void OnBeginLoad () + { } - + /// <summary> - /// Gets extended properties. + /// Called when a load operation for this solution item has finished /// </summary> - /// <remarks> - /// This dictionary can be used by add-ins to store arbitrary information about this solution item. - /// Keys and values can be of any type. - /// If a value implements IDisposable, the value will be disposed when this solution item is disposed. - /// Values in this dictionary won't be serialized, unless they are registered as serializable using - /// the /MonoDevelop/ProjectModel/ExtendedProperties extension point. - /// </remarks> - public IDictionary ExtendedProperties { - get { return InternalGetExtendedProperties; } + protected virtual void OnEndLoad () + { + fileStatusTracker.ResetLoadTimes (); + + if (syncReleaseVersion && ParentSolution != null) + releaseVersion = ParentSolution.Version; } + + [ItemProperty ("ReleaseVersion", DefaultValue="0.1")] + string releaseVersion = "0.1"; - /// <summary> - /// Gets policies. - /// </summary> - /// <remarks> - /// Returns a policy container which can be used to query policies specific for this - /// solution item. If a policy is not defined for this item, the inherited value will be returned. - /// </remarks> - public MonoDevelop.Projects.Policies.PolicyBag Policies { + [ItemProperty ("SynchReleaseVersion", DefaultValue = true)] + bool syncReleaseVersion = true; + + public string Version { get { - //newly created (i.e. not deserialised) SolutionItems may have a null PolicyBag - if (policies == null) - policies = new MonoDevelop.Projects.Policies.PolicyBag (); - //this is the easiest reliable place to associate a deserialised Policybag with its owner - policies.Owner = this; - return policies; + // If syncReleaseVersion is set, releaseVersion will already contain the solution's version + // That's because the version must be up to date even when loading the project individually + return releaseVersion; } - //setter so that a solution can deserialise the PropertyBag on its RootFolder - internal set { - policies = value; + set { + releaseVersion = value; + NotifyModified ("Version"); } } - PolicyContainer IPolicyProvider.Policies { + public bool SyncVersionWithSolution { get { - return Policies; + return syncReleaseVersion; + } + set { + syncReleaseVersion = value; + if (syncReleaseVersion && ParentSolution != null) + Version = ParentSolution.Version; + NotifyModified ("SyncVersionWithSolution"); } } - /// <summary> - /// Gets solution item properties specific to the current user - /// </summary> - /// <remarks> - /// These properties are not stored in the project file, but in a separate file which is not to be shared - /// with other users. - /// User properties are only loaded when the project is loaded inside the IDE. - /// </remarks> - public PropertyBag UserProperties { - get { - if (userProperties == null) - userProperties = new PropertyBag (); - return userProperties; + protected override string OnGetName () + { + return name ?? string.Empty; + } + + protected override void OnSetName (string value) + { + name = value; + if (!Loading && SyncFileName) { + if (string.IsNullOrEmpty (fileName)) + FileName = value; + else { + string ext = fileName.Extension; + FileName = fileName.ParentDirectory.Combine (value) + ext; + } } } - + /// <summary> - /// Initializes the user properties of the item + /// Returns a value indicating whether the name of the solution item should be the same as the name of the file /// </summary> - /// <param name='properties'> - /// Properties to be set - /// </param> - /// <exception cref='InvalidOperationException'> - /// The user properties have already been set - /// </exception> - /// <remarks> - /// This method is used by the IDE to initialize the user properties when a project is loaded. - /// </remarks> - public void LoadUserProperties (PropertyBag properties) - { - if (userProperties != null) - throw new InvalidOperationException ("User properties already loaded."); - userProperties = properties; + /// <value> + /// <c>true</c> if the file name must be in sync with the solution item name; otherwise, <c>false</c>. + /// </value> + protected virtual bool SyncFileName { + get { return true; } } - /// <summary> - /// Gets the parent solution folder. - /// </summary> - public SolutionFolder ParentFolder { + public virtual FilePath FileName { get { - return parentFolder; + return fileName; } - internal set { - parentFolder = value; - if (internalChildren != null) { - internalChildren.ParentFolder = value; - } - if (value != null && value.ParentSolution != null) { - NotifyBoundToSolution (false); + set { + if (FileFormat != null) + value = FileFormat.GetValidFileName (this, value); + if (value != fileName) { + fileName = value; + if (SyncFileName) + Name = fileName.FileNameWithoutExtension; + NotifyModified ("FileName"); } } } - // Normally, the ParentFolder setter fires OnBoundToSolution. However, when deserializing, child - // ParentFolder hierarchies can become connected before the ParentSolution becomes set. This method - // enables us to recursively fire the OnBoundToSolution call in those cases. - void NotifyBoundToSolution (bool includeInternalChildren) - { - var folder = this as SolutionFolder; - if (folder != null) { - var items = folder.GetItemsWithoutCreating (); - if (items != null) { - foreach (var item in items) { - item.NotifyBoundToSolution (includeInternalChildren); - } + public bool Enabled { + get { return ParentSolution != null ? ParentSolution.IsSolutionItemEnabled (FileName) : true; } + set { + if (ParentSolution != null) + ParentSolution.SetSolutionItemEnabled (FileName, value); + } + } + + public FileFormat FileFormat { + get { + if (ParentSolution != null) { + if (ParentSolution.FileFormat.Format.SupportsMixedFormats && fileFormat != null) + return fileFormat; + return ParentSolution.FileFormat; } + if (fileFormat == null) + fileFormat = Services.ProjectService.GetDefaultFormat (this); + return fileFormat; } - if (includeInternalChildren && internalChildren != null) { - internalChildren.NotifyBoundToSolution (includeInternalChildren); + set { + if (ParentSolution != null && !ParentSolution.FileFormat.Format.SupportsMixedFormats) + throw new InvalidOperationException ("The file format can't be changed when the item belongs to a solution."); + InstallFormat (value); + fileFormat.Format.ConvertToFormat (this); + NeedsReload = false; + NotifyModified ("FileFormat"); } - OnBoundToSolution (); + } + + protected override object OnGetService (Type t) + { + return null; } + public ProjectItemCollection Items { + get { return items; } + } + internal ProjectItemCollection WildcardItems { + get { return wildcardItems; } + } + /// <summary> - /// Gets a value indicating whether this <see cref="MonoDevelop.Projects.SolutionItem"/> has been disposed. + /// Projects that need to be built before building this one /// </summary> - /// <value> - /// <c>true</c> if disposed; otherwise, <c>false</c>. - /// </value> - internal protected bool Disposed { get; private set; } + /// <value>The dependencies.</value> + public ItemCollection<SolutionItem> ItemDependencies { + get { return dependencies; } + } /// <summary> - /// Releases all resource used by the <see cref="MonoDevelop.Projects.SolutionItem"/> object. + /// Gets a value indicating whether this item is currently being loaded from a file /// </summary> /// <remarks> - /// Call <see cref="Dispose"/> when you are finished using the <see cref="MonoDevelop.Projects.SolutionItem"/>. The - /// <see cref="Dispose"/> method leaves the <see cref="MonoDevelop.Projects.SolutionItem"/> in an unusable state. - /// After calling <see cref="Dispose"/>, you must release all references to the - /// <see cref="MonoDevelop.Projects.SolutionItem"/> so the garbage collector can reclaim the memory that the - /// <see cref="MonoDevelop.Projects.SolutionItem"/> was occupying. + /// While an item is loading, some events such as project file change events may be fired. + /// This flag can be used to check if change events are caused by data being loaded. /// </remarks> - public virtual void Dispose () - { - Disposed = true; - - if (extendedProperties != null) { - foreach (object ob in extendedProperties.Values) { - IDisposable disp = ob as IDisposable; - if (disp != null) - disp.Dispose (); - } - extendedProperties = null; - } - if (handler != null) { - handler.Dispose (); - // handler = null; - } - if (userProperties != null) { - ((IDisposable)userProperties).Dispose (); - userProperties = null; - } - - // parentFolder = null; - // parentSolution = null; - // internalChildren = null; - // policies = null; + public bool Loading { + get { return loading > 0; } } - + /// <summary> /// Gets solution items referenced by this instance (items on which this item depends) /// </summary> @@ -448,94 +330,215 @@ namespace MonoDevelop.Projects /// <param name='configuration'> /// Configuration for which to get the referenced items /// </param> - public virtual IEnumerable<SolutionItem> GetReferencedItems (ConfigurationSelector configuration) + public IEnumerable<SolutionItem> GetReferencedItems (ConfigurationSelector configuration) + { + return ItemExtension.OnGetReferencedItems (configuration); + } + + protected virtual IEnumerable<SolutionItem> OnGetReferencedItems (ConfigurationSelector configuration) + { + return dependencies; + } + + Task IWorkspaceFileObject.ConvertToFormat (FileFormat format, bool convertChildren) + { + this.FileFormat = format; + return Task.FromResult (0); + } + + public bool SupportsFormat (FileFormat format) + { + return ItemExtension.OnGetSupportsFormat (format); + } + + protected virtual bool OnGetSupportsFormat (FileFormat format) + { + return true; + } + + internal void InstallFormat (FileFormat format) { - return new SolutionItem [0]; + fileFormat = format; + if (fileName != FilePath.Null) + fileName = fileFormat.GetValidFileName (this, fileName); } /// <summary> - /// Runs a build or execution target. + /// Initializes a new instance of this item, using an xml element as template /// </summary> - /// <returns> - /// The result of the operation - /// </returns> - /// <param name='monitor'> - /// A progress monitor - /// </param> - /// <param name='target'> - /// Name of the target - /// </param> - /// <param name='configuration'> - /// Configuration to use to run the target + /// <param name='template'> + /// The template /// </param> - public BuildResult RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration) + public void InitializeFromTemplate (XmlElement template) { - return Services.ProjectService.GetExtensionChain (this).RunTarget (monitor, this, target, configuration); + ItemExtension.OnInitializeFromTemplate (template); } - - public bool SupportsTarget (string target) + + protected virtual void OnInitializeFromTemplate (XmlElement template) { - return Services.ProjectService.GetExtensionChain (this).SupportsTarget (this, target); } - public bool SupportsBuild () + public virtual void InitializeNew (ProjectCreateInformation projectCreateInfo, XmlElement projectOptions) { - return SupportsTarget (ProjectService.BuildTarget); } - public bool SupportsExecute () + protected override FilePath GetDefaultBaseDirectory ( ) { - return Services.ProjectService.GetExtensionChain (this).SupportsExecute (this); + return ItemExtension.OnGetDefaultBaseDirectory (); } + internal Task LoadAsync (ProgressMonitor monitor, FilePath fileName, MSBuildFileFormat format) + { + FileName = fileName; + Name = Path.GetFileNameWithoutExtension (fileName); + SetSolutionFormat (format ?? new MSBuildFileFormatVS12 (), false); + return ItemExtension.OnLoad (monitor); + } + + public void Save (ProgressMonitor monitor, FilePath fileName) + { + SaveAsync (monitor, fileName).Wait (); + } + + public Task SaveAsync (ProgressMonitor monitor, FilePath fileName) + { + FileName = fileName; + return SaveAsync (monitor); + } + /// <summary> - /// Cleans the files produced by this solution item + /// Saves the solution item /// </summary> /// <param name='monitor'> - /// A progress monitor - /// </param> - /// <param name='configuration'> - /// Configuration to use to clean the project + /// A progress monitor. /// </param> - public void Clean (IProgressMonitor monitor, ConfigurationSelector configuration) + public void Save (ProgressMonitor monitor) { - ITimeTracker tt = Counters.BuildProjectTimer.BeginTiming ("Cleaning " + Name); + ItemExtension.OnSave (monitor).Wait (); + } + + + public async Task SaveAsync (ProgressMonitor monitor) + { + await ItemExtension.OnSave (monitor); + + if (HasSlnData && !SavingSolution && ParentSolution != null) { + // The project has data that has to be saved in the solution, but the solution is not being saved. Do it now. + await SolutionFormat.SlnFileFormat.WriteFile (ParentSolution.FileName, ParentSolution, false, monitor); + ParentSolution.NeedsReload = false; + } + } + + async Task DoSave (ProgressMonitor monitor) + { + if (string.IsNullOrEmpty (FileName)) + throw new InvalidOperationException ("Project does not have a file name"); + try { - //SolutionFolder handles the begin/end task itself, don't duplicate - if (this is SolutionFolder) { - RunTarget (monitor, ProjectService.CleanTarget, configuration); - return; - } - - try { - SolutionEntityItem it = this as SolutionEntityItem; - SolutionItemConfiguration iconf = it != null ? it.GetConfiguration (configuration) : null; - string confName = iconf != null ? iconf.Id : configuration.ToString (); - monitor.BeginTask (GettextCatalog.GetString ("Cleaning: {0} ({1})", Name, confName), 1); - RunTarget (monitor, ProjectService.CleanTarget, configuration); - } finally { - monitor.EndTask (); - } + fileStatusTracker.BeginSave (); + await OnSave (monitor); + OnSaved (thisItemArgs); + } finally { + fileStatusTracker.EndSave (); } - finally { - tt.End (); + FileService.NotifyFileChanged (FileName); + } + + internal bool IsSaved { + get { + return !string.IsNullOrEmpty (FileName) && File.Exists (FileName); } } + public override bool NeedsReload { + get { return fileStatusTracker.NeedsReload; } + set { fileStatusTracker.NeedsReload = value; } + } + + public virtual bool ItemFilesChanged { + get { return ItemExtension.ItemFilesChanged; } + } + + bool BaseItemFilesChanged { + get { return fileStatusTracker.ItemFilesChanged; } + } + + public bool SupportsBuild () + { + return ItemExtension.OnSupportsBuild (); + } + + protected virtual bool OnGetSupportsBuild () + { + return true; + } + + public bool SupportsExecute () + { + return ItemExtension.OnSupportsExecute (); + } + + protected virtual bool OnGetSupportsExecute () + { + return true; + } + + public virtual bool SupportsConfigurations () + { + // TODO NPM: -> extension chain + return SupportsBuild (); + } + + /// <summary> + /// Gets a value indicating whether this project is supported. + /// </summary> + /// <remarks> + /// Unsupported projects are shown in the solution pad, but operations such as building on executing won't be available. + /// </remarks> + public bool IsUnsupportedProject { get; protected set; } + + /// <summary> + /// Gets a message that explain why the project is not supported (when IsUnsupportedProject returns true) + /// </summary> + public string UnsupportedProjectMessage { + get { return IsUnsupportedProject ? (loadError ?? GettextCatalog.GetString ("Unknown project type")) : ""; } + set { loadError = value; } + } + string loadError; + + public bool NeedsBuilding (ConfigurationSelector configuration) + { + return ItemExtension.OnNeedsBuilding (configuration); + } + + internal protected virtual bool OnGetNeedsBuilding (ConfigurationSelector configuration) + { + return false; + } + + public void SetNeedsBuilding (ConfigurationSelector configuration) + { + OnSetNeedsBuilding (configuration); + } + + protected virtual void OnSetNeedsBuilding (ConfigurationSelector configuration) + { + } + /// <summary> /// Builds the solution item /// </summary> /// <param name='monitor'> /// A progress monitor /// </param> - /// <param name='configuration'> + /// <param name='solutionConfiguration'> /// Configuration to use to build the project /// </param> - public BuildResult Build (IProgressMonitor monitor, ConfigurationSelector configuration) + public Task<BuildResult> Build (ProgressMonitor monitor, ConfigurationSelector solutionConfiguration) { - return Build (monitor, configuration, false); + return Build (monitor, solutionConfiguration, false); } - + /// <summary> /// Builds the solution item /// </summary> @@ -548,54 +551,47 @@ namespace MonoDevelop.Projects /// <param name='buildReferences'> /// When set to <c>true</c>, the referenced items will be built before building this item /// </param> - public BuildResult Build (IProgressMonitor monitor, ConfigurationSelector solutionConfiguration, bool buildReferences) + public async Task<BuildResult> Build (ProgressMonitor monitor, ConfigurationSelector solutionConfiguration, bool buildReferences) { ITimeTracker tt = Counters.BuildProjectTimer.BeginTiming ("Building " + Name); try { if (!buildReferences) { - //SolutionFolder's OnRunTarget handles the begin/end task itself, don't duplicate - if (this is SolutionFolder) { - return RunTarget (monitor, ProjectService.BuildTarget, solutionConfiguration); - } - try { - SolutionEntityItem it = this as SolutionEntityItem; - SolutionItemConfiguration iconf = it != null ? it.GetConfiguration (solutionConfiguration) : null; + SolutionItemConfiguration iconf = GetConfiguration (solutionConfiguration); string confName = iconf != null ? iconf.Id : solutionConfiguration.ToString (); monitor.BeginTask (GettextCatalog.GetString ("Building: {0} ({1})", Name, confName), 1); - - // This will end calling OnBuild () - return RunTarget (monitor, ProjectService.BuildTarget, solutionConfiguration); - + + return await InternalBuild (monitor, solutionConfiguration); + } finally { monitor.EndTask (); } } - + // Get a list of all items that need to be built (including this), // and build them in the correct order - - List<SolutionItem> referenced = new List<SolutionItem> ();
- Set<SolutionItem> visited = new Set<SolutionItem> ();
+ + var referenced = new List<SolutionItem> (); + var visited = new Set<SolutionItem> (); GetBuildableReferencedItems (visited, referenced, this, solutionConfiguration); - - ReadOnlyCollection<SolutionItem> sortedReferenced = SolutionFolder.TopologicalSort (referenced, solutionConfiguration); - + + var sortedReferenced = TopologicalSort (referenced, solutionConfiguration); + BuildResult cres = new BuildResult (); cres.BuildCount = 0; - HashSet<SolutionItem> failedItems = new HashSet<SolutionItem> (); - + var failedItems = new HashSet<SolutionItem> (); + monitor.BeginTask (null, sortedReferenced.Count); - foreach (SolutionItem p in sortedReferenced) { + foreach (var p in sortedReferenced) { if (!p.ContainsReferences (failedItems, solutionConfiguration)) { - BuildResult res = p.Build (monitor, solutionConfiguration, false); + BuildResult res = await p.Build (monitor, solutionConfiguration, false); cres.Append (res); if (res.ErrorCount > 0) failedItems.Add (p); } else failedItems.Add (p); monitor.Step (1); - if (monitor.IsCancelRequested) + if (monitor.CancellationToken.IsCancellationRequested) break; } monitor.EndTask (); @@ -604,40 +600,258 @@ namespace MonoDevelop.Projects tt.End (); } } - + + async Task<BuildResult> InternalBuild (ProgressMonitor monitor, ConfigurationSelector configuration) + { + if (IsUnsupportedProject) { + var r = new BuildResult (); + r.AddError (UnsupportedProjectMessage); + return r; + } + + SolutionItemConfiguration conf = GetConfiguration (configuration) as SolutionItemConfiguration; + if (conf != null) { + if (conf.CustomCommands.CanExecute (this, CustomCommandType.BeforeBuild, null, configuration)) { + if (!await conf.CustomCommands.ExecuteCommand (monitor, this, CustomCommandType.BeforeBuild, configuration)) { + var r = new BuildResult (); + r.AddError (GettextCatalog.GetString ("Custom command execution failed")); + return r; + } + } + } + + if (monitor.CancellationToken.IsCancellationRequested) + return new BuildResult (new CompilerResults (null), ""); + + BuildResult res = await ItemExtension.OnBuild (monitor, configuration); + + if (conf != null && !monitor.CancellationToken.IsCancellationRequested && !res.Failed) { + if (conf.CustomCommands.CanExecute (this, CustomCommandType.AfterBuild, null, configuration)) { + if (!await conf.CustomCommands.ExecuteCommand (monitor, this, CustomCommandType.AfterBuild, configuration)) + res.AddError (GettextCatalog.GetString ("Custom command execution failed")); + } + } + + return res; + } + + /// <summary> + /// Builds the solution item + /// </summary> + /// <param name='monitor'> + /// A progress monitor + /// </param> + /// <param name='configuration'> + /// Configuration to use to build the project + /// </param> + protected virtual Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return Task.FromResult (BuildResult.Success); + } + + void GetBuildableReferencedItems (Set<SolutionItem> visited, List<SolutionItem> referenced, SolutionItem item, ConfigurationSelector configuration) + { + if (!visited.Add(item)) + return; + + referenced.Add (item); + + foreach (var ritem in item.GetReferencedItems (configuration)) + GetBuildableReferencedItems (visited, referenced, ritem, configuration); + } + internal bool ContainsReferences (HashSet<SolutionItem> items, ConfigurationSelector conf) { - foreach (SolutionItem it in GetReferencedItems (conf)) + foreach (var it in GetReferencedItems (conf)) if (items.Contains (it)) return true; return false; } /// <summary> - /// Gets the time of the last build + /// Cleans the files produced by this solution item + /// </summary> + /// <param name='monitor'> + /// A progress monitor + /// </param> + /// <param name='configuration'> + /// Configuration to use to clean the project + /// </param> + public async Task<BuildResult> Clean (ProgressMonitor monitor, ConfigurationSelector configuration) + { + ITimeTracker tt = Counters.BuildProjectTimer.BeginTiming ("Cleaning " + Name); + try { + try { + SolutionItemConfiguration iconf = GetConfiguration (configuration); + string confName = iconf != null ? iconf.Id : configuration.ToString (); + monitor.BeginTask (GettextCatalog.GetString ("Cleaning: {0} ({1})", Name, confName), 1); + + SolutionItemConfiguration conf = GetConfiguration (configuration); + if (conf != null) { + if (conf.CustomCommands.CanExecute (this, CustomCommandType.BeforeClean, null, configuration)) { + if (!await conf.CustomCommands.ExecuteCommand (monitor, this, CustomCommandType.BeforeClean, configuration)) { + var r = new BuildResult (); + r.AddError (GettextCatalog.GetString ("Custom command execution failed")); + return r; + } + } + } + + if (monitor.CancellationToken.IsCancellationRequested) + return BuildResult.Success; + + var res = await ItemExtension.OnClean (monitor, configuration); + + if (conf != null && !monitor.CancellationToken.IsCancellationRequested) { + if (conf.CustomCommands.CanExecute (this, CustomCommandType.AfterClean, null, configuration)) { + if (!await conf.CustomCommands.ExecuteCommand (monitor, this, CustomCommandType.AfterClean, configuration)) + res.AddError (GettextCatalog.GetString ("Custom command execution failed")); + } + } + return res; + + } finally { + monitor.EndTask (); + } + } + finally { + tt.End (); + } + } + + /// <summary> + /// Cleans the files produced by this solution item + /// </summary> + /// <param name='monitor'> + /// A progress monitor + /// </param> + /// <param name='configuration'> + /// Configuration to use to clean the project + /// </param> + protected virtual Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return Task.FromResult (BuildResult.Success); + } + + /// <summary> + /// Sorts a collection of solution items, taking into account the dependencies between them /// </summary> /// <returns> - /// The last build time. + /// The sorted collection of items /// </returns> + /// <param name='items'> + /// Items to sort + /// </param> /// <param name='configuration'> - /// Configuration for which to get the last build time. + /// A configuration /// </param> - public DateTime GetLastBuildTime (ConfigurationSelector configuration) + /// <remarks> + /// This methods sorts a collection of items, ensuring that every item is placed after all the items + /// on which it depends. + /// </remarks> + public static ReadOnlyCollection<T> TopologicalSort<T> (IEnumerable<T> items, ConfigurationSelector configuration) where T: SolutionItem + { + IList<T> allItems; + allItems = items as IList<T>; + if (allItems == null) + allItems = new List<T> (items); + + List<T> sortedEntries = new List<T> (); + bool[] inserted = new bool[allItems.Count]; + bool[] triedToInsert = new bool[allItems.Count]; + for (int i = 0; i < allItems.Count; ++i) { + if (!inserted[i]) + Insert<T> (i, allItems, sortedEntries, inserted, triedToInsert, configuration); + } + return sortedEntries.AsReadOnly (); + } + + static void Insert<T> (int index, IList<T> allItems, List<T> sortedItems, bool[] inserted, bool[] triedToInsert, ConfigurationSelector solutionConfiguration) where T: SolutionItem { - return OnGetLastBuildTime (configuration); + if (triedToInsert[index]) { + throw new CyclicDependencyException (); + } + triedToInsert[index] = true; + var insertItem = allItems[index]; + + foreach (var reference in insertItem.GetReferencedItems (solutionConfiguration)) { + for (int j=0; j < allItems.Count; ++j) { + SolutionFolderItem checkItem = allItems[j]; + if (reference == checkItem) { + if (!inserted[j]) + Insert (j, allItems, sortedItems, inserted, triedToInsert, solutionConfiguration); + break; + } + } + } + sortedItems.Add (insertItem); + inserted[index] = true; } - - void GetBuildableReferencedItems (Set<SolutionItem> visited, List<SolutionItem> referenced, SolutionItem item, ConfigurationSelector configuration) - {
- if (!visited.Add(item)) + + /// <summary> + /// Executes this solution item + /// </summary> + /// <param name='monitor'> + /// A progress monitor + /// </param> + /// <param name='context'> + /// An execution context + /// </param> + /// <param name='configuration'> + /// Configuration to use to execute the item + /// </param> + public async Task Execute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + { + SolutionItemConfiguration conf = GetConfiguration (configuration) as SolutionItemConfiguration; + if (conf != null) { + ExecutionContext localContext = new ExecutionContext (Runtime.ProcessService.DefaultExecutionHandler, context.ConsoleFactory, context.ExecutionTarget); + + if (conf.CustomCommands.CanExecute (this, CustomCommandType.BeforeExecute, localContext, configuration)) { + if (!await conf.CustomCommands.ExecuteCommand (monitor, this, CustomCommandType.BeforeExecute, localContext, configuration)) + return; + } + } + + if (monitor.CancellationToken.IsCancellationRequested) return; - - referenced.Add (item); - foreach (SolutionItem ritem in item.GetReferencedItems (configuration)) - GetBuildableReferencedItems (visited, referenced, ritem, configuration); + await ItemExtension.OnExecute (monitor, context, configuration); + + if (conf != null && !monitor.CancellationToken.IsCancellationRequested) { + ExecutionContext localContext = new ExecutionContext (Runtime.ProcessService.DefaultExecutionHandler, context.ConsoleFactory, context.ExecutionTarget); + + if (conf.CustomCommands.CanExecute (this, CustomCommandType.AfterExecute, localContext, configuration)) + await conf.CustomCommands.ExecuteCommand (monitor, this, CustomCommandType.AfterExecute, localContext, configuration); + } } - + + /// <summary> + /// Determines whether this solution item can be executed using the specified context and configuration. + /// </summary> + /// <returns> + /// <c>true</c> if this instance can be executed; otherwise, <c>false</c>. + /// </returns> + /// <param name='context'> + /// An execution context + /// </param> + /// <param name='configuration'> + /// Configuration to use to execute the item + /// </param> + public bool CanExecute (ExecutionContext context, ConfigurationSelector configuration) + { + return !IsUnsupportedProject && ItemExtension.OnGetCanExecute (context, configuration); + } + + async Task DoExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + { + SolutionItemConfiguration conf = GetConfiguration (configuration) as SolutionItemConfiguration; + if (conf != null && conf.CustomCommands.HasCommands (CustomCommandType.Execute)) { + await conf.CustomCommands.ExecuteCommand (monitor, this, CustomCommandType.Execute, context, configuration); + return; + } + await OnExecute (monitor, context, configuration); + } + /// <summary> /// Executes this solution item /// </summary> @@ -650,11 +864,19 @@ namespace MonoDevelop.Projects /// <param name='configuration'> /// Configuration to use to execute the item /// </param> - public void Execute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + protected virtual Task OnExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { - Services.ProjectService.GetExtensionChain (this).Execute (monitor, this, context, configuration); + return Task.FromResult (0); } - + + bool DoGetCanExecute (ExecutionContext context, ConfigurationSelector configuration) + { + SolutionItemConfiguration conf = GetConfiguration (configuration) as SolutionItemConfiguration; + if (conf != null && conf.CustomCommands.HasCommands (CustomCommandType.Execute)) + return conf.CustomCommands.CanExecute (this, CustomCommandType.Execute, context, configuration); + return OnGetCanExecute (context, configuration); + } + /// <summary> /// Determines whether this solution item can be executed using the specified context and configuration. /// </summary> @@ -667,11 +889,9 @@ namespace MonoDevelop.Projects /// <param name='configuration'> /// Configuration to use to execute the item /// </param> - public bool CanExecute (ExecutionContext context, ConfigurationSelector configuration) + protected virtual bool OnGetCanExecute (ExecutionContext context, ConfigurationSelector configuration) { - if (!SupportsExecute ()) - return false; - return Services.ProjectService.GetExtensionChain (this).CanExecute (this, context, configuration); + return ItemExtension.OnGetCanExecute (context, configuration); } /// <summary> @@ -681,7 +901,12 @@ namespace MonoDevelop.Projects /// <param name="configuration">The configuration.</param> public IEnumerable<ExecutionTarget> GetExecutionTargets (ConfigurationSelector configuration) { - return Services.ProjectService.GetExtensionChain (this).GetExecutionTargets (this, configuration); + return ItemExtension.OnGetExecutionTargets (configuration); + } + + protected void NotifyExecutionTargetsChanged () + { + ItemExtension.OnExecutionTargetsChanged (); } public event EventHandler ExecutionTargetsChanged; @@ -691,429 +916,480 @@ namespace MonoDevelop.Projects if (ExecutionTargetsChanged != null) ExecutionTargetsChanged (this, EventArgs.Empty); } - - /// <summary> - /// Checks if this solution item has modified files and has to be built - /// </summary> - /// <returns> - /// <c>true</c> if the solution item has to be built - /// </returns> - /// <param name='configuration'> - /// Configuration for which to do the check - /// </param> - [Obsolete ("This method will be removed in future releases")] - public bool NeedsBuilding (ConfigurationSelector configuration) + + protected virtual Task OnLoad (ProgressMonitor monitor) { - return true; + return Task.FromResult (0); } - internal bool InternalCheckNeedsBuild (ConfigurationSelector configuration) + protected internal virtual Task OnSave (ProgressMonitor monitor) { - using (Counters.NeedsBuildingTimer.BeginTiming ("NeedsBuilding check for " + Name)) { - return Services.ProjectService.GetExtensionChain (this).GetNeedsBuilding (this, configuration); - } + return Task.FromResult (0); } - /// <summary> - /// States whether this solution item needs to be built or not - /// </summary> - /// <param name='value'> - /// Whether this solution item needs to be built or not - /// </param> - /// <param name='configuration'> - /// Configuration for which to set the flag - /// </param> - [Obsolete ("This method will be removed in future releases")] - public void SetNeedsBuilding (bool value, ConfigurationSelector configuration) + public FilePath GetAbsoluteChildPath (FilePath relPath) { - // Nothing to be done. + return relPath.ToAbsolute (BaseDirectory); } - - /// <summary> - /// Gets or sets a value indicating whether this <see cref="MonoDevelop.Projects.SolutionItem"/> needs to be reload due to changes in project or solution file - /// </summary> - /// <value> - /// <c>true</c> if needs reload; otherwise, <c>false</c>. - /// </value> - public virtual bool NeedsReload { - get { - if (ParentSolution != null) - return ParentSolution.NeedsReload; - else - return false; - } - set { - } + + public FilePath GetRelativeChildPath (FilePath absPath) + { + return absPath.ToRelative (BaseDirectory); } - - /// <summary> - /// Registers an internal child item. - /// </summary> - /// <param name='item'> - /// An item - /// </param> - /// <remarks> - /// Some kind of projects may be composed of several child projects. - /// By registering those child projects using this method, the child - /// projects will be plugged into the parent solution infrastructure - /// (so for example, the ParentSolution property for those projects - /// will return the correct value) - /// </remarks> - protected void RegisterInternalChild (SolutionItem item) + + public IEnumerable<FilePath> GetItemFiles (bool includeReferencedFiles) { - if (internalChildren == null) { - internalChildren = new SolutionFolder (); - internalChildren.ParentFolder = parentFolder; - } - internalChildren.Items.Add (item); + return ItemExtension.OnGetItemFiles (includeReferencedFiles); } - - /// <summary> - /// Unregisters an internal child item. - /// </summary> - /// <param name='item'> - /// The item - /// </param> - protected void UnregisterInternalChild (SolutionItem item) + + protected virtual IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles) { - if (internalChildren != null) - internalChildren.Items.Remove (item); + List<FilePath> col = FileFormat.Format.GetItemFiles (this); + if (!string.IsNullOrEmpty (FileName) && !col.Contains (FileName)) + col.Add (FileName); + return col; } - - /// <summary> - /// Gets the string tag model description for this solution item - /// </summary> - /// <returns> - /// The string tag model description - /// </returns> - /// <param name='conf'> - /// Configuration for which to get the string tag model description - /// </param> - public virtual StringTagModelDescription GetStringTagModelDescription (ConfigurationSelector conf) + + protected override void OnNameChanged (SolutionItemRenamedEventArgs e) { - StringTagModelDescription model = new StringTagModelDescription (); - model.Add (GetType ()); - model.Add (typeof(Solution)); - return model; + Solution solution = this.ParentSolution; + + if (solution != null) { + foreach (DotNetProject project in solution.GetAllItems<DotNetProject>()) { + if (project == this) + continue; + + project.RenameReferences (e.OldName, e.NewName); + } + } + fileStatusTracker.ResetLoadTimes (); + base.OnNameChanged (e); } - /// <summary> - /// Gets the string tag model for this solution item - /// </summary> - /// <returns> - /// The string tag model - /// </returns> - /// <param name='conf'> - /// Configuration for which to get the string tag model - /// </param> - public virtual StringTagModel GetStringTagModel (ConfigurationSelector conf) + protected virtual void OnSaved (SolutionItemEventArgs args) { - StringTagModel source = new StringTagModel (); - source.Add (this); - if (ParentSolution != null) - source.Add (ParentSolution.GetStringTagModel ()); - return source; + if (Saved != null) + Saved (this, args); } - /// <summary> - /// Sorts a collection of solution items, taking into account the dependencies between them - /// </summary> - /// <returns> - /// The sorted collection of items - /// </returns> - /// <param name='items'> - /// Items to sort - /// </param> - /// <param name='configuration'> - /// A configuration - /// </param> - /// <remarks> - /// This methods sorts a collection of items, ensuring that every item is placed after all the items - /// on which it depends. - /// </remarks> - public static ReadOnlyCollection<T> TopologicalSort<T> (IEnumerable<T> items, ConfigurationSelector configuration) where T: SolutionItem - { - IList<T> allItems; - allItems = items as IList<T>; - if (allItems == null) - allItems = new List<T> (items); - - List<T> sortedEntries = new List<T> (); - bool[] inserted = new bool[allItems.Count]; - bool[] triedToInsert = new bool[allItems.Count]; - for (int i = 0; i < allItems.Count; ++i) { - if (!inserted[i]) - Insert<T> (i, allItems, sortedEntries, inserted, triedToInsert, configuration); + public virtual string[] SupportedPlatforms { + get { + return new string [0]; } - return sortedEntries.AsReadOnly (); } - static void Insert<T> (int index, IList<T> allItems, List<T> sortedItems, bool[] inserted, bool[] triedToInsert, ConfigurationSelector solutionConfiguration) where T: SolutionItem + public virtual SolutionItemConfiguration GetConfiguration (ConfigurationSelector configuration) { - if (triedToInsert[index]) { - throw new CyclicDependencyException (); + return (SolutionItemConfiguration) configuration.GetConfiguration (this) ?? DefaultConfiguration; + } + + ItemConfiguration IConfigurationTarget.DefaultConfiguration { + get { return DefaultConfiguration; } + set { DefaultConfiguration = (SolutionItemConfiguration) value; } + } + + public SolutionItemConfiguration DefaultConfiguration { + get { + if (activeConfiguration == null && configurations.Count > 0) { + return configurations[0]; + } + return activeConfiguration; } - triedToInsert[index] = true; - SolutionItem insertItem = allItems[index]; - - foreach (SolutionItem reference in insertItem.GetReferencedItems (solutionConfiguration)) { - for (int j=0; j < allItems.Count; ++j) { - SolutionItem checkItem = allItems[j]; - if (reference == checkItem) { - if (!inserted[j]) - Insert (j, allItems, sortedItems, inserted, triedToInsert, solutionConfiguration); - break; - } + set { + if (activeConfiguration != value) { + activeConfiguration = value; + NotifyModified ("DefaultConfiguration"); + OnDefaultConfigurationChanged (new ConfigurationEventArgs (this, value)); } } - sortedItems.Add ((T)insertItem); - inserted[index] = true; } - internal virtual IDictionary InternalGetExtendedProperties { + public string DefaultConfigurationId { get { - if (extendedProperties == null) - extendedProperties = new Hashtable (); - return extendedProperties; + if (DefaultConfiguration != null) + return DefaultConfiguration.Id; + else + return null; + } + set { + DefaultConfiguration = GetConfiguration (new ItemConfigurationSelector (value)); } } - void ILoadController.BeginLoad () + public virtual ReadOnlyCollection<string> GetConfigurations () { - loading++; - OnBeginLoad (); + List<string> configs = new List<string> (); + foreach (SolutionItemConfiguration conf in Configurations) + configs.Add (conf.Id); + return configs.AsReadOnly (); } - void ILoadController.EndLoad () - { - loading--; - OnEndLoad (); + [ItemProperty ("Configurations")] + [ItemProperty ("Configuration", ValueType=typeof(SolutionItemConfiguration), Scope="*")] + public SolutionItemConfigurationCollection Configurations { + get { + return configurations; + } } - /// <summary> - /// Called when a load operation for this solution item has started - /// </summary> - protected virtual void OnBeginLoad () - { + IItemConfigurationCollection IConfigurationTarget.Configurations { + get { + return Configurations; + } } - /// <summary> - /// Called when a load operation for this solution item has finished - /// </summary> - protected virtual void OnEndLoad () + public SolutionItemConfiguration AddNewConfiguration (string name) { + SolutionItemConfiguration config = CreateConfiguration (name); + Configurations.Add (config); + return config; } - /// <summary> - /// Notifies that this solution item has been modified - /// </summary> - /// <param name='hint'> - /// Hint about which part of the solution item has been modified. This will typically be the property name. - /// </param> - internal protected void NotifyModified (string hint) + ItemConfiguration IConfigurationTarget.CreateConfiguration (string name) { - if (!Loading) - ItemHandler.OnModified (hint); - OnModified (new SolutionItemModifiedEventArgs (this, hint)); + return CreateConfiguration (name); } - - /// <summary> - /// Raises the modified event. - /// </summary> - /// <param name='args'> - /// Arguments. - /// </param> - protected virtual void OnModified (SolutionItemModifiedEventArgs args) + + public virtual SolutionItemConfiguration CreateConfiguration (string name) { - if (Modified != null && !Disposed) - Modified (this, args); + return ItemExtension.OnCreateConfiguration (name); } - /// <summary> - /// Raises the name changed event. - /// </summary> - /// <param name='e'> - /// Arguments. - /// </param> - protected virtual void OnNameChanged (SolutionItemRenamedEventArgs e) + void OnConfigurationAddedToCollection (object ob, ConfigurationEventArgs args) { - NotifyModified ("Name"); - if (NameChanged != null && !Disposed) - NameChanged (this, e); + NotifyModified ("Configurations"); + OnConfigurationAdded (new ConfigurationEventArgs (this, args.Configuration)); + if (ConfigurationsChanged != null) + ConfigurationsChanged (this, EventArgs.Empty); + if (activeConfiguration == null) + DefaultConfigurationId = args.Configuration.Id; } - /// <summary> - /// Initializes the item handler. - /// </summary> - /// <remarks> - /// This method is called the first time an item handler is requested. - /// Subclasses should override this method use SetItemHandler to - /// assign a handler to this item. - /// </remarks> - protected virtual void InitializeItemHandler () + void OnConfigurationRemovedFromCollection (object ob, ConfigurationEventArgs args) { + if (activeConfiguration == args.Configuration) { + if (Configurations.Count > 0) + DefaultConfiguration = Configurations [0]; + else + DefaultConfiguration = null; + } + NotifyModified ("Configurations"); + OnConfigurationRemoved (new ConfigurationEventArgs (this, args.Configuration)); + if (ConfigurationsChanged != null) + ConfigurationsChanged (this, EventArgs.Empty); } - /// <summary> - /// Runs a build or execution target. - /// </summary> - /// <returns> - /// The result of the operation - /// </returns> - /// <param name='monitor'> - /// A progress monitor - /// </param> - /// <param name='target'> - /// Name of the target - /// </param> - /// <param name='configuration'> - /// Configuration to use to run the target - /// </param> - /// <remarks> - /// Subclasses can override this method to provide a custom implementation of project operations such as - /// build or clean. The default implementation delegates the execution to the more specific OnBuild - /// and OnClean methods, or to the item handler for other targets. - /// </remarks> - internal protected virtual BuildResult OnRunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration) + public override StringTagModelDescription GetStringTagModelDescription (ConfigurationSelector conf) { - if (target == ProjectService.BuildTarget) - return OnBuild (monitor, configuration); - else if (target == ProjectService.CleanTarget) { - OnClean (monitor, configuration); - return new BuildResult (); - } - return ItemHandler.RunTarget (monitor, target, configuration) ?? new BuildResult (); + return ItemExtension.OnGetStringTagModelDescription (conf); } - /// <summary> - /// Cleans the files produced by this solution item - /// </summary> - /// <param name='monitor'> - /// A progress monitor - /// </param> - /// <param name='configuration'> - /// Configuration to use to clean the project - /// </param> - protected abstract void OnClean (IProgressMonitor monitor, ConfigurationSelector configuration); + StringTagModelDescription DoGetStringTagModelDescription (ConfigurationSelector conf) + { + StringTagModelDescription model = base.GetStringTagModelDescription (conf); + SolutionItemConfiguration config = GetConfiguration (conf); + if (config != null) + model.Add (config.GetType ()); + else + model.Add (typeof(SolutionItemConfiguration)); + return model; + } + + public override StringTagModel GetStringTagModel (ConfigurationSelector conf) + { + return ItemExtension.OnGetStringTagModel (conf); + } - /// <summary> - /// Builds the solution item - /// </summary> - /// <param name='monitor'> - /// A progress monitor - /// </param> - /// <param name='configuration'> - /// Configuration to use to build the project - /// </param> - protected abstract BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration); + StringTagModel DoGetStringTagModel (ConfigurationSelector conf) + { + StringTagModel source = base.GetStringTagModel (conf); + SolutionItemConfiguration config = GetConfiguration (conf); + if (config != null) + source.Add (config); + return source; + } + + internal protected override DateTime OnGetLastBuildTime (ConfigurationSelector configuration) + { + return ItemExtension.OnGetLastBuildTime (configuration); + } + + DateTime DoGetLastBuildTime (ConfigurationSelector configuration) + { + return base.OnGetLastBuildTime (configuration); + } + + internal protected virtual void OnItemsAdded (IEnumerable<ProjectItem> objs) + { + ItemExtension.OnItemsAdded (objs); + } - /// <summary> - /// Executes this solution item - /// </summary> - /// <param name='monitor'> - /// A progress monitor - /// </param> - /// <param name='context'> - /// An execution context - /// </param> - /// <param name='configuration'> - /// Configuration to use to execute the item - /// </param> - internal protected abstract void OnExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration); + void DoOnItemsAdded (IEnumerable<ProjectItem> objs) + { + NotifyModified ("Items"); + var args = new ProjectItemEventArgs (); + args.AddRange (objs.Select (pi => new ProjectItemEventInfo (this, pi))); + if (ProjectItemAdded != null) + ProjectItemAdded (this, args); + } + + internal protected virtual void OnItemsRemoved (IEnumerable<ProjectItem> objs) + { + ItemExtension.OnItemsRemoved (objs); + } - /// <summary> - /// Checks if this solution item has modified files and has to be built - /// </summary> - /// <returns> - /// <c>true</c> if the solution item has to be built - /// </returns> - /// <param name='configuration'> - /// Configuration for which to do the check - /// </param> - internal protected virtual bool OnGetNeedsBuilding (ConfigurationSelector configuration) + void DoOnItemsRemoved (IEnumerable<ProjectItem> objs) { - return true; + NotifyModified ("Items"); + var args = new ProjectItemEventArgs (); + args.AddRange (objs.Select (pi => new ProjectItemEventInfo (this, pi))); + if (ProjectItemRemoved != null) + ProjectItemRemoved (this, args); + } + + protected virtual void OnDefaultConfigurationChanged (ConfigurationEventArgs args) + { + ItemExtension.OnDefaultConfigurationChanged (args); } - /// <summary> - /// States whether this solution item needs to be built or not - /// </summary> - /// <param name='val'> - /// Whether this solution item needs to be built or not - /// </param> - /// <param name='configuration'> - /// Configuration for which to set the flag - /// </param> - internal protected virtual void OnSetNeedsBuilding (bool val, ConfigurationSelector configuration) + void DoOnDefaultConfigurationChanged (ConfigurationEventArgs args) + { + if (DefaultConfigurationChanged != null) + DefaultConfigurationChanged (this, args); + } + + protected virtual void OnConfigurationAdded (ConfigurationEventArgs args) { + ItemExtension.OnConfigurationAdded (args); } - /// <summary> - /// Gets the time of the last build - /// </summary> - /// <returns> - /// The last build time. - /// </returns> - /// <param name='configuration'> - /// Configuration for which to get the last build time. - /// </param> - internal protected virtual DateTime OnGetLastBuildTime (ConfigurationSelector configuration) + void DoOnConfigurationAdded (ConfigurationEventArgs args) { - return DateTime.MinValue; + if (ConfigurationAdded != null) + ConfigurationAdded (this, args); + } + + protected virtual void OnConfigurationRemoved (ConfigurationEventArgs args) + { + ItemExtension.OnConfigurationRemoved (args); } - internal protected virtual bool OnGetSupportsTarget (string target) + void DoOnConfigurationRemoved (ConfigurationEventArgs args) { - return true; + if (ConfigurationRemoved != null) + ConfigurationRemoved (this, args); } - internal protected virtual bool OnGetSupportsExecute () + protected virtual void OnReloadRequired (SolutionItemEventArgs args) { - return true; + ItemExtension.OnReloadRequired (args); + } + + void DoOnReloadRequired (SolutionItemEventArgs args) + { + fileStatusTracker.FireReloadRequired (args); } - /// <summary> - /// Determines whether this solution item can be executed using the specified context and configuration. - /// </summary> - /// <returns> - /// <c>true</c> if this instance can be executed; otherwise, <c>false</c>. - /// </returns> - /// <param name='context'> - /// An execution context - /// </param> - /// <param name='configuration'> - /// Configuration to use to execute the item - /// </param> - internal protected virtual bool OnGetCanExecute (ExecutionContext context, ConfigurationSelector configuration) + protected override void OnBoundToSolution () { - return false; + ParentSolution.SolutionItemRemoved += HandleSolutionItemRemoved; + ParentSolution.SolutionItemAdded += HandleSolutionItemAdded; + ItemExtension.OnBoundToSolution (); } - internal protected virtual IEnumerable<ExecutionTarget> OnGetExecutionTargets (ConfigurationSelector configuration) + void DoOnBoundToSolution () { - yield break; + base.OnBoundToSolution (); } - protected virtual void OnBoundToSolution () + protected override void OnUnboundFromSolution () { + ParentSolution.SolutionItemAdded -= HandleSolutionItemAdded; + ParentSolution.SolutionItemRemoved -= HandleSolutionItemRemoved; + ItemExtension.OnUnboundFromSolution (); } - internal protected virtual object OnGetService (Type t) + void DoOnUnboundFromSolution () { - return ItemHandler.GetService (t); + base.OnUnboundFromSolution (); } - /// <summary> - /// Occurs when the name of the item changes - /// </summary> - public event SolutionItemRenamedEventHandler NameChanged; + + public event SolutionItemEventHandler Saved; - /// <summary> - /// Occurs when the item is modified. - /// </summary> - public event SolutionItemModifiedEventHandler Modified; - } + class DefaultMSBuildItemExtension: SolutionItemExtension + { + internal protected override void OnInitializeFromTemplate (XmlElement template) + { + Item.OnInitializeFromTemplate (template); + } + + internal protected override FilePath OnGetDefaultBaseDirectory () + { + return Item.FileName.IsNullOrEmpty ? FilePath.Empty : Item.FileName.ParentDirectory; + } + + internal protected override IEnumerable<SolutionItem> OnGetReferencedItems (ConfigurationSelector configuration) + { + return Item.OnGetReferencedItems (configuration); + } + + internal protected override StringTagModelDescription OnGetStringTagModelDescription (ConfigurationSelector conf) + { + return Item.DoGetStringTagModelDescription (conf); + } + + internal protected override StringTagModel OnGetStringTagModel (ConfigurationSelector conf) + { + return Item.DoGetStringTagModel (conf); + } + + internal protected override bool OnGetSupportsFormat (FileFormat format) + { + return Item.OnGetSupportsFormat (format); + } + + internal protected override IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles) + { + return Item.OnGetItemFiles (includeReferencedFiles); + } + + internal protected override SolutionItemConfiguration OnCreateConfiguration (string name) + { + return new SolutionItemConfiguration (name); + } + + internal protected override string[] SupportedPlatforms { + get { + return new string [0]; + } + } + + internal protected override DateTime OnGetLastBuildTime (ConfigurationSelector configuration) + { + return Item.DoGetLastBuildTime (configuration); + } + + internal protected override Task OnLoad (ProgressMonitor monitor) + { + return Item.OnLoad (monitor); + } + + internal protected override Task OnSave (ProgressMonitor monitor) + { + return Item.DoSave (monitor); + } + + internal protected override bool OnSupportsBuild () + { + return Item.OnGetSupportsBuild (); + } + + internal protected override bool OnSupportsExecute () + { + return Item.OnGetSupportsExecute (); + } + + internal protected override Task OnExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + { + return Item.DoExecute (monitor, context, configuration); + } + + internal protected override bool OnGetCanExecute (ExecutionContext context, ConfigurationSelector configuration) + { + return Item.DoGetCanExecute (context, configuration); + } + + internal protected override IEnumerable<ExecutionTarget> OnGetExecutionTargets (ConfigurationSelector configuration) + { + yield break; + } + + internal protected override void OnExecutionTargetsChanged () + { + Item.OnExecutionTargetsChanged (); + } + + internal protected override void OnReloadRequired (SolutionItemEventArgs args) + { + Item.DoOnReloadRequired (args); + } + + internal protected override void OnItemsAdded (IEnumerable<ProjectItem> objs) + { + Item.DoOnItemsAdded (objs); + } + + internal protected override void OnItemsRemoved (IEnumerable<ProjectItem> objs) + { + Item.DoOnItemsRemoved (objs); + } + + internal protected override void OnDefaultConfigurationChanged (ConfigurationEventArgs args) + { + Item.DoOnDefaultConfigurationChanged (args); + } + + internal protected override void OnBoundToSolution () + { + Item.DoOnBoundToSolution (); + } + + internal protected override void OnUnboundFromSolution () + { + Item.DoOnUnboundFromSolution (); + } + + internal protected override void OnConfigurationAdded (ConfigurationEventArgs args) + { + Item.DoOnConfigurationAdded (args); + } + + internal protected override void OnConfigurationRemoved (ConfigurationEventArgs args) + { + Item.DoOnConfigurationRemoved (args); + } + + internal protected override void OnModified (SolutionItemModifiedEventArgs args) + { + Item.OnModified (args); + } + + internal protected override void OnNameChanged (SolutionItemRenamedEventArgs e) + { + Item.OnNameChanged (e); + } + + internal protected override IconId StockIcon { + get { + return "md-project"; + } + } + + internal protected override bool ItemFilesChanged { + get { + return Item.BaseItemFilesChanged; + } + } + + internal protected override Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return Item.OnBuild (monitor, configuration); + } + + internal protected override Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return Item.OnClean (monitor, configuration); + } + + internal protected override bool OnNeedsBuilding (ConfigurationSelector configuration) + { + return Item.OnGetNeedsBuilding (configuration); + } + } + } + [Mono.Addins.Extension] class SolutionItemTagProvider: StringTagProvider<SolutionItem>, IStringTagProvider { @@ -1126,32 +1402,37 @@ namespace MonoDevelop.Projects yield return new StringTagDescription ("AuthorCopyright", "Project Author Copyright"); yield return new StringTagDescription ("AuthorCompany", "Project Author Company"); yield return new StringTagDescription ("AuthorTrademark", "Project Trademark"); + yield return new StringTagDescription ("ProjectFile", "Project File"); } - + public override object GetTagValue (SolutionItem item, string tag) { switch (tag) { - case "ITEMNAME": - case "PROJECTNAME": - return item.Name; - case "AUTHORCOPYRIGHT": - AuthorInformation authorInfo = item.AuthorInformation ?? AuthorInformation.Default; - return authorInfo.Copyright; - case "AUTHORCOMPANY": - authorInfo = item.AuthorInformation ?? AuthorInformation.Default; - return authorInfo.Company; - case "AUTHORTRADEMARK": - authorInfo = item.AuthorInformation ?? AuthorInformation.Default; - return authorInfo.Trademark; - case "AUTHOREMAIL": - authorInfo = item.AuthorInformation ?? AuthorInformation.Default; - return authorInfo.Email; - case "AUTHORNAME": - authorInfo = item.AuthorInformation ?? AuthorInformation.Default; - return authorInfo.Name; - case "ITEMDIR": - case "PROJECTDIR": - return item.BaseDirectory; + case "ITEMNAME": + case "PROJECTNAME": + return item.Name; + case "AUTHORCOPYRIGHT": + AuthorInformation authorInfo = item.AuthorInformation ?? AuthorInformation.Default; + return authorInfo.Copyright; + case "AUTHORCOMPANY": + authorInfo = item.AuthorInformation ?? AuthorInformation.Default; + return authorInfo.Company; + case "AUTHORTRADEMARK": + authorInfo = item.AuthorInformation ?? AuthorInformation.Default; + return authorInfo.Trademark; + case "AUTHOREMAIL": + authorInfo = item.AuthorInformation ?? AuthorInformation.Default; + return authorInfo.Email; + case "AUTHORNAME": + authorInfo = item.AuthorInformation ?? AuthorInformation.Default; + return authorInfo.Name; + case "ITEMDIR": + case "PROJECTDIR": + return item.BaseDirectory; + case "ITEMFILE": + case "PROJECTFILE": + case "PROJECTFILENAME": + return item.FileName; } throw new NotSupportedException (); } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemConfiguration.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemConfiguration.cs index 8ec16e80e2..49bdaaa7a0 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemConfiguration.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemConfiguration.cs @@ -37,7 +37,7 @@ namespace MonoDevelop.Projects [DataItem (FallbackType=typeof(UnknownConfiguration))] public class SolutionItemConfiguration : ItemConfiguration { - SolutionEntityItem parentItem; + SolutionItem parentItem; public SolutionItemConfiguration () { @@ -47,7 +47,7 @@ namespace MonoDevelop.Projects { } - public SolutionEntityItem ParentItem { + public SolutionItem ParentItem { get { return parentItem; } } @@ -58,7 +58,7 @@ namespace MonoDevelop.Projects ?? configs.FirstOrDefault (c => Name == c.Name && (c.Platform == "" || c.Platform == "Any CPU")); } - internal void SetParentItem (SolutionEntityItem item) + internal void SetParentItem (SolutionItem item) { parentItem = item; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemConfigurationCollection.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemConfigurationCollection.cs index a470671b40..0e0a37dd06 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemConfigurationCollection.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemConfigurationCollection.cs @@ -38,13 +38,13 @@ namespace MonoDevelop.Projects { public class SolutionItemConfigurationCollection : ItemConfigurationCollection<SolutionItemConfiguration> { - SolutionEntityItem parentItem; + SolutionItem parentItem; public SolutionItemConfigurationCollection () { } - internal SolutionItemConfigurationCollection (SolutionEntityItem parentItem) + internal SolutionItemConfigurationCollection (SolutionItem parentItem) { this.parentItem = parentItem; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemEventArgs.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemEventArgs.cs index d9b34ca114..0ca212bfdd 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemEventArgs.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemEventArgs.cs @@ -36,10 +36,10 @@ namespace MonoDevelop.Projects public class SolutionItemEventArgs : EventArgs { - SolutionItem entry; + SolutionFolderItem entry; Solution solution; - public SolutionItem SolutionItem { + public SolutionFolderItem SolutionItem { get { return entry; } @@ -51,12 +51,12 @@ namespace MonoDevelop.Projects } } - public SolutionItemEventArgs (SolutionItem entry) + public SolutionItemEventArgs (SolutionFolderItem entry) { this.entry = entry; } - public SolutionItemEventArgs (SolutionItem entry, Solution solution) + public SolutionItemEventArgs (SolutionFolderItem entry, Solution solution) { this.solution = solution; this.entry = entry; @@ -69,7 +69,7 @@ namespace MonoDevelop.Projects { bool reloading; - public SolutionItemChangeEventArgs (SolutionItem item, Solution parentSolution, bool reloading): base (item, parentSolution) + public SolutionItemChangeEventArgs (SolutionFolderItem item, Solution parentSolution, bool reloading): base (item, parentSolution) { this.reloading = reloading; } @@ -82,14 +82,14 @@ namespace MonoDevelop.Projects /// When Reloading is true, it returns the original solution item that is being reloaded /// </summary> /// <value>The replaced item.</value> - public SolutionItem ReplacedItem { get; internal set; } + public SolutionFolderItem ReplacedItem { get; internal set; } } public delegate void SolutionItemModifiedEventHandler (object sender, SolutionItemModifiedEventArgs e); public class SolutionItemModifiedEventArgs: EventArgsChain<SolutionItemModifiedEventInfo> { - public SolutionItemModifiedEventArgs (SolutionItem item, string hint) + public SolutionItemModifiedEventArgs (SolutionFolderItem item, string hint) { Add (new SolutionItemModifiedEventInfo (item, hint)); } @@ -99,7 +99,7 @@ namespace MonoDevelop.Projects { string hint; - public SolutionItemModifiedEventInfo (SolutionItem item, string hint): base (item) + public SolutionItemModifiedEventInfo (SolutionFolderItem item, string hint): base (item) { this.hint = hint; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemExtension.cs new file mode 100644 index 0000000000..cda42c19c3 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemExtension.cs @@ -0,0 +1,289 @@ +// +// SolutionItemExtension.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using MonoDevelop.Core; +using MonoDevelop.Core.StringParsing; +using MonoDevelop.Core.Execution; +using System.Xml; +using MonoDevelop.Projects.Formats.MSBuild; +using MonoDevelop.Projects.Extensions; +using System.Threading.Tasks; +using System.Linq; + +namespace MonoDevelop.Projects +{ + public class SolutionItemExtension: WorkspaceObjectExtension, ILoadController + { + SolutionItemExtension next; + + internal string FlavorGuid { get; set; } + + internal protected override void InitializeChain (ChainedExtension next) + { + base.InitializeChain (next); + this.next = FindNextImplementation<SolutionItemExtension> (next); + } + + internal protected override bool SupportsObject (WorkspaceObject item) + { + var p = item as SolutionItem; + if (p == null) + return false; + + return FlavorGuid == null || p.GetItemTypeGuids ().Any (id => id.Equals (FlavorGuid, StringComparison.OrdinalIgnoreCase)); + } + + #region ILoadController implementation + + void ILoadController.BeginLoad () + { + OnBeginLoad (); + } + + void ILoadController.EndLoad () + { + OnEndLoad (); + } + + #endregion + + public SolutionItem Item { + get { return (SolutionItem) Owner; } + } + + internal protected override void Initialize () + { + base.Initialize (); + ProjectExtensionUtil.LoadControl (this); + } + + internal protected virtual void OnInitializeNew (string languageName, ProjectCreateInformation info, XmlElement projectOptions) + { + next.OnInitializeNew (languageName, info, projectOptions); + } + + internal protected virtual void OnInitializeFromTemplate (XmlElement template) + { + next.OnInitializeFromTemplate (template); + } + + #region Project properties + + internal protected virtual IconId StockIcon { + get { + return next.StockIcon; + } + } + #endregion + + #region Project model + + internal protected virtual FilePath OnGetDefaultBaseDirectory () + { + return next.OnGetDefaultBaseDirectory (); + } + + internal protected virtual IEnumerable<SolutionItem> OnGetReferencedItems (ConfigurationSelector configuration) + { + return next.OnGetReferencedItems (configuration); + } + + internal protected virtual StringTagModelDescription OnGetStringTagModelDescription (ConfigurationSelector conf) + { + return next.OnGetStringTagModelDescription (conf); + } + + internal protected virtual StringTagModel OnGetStringTagModel (ConfigurationSelector conf) + { + return next.OnGetStringTagModel (conf); + } + + internal protected virtual bool OnGetSupportsFormat (FileFormat format) + { + return next.OnGetSupportsFormat (format); + } + + internal protected virtual IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles) + { + return next.OnGetItemFiles (includeReferencedFiles); + } + + internal protected virtual bool ItemFilesChanged { + get { + return next.ItemFilesChanged; + } + } + + internal protected virtual SolutionItemConfiguration OnCreateConfiguration (string name) + { + return next.OnCreateConfiguration (name); + } + + internal protected virtual string[] SupportedPlatforms { + get { + return next.SupportedPlatforms; + } + } + + #endregion + + #region Building + + internal protected virtual bool OnSupportsBuild () + { + return next.OnSupportsBuild (); + } + + internal protected virtual bool OnSupportsExecute () + { + return next.OnSupportsExecute (); + } + + internal protected virtual Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return next.OnClean (monitor, configuration); + } + + internal protected virtual bool OnNeedsBuilding (ConfigurationSelector configuration) + { + return next.OnNeedsBuilding (configuration); + } + + internal protected virtual Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) + { + return next.OnBuild (monitor, configuration); + } + + internal protected virtual DateTime OnGetLastBuildTime (ConfigurationSelector configuration) + { + return next.OnGetLastBuildTime (configuration); + } + + #endregion + + #region Load / Save + + internal protected virtual Task OnLoad (ProgressMonitor monitor) + { + return next.OnLoad (monitor); + } + + internal protected virtual Task OnSave (ProgressMonitor monitor) + { + return next.OnSave (monitor); + } + + protected virtual void OnBeginLoad () + { + } + + protected virtual void OnEndLoad () + { + } + + #endregion + + #region Execution + + internal protected virtual Task OnExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + { + return next.OnExecute (monitor, context, configuration); + } + + internal protected virtual bool OnGetCanExecute (ExecutionContext context, ConfigurationSelector configuration) + { + return next.OnGetCanExecute (context, configuration); + } + + internal protected virtual IEnumerable<ExecutionTarget> OnGetExecutionTargets (ConfigurationSelector configuration) + { + return next.OnGetExecutionTargets (configuration); + } + + internal protected virtual void OnExecutionTargetsChanged () + { + next.OnExecutionTargetsChanged (); + } + + #endregion + + #region Events + + internal protected virtual void OnReloadRequired (SolutionItemEventArgs args) + { + next.OnReloadRequired (args); + } + + internal protected virtual void OnItemsAdded (IEnumerable<ProjectItem> objs) + { + next.OnItemsAdded (objs); + } + + internal protected virtual void OnItemsRemoved (IEnumerable<ProjectItem> objs) + { + next.OnItemsRemoved (objs); + } + + internal protected virtual void OnDefaultConfigurationChanged (ConfigurationEventArgs args) + { + next.OnDefaultConfigurationChanged (args); + } + + internal protected virtual void OnBoundToSolution () + { + next.OnBoundToSolution (); + } + + internal protected virtual void OnUnboundFromSolution () + { + next.OnUnboundFromSolution (); + } + + internal protected virtual void OnConfigurationAdded (ConfigurationEventArgs args) + { + next.OnConfigurationAdded (args); + } + + internal protected virtual void OnConfigurationRemoved (ConfigurationEventArgs args) + { + next.OnConfigurationRemoved (args); + } + + internal protected virtual void OnModified (SolutionItemModifiedEventArgs args) + { + next.OnModified (args); + } + + internal protected virtual void OnNameChanged (SolutionItemRenamedEventArgs e) + { + next.OnNameChanged (e); + } + + #endregion + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemFactory.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemFactory.cs new file mode 100644 index 0000000000..9237ae7de1 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemFactory.cs @@ -0,0 +1,36 @@ +// +// SolutionItemFactory.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Threading.Tasks; + +namespace MonoDevelop.Projects +{ + public abstract class SolutionItemFactory + { + public abstract Task<SolutionItem> CreateItem (string fileName, string typeGuid); + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemReference.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemReference.cs index d50f388d81..7abc72f987 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemReference.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemReference.cs @@ -43,10 +43,10 @@ namespace MonoDevelop.Projects { } - public SolutionItemReference (SolutionItem item) + public SolutionItemReference (SolutionFolderItem item) { - if (item is SolutionEntityItem) { - path = ((SolutionEntityItem)item).FileName; + if (item is SolutionItem) { + path = ((SolutionItem)item).FileName; } else { path = item.ParentSolution.FileName; if ((item is SolutionFolder) && ((SolutionFolder)item).IsRoot) diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownProject.cs index 581d8a1b6a..e2142229bd 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownProject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownProject.cs @@ -1,4 +1,4 @@ -// +// // UnknownProject.cs // // Author: @@ -26,33 +26,31 @@ using System; using MonoDevelop.Core; using System.Collections.Generic; +using System.Threading.Tasks; namespace MonoDevelop.Projects { public class UnknownProject: Project { - string loadError = string.Empty; - bool unloaded; - // Store the file name locally to avoid the file format to change it FilePath fileName; public UnknownProject () { + IsUnsupportedProject = true; NeedsReload = false; - loadError = GettextCatalog.GetString ("Unknown project type"); } public UnknownProject (FilePath file, string loadError): this () { NeedsReload = false; FileName = file; - this.loadError = loadError; + UnsupportedProjectMessage = loadError; } - public override IEnumerable<string> GetProjectTypes () + public override bool SupportsConfigurations () { - yield return ""; + return true; } public override FilePath FileName { @@ -67,55 +65,36 @@ namespace MonoDevelop.Projects } } - - public string LoadError { - get { return unloaded ? GettextCatalog.GetString ("Unavailable") : loadError; } - set { loadError = value; } - } - - public bool UnloadedEntry { - get { return unloaded; } - set { unloaded = value; } - } - - public override string Name { - get { - if (!FileName.IsNullOrEmpty) - return FileName.FileNameWithoutExtension; - else - return GettextCatalog.GetString ("Unknown entry"); - } - set { } + protected override string OnGetName () + { + if (!FileName.IsNullOrEmpty) + return FileName.FileNameWithoutExtension; + else + return GettextCatalog.GetString ("Unknown entry"); } - internal protected override bool OnGetSupportsTarget (string target) + protected override bool OnGetSupportsTarget (string target) { // We can't do anything with unsupported projects, other than display them in the solution pad return false; } - protected override void OnClean (IProgressMonitor monitor, ConfigurationSelector configuration) + protected override Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration) { + return Task.FromResult (BuildResult.Success); } - protected override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration) + protected override Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { var r = new BuildResult (); - r.AddError (loadError); - return r; - } - - protected internal override void OnExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) - { - } - - protected internal override bool OnGetNeedsBuilding (ConfigurationSelector configuration) - { - return false; + r.AddError (UnsupportedProjectMessage); + return Task.FromResult (r); } - protected internal override void OnSetNeedsBuilding (bool value, ConfigurationSelector configuration) + protected override Task OnExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { + return new Task (delegate { + }); } public override SolutionItemConfiguration CreateConfiguration (string name) diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownSolutionItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownSolutionItem.cs index 08d8697279..9ab6a3102b 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownSolutionItem.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownSolutionItem.cs @@ -28,10 +28,11 @@ using System; using MonoDevelop.Core; +using System.Threading.Tasks; namespace MonoDevelop.Projects { - public class UnknownSolutionItem: SolutionEntityItem + public class UnknownSolutionItem: SolutionItem { string loadError = string.Empty; bool unloaded; @@ -41,7 +42,15 @@ namespace MonoDevelop.Projects public UnknownSolutionItem () { + Initialize (this); NeedsReload = false; + IsUnsupportedProject = true; + } + + public override bool SupportsConfigurations () + { + // The item is unknown, but we still want to read/write its configurations + return true; } public override FilePath FileName { @@ -70,48 +79,30 @@ namespace MonoDevelop.Projects loadError = GettextCatalog.GetString ("Unavailable"); } } - - public override string Name { - get { - if (!FileName.IsNullOrEmpty) - return FileName.FileNameWithoutExtension; - else - return GettextCatalog.GetString ("Unknown entry"); - } - set { } - } - internal protected override bool OnGetSupportsTarget (string target) + protected override string OnGetName () { - return false; + if (!FileName.IsNullOrEmpty) + return FileName.FileNameWithoutExtension; + else + return GettextCatalog.GetString ("Unknown entry"); } - - protected override void OnClean (IProgressMonitor monitor, ConfigurationSelector configuration) + + protected override Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration) { + return Task.FromResult (BuildResult.Success); } - protected override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration) + protected override Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { var r = new BuildResult (); r.AddError ("Project unavailable"); - return r; - } - - protected internal override void OnExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) - { - } - - protected internal override bool OnGetNeedsBuilding (ConfigurationSelector configuration) - { - return false; - } - - protected internal override void OnSetNeedsBuilding (bool value, ConfigurationSelector configuration) - { + return Task.FromResult (r); } - protected internal override void OnSave (IProgressMonitor monitor) + protected internal override Task OnSave (ProgressMonitor monitor) { + return Task.FromResult (0); } } @@ -119,6 +110,7 @@ namespace MonoDevelop.Projects { public UnloadedSolutionItem () { + Initialize (this); UnloadedEntry = true; } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownWorkspaceItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownWorkspaceItem.cs index a80b990f9c..3c598966a1 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownWorkspaceItem.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownWorkspaceItem.cs @@ -27,6 +27,7 @@ using System; using MonoDevelop.Core; +using System.Threading.Tasks; namespace MonoDevelop.Projects { @@ -40,6 +41,7 @@ namespace MonoDevelop.Projects public UnknownWorkspaceItem () { NeedsReload = false; + Initialize (this); } public string LoadError { @@ -52,19 +54,17 @@ namespace MonoDevelop.Projects set { unloaded = value; } } - protected internal override void OnSave (IProgressMonitor monitor) + protected internal override Task OnSave (ProgressMonitor monitor) { - Services.ProjectService.InternalWriteWorkspaceItem (monitor, FileName, this); + return Services.ProjectService.InternalWriteWorkspaceItem (monitor, FileName, this); } - public override string Name { - get { - if (!FileName.IsNullOrEmpty) - return FileName.FileNameWithoutExtension; - else - return GettextCatalog.GetString ("Unknown entry"); - } - set { } + protected override string OnGetName () + { + if (!FileName.IsNullOrEmpty) + return FileName.FileNameWithoutExtension; + else + return GettextCatalog.GetString ("Unknown entry"); } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Workspace.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Workspace.cs index a59cdab116..c75837c221 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Workspace.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Workspace.cs @@ -33,13 +33,20 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using MonoDevelop.Core; using MonoDevelop.Core.Serialization; +using System.Linq; +using System.Threading.Tasks; namespace MonoDevelop.Projects { [ProjectModelDataItem] - public class Workspace: WorkspaceItem, ICustomDataItem + public class Workspace: WorkspaceItem, ICustomDataItem, IBuildTarget { WorkspaceItemCollection items; + + public Workspace () + { + Initialize (this); + } public override void Dispose () { @@ -47,6 +54,37 @@ namespace MonoDevelop.Projects foreach (WorkspaceItem it in Items) it.Dispose (); } + + public async Task<BuildResult> Build (ProgressMonitor monitor, ConfigurationSelector configuration, bool buildReferencedTargets = false) + { + var res = new BuildResult { BuildCount = 0 }; + foreach (var bt in Items.OfType<IBuildTarget> ()) + res.Append (await bt.Build (monitor, configuration)); + return res; + } + + public async Task<BuildResult> Clean (ProgressMonitor monitor, ConfigurationSelector configuration) + { + var res = new BuildResult { BuildCount = 0 }; + foreach (var bt in Items.OfType<IBuildTarget> ()) + res.Append (await bt.Clean (monitor, configuration)); + return res; + } + + public Task Execute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + { + throw new NotSupportedException (); + } + + public bool CanExecute (ExecutionContext context, ConfigurationSelector configuration) + { + return false; + } + + public bool NeedsBuilding (ConfigurationSelector configuration) + { + return Items.OfType<IBuildTarget> ().Any (t => t.NeedsBuilding (configuration)); + } public override ReadOnlyCollection<string> GetConfigurations () { @@ -67,35 +105,12 @@ namespace MonoDevelop.Projects return items; } } - - public override ReadOnlyCollection<T> GetAllItems<T> () - { - List<T> list = new List<T> (); - GetAllItems<T> (list, this); - return list.AsReadOnly (); - } - - void GetAllItems<T> (List<T> list, WorkspaceItem item) where T: WorkspaceItem + + protected override IEnumerable<WorkspaceObject> OnGetChildren () { - if (item is T) - list.Add ((T) item); - - if (item is Workspace) { - foreach (WorkspaceItem citem in ((Workspace)item).Items) - GetAllItems<T> (list, citem); - } + return Items; } - public override SolutionEntityItem FindSolutionItem (string fileName) - { - foreach (WorkspaceItem it in Items) { - SolutionEntityItem si = it.FindSolutionItem (fileName); - if (si != null) - return si; - } - return null; - }
- [Obsolete("Use GetProjectsContainingFile() (plural) instead")]
public override Project GetProjectContainingFile (FilePath fileName) { @@ -116,7 +131,7 @@ namespace MonoDevelop.Projects } } - public override bool ContainsItem (IWorkspaceObject obj) + public override bool ContainsItem (WorkspaceObject obj) { if (base.ContainsItem (obj)) return true; @@ -129,53 +144,16 @@ namespace MonoDevelop.Projects } - public override ReadOnlyCollection<T> GetAllSolutionItems<T> () - { - List<T> list = new List<T> (); - foreach (WorkspaceItem it in Items) { - list.AddRange (it.GetAllSolutionItems<T> ()); - } - return list.AsReadOnly (); - } - - public override void ConvertToFormat (FileFormat format, bool convertChildren) + public async override Task ConvertToFormat (FileFormat format, bool convertChildren) { - base.ConvertToFormat (format, convertChildren); + await base.ConvertToFormat (format, convertChildren); if (convertChildren) { foreach (WorkspaceItem it in Items) - it.ConvertToFormat (format, true); + await it.ConvertToFormat (format, true); } } - - internal protected override BuildResult OnRunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration) - { - BuildResult result = null; - monitor.BeginTask (null, Items.Count); - try { - foreach (WorkspaceItem it in Items) { - BuildResult res = it.RunTarget (monitor, target, configuration); - if (res != null) { - if (result == null) { - result = new BuildResult (); - result.BuildCount = 0; - } - result.Append (res); - } - monitor.Step (1); - } - } finally { - monitor.EndTask (); - } - return result; - } - - protected internal override void OnExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) - { - throw new NotImplementedException (); - } - - public WorkspaceItem ReloadItem (IProgressMonitor monitor, WorkspaceItem item) + public async Task<WorkspaceItem> ReloadItem (ProgressMonitor monitor, WorkspaceItem item) { if (Items.IndexOf (item) == -1) throw new InvalidOperationException ("Item '" + item.Name + "' does not belong to workspace '" + Name + "'"); @@ -184,7 +162,7 @@ namespace MonoDevelop.Projects WorkspaceItem newItem; try { - newItem = Services.ProjectService.ReadWorkspaceItem (monitor, item.FileName); + newItem = await Services.ProjectService.ReadWorkspaceItem (monitor, item.FileName); } catch (Exception ex) { UnknownWorkspaceItem e = new UnknownWorkspaceItem (); e.LoadError = ex.Message; @@ -203,9 +181,9 @@ namespace MonoDevelop.Projects return newItem; }
- public override List<FilePath> GetItemFiles (bool includeReferencedFiles) + protected override IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles) {
- List<FilePath> list = base.GetItemFiles (includeReferencedFiles); + List<FilePath> list = base.OnGetItemFiles (includeReferencedFiles).ToList (); if (includeReferencedFiles) { foreach (WorkspaceItem it in Items) list.AddRange (it.GetItemFiles (true)); @@ -271,20 +249,20 @@ namespace MonoDevelop.Projects return data; } - void ICustomDataItem.Deserialize (ITypeSerializer handler, DataCollection data) + async void ICustomDataItem.Deserialize (ITypeSerializer handler, DataCollection data) { DataItem items = (DataItem) data.Extract ("Items"); handler.Deserialize (this, data); - IProgressMonitor monitor = handler.SerializationContext.ProgressMonitor; + ProgressMonitor monitor = handler.SerializationContext.ProgressMonitor; if (monitor == null) - monitor = new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor (); + monitor = new ProgressMonitor (); if (items != null) { string baseDir = Path.GetDirectoryName (handler.SerializationContext.BaseFile); monitor.BeginTask (null, items.ItemData.Count); try { foreach (DataValue item in items.ItemData) { string file = Path.Combine (baseDir, item.Value); - WorkspaceItem it = Services.ProjectService.ReadWorkspaceItem (monitor, file); + WorkspaceItem it = await Services.ProjectService.ReadWorkspaceItem (monitor, file); if (it != null) Items.Add (it); monitor.Step (1); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItem.cs index 8455a52481..d570d0792e 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItem.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItem.cs @@ -41,15 +41,17 @@ using MonoDevelop.Core.Serialization; using MonoDevelop.Core.StringParsing; using MonoDevelop.Core.Execution; using MonoDevelop.Projects.Extensions; +using Mono.Addins; +using System.Linq; +using System.Threading.Tasks; namespace MonoDevelop.Projects { - public abstract class WorkspaceItem : IBuildTarget, IWorkspaceFileObject, ILoadController + public abstract class WorkspaceItem : WorkspaceObject, IWorkspaceFileObject, ILoadController { Workspace parentWorkspace; FileFormat format; internal bool FormatSet; - Hashtable extendedProperties;
FilePath fileName; int loading; PropertyBag userProperties; @@ -57,17 +59,12 @@ namespace MonoDevelop.Projects [ProjectPathItemProperty ("BaseDirectory", DefaultValue=null)]
FilePath baseDirectory; - + public Workspace ParentWorkspace { get { return parentWorkspace; } - internal set { parentWorkspace = value; } - } - - public IDictionary ExtendedProperties { - get { - if (extendedProperties == null) - extendedProperties = new Hashtable (); - return extendedProperties; + internal set { + parentWorkspace = value; + ParentObject = value; } } @@ -80,12 +77,9 @@ namespace MonoDevelop.Projects } } - public virtual string Name { - get {
- if (fileName.IsNullOrEmpty)
- return string.Empty;
- else
- return fileName.FileNameWithoutExtension; + public new string Name { + get { + return base.Name;
} set { if (fileName.IsNullOrEmpty)
@@ -97,6 +91,14 @@ namespace MonoDevelop.Projects } } } + + protected override string OnGetName () + { + if (fileName.IsNullOrEmpty) + return string.Empty; + else + return fileName.FileNameWithoutExtension; + } public virtual FilePath FileName { get { @@ -124,12 +126,9 @@ namespace MonoDevelop.Projects FileName = baseDirectory.Combine (name) + ".x"; } - public FilePath BaseDirectory { + public new FilePath BaseDirectory { get { - if (baseDirectory.IsNull) - return FileName.ParentDirectory.FullPath; - else - return baseDirectory; + return base.BaseDirectory; } set { if (!value.IsNull && !FileName.IsNull && FileName.ParentDirectory.FullPath == value.FullPath) @@ -141,82 +140,64 @@ namespace MonoDevelop.Projects NotifyModified (); } } + + protected override string OnGetBaseDirectory () + { + if (baseDirectory.IsNull) + return FileName.ParentDirectory.FullPath; + else + return baseDirectory; + } - public FilePath ItemDirectory { - get { return FileName.ParentDirectory.FullPath; } + protected override string OnGetItemDirectory () + { + return FileName.ParentDirectory.FullPath; } protected bool Loading { get { return loading > 0; } } - public WorkspaceItem () + protected WorkspaceItem () { - MonoDevelop.Projects.Extensions.ProjectExtensionUtil.LoadControl (this); + ProjectExtensionUtil.LoadControl (this); fileStatusTracker = new FileStatusTracker<WorkspaceItemEventArgs> (this, OnReloadRequired, new WorkspaceItemEventArgs (this)); + Initialize (this); }
- public T GetService<T> () where T: class + WorkspaceItemExtension itemExtension; + + WorkspaceItemExtension ItemExtension { + get { + if (itemExtension == null) + itemExtension = ExtensionChain.GetExtension<WorkspaceItemExtension> (); + return itemExtension; + } + } + + protected override IEnumerable<WorkspaceObjectExtension> CreateDefaultExtensions () { - return (T) GetService (typeof(T)); + yield return new DefaultWorkspaceItemExtension (); } - - public virtual object GetService (Type t) + + public IEnumerable<FilePath> GetItemFiles (bool includeReferencedFiles) { - return Services.ProjectService.GetExtensionChain (this).GetService (this, t); + return ItemExtension.GetItemFiles (includeReferencedFiles);
} - public virtual List<FilePath> GetItemFiles (bool includeReferencedFiles) - {
+ protected virtual IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles) + { List<FilePath> col = FileFormat.Format.GetItemFiles (this); if (!string.IsNullOrEmpty (FileName) && !col.Contains (FileName)) col.Add (FileName); return col; } - - public virtual SolutionEntityItem FindSolutionItem (string fileName) - { - return null; - } - - public virtual bool ContainsItem (IWorkspaceObject obj) + + public virtual bool ContainsItem (WorkspaceObject obj) { return this == obj; } - public ReadOnlyCollection<SolutionItem> GetAllSolutionItems () - { - return GetAllSolutionItems<SolutionItem> (); - } - - public virtual ReadOnlyCollection<T> GetAllSolutionItems<T> () where T: SolutionItem - { - return new List<T> ().AsReadOnly (); - } - - public ReadOnlyCollection<Project> GetAllProjects () - { - return GetAllSolutionItems<Project> (); - } - - public virtual ReadOnlyCollection<Solution> GetAllSolutions () - { - return GetAllItems<Solution> (); - } - - public ReadOnlyCollection<WorkspaceItem> GetAllItems () - { - return GetAllItems<WorkspaceItem> (); - } - - public virtual ReadOnlyCollection<T> GetAllItems<T> () where T: WorkspaceItem - { - List<T> list = new List<T> (); - if (this is T) - list.Add ((T)this); - return list.AsReadOnly (); - }
- [Obsolete("Use GetProjectsContainingFile() (plural) instead")]
public virtual Project GetProjectContainingFile (FilePath fileName) { @@ -232,119 +213,12 @@ namespace MonoDevelop.Projects { return new ReadOnlyCollection<string> (new string [0]); } - - protected internal virtual void OnSave (IProgressMonitor monitor) - { - Services.ProjectService.InternalWriteWorkspaceItem (monitor, FileName, this); - } - + internal void SetParentWorkspace (Workspace workspace) { parentWorkspace = workspace; } - - public BuildResult RunTarget (IProgressMonitor monitor, string target, string configuration) - { - return RunTarget (monitor, target, (SolutionConfigurationSelector) configuration); - } - - public BuildResult RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration) - { - return Services.ProjectService.GetExtensionChain (this).RunTarget (monitor, this, target, configuration); - } - - public bool SupportsBuild () - { - return SupportsTarget (ProjectService.BuildTarget); - } - public void Clean (IProgressMonitor monitor, string configuration) - { - Clean (monitor, (SolutionConfigurationSelector) configuration); - } - - public void Clean (IProgressMonitor monitor, ConfigurationSelector configuration) - { - Services.ProjectService.GetExtensionChain (this).RunTarget (monitor, this, ProjectService.CleanTarget, configuration); - } - - public bool SupportsTarget (string target) - { - return Services.ProjectService.GetExtensionChain (this).SupportsTarget (this, target); - } - - public bool SupportsExecute () - { - return Services.ProjectService.GetExtensionChain (this).SupportsExecute (this); - } - - public BuildResult Build (IProgressMonitor monitor, string configuration) - { - return InternalBuild (monitor, (SolutionConfigurationSelector) configuration); - } - - public BuildResult Build (IProgressMonitor monitor, ConfigurationSelector configuration) - { - return InternalBuild (monitor, configuration); - } - - public void Execute (IProgressMonitor monitor, ExecutionContext context, string configuration) - { - Execute (monitor, context, (SolutionConfigurationSelector) configuration); - } - - public void Execute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) - { - Services.ProjectService.GetExtensionChain (this).Execute (monitor, this, context, configuration); - } - - public bool CanExecute (ExecutionContext context, string configuration) - { - return CanExecute (context, (SolutionConfigurationSelector) configuration); - } - - public bool CanExecute (ExecutionContext context, ConfigurationSelector configuration) - { - return Services.ProjectService.GetExtensionChain (this).CanExecute (this, context, configuration); - } - - public IEnumerable<ExecutionTarget> GetExecutionTargets (string configuration) - { - return GetExecutionTargets ((SolutionConfigurationSelector) configuration); - } - - public IEnumerable<ExecutionTarget> GetExecutionTargets (ConfigurationSelector configuration) - { - return Services.ProjectService.GetExtensionChain (this).GetExecutionTargets (this, configuration); - } - - [Obsolete ("This method will be removed in future releases")] - public bool NeedsBuilding (string configuration) - { - return true; - } - - [Obsolete ("This method will be removed in future releases")] - public bool NeedsBuilding (ConfigurationSelector configuration) - { - return true; - } - - [Obsolete ("This method will be removed in future releases")] - public void SetNeedsBuilding (bool value) - { - } - - [Obsolete ("This method will be removed in future releases")] - public void SetNeedsBuilding (bool needsBuilding, string configuration) - { - } - - [Obsolete ("This method will be removed in future releases")] - public void SetNeedsBuilding (bool needsBuilding, ConfigurationSelector configuration) - { - } - public virtual FileFormat FileFormat { get { if (format == null) { @@ -359,17 +233,13 @@ namespace MonoDevelop.Projects return true; } - public virtual void ConvertToFormat (FileFormat format, bool convertChildren) + public virtual Task ConvertToFormat (FileFormat format, bool convertChildren) { FormatSet = true; this.format = format; if (!string.IsNullOrEmpty (FileName)) FileName = format.GetValidFileName (this, FileName); - } - - internal virtual BuildResult InternalBuild (IProgressMonitor monitor, ConfigurationSelector configuration) - { - return Services.ProjectService.GetExtensionChain (this).RunTarget (monitor, this, ProjectService.BuildTarget, configuration); + return Task.FromResult (0); } protected virtual void OnConfigurationsChanged () @@ -380,17 +250,27 @@ namespace MonoDevelop.Projects ParentWorkspace.OnConfigurationsChanged (); }
- public void Save (FilePath fileName, IProgressMonitor monitor) + public void Save (FilePath fileName, ProgressMonitor monitor) { - FileName = fileName; - Save (monitor); + SaveAsync (fileName, monitor).Wait (); } - public void Save (IProgressMonitor monitor) + public Task SaveAsync (FilePath fileName, ProgressMonitor monitor) + { + FileName = fileName; + return SaveAsync (monitor); + } + + public void Save (ProgressMonitor monitor) + { + SaveAsync (monitor).Wait (); + } + + public async Task SaveAsync (ProgressMonitor monitor) { try { fileStatusTracker.BeginSave (); - Services.ProjectService.GetExtensionChain (this).Save (monitor, this); + await ItemExtension.Save (monitor); SaveUserProperties (); OnSaved (new WorkspaceItemEventArgs (this)); @@ -400,7 +280,12 @@ namespace MonoDevelop.Projects } FileService.NotifyFileChanged (FileName); } - + + protected internal virtual Task OnSave (ProgressMonitor monitor) + { + return Services.ProjectService.InternalWriteWorkspaceItem (monitor, FileName, this); + } + public virtual bool NeedsReload { get { return fileStatusTracker.NeedsReload; @@ -416,59 +301,11 @@ namespace MonoDevelop.Projects } } - internal protected virtual BuildResult OnRunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration) - { - if (target == ProjectService.BuildTarget) - return OnBuild (monitor, configuration); - else if (target == ProjectService.CleanTarget) { - OnClean (monitor, configuration); - return null; - } - return null; - } - - internal protected virtual bool OnGetSupportsTarget (string target) - { - return true; - } - internal protected virtual bool OnGetSupportsExecute () { return true; } - protected virtual void OnClean (IProgressMonitor monitor, ConfigurationSelector configuration) - { - } - - protected virtual BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration) - { - return null; - } - - internal protected virtual void OnExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) - { - } - - internal protected virtual bool OnGetCanExecute (ExecutionContext context, ConfigurationSelector configuration) - { - return true; - } - - internal protected virtual IEnumerable<ExecutionTarget> OnGetExecutionTargets (ConfigurationSelector configuration) - { - yield break; - } - - internal protected virtual bool OnGetNeedsBuilding (ConfigurationSelector configuration) - { - return true; - } - - internal protected virtual void OnSetNeedsBuilding (bool val, ConfigurationSelector configuration) - { - } - void ILoadController.BeginLoad () { loading++; @@ -571,15 +408,9 @@ namespace MonoDevelop.Projects return absPath.ToRelative (BaseDirectory); } - public virtual void Dispose() + public override void Dispose() { - if (extendedProperties != null) { - foreach (object ob in extendedProperties.Values) { - IDisposable disp = ob as IDisposable; - if (disp != null) - disp.Dispose (); - } - } + base.Dispose (); if (userProperties != null) userProperties.Dispose (); } @@ -592,11 +423,6 @@ namespace MonoDevelop.Projects NameChanged (this, e); } - internal protected virtual object OnGetService (Type t) - { - return null; - } - protected void NotifyModified () { OnModified (new WorkspaceItemEventArgs (this)); @@ -632,6 +458,19 @@ namespace MonoDevelop.Projects fileStatusTracker.ReloadRequired -= value; } }*/ + + internal class DefaultWorkspaceItemExtension: WorkspaceItemExtension + { + internal protected override IEnumerable<FilePath> GetItemFiles (bool includeReferencedFiles) + { + return Item.OnGetItemFiles (includeReferencedFiles); + } + + internal protected override Task Save (ProgressMonitor monitor) + { + return Item.OnSave (monitor); + } + } } class FileStatusTracker<TEventArgs> where TEventArgs:EventArgs diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItemExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItemExtension.cs new file mode 100644 index 0000000000..5d3d7643ac --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItemExtension.cs @@ -0,0 +1,67 @@ +// +// WorkspaceItemExtension.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using MonoDevelop.Core; +using System.Threading.Tasks; + +namespace MonoDevelop.Projects +{ + public class WorkspaceItemExtension: WorkspaceObjectExtension + { + WorkspaceItemExtension next; + + internal protected override bool SupportsObject (WorkspaceObject item) + { + return item is WorkspaceItem; + } + + internal protected override void InitializeChain (ChainedExtension next) + { + this.next = FindNextImplementation<WorkspaceItemExtension> (next); + } + + protected WorkspaceItem Item { + get { return (WorkspaceItem) base.Owner; } + } + + internal protected virtual bool SupportsItem (WorkspaceItem item) + { + return next.SupportsItem (item); + } + + internal protected virtual Task Save (ProgressMonitor monitor) + { + return next.Save (monitor); + } + + internal protected virtual IEnumerable<FilePath> GetItemFiles (bool includeReferencedFiles) + { + return next.GetItemFiles (includeReferencedFiles); + } + } +} + diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObject.cs new file mode 100644 index 0000000000..ec464b7769 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObject.cs @@ -0,0 +1,303 @@ +// IWorkspaceObject.cs +// +// Author: +// Lluis Sanchez Gual <lluis@novell.com> +// +// Copyright (c) 2008 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// + +using System; +using System.Collections.Generic; +using MonoDevelop.Core; +using MonoDevelop.Core.Serialization; +using System.Collections; +using MonoDevelop.Projects.Extensions; +using Mono.Addins; +using System.Linq; +using System.Threading.Tasks; + + +namespace MonoDevelop.Projects +{ + public abstract class WorkspaceObject: IExtendedDataItem, IFolderItem, IDisposable + { + Hashtable extendedProperties; + bool initializeCalled; + + protected void Initialize<T> (T instance) + { + if (instance.GetType () != typeof(T)) + return; + initializeCalled = true; + OnInitialize (); + InitializeExtensionChain (); + OnExtensionChainInitialized (); + } + + public string Name { + get { return OnGetName (); } + } +
+ public FilePath ItemDirectory { + get { return OnGetItemDirectory (); } + } +
+ public FilePath BaseDirectory { + get { return OnGetBaseDirectory (); } + } + + public WorkspaceObject ParentObject { get; protected set; } + + public IEnumerable<WorkspaceObject> GetChildren () + { + return OnGetChildren (); + } + + public IEnumerable<T> GetAllItems<T> () where T: WorkspaceObject + { + if (this is T) + yield return (T)this; + foreach (var c in OnGetChildren ()) { + foreach (var r in c.GetAllItems<T> ()) + yield return r; + } + } + + /// <summary> + /// Gets extended properties. + /// </summary> + /// <remarks> + /// This dictionary can be used by add-ins to store arbitrary information about this solution item. + /// Keys and values can be of any type. + /// If a value implements IDisposable, the value will be disposed when this item is disposed. + /// </remarks> + public IDictionary ExtendedProperties { + get { + return OnGetExtendedProperties (); + } + } + + /// <summary> + /// Gets a value indicating whether this <see cref="MonoDevelop.Projects.SolutionItem"/> has been disposed. + /// </summary> + /// <value> + /// <c>true</c> if disposed; otherwise, <c>false</c>. + /// </value> + internal protected bool Disposed { get; private set; } + + public virtual void Dispose () + { + if (Disposed) + return; + + Disposed = true; + + if (extensionChain != null) { + extensionChain.Dispose (); + extensionChain = null; + } + + if (extendedProperties != null) { + foreach (object ob in extendedProperties.Values) { + IDisposable disp = ob as IDisposable; + if (disp != null) + disp.Dispose (); + } + extendedProperties = null; + } + } + + /// <summary> + /// Gets a service instance of a given type + /// </summary> + /// <returns> + /// The service. + /// </returns> + /// <typeparam name='T'> + /// Type of the service + /// </typeparam> + /// <remarks> + /// This method looks for an imlpementation of a service of the given type. + /// </remarks> + public T GetService<T> () + { + return (T) GetService (typeof(T)); + } + + /// <summary> + /// Gets a service instance of a given type + /// </summary> + /// <returns> + /// The service. + /// </returns> + /// <param name='t'> + /// Type of the service + /// </param> + /// <remarks> + /// This method looks for an imlpementation of a service of the given type. + /// </remarks> + public object GetService (Type t) + { + return ItemExtension.GetService (t); + } + + /// <summary> + /// Gets a value indicating whether the extension chain for this object has already been created and initialized + /// </summary> + protected bool IsExtensionChainCreated { + get { return extensionChain != null; } + } + + ExtensionChain extensionChain; + protected ExtensionChain ExtensionChain { + get { + if (extensionChain == null) { + if (!initializeCalled) + throw new InvalidOperationException ("The constructor of type " + GetType () + " must call Initialize(this)"); + else + throw new InvalidOperationException ("The extension chain can't be used before OnExtensionChainInitialized() method is called"); + } + return extensionChain; + } + } + + WorkspaceObjectExtension itemExtension; + + WorkspaceObjectExtension ItemExtension { + get { + if (itemExtension == null) + itemExtension = ExtensionChain.GetExtension<WorkspaceObjectExtension> (); + return itemExtension; + } + } + + void InitializeExtensionChain () + { + // Create an initial empty extension chain. This avoid crashes in case a call to SupportsObject ends + // calling methods from the extension + + var tempExtensions = new List<WorkspaceObjectExtension> (); + tempExtensions.AddRange (CreateDefaultExtensions ().Reverse ()); + extensionChain = ExtensionChain.Create (tempExtensions.ToArray ()); + foreach (var e in tempExtensions) + e.Init (this); + + // Collect extensions that support this object + + var extensions = new List<WorkspaceObjectExtension> (); + foreach (ProjectModelExtensionNode node in AddinManager.GetExtensionNodes (ProjectService.ProjectModelExtensionsPath)) { + if (node.CanHandleObject (this)) { + var ext = node.CreateExtension (); + if (ext.SupportsObject (this)) + extensions.Add (ext); + else + ext.Dispose (); + } + } + + foreach (var e in tempExtensions) + e.Dispose (); + + // Now create the final extension chain + + extensions.Reverse (); + extensions.AddRange (CreateDefaultExtensions ().Reverse ()); + extensionChain = ExtensionChain.Create (extensions.ToArray ()); + foreach (var e in extensions) + e.Init (this); + } + + protected virtual IEnumerable<WorkspaceObjectExtension> CreateDefaultExtensions () + { + yield return new DefaultWorkspaceObjectExtension (); + } + + /// <summary> + /// Called after the object is created, but before the extension chain has been created. + /// </summary> + protected virtual void OnInitialize () + { + } + + /// <summary> + /// Called when the extension chain for this object has been created. This method can be overriden + /// to do initializations on the object that require access to the extension chain + /// </summary> + protected virtual void OnExtensionChainInitialized () + { + } + + protected virtual IDictionary OnGetExtendedProperties () + { + if (extendedProperties == null) + extendedProperties = new Hashtable (); + return extendedProperties; + } + + protected virtual IEnumerable<WorkspaceObject> OnGetChildren () + { + yield break; + } + + protected virtual object OnGetService (Type t) + { + return t.IsInstanceOfType (this) ? this : null; + } + + protected abstract string OnGetName (); + + protected abstract string OnGetItemDirectory (); + + protected abstract string OnGetBaseDirectory (); + + internal class DefaultWorkspaceObjectExtension: WorkspaceObjectExtension + { + internal protected override object GetService (Type t) + { + return Owner.OnGetService (t); + } + } + } + + public static class WorkspaceObjectExtensions + { + public static T As<T> (this WorkspaceObject ob) where T:class + { + return ob != null ? ob.GetService<T> () : null; + } + } + + public interface IWorkspaceFileObject: IFileItem, IDisposable + { + FileFormat FileFormat { get; } + Task ConvertToFormat (FileFormat format, bool convertChildren); + bool SupportsFormat (FileFormat format);
+ IEnumerable<FilePath> GetItemFiles (bool includeReferencedFiles); + new FilePath FileName { get; set; } + bool NeedsReload { get; set; } + bool ItemFilesChanged { get; } + Task SaveAsync (ProgressMonitor monitor); + string Name { get; set; } + FilePath BaseDirectory { get; } + FilePath ItemDirectory { get; } + } +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObjectExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObjectExtension.cs new file mode 100644 index 0000000000..541c25ad7c --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObjectExtension.cs @@ -0,0 +1,63 @@ +// +// WorkspaceObjectExtension.cs +// +// Author: +// Lluis Sanchez Gual <lluis@xamarin.com> +// +// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Mono.Addins; + +namespace MonoDevelop.Projects +{ + public class WorkspaceObjectExtension: ChainedExtension + { + WorkspaceObjectExtension next; + + internal protected override void InitializeChain (ChainedExtension next) + { + this.next = FindNextImplementation<WorkspaceObjectExtension> (next); + } + + protected WorkspaceObject Owner { get; private set; } + + internal protected virtual bool SupportsObject (WorkspaceObject item) + { + return true; + } + + internal void Init (WorkspaceObject item) + { + Owner = item; + Initialize (); + } + + internal protected virtual void Initialize () + { + } + + internal protected virtual object GetService (Type t) + { + return t.IsInstanceOfType (this) ? this : next.GetService (t); + } + } +} + diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml index c0acbc5e14..bf5ddd7d9d 100644 --- a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml +++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml @@ -78,7 +78,7 @@ icon = "gtk-redo" _description = "Redo last undone action" shortcut = "Control|Shift|Z" - winShortcut = "Control|Y" + winShortcut = "Control|Y Control|Shift|Z" macShortcut = "Meta|Shift|Z" /> <Command id = "MonoDevelop.Ide.Commands.EditCommands.SelectAll" _label = "Select _All" diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/ItemOptionPanels.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/ItemOptionPanels.addin.xml index 2a9bfa6b3a..221e3ce56f 100644 --- a/main/src/core/MonoDevelop.Ide/ExtensionModel/ItemOptionPanels.addin.xml +++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/ItemOptionPanels.addin.xml @@ -6,6 +6,9 @@ <ConditionType id="ItemType" type="MonoDevelop.Projects.Extensions.ItemTypeCondition"> <Description>Type of the item. If no namespace is provided, MonoDevelop.Projects is assumed.</Description> </ConditionType> + <ConditionType id="FlavorType" type="MonoDevelop.Projects.Extensions.FlavorTypeCondition"> + <Description>Type of a flavor that a project must have. If no namespace is provided, MonoDevelop.Projects is assumed.</Description> + </ConditionType> <ConditionType id="ActiveLanguage" type="MonoDevelop.Projects.Extensions.ProjectLanguageCondition"> <Description>Language of the project. It will evaluate to false if the project is not a .NET project.</Description> </ConditionType> diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/StockIcons.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/StockIcons.addin.xml index 61a5a98e4c..ad11145e49 100644 --- a/main/src/core/MonoDevelop.Ide/ExtensionModel/StockIcons.addin.xml +++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/StockIcons.addin.xml @@ -155,6 +155,9 @@ <StockIcon stockid="md-prefs-updates" resource="prefs-updates-light-16.png" size="Menu" /> <StockIcon stockid="md-project" resource="project-light-16.png" size="Menu" /> <StockIcon stockid="md-project" resource="project-light-32.png" size="Dnd" /> + <StockIcon stockid="md-project-status-information" resource="project-status-information-light-16.png" size="Menu" /> + <StockIcon stockid="md-project-status-warning" resource="project-status-warning-light-16.png" size="Menu" /> + <StockIcon stockid="md-project-status-error" resource="project-status-error-light-16.png" size="Menu" /> <StockIcon stockid="md-project-overlay" resource="project-reference-overlay-light-16.png" size="Menu" /> <StockIcon stockid="md-properties" resource="properties-light-16.png" size="Menu" /> <StockIcon stockid="md-property" resource="element-property-light-16.png" size="Menu" /> @@ -365,7 +368,7 @@ <StockIcon stockid="md-ProtectedOrInternal-static-event" icon="res:element-event-light-16.png|res:element-visibility-static-overlay-light-16.png|res:element-visibility-internal-or-protected-overlay-light-16.png" size="Menu" /> <StockIcon stockid="md-ProtectedOrInternal-static-field" icon="res:element-field-light-16.png|res:element-visibility-static-overlay-light-16.png|res:element-visibility-internal-or-protected-overlay-light-16.png" size="Menu" /> <StockIcon stockid="md-ProtectedOrInternal-static-method" icon="res:element-method-light-16.png|res:element-visibility-static-overlay-light-16.png|res:element-visibility-internal-or-protected-overlay-light-16.png" size="Menu" /> - <StockIcon stockid="md-ProtectedOrInternal-static-property" icon="res:element-property-light-16.png|res:element-visibility-static-overlay-light-16element-visibility-static-overlay-light-16.png|res:element-visibility-internal-or-protected-overlay-light-16.png" size="Menu" /> + <StockIcon stockid="md-ProtectedOrInternal-static-property" icon="res:element-property-light-16.png|res:element-visibility-static-overlay-light-16.png|res:element-visibility-internal-or-protected-overlay-light-16.png" size="Menu" /> <StockIcon stockid="md-ProtectedOrInternal-struct" icon="res:element-structure-light-16.png|res:element-visibility-internal-or-protected-overlay-light-16.png" size="Menu" /> <StockIcon stockid="md-reference-folder" icon="md-reference|md-folder-overlay" size="Menu" /> <StockIcon stockid="md-reference-package" icon="md-reference" size="Menu" /> diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands.ExtensionNodes/CommandCodon.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands.ExtensionNodes/CommandCodon.cs index 6fe0b2c50d..4a3f6fe307 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands.ExtensionNodes/CommandCodon.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands.ExtensionNodes/CommandCodon.cs @@ -35,6 +35,7 @@ using MonoDevelop.Core; using MonoDevelop.Components.Commands; using Mono.Addins; using System.ComponentModel; +using System.Linq; namespace MonoDevelop.Components.Commands.ExtensionNodes { @@ -158,7 +159,12 @@ namespace MonoDevelop.Components.Commands.ExtensionNodes var keyBinding = Platform.IsMac ? macShortcut : shortcut; if (Platform.IsWindows && !string.IsNullOrEmpty (winShortcut)) keyBinding = winShortcut; - cmd.AccelKey = KeyBindingManager.CanonicalizeBinding (keyBinding); + string[] splittedKeys = (keyBinding ?? "").Split (' '); + + cmd.AccelKey = KeyBindingManager.CanonicalizeBinding (splittedKeys[0]); + if (splittedKeys.Length > 1) { + cmd.AlternateAccelKeys = splittedKeys.Skip (1).ToArray (); + } cmd.DisabledVisible = disabledVisible; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/Command.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/Command.cs index 5bac1ff279..9a0a69b78d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/Command.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/Command.cs @@ -95,10 +95,39 @@ namespace MonoDevelop.Components.Commands KeyBindingChanged (this, new KeyBindingChangedEventArgs (this, oldKeyBinding)); } } - + + string[] alternateAccelKeys; + KeyBinding[] alternateKeyBindings; + static readonly KeyBinding[] emptyBindings = new KeyBinding[0]; + + public string[] AlternateAccelKeys { + get { return alternateAccelKeys; } + set { + var oldKeybindings = alternateKeyBindings; + if (value == null || value.Length == 0) { + alternateKeyBindings = null; + } else { + alternateKeyBindings = new KeyBinding[value.Length]; + for (int i = 0; i < value.Length; i++) { + KeyBinding b; + KeyBinding.TryParse (value[i], out b); + alternateKeyBindings [i] = b; + } + } + alternateAccelKeys = value; + if (AlternateKeyBindingChanged != null) + AlternateKeyBindingChanged (this, new AlternateKeyBindingChangedEventArgs (this, oldKeybindings)); + } + } + public KeyBinding KeyBinding { get { return binding; } } + + public KeyBinding[] AlternateKeyBindings { + get { return alternateKeyBindings ?? emptyBindings; } + } + public bool DisabledVisible { get { return disabledVisible; } @@ -116,26 +145,49 @@ namespace MonoDevelop.Components.Commands } public event KeyBindingChangedEventHandler KeyBindingChanged; + public event EventHandler<AlternateKeyBindingChangedEventArgs> AlternateKeyBindingChanged; } - public class KeyBindingChangedEventArgs { + public class KeyBindingChangedEventArgs : EventArgs + { public KeyBindingChangedEventArgs (Command command, KeyBinding oldKeyBinding) { OldKeyBinding = oldKeyBinding; Command = command; } - + public Command Command { get; private set; } - + public KeyBinding OldKeyBinding { get; private set; } - + public KeyBinding NewKeyBinding { get { return Command.KeyBinding; } } } + + public class AlternateKeyBindingChangedEventArgs : EventArgs + { + public AlternateKeyBindingChangedEventArgs (Command command, KeyBinding[] oldKeyBinding) + { + OldKeyBinding = oldKeyBinding; + Command = command; + } + + public Command Command { + get; private set; + } + + public KeyBinding[] OldKeyBinding { + get; private set; + } + + public KeyBinding[] NewKeyBinding { + get { return Command.AlternateKeyBindings; } + } + } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandEntry.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandEntry.cs index 47aea630e4..00d9cb82ef 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandEntry.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandEntry.cs @@ -30,6 +30,15 @@ using System; namespace MonoDevelop.Components.Commands { + public enum CommandEntryDisplayType + { + Default, + TextOnly, + IconOnly, + IconHasPriority, + IconAndText + } + public class CommandEntry { object cmdId; @@ -66,6 +75,11 @@ namespace MonoDevelop.Components.Commands get { return disabledVisible; } set { disabledVisible = value; } } + + public CommandEntryDisplayType DispayType { + get; + set; + } public virtual Command GetCommand (CommandManager manager) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs index 4d4df70d59..490c249e07 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs @@ -455,19 +455,21 @@ namespace MonoDevelop.Components.Commands /// <summary> /// Disables all commands /// </summary> - public void LockAll () + public bool LockAll () { guiLock++; if (guiLock == 1) { foreach (ICommandBar toolbar in toolbars) toolbar.SetEnabled (false); - } + return true; + } else + return false; } /// <summary> /// Unlocks the command manager /// </summary> - public void UnlockAll () + public bool UnlockAll () { if (guiLock == 1) { foreach (ICommandBar toolbar in toolbars) @@ -476,6 +478,7 @@ namespace MonoDevelop.Components.Commands if (guiLock > 0) guiLock--; + return guiLock == 0; } /// <summary> diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/KeyBindingManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/KeyBindingManager.cs index ced8041eb8..b4a590202b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/KeyBindingManager.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/KeyBindingManager.cs @@ -644,7 +644,17 @@ namespace MonoDevelop.Components.Commands { SetBinding (args.Command, args.OldKeyBinding, args.NewKeyBinding); } - + + void OnAlternateKeyBindingChanged (object sender, AlternateKeyBindingChangedEventArgs args) + { + var upperBound = Math.Max (args.NewKeyBinding != null ? args.NewKeyBinding.Length : 0, args.OldKeyBinding != null ? args.OldKeyBinding.Length : 0); + for (int i = 0; i < upperBound; i++) { + SetBinding (args.Command, + args.OldKeyBinding != null && i < args.OldKeyBinding.Length ? args.OldKeyBinding[i] : null, + args.NewKeyBinding != null && i < args.NewKeyBinding.Length ? args.NewKeyBinding[i] : null ); + } + } + public bool CommandIsRegistered (Command command) { return commands.Contains (command); @@ -658,36 +668,48 @@ namespace MonoDevelop.Components.Commands } SetBinding (command, null, command.KeyBinding); + foreach (var binding in command.AlternateKeyBindings) { + SetBinding (command, null, binding); + } + command.KeyBindingChanged += OnKeyBindingChanged; + command.AlternateKeyBindingChanged += OnAlternateKeyBindingChanged; commands.Add (command); } - + + public void UnregisterCommand (Command command) { - List<Command> list; - int refs; - if (!commands.Contains (command)) { Console.WriteLine ("WARNING: trying to unregister unknown command {0}", command); return; } command.KeyBindingChanged -= OnKeyBindingChanged; + command.AlternateKeyBindingChanged -= OnAlternateKeyBindingChanged; commands.Remove (command); - - if (command.KeyBinding == null) - return; - list = bindings[command.KeyBinding]; + RemoveKeyBinding (command, command.KeyBinding); + foreach (var altBinding in command.AlternateKeyBindings) { + RemoveKeyBinding (command, altBinding); + } + } + + void RemoveKeyBinding (Command command, KeyBinding bindingToRemove) + { + if (bindingToRemove == null) + return; + var list = bindings [bindingToRemove]; + int refs; list.Remove (command); if (list.Count == 0) - bindings.Remove (command.KeyBinding); - - if (!command.KeyBinding.Chord.IsEmpty && chords.ContainsKey (command.KeyBinding.Chord)) { - if ((refs = chords[command.KeyBinding.Chord] - 1) == 0) - chords.Remove (command.KeyBinding.Chord); + bindings.Remove (bindingToRemove); + + if (!bindingToRemove.Chord.IsEmpty && chords.ContainsKey (bindingToRemove.Chord)) { + if ((refs = chords [bindingToRemove.Chord] - 1) == 0) + chords.Remove (bindingToRemove.Chord); else - chords[command.KeyBinding.Chord] = refs; + chords [bindingToRemove.Chord] = refs; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs index 05dc14f4d0..9cc941f9d5 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs @@ -75,6 +75,8 @@ namespace MonoDevelop.Components.DockNotebook ShowAll (); + contentBox.NoShowAll = true; + tabStrip.DropDownButton.Sensitive = false; tabStrip.DropDownButton.MenuCreator = delegate { @@ -206,7 +208,7 @@ namespace MonoDevelop.Components.DockNotebook } } - void SelectLastActiveTab () + void SelectLastActiveTab (int lastClosed) { if (pages.Count == 0) { CurrentTab = null; @@ -218,8 +220,12 @@ namespace MonoDevelop.Components.DockNotebook if (pagesHistory.Count > 0) CurrentTab = pagesHistory [0]; - else - CurrentTab = null; + else { + if (lastClosed + 1 < pages.Count) + CurrentTab = pages [lastClosed + 1]; + else + CurrentTab = pages [lastClosed - 1]; + } } public int TabCount { @@ -338,8 +344,10 @@ namespace MonoDevelop.Components.DockNotebook if (animate) tabStrip.StartCloseAnimation ((DockNotebookTab)tab); pagesHistory.Remove (tab); - if (page == CurrentTabIndex) - SelectLastActiveTab (); + if (pages.Count == 1) + CurrentTab = null; + else if (page == CurrentTabIndex) + SelectLastActiveTab (page); pages.RemoveAt (page); UpdateIndexes (page); tabStrip.Update (); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/AutoHideBox.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/AutoHideBox.cs index 87d84df650..b3d5cf4779 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/AutoHideBox.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/AutoHideBox.cs @@ -59,9 +59,9 @@ namespace MonoDevelop.Components.Docking bool disposed; bool insideGrip; - const int gripSize = 8; + int gripSize = 8; - public AutoHideBox (DockFrame frame, DockItem item, Gtk.PositionType pos, int size) + public AutoHideBox (DockFrame frame, DockItem item, Gtk.PositionType pos, int size): base (frame) { this.position = pos; this.frame = frame; @@ -73,11 +73,22 @@ namespace MonoDevelop.Components.Docking Box fr; CustomFrame cframe = new CustomFrame (); switch (pos) { - case PositionType.Left: cframe.SetMargins (0, 0, 1, 1); break; - case PositionType.Right: cframe.SetMargins (0, 0, 1, 1); break; - case PositionType.Top: cframe.SetMargins (1, 1, 0, 0); break; - case PositionType.Bottom: cframe.SetMargins (1, 1, 0, 0); break; + case PositionType.Left: cframe.SetMargins (0, 0, 1, 1); break; + case PositionType.Right: cframe.SetMargins (0, 0, 1, 1); break; + case PositionType.Top: cframe.SetMargins (1, 1, 0, 0); break; + case PositionType.Bottom: cframe.SetMargins (1, 1, 0, 0); break; } + + if (frame.UseWindowsForTopLevelFrames) { + // When using a top level window on mac, clicks on the first 4 pixels next to the border + // are not detected. To avoid confusing the user (since the resize cursor is shown), + // we make the resize drag area smaller. + switch (pos) { + case PositionType.Left: cframe.SetPadding (0, 0, 0, 4); gripSize = 4; break; + case PositionType.Right: cframe.SetPadding (0, 0, 4, 0); gripSize = 4; break; + } + } + EventBox sepBox = new EventBox (); cframe.Add (sepBox); @@ -128,12 +139,12 @@ namespace MonoDevelop.Components.Docking sepBox.EnterNotifyEvent += delegate { insideGrip = true; sepBox.QueueDraw (); }; sepBox.LeaveNotifyEvent += delegate { insideGrip = false; sepBox.QueueDraw (); }; } - + public bool Disposed { get { return disposed; } set { disposed = value; } } - + public void AnimateShow () { #if ANIMATE_DOCKING @@ -143,18 +154,18 @@ namespace MonoDevelop.Components.Docking switch (position) { case PositionType.Left: - WidthRequest = 0; + Width = 0; break; case PositionType.Right: - targetPos = X = X + WidthRequest; - WidthRequest = 0; + targetPos = X = X + Width; + Width = 0; break; case PositionType.Top: - HeightRequest = 0; + Height = 0; break; case PositionType.Bottom: - targetPos = Y = Y + HeightRequest; - HeightRequest = 0; + targetPos = Y = Y + Height; + Height = 0; break; } Show (); @@ -183,34 +194,34 @@ namespace MonoDevelop.Components.Docking switch (position) { case PositionType.Left: - WidthRequest += 1 + (targetSize - WidthRequest) / 3; - if (WidthRequest < targetSize) + Width += 1 + (targetSize - Width) / 3; + if (Width < targetSize) return true; break; case PositionType.Right: - WidthRequest += 1 + (targetSize - WidthRequest) / 3; - X = targetPos - WidthRequest; - if (WidthRequest < targetSize) + Width += 1 + (targetSize - Width) / 3; + X = targetPos - Width; + if (Width < targetSize) return true; break; case PositionType.Top: - HeightRequest += 1 + (targetSize - HeightRequest) / 3; - if (HeightRequest < targetSize) + Height += 1 + (targetSize - Height) / 3; + if (Height < targetSize) return true; break; case PositionType.Bottom: - HeightRequest += 1 + (targetSize - HeightRequest) / 3; - Y = targetPos - HeightRequest; - if (HeightRequest < targetSize) + Height += 1 + (targetSize - Height) / 3; + Y = targetPos - Height; + if (Height < targetSize) return true; break; } scrollable.ScrollMode = false; if (horiz) - WidthRequest = targetSize; + Width = targetSize; else - HeightRequest = targetSize; + Height = targetSize; animating = false; return false; } @@ -222,34 +233,34 @@ namespace MonoDevelop.Components.Docking switch (position) { case PositionType.Left: { - int ns = WidthRequest - 1 - WidthRequest / 3; + int ns = Width - 1 - Width / 3; if (ns > 0) { - WidthRequest = ns; + Width = ns; return true; } break; } case PositionType.Right: { - int ns = WidthRequest - 1 - WidthRequest / 3; + int ns = Width - 1 - Width / 3; if (ns > 0) { - WidthRequest = ns; + Width = ns; X = targetPos - ns; return true; } break; } case PositionType.Top: { - int ns = HeightRequest - 1 - HeightRequest / 3; + int ns = Height - 1 - Height / 3; if (ns > 0) { - HeightRequest = ns; + Height = ns; return true; } break; } case PositionType.Bottom: { - int ns = HeightRequest - 1 - HeightRequest / 3; + int ns = Height - 1 - Height / 3; if (ns > 0) { - HeightRequest = ns; + Height = ns; Y = targetPos - ns; return true; } @@ -275,25 +286,26 @@ namespace MonoDevelop.Components.Docking return true; } - public int Size { + public int PadSize { get { - return horiz ? WidthRequest : HeightRequest; + return horiz ? Width : Height; } } - + + [GLib.ConnectBefore] void OnSizeButtonPress (object ob, Gtk.ButtonPressEventArgs args) { if (!animating && args.Event.Button == 1 && !args.Event.TriggersContextMenu ()) { int n; if (horiz) { - Toplevel.GetPointer (out resizePos, out n); - origSize = WidthRequest; + frame.Toplevel.GetPointer (out resizePos, out n); + origSize = Width; if (!startPos) { origPos = X + origSize; } } else { - Toplevel.GetPointer (out n, out resizePos); - origSize = HeightRequest; + frame.Toplevel.GetPointer (out n, out resizePos); + origSize = Height; if (!startPos) { origPos = Y + origSize; } @@ -312,7 +324,7 @@ namespace MonoDevelop.Components.Docking if (resizing) { int newPos, n; if (horiz) { - Toplevel.GetPointer (out newPos, out n); + frame.Toplevel.GetPointer (out newPos, out n); int diff = startPos ? (newPos - resizePos) : (resizePos - newPos); int newSize = origSize + diff; if (newSize < Child.SizeRequest ().Width) @@ -320,9 +332,9 @@ namespace MonoDevelop.Components.Docking if (!startPos) { X = origPos - newSize; } - WidthRequest = newSize; + Width = newSize; } else { - Toplevel.GetPointer (out n, out newPos); + frame.Toplevel.GetPointer (out n, out newPos); int diff = startPos ? (newPos - resizePos) : (resizePos - newPos); int newSize = origSize + diff; if (newSize < Child.SizeRequest ().Height) @@ -330,7 +342,7 @@ namespace MonoDevelop.Components.Docking if (!startPos) { Y = origPos - newSize; } - HeightRequest = newSize; + Height = newSize; } frame.QueueResize (); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBar.cs index 686d3c0054..c3d7ae3c1a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBar.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBar.cs @@ -146,13 +146,17 @@ namespace MonoDevelop.Components.Docking internal void UpdateVisibility () { - filler.Visible = (Frame.CompactGuiLevel < 3); - int visibleCount = 0; - foreach (Gtk.Widget w in box.Children) { - if (w.Visible) - visibleCount++; + if (Frame.OverlayWidgetVisible) { + Visible = false; + } else { + filler.Visible = (Frame.CompactGuiLevel < 3); + int visibleCount = 0; + foreach (Gtk.Widget w in box.Children) { + if (w.Visible) + visibleCount++; + } + Visible = alwaysVisible || filler.Visible || visibleCount > 0; } - Visible = alwaysVisible || filler.Visible || visibleCount > 0; } internal void RemoveItem (DockBarItem it) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs index a9e983fe75..181137d274 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs @@ -169,6 +169,9 @@ namespace MonoDevelop.Components.Docking lastFrameSize = args.Allocation.Size; if (autoShowFrame != null) bar.Frame.UpdateSize (bar, autoShowFrame); + + UnscheduleAutoHide (); + AutoHide (false); } } @@ -301,7 +304,7 @@ namespace MonoDevelop.Components.Docking { UnscheduleAutoShow (); if (autoShowFrame != null) { - size = autoShowFrame.Size; + size = autoShowFrame.PadSize; hiddenFrame = autoShowFrame; autoShowFrame.Hidden += delegate { hiddenFrame = null; @@ -344,7 +347,7 @@ namespace MonoDevelop.Components.Docking if (it.ShowingContextMemu) return true; // Don't hide the item if it has the focus. Try again later. - if (it.Widget.FocusChild != null && !force) + if (it.Widget.FocusChild != null && !force && ((Gtk.Window)autoShowFrame.Toplevel).HasToplevelFocus) return true; // Don't hide the item if the mouse pointer is still inside the window. Try again later. int px, py; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs index 9fabdf0597..7c3e5810db 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs @@ -35,6 +35,7 @@ using System.Collections.Generic; using Gtk; using Gdk; using Xwt.Motion; +using MonoDevelop.Core; namespace MonoDevelop.Components.Docking { @@ -86,13 +87,20 @@ namespace MonoDevelop.Components.Docking mainBox.ShowAll (); mainBox.NoShowAll = true; CompactGuiLevel = 2; - dockBarTop.UpdateVisibility ();
- dockBarBottom.UpdateVisibility (); - dockBarLeft.UpdateVisibility (); - dockBarRight.UpdateVisibility (); + UpdateDockbarsVisibility (); DefaultVisualStyle = new DockVisualStyle (); } + + public bool DockbarsVisible { + get { + return !OverlayWidgetVisible; + } + } + + internal bool UseWindowsForTopLevelFrames { + get { return Platform.IsMac; } + } /// <summary> /// Compactness level of the gui, from 1 (not compact) to 5 (very compact). @@ -137,6 +145,8 @@ namespace MonoDevelop.Components.Docking currentOverlayPosition = Math.Max (0, Allocation.Y); QueueResize (); } + + UpdateDockbarsVisibility (); } public void RemoveOverlayWidget (bool animate = false) @@ -164,10 +174,20 @@ namespace MonoDevelop.Components.Docking QueueResize (); } } + + UpdateDockbarsVisibility (); } int currentOverlayPosition; + void UpdateDockbarsVisibility () + { + dockBarTop.UpdateVisibility (); + dockBarBottom.UpdateVisibility (); + dockBarLeft.UpdateVisibility (); + dockBarRight.UpdateVisibility (); + } + void ShowOverlayWidgetAnimation (double value) { currentOverlayPosition = Allocation.Y + (int)((double)Allocation.Height * (1f - value)); @@ -511,11 +531,31 @@ namespace MonoDevelop.Components.Docking DockLayout dl; if (!layouts.TryGetValue (layoutName, out dl)) return false; - + + var focus = GetActiveWidget (); + container.LoadLayout (dl); + + // Keep the currently focused widget when switching layouts + if (focus != null && focus.IsRealized && focus.Visible) + DockItem.SetFocus (focus); + return true; } - + + Gtk.Widget GetActiveWidget () + { + Gtk.Widget widget = this; + while (widget is Gtk.Container) { + Gtk.Widget child = ((Gtk.Container)widget).FocusChild; + if (child != null) + widget = child; + else + break; + } + return widget; + } + public void CreateLayout (string name) { CreateLayout (name, false); @@ -814,14 +854,36 @@ namespace MonoDevelop.Components.Docking return null; } - internal void AddTopLevel (DockFrameTopLevel w, int x, int y) + internal void AddTopLevel (DockFrameTopLevel w, int x, int y, int width, int height) { - w.Parent = this; w.X = x; w.Y = y; - Requisition r = w.SizeRequest (); - w.Allocation = new Gdk.Rectangle (Allocation.X + x, Allocation.Y + y, r.Width, r.Height); - topLevels.Add (w); + + if (UseWindowsForTopLevelFrames) { + var win = new Gtk.Window (Gtk.WindowType.Toplevel); + win.AcceptFocus = false; + win.SkipTaskbarHint = true; + win.Decorated = false; + win.TypeHint = Gdk.WindowTypeHint.Toolbar; + w.ContainerWindow = win; + w.Size = new Size (width, height); + win.Add (w); + w.Show (); + var p = this.GetScreenCoordinates (new Gdk.Point (x, y)); + win.Opacity = 0.0; + win.Move (p.X, p.Y); + win.Resize (width, height); + win.Show (); + Ide.DesktopService.AddChildWindow ((Gtk.Window)Toplevel, win); + win.AcceptFocus = true; + win.Opacity = 1.0; + } else { + w.Parent = this; + w.Size = new Size (width, height); + Requisition r = w.SizeRequest (); + w.Allocation = new Gdk.Rectangle (Allocation.X + x, Allocation.Y + y, r.Width, r.Height); + topLevels.Add (w); + } } internal void RemoveTopLevel (DockFrameTopLevel w) @@ -875,27 +937,29 @@ namespace MonoDevelop.Components.Docking Gdk.Size sBot = GetBarFrameSize (dockBarBottom); Gdk.Size sLeft = GetBarFrameSize (dockBarLeft); Gdk.Size sRgt = GetBarFrameSize (dockBarRight); - - int x,y; + + int x,y,w,h; if (bar == dockBarLeft || bar == dockBarRight) { - aframe.HeightRequest = Allocation.Height - sTop.Height - sBot.Height; - aframe.WidthRequest = size; + h = Allocation.Height - sTop.Height - sBot.Height; + w = size; y = sTop.Height; if (bar == dockBarLeft) x = sLeft.Width; else x = Allocation.Width - size - sRgt.Width; } else { - aframe.WidthRequest = Allocation.Width - sLeft.Width - sRgt.Width; - aframe.HeightRequest = size; + w = Allocation.Width - sLeft.Width - sRgt.Width; + h = size; x = sLeft.Width; if (bar == dockBarTop) y = sTop.Height; else y = Allocation.Height - size - sBot.Height; } - AddTopLevel (aframe, x, y); + + AddTopLevel (aframe, x, y, w, h); aframe.AnimateShow (); + return aframe; } @@ -957,7 +1021,11 @@ namespace MonoDevelop.Components.Docking } parent.Remove (item.TitleTab); } - RemoveTopLevel (widget); + if (widget.ContainerWindow != null) { + widget.ContainerWindow.Destroy (); + } else + RemoveTopLevel (widget); + widget.Disposed = true; widget.Destroy ();
} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrameTopLevel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrameTopLevel.cs index 7cb00af05b..ca29672dcd 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrameTopLevel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrameTopLevel.cs @@ -32,19 +32,27 @@ using System; using Gtk; +using MonoDevelop.Ide; namespace MonoDevelop.Components.Docking { class DockFrameTopLevel: EventBox { int x, y; + int width, height; + bool repositionRequested; + DockFrame frame; + + public DockFrameTopLevel (DockFrame frame) + { + this.frame = frame; + } public int X { get { return x; } set { x = value; - if (Parent != null) - Parent.QueueResize (); + UpdateWindowPos (); } } @@ -52,10 +60,85 @@ namespace MonoDevelop.Components.Docking get { return y; } set { y = value; - if (Parent != null) - Parent.QueueResize (); + UpdateWindowPos (); } } + + public Gdk.Size Size { + get { + if (ContainerWindow != null) { + int w, h; + ContainerWindow.GetSize (out w, out h); + return new Gdk.Size (w, h); + } else { + return new Gdk.Size (WidthRequest, HeightRequest); + } + } + set { + width = value.Width; + height = value.Height; + if (ContainerWindow != null) + UpdateWindowPos (); + else { + WidthRequest = value.Width; + HeightRequest = value.Height; + } + } + } + + public int Width { + get { + if (ContainerWindow != null) { + int w, h; + ContainerWindow.GetSize (out w, out h); + return w; + } else + return WidthRequest; + } + set { + width = value; + if (ContainerWindow != null) + UpdateWindowPos (); + else + WidthRequest = value; + } + } + + public int Height { + get { + if (ContainerWindow != null) { + int w, h; + ContainerWindow.GetSize (out w, out h); + return h; + } else + return HeightRequest; + } + set { + height = value; + if (ContainerWindow != null) + UpdateWindowPos (); + else + HeightRequest = value; + } + } + + + void UpdateWindowPos () + { + if (ContainerWindow != null) { + if (!repositionRequested && width != 0 && height != 0) { + repositionRequested = true; + Application.Invoke (delegate { + var pos = frame.GetScreenCoordinates (new Gdk.Point (x, y)); + DesktopService.PlaceWindow (ContainerWindow, pos.X, pos.Y, width, height); + repositionRequested = false; + }); + } + } else if (Parent != null) + Parent.QueueResize (); + } + + internal Gtk.Window ContainerWindow { get; set; } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/IExtendedTitleBarDialogBackend.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/IExtendedTitleBarDialogBackend.cs index d5b01d894e..8818409edd 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/IExtendedTitleBarDialogBackend.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/IExtendedTitleBarDialogBackend.cs @@ -42,7 +42,7 @@ namespace MonoDevelop.Components.Extensions { base.Initialize (); toolbar = new HeaderBox (); - toolbar.GradientBackround = true; + toolbar.GradientBackground = true; toolbar.SetMargins (0, 1, 0, 0); MainBox.PackStart (toolbar, false, false, 0); ((Gtk.Box.BoxChild)MainBox [toolbar]).Position = 0; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/IExtendedTitleBarWindowBackend.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/IExtendedTitleBarWindowBackend.cs index 4d10b5a24c..316b133285 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/IExtendedTitleBarWindowBackend.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/IExtendedTitleBarWindowBackend.cs @@ -42,7 +42,7 @@ namespace MonoDevelop.Components.Extensions { base.Initialize (); toolbar = new HeaderBox (); - toolbar.GradientBackround = true; + toolbar.GradientBackground = true; toolbar.SetMargins (0, 1, 0, 0); MainBox.PackStart (toolbar, false, false, 0); ((Gtk.Box.BoxChild)MainBox [toolbar]).Position = 0; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ConfigurationMerger.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ConfigurationMerger.cs index 965ed07fe2..e5e44ae752 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ConfigurationMerger.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ConfigurationMerger.cs @@ -307,7 +307,7 @@ namespace MonoDevelop.Components.MainToolbar bool ConfigurationEquals (Solution sol, SolutionConfiguration s1, SolutionConfiguration s2) { - foreach (var p in sol.GetAllSolutionItems<SolutionEntityItem> ()) { + foreach (var p in sol.GetAllItems<SolutionItem> ()) { var c1 = s1.GetEntryForItem (p); var c2 = s2.GetEntryForItem (p); if (c1 == null && c2 == null) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs index b32a1749bc..4ea9fd8a0e 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs @@ -85,7 +85,7 @@ namespace MonoDevelop.Components.MainToolbar Solution currentSolution; bool settingGlobalConfig; - SolutionEntityItem currentStartupProject; + SolutionItem currentStartupProject; int ignoreConfigurationChangedCount; int ignoreRuntimeChangedCount; @@ -148,6 +148,12 @@ namespace MonoDevelop.Components.MainToolbar renderer.Visible = ci.Visible; renderer.Sensitive = ci.Enabled; renderer.Xpad = 3; + + // it seems that once we add the ExecutionTargetGroups to the drop down then the width + // calculation for items needs some help in calculating the correct width + // doing this helps. + if (Platform.IsMac) + renderer.WidthChars = renderer.Text != null ? renderer.Text.Length : 0; return; } renderer.Sensitive = !(target is ExecutionTargetGroup) && (target != null && target.Enabled); @@ -190,6 +196,14 @@ namespace MonoDevelop.Components.MainToolbar return sb.ToString (); } + void DestroyPopup () + { + if (popup != null) { + popup.Destroy (); + popup = null; + } + } + public MainToolbar () { executionTargetsChanged = DispatchService.GuiDispatch (new EventHandler (HandleExecutionTargetsChanged)); @@ -303,7 +317,7 @@ namespace MonoDevelop.Components.MainToolbar matchEntry.Activated += (sender, e) => { var pattern = SearchPopupSearchPattern.ParsePattern (matchEntry.Entry.Text); if (pattern.Pattern == null && pattern.LineNumber > 0) { - popup.Destroy (); + DestroyPopup (); var doc = IdeApp.Workbench.ActiveDocument; if (doc != null && doc.Editor != null) { doc.Select (); @@ -320,8 +334,7 @@ namespace MonoDevelop.Components.MainToolbar if (args.Event.Key == Gdk.Key.Escape) { var doc = IdeApp.Workbench.ActiveDocument; if (doc != null) { - if (popup != null) - popup.Destroy (); + DestroyPopup (); doc.Select (); } return; @@ -517,8 +530,7 @@ namespace MonoDevelop.Components.MainToolbar void HandleSearchEntryChanged (object sender, EventArgs e) { if (string.IsNullOrEmpty (matchEntry.Entry.Text)){ - if (popup != null) - popup.Destroy (); + DestroyPopup (); return; } var pattern = SearchPopupSearchPattern.ParsePattern (matchEntry.Entry.Text); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusArea.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusArea.cs index c92582f04c..f53bf4df66 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusArea.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusArea.cs @@ -321,7 +321,7 @@ namespace MonoDevelop.Components.MainToolbar TaskEventHandler updateHandler = delegate { int ec=0, wc=0; - foreach (Task t in TaskService.Errors) { + foreach (UserTask t in TaskService.Errors) { if (t.Severity == TaskSeverity.Error) ec++; else if (t.Severity == TaskSeverity.Warning) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs index 2e4b284eb4..81de104e62 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs @@ -26,6 +26,7 @@ // using System; +using System.Linq; using System.Collections.Generic; using Gtk; using System.Runtime.InteropServices; @@ -36,7 +37,9 @@ namespace MonoDevelop.Components public static class GtkUtil { static Dictionary<TreeView, TreeViewTooltipsData> treeData = new Dictionary<TreeView, TreeViewTooltipsData> (); - + + static readonly Xwt.Toolkit gtkToolkit = Xwt.Toolkit.Load (Xwt.ToolkitType.Gtk); + public static Cairo.Color ToCairoColor (this Gdk.Color color) { return new Cairo.Color ((double)color.Red / ushort.MaxValue, @@ -95,32 +98,32 @@ namespace MonoDevelop.Components public static Xwt.Drawing.Context CreateXwtContext (this Gtk.Widget w) { var c = Gdk.CairoHelper.Create (w.GdkWindow); - return Xwt.Toolkit.CurrentEngine.WrapContext (w, c); + return gtkToolkit.WrapContext (w, c); } public static Gtk.Widget ToGtkWidget (this Xwt.Widget widget) { - return (Gtk.Widget) Xwt.Toolkit.CurrentEngine.GetNativeWidget (widget); + return (Gtk.Widget) gtkToolkit.GetNativeWidget (widget); } public static void DrawImage (this Cairo.Context s, Gtk.Widget widget, Xwt.Drawing.Image image, double x, double y) { - Xwt.Toolkit.CurrentEngine.RenderImage (widget, s, image, x, y); + gtkToolkit.RenderImage (widget, s, image, x, y); } public static Xwt.Drawing.Image ToXwtImage (this Gdk.Pixbuf pix) { - return Xwt.Toolkit.CurrentEngine.WrapImage (pix); + return gtkToolkit.WrapImage (pix); } public static Gdk.Pixbuf ToPixbuf (this Xwt.Drawing.Image image) { - return (Gdk.Pixbuf)Xwt.Toolkit.CurrentEngine.GetNativeImage (image); + return (Gdk.Pixbuf)gtkToolkit.GetNativeImage (image); } public static Gdk.Pixbuf ToPixbuf (this Xwt.Drawing.Image image, Gtk.IconSize size) { - return (Gdk.Pixbuf)Xwt.Toolkit.CurrentEngine.GetNativeImage (image.WithSize (size)); + return (Gdk.Pixbuf)gtkToolkit.GetNativeImage (image.WithSize (size)); } public static Xwt.Drawing.Image WithSize (this Xwt.Drawing.Image image, Gtk.IconSize size) @@ -152,6 +155,18 @@ namespace MonoDevelop.Components } } + public static Gdk.Point GetScreenCoordinates (this Gtk.Widget w, Gdk.Point p) + { + if (w.ParentWindow == null) + return Gdk.Point.Zero; + int x, y; + w.ParentWindow.GetOrigin (out x, out y); + var a = w.Allocation; + x += a.X; + y += a.Y; + return new Gdk.Point (x + p.X, y + p.Y); + } + public static void EnableAutoTooltips (this Gtk.TreeView tree) { TreeViewTooltipsData data = new TreeViewTooltipsData (); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs index c1005ea88e..6edbdf9213 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs @@ -100,7 +100,7 @@ namespace MonoDevelop.Components } } - public bool GradientBackround { get; set; } + public bool GradientBackground { get; set; } public Gdk.Color? BorderColor { get; set; } @@ -159,7 +159,7 @@ namespace MonoDevelop.Components { Gdk.Rectangle rect; - if (GradientBackround) { + if (GradientBackground) { rect = new Gdk.Rectangle (Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height); var gcol = Style.Background (Gtk.StateType.Normal).ToXwtColor (); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs index b5f4de70e1..9f8890bda6 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs @@ -230,6 +230,9 @@ namespace MonoDevelop.Components var screen = parent.Screen; Gdk.Rectangle geometry = GtkWorkarounds.GetUsableMonitorGeometry (screen, screen.GetMonitorAtPoint (x, y)); + // Add some spacing between the screen border and the popover window + geometry.Inflate (-5, -5); + // Flip the orientation if the window doesn't fit the screen. int intPos = (int) position; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs index 4292e1b288..44bd4e78ed 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs @@ -103,6 +103,9 @@ namespace MonoDevelop.Components public bool RoundedShape { get { return roundedShape; } set { + if (!Platform.IsMac) + return; + roundedShape = value; if (value) entry.Name = "search-entry"; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipPopoverWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipPopoverWindow.cs index 8e4e9ebd94..d26b2d4bac 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipPopoverWindow.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipPopoverWindow.cs @@ -24,12 +24,18 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; +using MonoDevelop.Ide.Tasks; +using MonoDevelop.Ide.Gui; namespace MonoDevelop.Components { public class TooltipPopoverWindow: PopoverWindow { Gtk.Label label; + TaskSeverity? severity; + bool hasMarkup; + string text; + Gtk.Alignment alignment; public TooltipPopoverWindow () { @@ -40,43 +46,106 @@ namespace MonoDevelop.Components public string Text { get { - return label != null ? label.Text : string.Empty; + return text; } set { + hasMarkup = false; + text = value; AddLabel (); - label.Text = value; + UpdateLabel (); AdjustSize (); } } public string Markup { get { - return label != null ? label.Text : string.Empty; + return text; } set { + hasMarkup = true; + text = value; AddLabel (); - label.Markup = value; + UpdateLabel (); AdjustSize (); } } + public TaskSeverity? Severity { + get { return severity; } + set { + severity = value; + UpdateLabel (); + if (severity.HasValue) { + Theme.Padding = 3; + Theme.CornerRadius = 5; + alignment.SetPadding (4, 6, 6, 6); + Theme.BorderColor = new Cairo.Color (0, 0, 0, 0); + var f = Style.FontDescription.Copy (); + f.Size = ((f.Size / (int)Pango.Scale.PangoScale) - 1) * (int) Pango.Scale.PangoScale; + label.ModifyFont (f); + switch (severity.Value) { + case TaskSeverity.Information: + Theme.SetFlatColor (Styles.PopoverWindow.InformationBackgroundColor); + Theme.BorderColor = Styles.PopoverWindow.InformationBackgroundColor; + break; + case TaskSeverity.Comment: + Theme.SetFlatColor (Styles.PopoverWindow.InformationBackgroundColor); + Theme.BorderColor = Styles.PopoverWindow.InformationBackgroundColor; + break; + case TaskSeverity.Error: + Theme.SetFlatColor (Styles.PopoverWindow.ErrorBackgroundColor); + Theme.BorderColor = Styles.PopoverWindow.ErrorBackgroundColor; + return; + case TaskSeverity.Warning: + Theme.SetFlatColor (Styles.PopoverWindow.WarningBackgroundColor); + Theme.BorderColor = Styles.PopoverWindow.WarningBackgroundColor; + return; + } + } else { + Theme.SetFlatColor (new Cairo.Color (1d, 243d / 255d, 207d / 255d, 0.9d)); + Theme.BorderColor = new Cairo.Color (128d/255d, 122d / 255d, 104d / 255d); + } + } + } + void AddLabel () { if (label == null) { - Gtk.Alignment al = new Gtk.Alignment (0.5f, 0.5f, 1f, 1f); - al.SetPadding (6, 6, 6, 6); + alignment = new Gtk.Alignment (0.5f, 0.5f, 1f, 1f); + alignment.SetPadding (6, 6, 6, 6); label = new Gtk.Label (); - al.Add (label); - ContentBox.Add (al); - al.ShowAll (); + alignment.Add (label); + ContentBox.Add (alignment); + alignment.ShowAll (); + } + } + + void UpdateLabel () + { + if (severity.HasValue) { + string msg = hasMarkup ? text : GLib.Markup.EscapeText (text); + switch (severity.Value) { + case TaskSeverity.Information: + case TaskSeverity.Comment: + case TaskSeverity.Error: + label.Markup = "<b><span color='white'>" + text + "</span></b>"; + return; + case TaskSeverity.Warning: + label.Markup = "<b><span color='#6D5607'>" + text + "</span></b>"; + return; + } } + if (hasMarkup) + label.Markup = text; + else + label.Text = text; } void AdjustSize () { - if (label.SizeRequest ().Width > 300) { + if (label.SizeRequest ().Width > 330) { label.Wrap = true; - label.WidthRequest = 300; + label.WidthRequest = 330; } else { label.Wrap = false; label.WidthRequest = -1; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormattingCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormattingCommands.cs index bd0fc82a91..12c91fdb78 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormattingCommands.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormattingCommands.cs @@ -69,7 +69,11 @@ namespace MonoDevelop.Ide.CodeFormatting formatter.OnTheFlyFormat (doc, 0, doc.Editor.Length); } } else { - doc.Editor.Text = formatter.FormatText (doc.Project.Policies, doc.Editor.Text); + string formattedText = formatter.FormatText (doc.Project.Policies, doc.Editor.Text); + if (formattedText == null) + return; + + doc.Editor.Replace (0, doc.Editor.Text.Length, formattedText); } doc.Editor.Document.CommitUpdateAll (); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs index f88be41210..f259dfdf67 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs @@ -104,11 +104,13 @@ namespace MonoDevelop.Ide.CodeTemplates AlertButton.Cancel, AlertButton.Remove) == AlertButton.Remove) { templates.Remove (template); templateStore.Remove (ref selected); + templatesToRemove.Add (template); } } } } List<CodeTemplate> templatesToSave = new List<CodeTemplate> (); + List<CodeTemplate> templatesToRemove = new List<CodeTemplate> (); void ButtonEditClicked (object sender, EventArgs e) { var template = GetSelectedTemplate (); @@ -142,8 +144,10 @@ namespace MonoDevelop.Ide.CodeTemplates public void Store () { - templatesToSave.ForEach (template => CodeTemplateService.SaveTemplate (template)); + templatesToSave.ForEach (CodeTemplateService.SaveTemplate); templatesToSave.Clear (); + templatesToRemove.ForEach (CodeTemplateService.DeleteTemplate); + templatesToRemove.Clear (); CodeTemplateService.Templates = templates; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateService.cs index 804a7babf4..90ab1ee87b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateService.cs @@ -138,6 +138,17 @@ namespace MonoDevelop.Ide.CodeTemplates writer.Close (); } } + + public static void DeleteTemplate (CodeTemplate template) + { + try { + var fileName = Path.Combine (TemplatePath, template.Shortcut + ".template.xml"); + if (File.Exists (fileName)) + File.Delete (fileName); + } catch (Exception e) { + LoggingService.LogError ("Error while removing template file", e); + } + } public static void SaveTemplate (CodeTemplate template) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs index 4f6b0d1812..be6db6d0e2 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs @@ -114,7 +114,7 @@ namespace MonoDevelop.Ide.Commands protected override void Run () { - IdeApp.ProjectOperations.ShowOptions (IdeApp.ProjectOperations.CurrentSelectedBuildTarget); + IdeApp.ProjectOperations.ShowOptions (IdeApp.ProjectOperations.CurrentSelectedObject); } } @@ -127,7 +127,7 @@ namespace MonoDevelop.Ide.Commands protected override void Run () { - IdeApp.ProjectOperations.ShowOptions (IdeApp.ProjectOperations.CurrentSelectedBuildTarget); + IdeApp.ProjectOperations.ShowOptions (IdeApp.ProjectOperations.CurrentSelectedObject); } } @@ -143,12 +143,12 @@ namespace MonoDevelop.Ide.Commands info.Bypass = false; } - protected override void Run () + protected override async void Run () { //Edit references DotNetProject p = IdeApp.ProjectOperations.CurrentSelectedProject as DotNetProject; if (IdeApp.ProjectOperations.AddReferenceToProject (p)) - IdeApp.ProjectOperations.Save (p); + await IdeApp.ProjectOperations.SaveAsync (p); } } @@ -173,7 +173,7 @@ namespace MonoDevelop.Ide.Commands { if (IdeApp.Workspace.IsOpen) { IBuildTarget buildTarget = IdeApp.ProjectOperations.CurrentSelectedBuildTarget; - info.Enabled = ((buildTarget != null) && (IdeApp.ProjectOperations.CurrentBuildOperation.IsCompleted)) && buildTarget.SupportsTarget (ProjectService.BuildTarget); + info.Enabled = (buildTarget != null) && (IdeApp.ProjectOperations.CurrentBuildOperation.IsCompleted); if (buildTarget != null) { info.Text = GettextCatalog.GetString ("B_uild {0}", buildTarget.Name.Replace ("_","__")); if (buildTarget is SolutionFolder) @@ -184,24 +184,13 @@ namespace MonoDevelop.Ide.Commands info.Description = GettextCatalog.GetString ("Build {0}", buildTarget.Name); } } - else { - info.Enabled = ((IdeApp.Workbench.ActiveDocument != null) && (IdeApp.Workbench.ActiveDocument.IsBuildTarget) && (IdeApp.ProjectOperations.CurrentBuildOperation.IsCompleted)); - if (IdeApp.Workbench.ActiveDocument != null) { - info.Text = GettextCatalog.GetString ("B_uild {0}", Path.GetFileName (IdeApp.Workbench.ActiveDocument.Name).Replace ("_","__")); - info.Description = GettextCatalog.GetString ("Build {0}", Path.GetFileName (IdeApp.Workbench.ActiveDocument.Name)); - } - } + else + info.Enabled = false; } protected override void Run () { - if (IdeApp.Workspace.IsOpen) { - IdeApp.ProjectOperations.Build (IdeApp.ProjectOperations.CurrentSelectedBuildTarget); - } - else { - IdeApp.Workbench.ActiveDocument.Save (); - IdeApp.Workbench.ActiveDocument.Build (); - } + IdeApp.ProjectOperations.Build (IdeApp.ProjectOperations.CurrentSelectedBuildTarget); } } @@ -225,30 +214,19 @@ namespace MonoDevelop.Ide.Commands { if (IdeApp.Workspace.IsOpen) { IBuildTarget buildTarget = IdeApp.ProjectOperations.CurrentSelectedBuildTarget; - info.Enabled = ((buildTarget != null) && (IdeApp.ProjectOperations.CurrentBuildOperation.IsCompleted)) && buildTarget.SupportsTarget (ProjectService.BuildTarget); + info.Enabled = (buildTarget != null) && (IdeApp.ProjectOperations.CurrentBuildOperation.IsCompleted); if (buildTarget != null) { info.Text = GettextCatalog.GetString ("R_ebuild {0}", IdeApp.ProjectOperations.CurrentSelectedBuildTarget.Name.Replace ("_","__")); info.Description = GettextCatalog.GetString ("Rebuild {0}", IdeApp.ProjectOperations.CurrentSelectedBuildTarget.Name); } } - else { - info.Enabled = ((IdeApp.Workbench.ActiveDocument != null) && (IdeApp.Workbench.ActiveDocument.IsBuildTarget) && (IdeApp.ProjectOperations.CurrentBuildOperation.IsCompleted)); - if (info.Enabled) { - info.Text = GettextCatalog.GetString ("R_ebuild {0}", IdeApp.Workbench.ActiveDocument.FileName.FileName.Replace ("_","__")); - info.Description = GettextCatalog.GetString ("Rebuild {0}", IdeApp.Workbench.ActiveDocument.FileName); - } - } + else + info.Enabled = false; } protected override void Run () { - if (IdeApp.Workspace.IsOpen) { - IdeApp.ProjectOperations.Rebuild (IdeApp.ProjectOperations.CurrentSelectedBuildTarget); - } - else { - IdeApp.Workbench.ActiveDocument.Save (); - IdeApp.Workbench.ActiveDocument.Rebuild (); - } + IdeApp.ProjectOperations.Rebuild (IdeApp.ProjectOperations.CurrentSelectedBuildTarget); } } @@ -273,12 +251,11 @@ namespace MonoDevelop.Ide.Commands public static bool CanRun (IExecutionHandler executionHandler) { - if (IdeApp.Workspace.IsOpen) { + if (IdeApp.Workspace.IsOpen) { var target = GetRunTarget (); return target != null && IdeApp.ProjectOperations.CanExecute (target, executionHandler); - } - else - return (IdeApp.Workbench.ActiveDocument != null) && (IdeApp.Workbench.ActiveDocument.CanRun (executionHandler)); + } else + return false; } public static void RunMethod (IExecutionHandler executionHandler) @@ -290,27 +267,16 @@ namespace MonoDevelop.Ide.Commands IdeApp.ProjectOperations.CurrentRunOperation.WaitForCompleted (); } - if (!IdeApp.Workspace.IsOpen) { - if (!IdeApp.Preferences.BuildBeforeExecuting) - IdeApp.Workbench.ActiveDocument.Run (executionHandler); - else { - IAsyncOperation asyncOperation = IdeApp.Workbench.ActiveDocument.Build (); - asyncOperation.Completed += delegate { - if ((asyncOperation.Success) || (IdeApp.Preferences.RunWithWarnings && asyncOperation.SuccessWithWarnings)) - IdeApp.Workbench.ActiveDocument.Run (executionHandler); - }; - } - } - else { + if (IdeApp.Workspace.IsOpen) { var target = GetRunTarget (); if (!IdeApp.Preferences.BuildBeforeExecuting) IdeApp.ProjectOperations.Execute (target, executionHandler); else { - IAsyncOperation asyncOperation = IdeApp.ProjectOperations.Build (target); - asyncOperation.Completed += delegate { - if ((asyncOperation.Success) || (IdeApp.Preferences.RunWithWarnings && asyncOperation.SuccessWithWarnings)) - IdeApp.ProjectOperations.Execute (target, executionHandler); - }; + AsyncOperation<BuildResult> asyncOperation = IdeApp.ProjectOperations.Build (target); + asyncOperation.Task.ContinueWith (ta => { + if (!ta.Result.HasErrors && (!ta.Result.HasWarnings || IdeApp.Preferences.RunWithWarnings)) + IdeApp.ProjectOperations.Execute (target, executionHandler); + }); } } @@ -357,12 +323,11 @@ namespace MonoDevelop.Ide.Commands if (!IdeApp.Preferences.BuildBeforeExecuting) IdeApp.ProjectOperations.Execute (IdeApp.ProjectOperations.CurrentSelectedBuildTarget); else { - IAsyncOperation asyncOperation = IdeApp.ProjectOperations.Build (IdeApp.ProjectOperations.CurrentSelectedBuildTarget); - asyncOperation.Completed += delegate - { - if ((asyncOperation.Success) || (IdeApp.Preferences.RunWithWarnings && asyncOperation.SuccessWithWarnings)) - IdeApp.ProjectOperations.Execute (IdeApp.ProjectOperations.CurrentSelectedBuildTarget); - }; + var asyncOperation = IdeApp.ProjectOperations.Build (IdeApp.ProjectOperations.CurrentSelectedBuildTarget); + asyncOperation.Task.ContinueWith (t => { + if (!t.Result.HasErrors && (!t.Result.HasWarnings || IdeApp.Preferences.RunWithWarnings)) + IdeApp.ProjectOperations.Execute (IdeApp.ProjectOperations.CurrentSelectedBuildTarget); + }); } } } @@ -371,7 +336,7 @@ namespace MonoDevelop.Ide.Commands { protected override void Update (CommandArrayInfo info) { - SolutionEntityItem item = IdeApp.ProjectOperations.CurrentSelectedBuildTarget as SolutionEntityItem; + SolutionItem item = IdeApp.ProjectOperations.CurrentSelectedBuildTarget as SolutionItem; if (item != null) { ExecutionModeCommandService.GenerateExecutionModeCommands ( item, @@ -392,12 +357,11 @@ namespace MonoDevelop.Ide.Commands if (!IdeApp.Preferences.BuildBeforeExecuting) IdeApp.ProjectOperations.Execute (target, h); else { - IAsyncOperation asyncOperation = IdeApp.ProjectOperations.Build (target); - asyncOperation.Completed += delegate - { - if ((asyncOperation.Success) || (IdeApp.Preferences.RunWithWarnings && asyncOperation.SuccessWithWarnings)) + var asyncOperation = IdeApp.ProjectOperations.Build (target); + asyncOperation.Task.ContinueWith (t => { + if (!t.Result.HasErrors && (!t.Result.HasWarnings || IdeApp.Preferences.RunWithWarnings)) IdeApp.ProjectOperations.Execute (target, h); - }; + }); } } } @@ -409,7 +373,6 @@ namespace MonoDevelop.Ide.Commands if (IdeApp.ProjectOperations.CurrentSelectedBuildTarget == null) info.Enabled = false; else { - info.Enabled = IdeApp.ProjectOperations.CurrentSelectedBuildTarget.SupportsTarget (ProjectService.BuildTarget); info.Text = GettextCatalog.GetString ("C_lean {0}", IdeApp.ProjectOperations.CurrentSelectedBuildTarget.Name.Replace ("_","__")); info.Description = GettextCatalog.GetString ("Clean {0}", IdeApp.ProjectOperations.CurrentSelectedBuildTarget.Name); } @@ -473,9 +436,9 @@ namespace MonoDevelop.Ide.Commands protected override void Run (object dataItem) { - IWorkspaceObject ce = IdeApp.ProjectOperations.CurrentSelectedBuildTarget; + var ce = IdeApp.ProjectOperations.CurrentSelectedBuildTarget as WorkspaceObject; CustomCommand cmd = (CustomCommand) dataItem; - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor (); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor (); Thread t = new Thread ( delegate () { @@ -498,7 +461,7 @@ namespace MonoDevelop.Ide.Commands protected override void Update (CommandInfo info) { // FIXME: Once we fix Workspaces to offer Visual Studio formats (instead of the deprecated MonoDevelop 1.0 format), we can allow exporting of Workspaces as well. - if (!(IdeApp.ProjectOperations.CurrentSelectedItem is Solution) && !(IdeApp.ProjectOperations.CurrentSelectedItem is SolutionEntityItem)) + if (!(IdeApp.ProjectOperations.CurrentSelectedItem is Solution) && !(IdeApp.ProjectOperations.CurrentSelectedItem is SolutionItem)) info.Enabled = false; } @@ -507,7 +470,7 @@ namespace MonoDevelop.Ide.Commands WorkspaceItem workspace; if (!(IdeApp.ProjectOperations.CurrentSelectedItem is WorkspaceItem)) - workspace = ((SolutionEntityItem) IdeApp.ProjectOperations.CurrentSelectedItem).ParentSolution; + workspace = ((SolutionItem) IdeApp.ProjectOperations.CurrentSelectedItem).ParentSolution; else workspace = (WorkspaceItem) IdeApp.ProjectOperations.CurrentSelectedItem; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs index 797e266a66..fed013ddb5 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs @@ -93,7 +93,7 @@ namespace MonoDevelop.Ide.Commands string initialDirectoryTool = StringParserService.Parse (tool.InitialDirectory, IdeApp.Workbench.GetStringTagModel ()); //Execute tool - IProgressMonitor progressMonitor = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor (); + ProgressMonitor progressMonitor = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor (); try { progressMonitor.Log.WriteLine (GettextCatalog.GetString ("Running: {0} {1}", (commandTool), (argumentsTool))); progressMonitor.Log.WriteLine (); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomTool.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomTool.cs index 81bf74609c..3de3fad30f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomTool.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomTool.cs @@ -28,12 +28,13 @@ using System; using MonoDevelop.Projects; using System.CodeDom.Compiler; using MonoDevelop.Core; +using System.Threading.Tasks; namespace MonoDevelop.Ide.CustomTools { public interface ISingleFileCustomTool { - IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result); + Task Generate (ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result); } public class SingleFileCustomToolResult diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs index 78f2292634..00aa394ed9 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs @@ -31,20 +31,28 @@ using MonoDevelop.Core; using Mono.Addins; using MonoDevelop.Projects; using System.IO; -using MonoDevelop.Ide.Tasks; using System.CodeDom.Compiler; using MonoDevelop.Ide.Gui; using MonoDevelop.Core.ProgressMonitoring; using System.Linq; using System.Threading; +using Task = System.Threading.Tasks.Task; +using IdeTask = MonoDevelop.Ide.Tasks.UserTask; +using MonoDevelop.Ide.Tasks; namespace MonoDevelop.Ide.CustomTools { public static class CustomToolService { static readonly Dictionary<string,CustomToolExtensionNode> nodes = new Dictionary<string,CustomToolExtensionNode> (); - - static readonly Dictionary<string,IAsyncOperation> runningTasks = new Dictionary<string, IAsyncOperation> (); + + class TaskInfo { + public Task Task; + public CancellationTokenSource CancellationTokenSource; + public SingleFileCustomToolResult Result; + } + + static readonly Dictionary<string,TaskInfo> runningTasks = new Dictionary<string, TaskInfo> (); static CustomToolService () { @@ -103,7 +111,7 @@ namespace MonoDevelop.Ide.CustomTools return null; } - public static void Update (ProjectFile file, bool force) + public async static void Update (ProjectFile file, bool force) { var tool = GetGenerator (file.Generator); if (tool == null) @@ -122,49 +130,50 @@ namespace MonoDevelop.Ide.CustomTools //if this file is already being run, cancel it lock (runningTasks) { - IAsyncOperation runningTask; + TaskInfo runningTask; if (runningTasks.TryGetValue (file.FilePath, out runningTask)) { - runningTask.Cancel (); + runningTask.CancellationTokenSource.Cancel (); runningTasks.Remove (file.FilePath); } } - - var monitor = IdeApp.Workbench.ProgressMonitors.GetToolOutputProgressMonitor (false); + + CancellationTokenSource cs = new CancellationTokenSource (); + var monitor = IdeApp.Workbench.ProgressMonitors.GetToolOutputProgressMonitor (false).WithCancellationSource (cs); var result = new SingleFileCustomToolResult (); - var aggOp = new AggregatedOperationMonitor (monitor); + Task op; try { monitor.BeginTask (GettextCatalog.GetString ("Running generator '{0}' on file '{1}'...", file.Generator, file.Name), 1); - IAsyncOperation op = tool.Generate (monitor, file, result); - runningTasks.Add (file.FilePath, op); - aggOp.AddOperation (op); - op.Completed += delegate { - lock (runningTasks) { - IAsyncOperation runningTask; - if (runningTasks.TryGetValue (file.FilePath, out runningTask) && runningTask == op) { - runningTasks.Remove (file.FilePath); - UpdateCompleted (monitor, aggOp, file, genFile, result); - } else { - //it was cancelled because another was run for the same file, so just clean up - aggOp.Dispose (); - monitor.EndTask (); - monitor.ReportWarning (GettextCatalog.GetString ("Cancelled because generator ran again for the same file")); - monitor.Dispose (); - } - } - }; + op = tool.Generate (monitor, file, result); + runningTasks.Add (file.FilePath, new TaskInfo { + Task = op, + CancellationTokenSource = cs, + Result = result + }); } catch (Exception ex) { result.UnhandledException = ex; - UpdateCompleted (monitor, aggOp, file, genFile, result); + UpdateCompleted (monitor, file, genFile, result); + return; + } + await op; + lock (runningTasks) { + TaskInfo runningTask; + if (runningTasks.TryGetValue (file.FilePath, out runningTask) && runningTask.Task == op) { + runningTasks.Remove (file.FilePath); + UpdateCompleted (monitor, file, genFile, result); + } else { + //it was cancelled because another was run for the same file, so just clean up + monitor.EndTask (); + monitor.ReportWarning (GettextCatalog.GetString ("Cancelled because generator ran again for the same file")); + monitor.Dispose (); + } } } - static void UpdateCompleted (IProgressMonitor monitor, AggregatedOperationMonitor aggOp, - ProjectFile file, ProjectFile genFile, SingleFileCustomToolResult result) + static void UpdateCompleted (ProgressMonitor monitor, ProjectFile file, ProjectFile genFile, SingleFileCustomToolResult result) { monitor.EndTask (); - aggOp.Dispose (); - - if (monitor.IsCancelRequested) { + + if (monitor.CancellationToken.IsCancellationRequested) { monitor.ReportError (GettextCatalog.GetString ("Cancelled"), null); monitor.Dispose (); return; @@ -200,19 +209,23 @@ namespace MonoDevelop.Ide.CustomTools } if (result.Errors.Count > 0) { - foreach (CompilerError err in result.Errors) - TaskService.Errors.Add (new Task (file.FilePath, err.ErrorText, err.Column, err.Line, - err.IsWarning? TaskSeverity.Warning : TaskSeverity.Error, - TaskPriority.Normal, file.Project.ParentSolution, file)); + DispatchService.GuiDispatch (delegate { + foreach (CompilerError err in result.Errors) + TaskService.Errors.Add (new UserTask (file.FilePath, err.ErrorText, err.Column, err.Line, + err.IsWarning? TaskSeverity.Warning : TaskSeverity.Error, + TaskPriority.Normal, file.Project.ParentSolution, file)); + }); } if (broken) return; - + if (result.Success) monitor.ReportSuccess ("Generated file successfully."); + else if (result.SuccessWithWarnings) + monitor.ReportSuccess ("Warnings in file generation."); else - monitor.ReportError ("Failed to generate file. See error pad for details.", null); + monitor.ReportError ("Errors in file generation.", null); } finally { monitor.Dispose (); @@ -246,7 +259,7 @@ namespace MonoDevelop.Ide.CustomTools } if (projectChanged) - IdeApp.ProjectOperations.Save (file.Project); + IdeApp.ProjectOperations.SaveAsync (file.Project); }); } @@ -271,9 +284,9 @@ namespace MonoDevelop.Ide.CustomTools return ns; } - public static bool WaitForRunningTools (IProgressMonitor monitor) + public static bool WaitForRunningTools (ProgressMonitor monitor) { - IAsyncOperation[] operations; + TaskInfo[] operations; lock (runningTasks) { operations = runningTasks.Values.ToArray (); } @@ -285,27 +298,24 @@ namespace MonoDevelop.Ide.CustomTools var evt = new AutoResetEvent (false); - monitor.CancelRequested += delegate { - evt.Set (); - }; - - OperationHandler checkOp = delegate { - monitor.Step (1); - if (operations.All (op => op.IsCompleted)) - evt.Set (); - }; + foreach (var t in operations) { + t.Task.ContinueWith (ta => { + monitor.Step (1); + if (operations.All (op => op.Task.IsCompleted)) + evt.Set (); + }); + } - foreach (var o in operations) - o.Completed += checkOp; + monitor.CancellationToken.Register (delegate { + evt.Set (); + }); evt.WaitOne (); - bool success = operations.All (op => op.Success); - - if (!success) - monitor.ReportError ("Error in custom tool", null); monitor.EndTask (); - return success; + + //the tool operations display warnings themselves + return operations.Any (op => !op.Result.SuccessWithWarnings); } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/MSBuildCustomTool.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/MSBuildCustomTool.cs index 1edc9e59fc..5d7cd8fe35 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/MSBuildCustomTool.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/MSBuildCustomTool.cs @@ -27,6 +27,7 @@ using MonoDevelop.Core;
using MonoDevelop.Projects;
using System.CodeDom.Compiler;
+using System.Threading.Tasks;
namespace MonoDevelop.Ide.CustomTools
{
@@ -39,16 +40,14 @@ namespace MonoDevelop.Ide.CustomTools this.targetName = targetName;
}
- public IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result)
+ public async Task Generate (ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result)
{
- return new ThreadAsyncOperation (() => {
- var buildResult = file.Project.RunTarget (monitor, targetName, IdeApp.Workspace.ActiveConfiguration);
- foreach (var err in buildResult.Errors) {
- result.Errors.Add (new CompilerError (err.FileName, err.Line, err.Column, err.ErrorNumber, err.ErrorText) {
- IsWarning = err.IsWarning
- });
- }
- }, result);
+ var buildResult = await file.Project.RunTarget (monitor, targetName, IdeApp.Workspace.ActiveConfiguration);
+ foreach (var err in buildResult.Errors) {
+ result.Errors.Add (new CompilerError (err.FileName, err.Line, err.Column, err.ErrorNumber, err.ErrorText) {
+ IsWarning = err.IsWarning
+ });
+ }
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/PublicResXFileCodeGenerator.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/PublicResXFileCodeGenerator.cs index 48f9679587..82dcd12c3d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/PublicResXFileCodeGenerator.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/PublicResXFileCodeGenerator.cs @@ -38,14 +38,15 @@ using MonoDevelop.Projects; using MonoDevelop.Ide.CustomTools; using System.Resources.Tools; using System.CodeDom.Compiler; +using System.Threading.Tasks; namespace MonoDevelop.Ide.CustomTools { public class PublicResXFileCodeGenerator : ISingleFileCustomTool { - public IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) + public Task Generate (ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { - return new ThreadAsyncOperation (ResXFileCodeGenerator.GenerateFile (file, result, false), result); + return ResXFileCodeGenerator.GenerateFile (file, result, false); } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/ResXFileCodeGenerator.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/ResXFileCodeGenerator.cs index b54085a249..875c19baae 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/ResXFileCodeGenerator.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/ResXFileCodeGenerator.cs @@ -45,41 +45,43 @@ using MonoDevelop.Core.Assemblies; using System.Resources; using System.Collections.Generic; using System.Collections; +using System.Threading.Tasks; namespace MonoDevelop.Ide.CustomTools { public class ResXFileCodeGenerator : ISingleFileCustomTool { - public IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) + public Task Generate (ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { - return new ThreadAsyncOperation (GenerateFile (file, result, true), result); + return GenerateFile (file, result, true); } - public static Action GenerateFile (ProjectFile file, SingleFileCustomToolResult result, bool internalClass) + public async static Task GenerateFile (ProjectFile file, SingleFileCustomToolResult result, bool internalClass) { - return delegate { - var dnp = file.Project as DotNetProject; - if (dnp == null) { - var err = "ResXFileCodeGenerator can only be used with .NET projects"; - result.Errors.Add (new CompilerError (null, 0, 0, null, err)); - return; - } + var dnp = file.Project as DotNetProject; + if (dnp == null) { + var err = "ResXFileCodeGenerator can only be used with .NET projects"; + result.Errors.Add (new CompilerError (null, 0, 0, null, err)); + return; + } - var provider = dnp.LanguageBinding.GetCodeDomProvider (); - if (provider == null) { - var err = "ResXFileCodeGenerator can only be used with languages that support CodeDOM"; - result.Errors.Add (new CompilerError (null, 0, 0, null, err)); - return; - } + var provider = dnp.LanguageBinding.GetCodeDomProvider (); + if (provider == null) { + var err = "ResXFileCodeGenerator can only be used with languages that support CodeDOM"; + result.Errors.Add (new CompilerError (null, 0, 0, null, err)); + return; + } - var outputfile = file.FilePath.ChangeExtension (".Designer." + provider.FileExtension); - var ns = CustomToolService.GetFileNamespace (file, outputfile); - var cn = provider.CreateValidIdentifier (file.FilePath.FileNameWithoutExtension); - var rd = new Dictionary<object, object> (); + var outputfile = file.FilePath.ChangeExtension (".Designer." + provider.FileExtension); + var ns = CustomToolService.GetFileNamespace (file, outputfile); + var cn = provider.CreateValidIdentifier (file.FilePath.FileNameWithoutExtension); + var rd = new Dictionary<object, object> (); + var filePath = file.FilePath; + var targetsPcl2Framework = TargetsPcl2Framework (dnp); - using (var r = new ResXResourceReader (file.FilePath)) { - r.UseResXDataNodes = true; - r.BasePath = file.FilePath.ParentDirectory; + await Task.Factory.StartNew (() => { + using (var r = new ResXResourceReader (filePath)) { + r.BasePath = filePath.ParentDirectory; foreach (DictionaryEntry e in r) { rd.Add (e.Key, e.Value); @@ -88,21 +90,21 @@ namespace MonoDevelop.Ide.CustomTools string[] unmatchable; var ccu = StronglyTypedResourceBuilder.Create (rd, cn, ns, provider, internalClass, out unmatchable); - - if (TargetsPcl2Framework (dnp)) { + + if (targetsPcl2Framework) { FixupPclTypeInfo (ccu); } foreach (var p in unmatchable) { var msg = string.Format ("Could not generate property for resource ID '{0}'", p); - result.Errors.Add (new CompilerError (file.FilePath, 0, 0, null, msg)); + result.Errors.Add (new CompilerError (filePath, 0, 0, null, msg)); } using (var w = new StreamWriter (outputfile, false, Encoding.UTF8)) provider.GenerateCodeFromCompileUnit (ccu, w, new CodeGeneratorOptions ()); result.GeneratedFilePath = outputfile; - }; + }); } static bool TargetsPcl2Framework (DotNetProject dnp) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/ThreadAsyncOperation.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/ThreadAsyncOperation.cs deleted file mode 100644 index 83f1de0475..0000000000 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/ThreadAsyncOperation.cs +++ /dev/null @@ -1,120 +0,0 @@ -// -// TextTemplatingFileGenerator.cs -// -// Author: -// Michael Hutchinson <mhutchinson@novell.com> -// -// Copyright (c) 2010 Novell, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using MonoDevelop.Ide.CustomTools; -using MonoDevelop.Core; -using System.Threading; - -namespace MonoDevelop.Ide.CustomTools -{ - public class ThreadAsyncOperation : IAsyncOperation - { - readonly object locker = new object (); - readonly Thread thread; - readonly SingleFileCustomToolResult result; - readonly Action task; - - bool cancelled; - bool isCompleted; - - public ThreadAsyncOperation (Action task, SingleFileCustomToolResult result) - { - if (result == null) - throw new ArgumentNullException ("result"); - - this.task = task; - this.result = result; - thread = new Thread (Run); - thread.Start (); - } - - void Run () - { - try { - task (); - } catch (ThreadAbortException ex) { - result.UnhandledException = ex; - Thread.ResetAbort (); - } catch (Exception ex) { - result.UnhandledException = ex; - } - - OperationHandler c; - lock (locker) { - isCompleted = true; - c = completed; - completed = null; - } - - if (c != null) - c (this); - } - - OperationHandler completed; - - public event OperationHandler Completed { - add { - lock (locker) { - if (!isCompleted) { - completed += value; - return; - } - } - value (this); - } - remove { - lock (locker) { - if (completed != null) - completed -= value; - } - } - } - - public void Cancel () - { - cancelled = true; - thread.Abort (); - } - - public void WaitForCompleted () - { - thread.Join (); - } - - public bool IsCompleted { - get { return isCompleted; } - } - - public bool Success { - get { return !cancelled && result.Success; } - } - - public bool SuccessWithWarnings { - get { return !cancelled && result.SuccessWithWarnings; } - } - } -} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs index a0c7c71d58..dfedfb0155 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs @@ -55,10 +55,7 @@ namespace MonoDevelop.Ide.Desktop public abstract string Name { get; } - /// <summary> - /// Used in the text editor. Valid values are found in MonoDevelop.SourceEditor.ControlLeftRightMode in the - /// source editor project. - /// </summary> + [Obsolete] public virtual string DefaultControlLeftRightBehavior { get { return "MonoDevelop"; @@ -347,7 +344,7 @@ namespace MonoDevelop.Ide.Desktop } //must be implemented if CanOpenTerminal returns true - public virtual IProcessAsyncOperation StartConsoleProcess ( + public virtual ProcessAsyncOperation StartConsoleProcess ( string command, string arguments, string workingDirectory, IDictionary<string, string> environmentVariables, string title, bool pauseWhenFinished) @@ -458,5 +455,19 @@ namespace MonoDevelop.Ide.Desktop SetMainWindowDecorations (window); } } + + public virtual void AddChildWindow (Gtk.Window parent, Gtk.Window child) + { + } + + public virtual void RemoveChildWindow (Gtk.Window parent, Gtk.Window child) + { + } + + public virtual void PlaceWindow (Gtk.Window window, int x, int y, int width, int height) + { + window.Move (x, y); + window.Resize (width, height); + } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/CommandExecutionContext.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/CommandExecutionContext.cs index fe5e859e91..b02580b4a1 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/CommandExecutionContext.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/CommandExecutionContext.cs @@ -33,22 +33,22 @@ namespace MonoDevelop.Ide.Execution public class CommandExecutionContext { CanExecuteDelegate runCheckDelegate; - SolutionEntityItem project; + SolutionItem project; ExecutionCommand cmd; - public CommandExecutionContext (SolutionEntityItem project, CanExecuteDelegate runCheckDelegate) + public CommandExecutionContext (SolutionItem project, CanExecuteDelegate runCheckDelegate) { this.project = project; this.runCheckDelegate = runCheckDelegate; } - public CommandExecutionContext (SolutionEntityItem project, ExecutionCommand cmd) + public CommandExecutionContext (SolutionItem project, ExecutionCommand cmd) { this.project = project; this.cmd = cmd; } - public SolutionEntityItem Project { + public SolutionItem Project { get { return project; } } @@ -81,7 +81,7 @@ namespace MonoDevelop.Ide.Execution return true; } - public IProcessAsyncOperation Execute (MonoDevelop.Core.Execution.ExecutionCommand command, MonoDevelop.Core.Execution.IConsole console) + public ProcessAsyncOperation Execute (MonoDevelop.Core.Execution.ExecutionCommand command, MonoDevelop.Core.Execution.IConsole console) { throw new InvalidOperationException (); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/CustomExecutionMode.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/CustomExecutionMode.cs index 5913bb7548..fb2d3f916b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/CustomExecutionMode.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/CustomExecutionMode.cs @@ -66,7 +66,7 @@ namespace MonoDevelop.Ide.Execution [ItemProperty (DefaultValue=false)] public bool PromptForParameters { get; set; } - public SolutionEntityItem Project { get; set; } + public SolutionItem Project { get; set; } public CustomModeScope Scope { get; set; } @@ -117,12 +117,12 @@ namespace MonoDevelop.Ide.Execution return false; } - public IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) + public ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) { return Execute (command, console, true, false); } - public IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console, bool allowPrompt, bool forcePrompt) + public ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console, bool allowPrompt, bool forcePrompt) { if ((PromptForParameters || forcePrompt) && allowPrompt) { CommandExecutionContext ctx = new CommandExecutionContext (Project, command); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/ExecutionModeCommandService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/ExecutionModeCommandService.cs index a8a2955615..319e34fb0d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/ExecutionModeCommandService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/ExecutionModeCommandService.cs @@ -61,7 +61,7 @@ namespace MonoDevelop.Ide.Execution return null; } - public static void GenerateExecutionModeCommands (SolutionEntityItem project, CanExecuteDelegate runCheckDelegate, CommandArrayInfo info) + public static void GenerateExecutionModeCommands (SolutionItem project, CanExecuteDelegate runCheckDelegate, CommandArrayInfo info) { CommandExecutionContext ctx = new CommandExecutionContext (project, runCheckDelegate); bool supportsParameterization = false; @@ -262,7 +262,7 @@ namespace MonoDevelop.Ide.Execution } } - internal static void SaveCustomCommand (SolutionEntityItem project, CustomExecutionMode cmode) + internal static void SaveCustomCommand (SolutionItem project, CustomExecutionMode cmode) { CustomExecutionModes modes = GetCustomExecutionModeList (project, cmode.Scope); bool found = false; @@ -286,7 +286,7 @@ namespace MonoDevelop.Ide.Execution IdeApp.Workspace.SavePreferences (); } - static CustomExecutionModes GetCustomExecutionModeList (SolutionEntityItem project, CustomModeScope scope) + static CustomExecutionModes GetCustomExecutionModeList (SolutionItem project, CustomModeScope scope) { CustomExecutionModes modes; if (scope == CustomModeScope.Global) { @@ -309,7 +309,7 @@ namespace MonoDevelop.Ide.Execution return modes; } - internal static void RemoveCustomCommand (SolutionEntityItem project, CustomExecutionMode cmode) + internal static void RemoveCustomCommand (SolutionItem project, CustomExecutionMode cmode) { CustomExecutionModes modes = GetCustomExecutionModeList (project, cmode.Scope); modes.Data.Remove (cmode); @@ -437,7 +437,7 @@ namespace MonoDevelop.Ide.Execution return Mode.ExecutionHandler.CanExecute (command); } - public IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) + public ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) { if (Mode is CustomExecutionMode) return ((CustomExecutionMode)Mode).Execute (command, console, true, true); @@ -462,7 +462,7 @@ namespace MonoDevelop.Ide.Execution return Handler.CanExecute (command); } - public IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) + public ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) { return Handler.InternalExecute (Context, ParentMode, command, console); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/ParameterizedExecutionHandler.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/ParameterizedExecutionHandler.cs index fb3464c4fb..28cb2cad4f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/ParameterizedExecutionHandler.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Execution/ParameterizedExecutionHandler.cs @@ -29,6 +29,7 @@ using MonoDevelop.Projects; using MonoDevelop.Core; using MonoDevelop.Core.Execution; using MonoDevelop.Ide.Gui.Dialogs; +using System.Threading.Tasks; namespace MonoDevelop.Ide.Execution { @@ -42,12 +43,12 @@ namespace MonoDevelop.Ide.Execution { public abstract bool CanExecute (ExecutionCommand command); - public IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) + public ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console) { return InternalExecute (new CommandExecutionContext (null, command), new ExecutionMode ("", "", this), command, console); } - internal IProcessAsyncOperation InternalExecute (CommandExecutionContext ctx, IExecutionMode mode, ExecutionCommand command, IConsole console) + internal ProcessAsyncOperation InternalExecute (CommandExecutionContext ctx, IExecutionMode mode, ExecutionCommand command, IConsole console) { CustomExecutionMode cmode = ExecutionModeCommandService.ShowParamtersDialog (ctx, mode, null); if (cmode == null) @@ -71,7 +72,7 @@ namespace MonoDevelop.Ide.Execution /// <param name="configurationData"> /// Configuration information. Created by the IExecutionConfigurationEditor object. /// </param> - public abstract IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console, CommandExecutionContext ctx, object configurationData); + public abstract ProcessAsyncOperation Execute (ExecutionCommand command, IConsole console, CommandExecutionContext ctx, object configurationData); /// <summary> /// Creates an editor to be used to edit the execution handler arguments. @@ -83,50 +84,11 @@ namespace MonoDevelop.Ide.Execution } - class CancelledProcessAsyncOperation: IProcessAsyncOperation + class CancelledProcessAsyncOperation: ProcessAsyncOperation { - public int ExitCode { - get { - return 1; - } - } - - public int ProcessId { - get { - return 0; - } - } - - #region IAsyncOperation implementation - public event OperationHandler Completed { - add { - value (this); - } - remove { } - } - - public void Cancel () - { - } - - public void WaitForCompleted () + public CancelledProcessAsyncOperation () { + ExitCode = 1; } - - public bool IsCompleted { - get { return true; } - } - - public bool Success { - get { return false; } - } - - public bool SuccessWithWarnings { - get { return false; } - } - - #endregion - - void IDisposable.Dispose () {} } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Extensions/IdeCustomizer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Extensions/IdeCustomizer.cs index 71a050adb5..70d187388a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Extensions/IdeCustomizer.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Extensions/IdeCustomizer.cs @@ -37,9 +37,40 @@ namespace MonoDevelop.Ide.Extensions /// </remarks> public class IdeCustomizer { + /// <summary> + /// Called just after the initializer is created + /// </summary> internal protected virtual void Initialize () { } + + /// <summary> + /// Called when the add-in engine has been initialized + /// </summary> + internal protected virtual void OnCoreInitialized () + { + } + + /// <summary> + /// Called when the Ide has been initialized + /// </summary> + internal protected virtual void OnIdeInitialized () + { + } + + /// <summary> + /// Called after the main loop stops running + /// </summary> + internal protected virtual void OnIdeShutdown () + { + } + + /// <summary> + /// Called after the IDE core has been shut down + /// </summary> + internal protected virtual void OnCoreShutdown () + { + } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FileProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FileProvider.cs index cd1ab5e91b..0d1fd091d4 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FileProvider.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FileProvider.cs @@ -22,10 +22,10 @@ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE.
-
-using System.IO;
-using System.Linq;
+// THE SOFTWARE. + +using System.IO; +using System.Linq; using MonoDevelop.Projects; using MonoDevelop.Ide.Gui; using System.Text; @@ -80,8 +80,9 @@ namespace MonoDevelop.Ide.FindInFiles if (buffer != null) return buffer.ToString (); var doc = SearchDocument (); - if (doc != null) + if (doc != null && doc.Editor != null) { return doc.Editor.Text; + } try { if (!File.Exists (FileName)) return null; @@ -92,11 +93,11 @@ namespace MonoDevelop.Ide.FindInFiles } } - Document SearchDocument ()
- {
- return IdeApp.Workbench.Documents.FirstOrDefault(d => !string.IsNullOrEmpty (d.FileName) && Path.GetFullPath (d.FileName) == Path.GetFullPath (FileName));
- }
-
+ Document SearchDocument () + { + return IdeApp.Workbench.Documents.FirstOrDefault(d => !string.IsNullOrEmpty (d.FileName) && Path.GetFullPath (d.FileName) == Path.GetFullPath (FileName)); + } + Document document; StringBuilder buffer = null; bool somethingReplaced; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs index 8ddfbccf09..136bb723de 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs @@ -735,7 +735,7 @@ namespace MonoDevelop.Ide.FindInFiles SearchReplace (comboboxentryFind.Entry.Text, null, GetScope (), GetFilterOptions (), () => UpdateStopButton ()); } - readonly static List<ISearchProgressMonitor> searchesInProgress = new List<ISearchProgressMonitor> (); + readonly static List<CancellationTokenSource> searchesInProgress = new List<CancellationTokenSource> (); void UpdateStopButton () { buttonStop.Sensitive = searchesInProgress.Count > 0; @@ -746,19 +746,19 @@ namespace MonoDevelop.Ide.FindInFiles lock (searchesInProgress) { if (searchesInProgress.Count == 0) return; - ISearchProgressMonitor monitor = searchesInProgress[searchesInProgress.Count - 1]; - monitor.AsyncOperation.Cancel (); + var cs = searchesInProgress[searchesInProgress.Count - 1]; + cs.Cancel (); } } - internal static void SearchReplace (string findPattern, string replacePattern, Scope scope, FilterOptions options, System.Action UpdateStopButton) + internal async static void SearchReplace (string findPattern, string replacePattern, Scope scope, FilterOptions options, System.Action UpdateStopButton) { if (find != null && find.IsRunning) { if (!MessageService.Confirm (GettextCatalog.GetString ("There is a search already in progress. Do you want to stop it?"), AlertButton.Stop)) return; lock (searchesInProgress) { - foreach (var mon in searchesInProgress) - mon.AsyncOperation.Cancel (); + foreach (var cs in searchesInProgress) + cs.Cancel (); searchesInProgress.Clear (); } } @@ -779,57 +779,52 @@ namespace MonoDevelop.Ide.FindInFiles return; } - ThreadPool.QueueUserWorkItem (delegate { - using (ISearchProgressMonitor searchMonitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true)) { - searchMonitor.ReportStatus (scope.GetDescription (options, pattern, null)); - - lock (searchesInProgress) - searchesInProgress.Add (searchMonitor); - if (UpdateStopButton != null) { - Application.Invoke (delegate { - UpdateStopButton (); - }); + using (SearchProgressMonitor searchMonitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true)) { + searchMonitor.ReportStatus (scope.GetDescription (options, pattern, null)); + var cs = CancellationTokenSource.CreateLinkedTokenSource (searchMonitor.CancellationToken); + lock (searchesInProgress) + searchesInProgress.Add (cs); + if (UpdateStopButton != null) + UpdateStopButton (); + + DateTime timer = DateTime.Now; + string errorMessage = null; + + try { + ResultQueue<SearchResult> results = new ResultQueue<SearchResult> (); + find.FindAll (scope, searchMonitor, pattern, replacePattern, options, results); + SearchResult[] res = await results.DequeueMany (); + while (res.Length > 0) { + if (cs.IsCancellationRequested) + return; + searchMonitor.ReportResults (res); + res = await results.DequeueMany (); } - - DateTime timer = DateTime.Now; - string errorMessage = null; - - try { - var results = new List<SearchResult> (); - foreach (SearchResult result in find.FindAll (scope, searchMonitor, pattern, replacePattern, options)) { - if (searchMonitor.IsCancelRequested) - return; - results.Add (result); - } - searchMonitor.ReportResults (results); - } catch (Exception ex) { - errorMessage = ex.Message; - LoggingService.LogError ("Error while search", ex); - } - - string message; - if (errorMessage != null) { - message = GettextCatalog.GetString ("The search could not be finished: {0}", errorMessage); - searchMonitor.ReportError (message, null); - } else if (searchMonitor.IsCancelRequested) { - message = GettextCatalog.GetString ("Search cancelled."); - searchMonitor.ReportWarning (message); - } else { - string matches = string.Format (GettextCatalog.GetPluralString ("{0} match found", "{0} matches found", find.FoundMatchesCount), find.FoundMatchesCount); - string files = string.Format (GettextCatalog.GetPluralString ("in {0} file.", "in {0} files.", find.SearchedFilesCount), find.SearchedFilesCount); - message = GettextCatalog.GetString ("Search completed.") + Environment.NewLine + matches + " " + files; - searchMonitor.ReportSuccess (message); - } - searchMonitor.ReportStatus (message); - searchMonitor.Log.WriteLine (GettextCatalog.GetString ("Search time: {0} seconds."), (DateTime.Now - timer).TotalSeconds); - searchesInProgress.Remove (searchMonitor); + } catch (Exception ex) { + errorMessage = ex.Message; + LoggingService.LogError ("Error while search", ex); } - if (UpdateStopButton != null) { - Application.Invoke (delegate { - UpdateStopButton (); - }); + + string message; + if (errorMessage != null) { + message = GettextCatalog.GetString ("The search could not be finished: {0}", errorMessage); + searchMonitor.ReportError (message, null); + } else if (cs.IsCancellationRequested) { + message = GettextCatalog.GetString ("Search cancelled."); + searchMonitor.ReportWarning (message); + } else { + string matches = string.Format (GettextCatalog.GetPluralString ("{0} match found", "{0} matches found", find.FoundMatchesCount), find.FoundMatchesCount); + string files = string.Format (GettextCatalog.GetPluralString ("in {0} file.", "in {0} files.", find.SearchedFilesCount), find.SearchedFilesCount); + message = GettextCatalog.GetString ("Search completed.") + Environment.NewLine + matches + " " + files; + searchMonitor.ReportSuccess (message); } - }); + searchMonitor.ReportStatus (message); + searchMonitor.Log.WriteLine (GettextCatalog.GetString ("Search time: {0} seconds."), (DateTime.Now - timer).TotalSeconds); + searchesInProgress.Remove (cs); + } + if (UpdateStopButton != null) { + UpdateStopButton (); + } } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindReplace.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindReplace.cs index 5953b25a5f..80b0c2677a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindReplace.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindReplace.cs @@ -31,6 +31,9 @@ using System.Collections.Generic; using MonoDevelop.Core; using System.Linq; using Gtk; +using System.Threading.Tasks; +using System.Collections.Concurrent; +using System.Threading; namespace MonoDevelop.Ide.FindInFiles { @@ -71,7 +74,7 @@ namespace MonoDevelop.Ide.FindInFiles return true; } - public IEnumerable<SearchResult> FindAll (Scope scope, IProgressMonitor monitor, string pattern, string replacePattern, FilterOptions filter) + public async Task FindAll (Scope scope, ProgressMonitor monitor, string pattern, string replacePattern, FilterOptions filter, ResultQueue<SearchResult> results) { if (filter.RegexSearch) { RegexOptions regexOptions = RegexOptions.Compiled; @@ -84,42 +87,49 @@ namespace MonoDevelop.Ide.FindInFiles monitor.BeginTask (scope.GetDescription (filter, pattern, replacePattern), 50); try { - int totalWork = scope.GetTotalWork (filter); + int totalWork = await scope.GetTotalWork (filter); int step = Math.Max (1, totalWork / 50); string content; - - foreach (FileProvider provider in scope.GetFiles (monitor, filter)) { - if (monitor.IsCancelRequested)
- yield break; - SearchedFilesCount++; - try { - content = provider.ReadString (); + + var files = new ResultQueue<FileProvider> (); + scope.GetFiles (monitor, filter, files); + + await Task.Factory.StartNew (delegate { + FileProvider provider; + while (files.TryDequeue (out provider)) { + if (monitor.CancellationToken.IsCancellationRequested) + break;
+ SearchedFilesCount++; + try { + content = provider.ReadString (); + if (replacePattern != null) + provider.BeginReplace (content); + } catch (System.IO.FileNotFoundException) { + Application.Invoke (delegate { + MessageService.ShowError (string.Format (GettextCatalog.GetString ("File {0} not found.")), provider.FileName); + }); + continue; + } + foreach (SearchResult result in FindAll (monitor, provider, content, pattern, replacePattern, filter)) { + if (monitor.CancellationToken.IsCancellationRequested)
+ break; + FoundMatchesCount++; + results.Enqueue (result); + } if (replacePattern != null) - provider.BeginReplace (content); - } catch (System.IO.FileNotFoundException) { - Application.Invoke (delegate { - MessageService.ShowError (string.Format (GettextCatalog.GetString ("File {0} not found.")), provider.FileName); - }); - continue; - } - foreach (SearchResult result in FindAll (monitor, provider, content, pattern, replacePattern, filter)) { - if (monitor.IsCancelRequested)
- yield break; - FoundMatchesCount++; - yield return result; + provider.EndReplace ();
+ if (SearchedFilesCount % step == 0)
+ monitor.Step (1);
} - if (replacePattern != null) - provider.EndReplace ();
- if (SearchedFilesCount % step == 0)
- monitor.Step (1);
- } + results.SetComplete (); + }); } finally { monitor.EndTask (); IsRunning = false; } } - IEnumerable<SearchResult> FindAll (IProgressMonitor monitor, FileProvider provider, string content, string pattern, string replacePattern, FilterOptions filter) + IEnumerable<SearchResult> FindAll (ProgressMonitor monitor, FileProvider provider, string content, string pattern, string replacePattern, FilterOptions filter) { if (string.IsNullOrEmpty (pattern)) return Enumerable.Empty<SearchResult> (); @@ -130,12 +140,12 @@ namespace MonoDevelop.Ide.FindInFiles return Search (provider, content, pattern, replacePattern, filter); } - IEnumerable<SearchResult> RegexSearch (IProgressMonitor monitor, FileProvider provider, string content, string replacePattern, FilterOptions filter) + IEnumerable<SearchResult> RegexSearch (ProgressMonitor monitor, FileProvider provider, string content, string replacePattern, FilterOptions filter) { var results = new List<SearchResult> (); if (replacePattern == null) { foreach (Match match in regex.Matches (content)) { - if (monitor.IsCancelRequested) + if (monitor.CancellationToken.IsCancellationRequested) break; if (provider.SelectionStartPosition > -1 && match.Index < provider.SelectionStartPosition) continue; @@ -156,7 +166,7 @@ namespace MonoDevelop.Ide.FindInFiles } provider.BeginReplace (content); int delta = 0; - for (int i = 0; !monitor.IsCancelRequested && i < matches.Count; i++) { + for (int i = 0; !monitor.CancellationToken.IsCancellationRequested && i < matches.Count; i++) { Match match = matches[i]; if (!filter.WholeWordsOnly || FilterOptions.IsWholeWordAt (content, match.Index, match.Length)) { string replacement = match.Result (replacePattern); @@ -192,4 +202,66 @@ namespace MonoDevelop.Ide.FindInFiles } } } + + public class ResultQueue<T> + { + Queue<T> queue = new Queue<T>(); + bool complete; + + public void Enqueue (T v) + { + lock (queue) { + queue.Enqueue (v); + Monitor.PulseAll (queue); + } + } + + public bool TryDequeue (out T value) + { + lock (queue) { + if (queue.Count == 0) + WaitForValues (); + if (complete) { + value = default(T); + return false; + } + value = queue.Dequeue (); + return true; + } + } + + public async Task<T[]> DequeueMany () + { + lock (queue) { + if (queue.Count > 0 || complete) { + var res = queue.ToArray (); + queue.Clear (); + return res; + } + } + return await Task<T[]>.Factory.StartNew (() => { + WaitForValues (); + var res = queue.ToArray (); + queue.Clear (); + return res; + }); + } + + void WaitForValues () + { + lock (queue) { + while (queue.Count == 0 && !complete) { + Monitor.Wait (queue); + } + } + } + + public void SetComplete () + { + lock (queue) { + complete = true; + Monitor.PulseAll (queue); + } + } + } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ISearchProgressMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ISearchProgressMonitor.cs index af1da6d9a8..0dacb70a51 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ISearchProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ISearchProgressMonitor.cs @@ -32,7 +32,7 @@ using MonoDevelop.Core; namespace MonoDevelop.Ide.FindInFiles { - public interface ISearchProgressMonitor: IProgressMonitor + public interface ISearchProgressMonitor { void SetBasePath (string path); void ReportResult (SearchResult result); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ReferencesFinder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ReferencesFinder.cs index 0600d9f415..9691a93978 100755..100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ReferencesFinder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ReferencesFinder.cs @@ -76,12 +76,12 @@ namespace MonoDevelop.Ide.FindInFiles return codon != null ? codon.CreateFinder () : null; } - public static IEnumerable<MemberReference> FindReferences (object member, bool searchForAllOverloads, IProgressMonitor monitor = null) + public static IEnumerable<MemberReference> FindReferences (object member, bool searchForAllOverloads, ProgressMonitor monitor = null) { return FindReferences (IdeApp.ProjectOperations.CurrentSelectedSolution, member, searchForAllOverloads, RefactoryScope.Unknown, monitor); } - public static IEnumerable<MemberReference> FindReferences (object member, bool searchForAllOverloads, RefactoryScope scope, IProgressMonitor monitor = null) + public static IEnumerable<MemberReference> FindReferences (object member, bool searchForAllOverloads, RefactoryScope scope, ProgressMonitor monitor = null) { return FindReferences (IdeApp.ProjectOperations.CurrentSelectedSolution, member, searchForAllOverloads, scope, monitor); } @@ -95,7 +95,7 @@ namespace MonoDevelop.Ide.FindInFiles } static IEnumerable<SearchCollector.FileList> GetFileNames (Solution solution, object node, RefactoryScope scope, - IProgressMonitor monitor, IEnumerable<object> searchNodes) + ProgressMonitor monitor, IEnumerable<object> searchNodes) { if (!(node is IField) && !(node is IParameter) && node is IVariable || scope == RefactoryScope.File) { string fileName; @@ -147,7 +147,7 @@ namespace MonoDevelop.Ide.FindInFiles if (monitor != null) monitor.BeginTask (GettextCatalog.GetString ("Searching for references in solution..."), files.Count); foreach (var file in files) { - if (monitor != null && monitor.IsCancelRequested) + if (monitor != null && monitor.CancellationToken.IsCancellationRequested) yield break; yield return file; if (monitor != null) @@ -170,7 +170,7 @@ namespace MonoDevelop.Ide.FindInFiles return projects; } - public static IEnumerable<MemberReference> FindReferences (Solution solution, object member, bool searchForAllOverloads, RefactoryScope scope = RefactoryScope.Unknown, IProgressMonitor monitor = null) + public static IEnumerable<MemberReference> FindReferences (Solution solution, object member, bool searchForAllOverloads, RefactoryScope scope = RefactoryScope.Unknown, ProgressMonitor monitor = null) { if (member == null) yield break;
@@ -204,7 +204,7 @@ namespace MonoDevelop.Ide.FindInFiles foreach (var info in GetFileNames (solution, member, scope, monitor, searchNodes)) { string oldMime = null; foreach (var file in info.Files) { - if (monitor != null && monitor.IsCancelRequested) + if (monitor != null && monitor.CancellationToken.IsCancellationRequested) yield break; string mime = DesktopService.GetMimeTypeForUri (file); @@ -230,7 +230,7 @@ namespace MonoDevelop.Ide.FindInFiles foreach (var tuple in preparedFinders) { var finder = tuple.Item1; foreach (var foundReference in finder.FindReferences (tuple.Item2, tuple.Item3, tuple.Item4, monitor, searchNodes)) { - if (monitor != null && monitor.IsCancelRequested) + if (monitor != null && monitor.CancellationToken.IsCancellationRequested) yield break; var tag = Tuple.Create (foundReference.FileName, foundReference.Region); if (foundOccurrences.Contains (tag)) @@ -243,7 +243,7 @@ namespace MonoDevelop.Ide.FindInFiles monitor.EndTask (); } - public abstract IEnumerable<MemberReference> FindReferences (Project project, IProjectContent content, IEnumerable<FilePath> files, IProgressMonitor monitor, IEnumerable<object> searchedMembers);
+ public abstract IEnumerable<MemberReference> FindReferences (Project project, IProjectContent content, IEnumerable<FilePath> files, ProgressMonitor monitor, IEnumerable<object> searchedMembers);
internal static IEnumerable<IMember> CollectMembers (Solution solution, IMember member, RefactoryScope scope, bool includeOverloads = true)
{
@@ -252,8 +252,11 @@ namespace MonoDevelop.Ide.FindInFiles internal static IEnumerable<IEntity> CollectMembers (IType type) { - yield return (IEntity)type; - foreach (var c in type.GetDefinition ().GetMembers (m => m.SymbolKind == SymbolKind.Constructor, GetMemberOptions.IgnoreInheritedMembers)) { + var typeDefinition = type.GetDefinition (); + if (typeDefinition == null) + yield break; + yield return (IEntity)typeDefinition; + foreach (var c in typeDefinition.GetMembers (m => m.SymbolKind == SymbolKind.Constructor, GetMemberOptions.IgnoreInheritedMembers)) { if (!c.IsSynthetic) yield return c; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/Scope.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/Scope.cs index fff1d1202b..ca62a49cd9 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/Scope.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/Scope.cs @@ -33,6 +33,7 @@ using MonoDevelop.Ide.Gui; using MonoDevelop.Core; using System.Security.Permissions; using System.Security; +using System.Threading.Tasks; namespace MonoDevelop.Ide.FindInFiles @@ -44,22 +45,24 @@ namespace MonoDevelop.Ide.FindInFiles set; } - public abstract int GetTotalWork (FilterOptions filterOptions); - public abstract IEnumerable<FileProvider> GetFiles (IProgressMonitor monitor, FilterOptions filterOptions); + public abstract Task<int> GetTotalWork (FilterOptions filterOptions); + public abstract Task GetFiles (ProgressMonitor monitor, FilterOptions filterOptions, ResultQueue<FileProvider> results); public abstract string GetDescription (FilterOptions filterOptions, string pattern, string replacePattern); } public class DocumentScope : Scope { - public override int GetTotalWork (FilterOptions filterOptions) + public override Task<int> GetTotalWork (FilterOptions filterOptions) { - return 1; + return Task.FromResult (1); }
- public override IEnumerable<FileProvider> GetFiles (IProgressMonitor monitor, FilterOptions filterOptions) + public override Task GetFiles (ProgressMonitor monitor, FilterOptions filterOptions, ResultQueue<FileProvider> results) { monitor.Log.WriteLine (GettextCatalog.GetString ("Looking in '{0}'", IdeApp.Workbench.ActiveDocument.FileName)); - yield return new FileProvider(IdeApp.Workbench.ActiveDocument.FileName); + results.Enqueue (new FileProvider(IdeApp.Workbench.ActiveDocument.FileName)); + results.SetComplete (); + return Task.FromResult (0); } public override string GetDescription(FilterOptions filterOptions, string pattern, string replacePattern) @@ -73,15 +76,17 @@ namespace MonoDevelop.Ide.FindInFiles public class SelectionScope : Scope { - public override int GetTotalWork (FilterOptions filterOptions) + public override Task<int> GetTotalWork (FilterOptions filterOptions) { - return 1; + return Task.FromResult (1); }
- public override IEnumerable<FileProvider> GetFiles (IProgressMonitor monitor, FilterOptions filterOptions) + public override Task GetFiles (ProgressMonitor monitor, FilterOptions filterOptions, ResultQueue<FileProvider> results) { var selection = IdeApp.Workbench.ActiveDocument.Editor.SelectionRange; - yield return new FileProvider(IdeApp.Workbench.ActiveDocument.FileName, null, selection.Offset, selection.EndOffset); + results.Enqueue (new FileProvider (IdeApp.Workbench.ActiveDocument.FileName, null, selection.Offset, selection.EndOffset)); + results.SetComplete (); + return Task.FromResult (0); } public override string GetDescription(FilterOptions filterOptions, string pattern, string replacePattern) @@ -95,40 +100,44 @@ namespace MonoDevelop.Ide.FindInFiles public class WholeSolutionScope : Scope { - public override int GetTotalWork (FilterOptions filterOptions) + public override Task<int> GetTotalWork (FilterOptions filterOptions) { int result = 0; if (IdeApp.Workspace.IsOpen) result = IdeApp.Workspace.GetAllProjects ().Sum (p => p.Files.Count); - return result; + return Task.FromResult (result); } - public override IEnumerable<FileProvider> GetFiles (IProgressMonitor monitor, FilterOptions filterOptions) + public async override Task GetFiles (ProgressMonitor monitor, FilterOptions filterOptions, ResultQueue<FileProvider> results) { if (IdeApp.Workspace.IsOpen) { var alreadyVisited = new HashSet<string> (); - foreach (var solutionFolder in IdeApp.Workspace.GetAllSolutionItems().OfType<SolutionFolder>()) { - monitor.Log.WriteLine (GettextCatalog.GetString ("Looking in solution folder '{0}'", solutionFolder.Name)); - foreach (var file in solutionFolder.Files.Where (f => filterOptions.NameMatches (f.FileName) && File.Exists (f.FullPath))) { + var allFiles = IdeApp.Workspace.GetAllSolutionItems ().OfType<SolutionFolder> ().SelectMany (sf => sf.Files).Where (f => filterOptions.NameMatches (f.FileName)).Select (f => f.FullPath).ToArray (); + await Task.Factory.StartNew (delegate { + foreach (var file in allFiles.Where (f => File.Exists (f.FullPath))) { if (!IncludeBinaryFiles && !DesktopService.GetFileIsText (file.FullPath)) continue; if (alreadyVisited.Contains (file.FullPath)) continue; alreadyVisited.Add (file.FileName); - yield return new FileProvider (file.FullPath); + results.Enqueue (new FileProvider (file.FullPath)); } - } - foreach (Project project in IdeApp.Workspace.GetAllProjects ()) { - monitor.Log.WriteLine (GettextCatalog.GetString ("Looking in project '{0}'", project.Name)); - foreach (ProjectFile file in project.Files.Where (f => filterOptions.NameMatches (f.Name) && File.Exists (f.Name))) { - if (!IncludeBinaryFiles && !DesktopService.GetFileIsText (file.FilePath)) + results.SetComplete (); + }); + + var allProjectFiles = IdeApp.Workspace.GetAllProjects ().SelectMany (project => project.Files).Where (f => filterOptions.NameMatches (f.Name)).Select (f => new Tuple<Project,string>(f.Project,f.Name)).ToArray (); + await Task.Factory.StartNew (delegate { + foreach (var ft in allProjectFiles.Where (f => File.Exists (f.Item2))) { + var file = ft.Item2; + if (!IncludeBinaryFiles && !DesktopService.GetFileIsText (file)) continue; - if (alreadyVisited.Contains (file.Name)) + if (alreadyVisited.Contains (file)) continue; - alreadyVisited.Add (file.Name); - yield return new FileProvider (file.Name, project); + alreadyVisited.Add (file); + results.Enqueue (new FileProvider (file, ft.Item1)); } - } + results.SetComplete (); + }); } } @@ -144,9 +153,9 @@ namespace MonoDevelop.Ide.FindInFiles {
readonly Project project; - public override int GetTotalWork (FilterOptions filterOptions) + public override Task<int> GetTotalWork (FilterOptions filterOptions) { - return project.Files.Count; + return Task.FromResult (project.Files.Count); } public WholeProjectScope (Project project) @@ -157,21 +166,26 @@ namespace MonoDevelop.Ide.FindInFiles this.project = project; } - public override IEnumerable<FileProvider> GetFiles (IProgressMonitor monitor, FilterOptions filterOptions) + public override Task GetFiles (ProgressMonitor monitor, FilterOptions filterOptions, ResultQueue<FileProvider> results) { if (IdeApp.Workspace.IsOpen) { monitor.Log.WriteLine (GettextCatalog.GetString ("Looking in project '{0}'", project.Name)); var alreadyVisited = new HashSet<string> (); - foreach (ProjectFile file in project.Files.Where (f => filterOptions.NameMatches (f.Name) && File.Exists (f.Name))) { - if (!IncludeBinaryFiles && !DesktopService.GetFileIsText (file.Name)) - continue; + var allFiles = project.Files.Where (f => filterOptions.NameMatches (f.Name) && File.Exists (f.Name)).Select (f => f.Name).ToArray (); + return Task.Factory.StartNew (delegate { + foreach (string file in allFiles) { + if (!IncludeBinaryFiles && !DesktopService.GetFileIsText (file)) + continue; - if (alreadyVisited.Contains (file.Name)) - continue; - alreadyVisited.Add (file.Name); - yield return new FileProvider (file.Name, project); - } + if (alreadyVisited.Contains (file)) + continue; + alreadyVisited.Add (file); + results.Enqueue (new FileProvider (file, project)); + } + results.SetComplete (); + }); } + return Task.FromResult (0); } public override string GetDescription (FilterOptions filterOptions, string pattern, string replacePattern) @@ -185,18 +199,20 @@ namespace MonoDevelop.Ide.FindInFiles public class AllOpenFilesScope : Scope { - public override int GetTotalWork (FilterOptions filterOptions) + public override Task<int> GetTotalWork (FilterOptions filterOptions) { - return IdeApp.Workbench.Documents.Count; + return Task.FromResult (IdeApp.Workbench.Documents.Count); }
- public override IEnumerable<FileProvider> GetFiles (IProgressMonitor monitor, FilterOptions filterOptions) + public override Task GetFiles (ProgressMonitor monitor, FilterOptions filterOptions, ResultQueue<FileProvider> results) { foreach (Document document in IdeApp.Workbench.Documents) { monitor.Log.WriteLine (GettextCatalog.GetString ("Looking in '{0}'", document.FileName)); if (!string.IsNullOrEmpty (document.FileName) && filterOptions.NameMatches (document.FileName)) - yield return new FileProvider (document.FileName); + results.Enqueue (new FileProvider (document.FileName)); } + results.SetComplete (); + return Task.FromResult (0); } public override string GetDescription (FilterOptions filterOptions, string pattern, string replacePattern) @@ -218,9 +234,11 @@ namespace MonoDevelop.Ide.FindInFiles set; } - public override int GetTotalWork (FilterOptions filterOptions) + public override Task<int> GetTotalWork (FilterOptions filterOptions) { - return GetFileNames (null, filterOptions).Count (); + return Task<int>.Factory.StartNew (delegate { + return GetFileNames (null, filterOptions).Count (); + }); } public DirectoryScope (string path, bool recurse) @@ -229,7 +247,7 @@ namespace MonoDevelop.Ide.FindInFiles this.recurse = recurse; } - IEnumerable<string> GetFileNames (IProgressMonitor monitor, FilterOptions filterOptions) + IEnumerable<string> GetFileNames (ProgressMonitor monitor, FilterOptions filterOptions) { if (monitor != null) monitor.Log.WriteLine (GettextCatalog.GetString ("Looking in '{0}'", path)); @@ -282,9 +300,13 @@ namespace MonoDevelop.Ide.FindInFiles } } - public override IEnumerable<FileProvider> GetFiles (IProgressMonitor monitor, FilterOptions filterOptions)
- {
- return GetFileNames (monitor, filterOptions).Select (file => new FileProvider (file));
+ public override Task GetFiles (ProgressMonitor monitor, FilterOptions filterOptions, ResultQueue<FileProvider> results)
+ { + return Task.Factory.StartNew (delegate {
+ foreach (var r in GetFileNames (monitor, filterOptions).Select (file => new FileProvider (file))) + results.Enqueue (r); + results.SetComplete (); + });
}
public override string GetDescription (FilterOptions filterOptions, string pattern, string replacePattern) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchCollector.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchCollector.cs index 34f423630a..e33d6099f4 100755 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchCollector.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchCollector.cs @@ -249,7 +249,10 @@ namespace MonoDevelop.Ide.FindInFiles else { foreach (var project in ReferenceFinder.GetAllReferencingProjects (solution, sourceProject)) { if (entity.Accessibility == Accessibility.Internal || entity.Accessibility == Accessibility.ProtectedAndInternal) { - if (!entity.ParentAssembly.InternalsVisibleTo (TypeSystemService.GetProjectContentWrapper (project).Compilation.MainAssembly)) + var wrapper = TypeSystemService.GetProjectContentWrapper (project); + if (wrapper == null) + continue; + if (!entity.ParentAssembly.InternalsVisibleTo (wrapper.Compilation.MainAssembly)) continue; } AddProject (project); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchProgressMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchProgressMonitor.cs index 4923f53fd3..d695fc29fa 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchProgressMonitor.cs @@ -34,55 +34,52 @@ using MonoDevelop.Ide.Gui; namespace MonoDevelop.Ide.FindInFiles { - class SearchProgressMonitor : BaseProgressMonitor, ISearchProgressMonitor + public class SearchProgressMonitor : ProgressMonitor, ISearchProgressMonitor { SearchResultPad outputPad;
- readonly IProgressMonitor statusMonitor;
- public SearchProgressMonitor (Pad pad) + public SearchProgressMonitor (Pad pad): base (Runtime.MainSynchronizationContext) { + AddSlaveMonitor (IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor (GettextCatalog.GetString ("Searching..."), Stock.StatusSearch, false, true, false, pad)); + outputPad = (SearchResultPad) pad.Content; - outputPad.AsyncOperation = AsyncOperation; + outputPad.CancellationTokenSource = CancellationTokenSource; outputPad.BeginProgress (pad.Title); - statusMonitor = IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor (GettextCatalog.GetString ("Searching..."), Stock.StatusSearch, false, true, false, pad); - } - - [FreeDispatch] - public bool AllowReuse { - get { return outputPad.AllowReuse; } } - [FreeDispatch] public void SetBasePath (string path) { outputPad.BasePath = path; } - [AsyncDispatch] public void ReportResult (SearchResult result) { - try { - outputPad.ReportResult (result); - } catch (Exception ex) { - LoggingService.LogError ("Error adding search result for file {0}:{1} to result pad:\n{2}", - result.FileName, result.Offset, ex.ToString ()); - } + DispatchService.GuiDispatch (delegate { + try { + outputPad.ReportResult (result); + } catch (Exception ex) { + LoggingService.LogError ("Error adding search result for file {0}:{1} to result pad:\n{2}", + result.FileName, result.Offset, ex.ToString ()); + } + }); } - [AsyncDispatch] public void ReportResults (IEnumerable<SearchResult> results) { - try { - outputPad.ReportResults (results); - } catch (Exception ex) { - LoggingService.LogError ("Error adding search results.", ex.ToString ()); - } + DispatchService.GuiDispatch (delegate { + try { + outputPad.ReportResults (results); + } catch (Exception ex) { + LoggingService.LogError ("Error adding search results.", ex.ToString ()); + } + }); } - [AsyncDispatch] public void ReportStatus (string resultMessage) { - outputPad.ReportStatus (resultMessage); + DispatchService.GuiDispatch (delegate { + outputPad.ReportStatus (resultMessage); + }); } protected override void OnWriteLog (string text) @@ -93,8 +90,6 @@ namespace MonoDevelop.Ide.FindInFiles protected override void OnCompleted () { - statusMonitor.Dispose (); - if (outputPad == null) throw GetDisposedException (); outputPad.WriteText ("\n"); @@ -104,8 +99,8 @@ namespace MonoDevelop.Ide.FindInFiles foreach (string msg in Warnings) outputPad.WriteText (msg + "\n"); - foreach (string msg in Errors) - outputPad.WriteText (msg + "\n"); + foreach (var msg in Errors) + outputPad.WriteText (msg.Message + "\n"); outputPad.EndProgress (); base.OnCompleted (); @@ -117,47 +112,5 @@ namespace MonoDevelop.Ide.FindInFiles { return new InvalidOperationException ("Search progress monitor already disposed."); } - - public override void ReportError (string message, Exception ex) - { - base.ReportError (message, ex); - statusMonitor.ReportError (message, ex); - } - - public override void ReportSuccess (string message) - { - base.ReportSuccess (message); - statusMonitor.ReportSuccess (message); - } - - public override void ReportWarning (string message) - { - base.ReportWarning (message); - statusMonitor.ReportWarning (message); - } - - public override void Step (int work) - { - base.Step (work); - statusMonitor.Step (work); - } - - public override void BeginStepTask (string name, int totalWork, int stepSize) - { - base.BeginStepTask (name, totalWork, stepSize); - statusMonitor.BeginStepTask (name, totalWork, stepSize); - } - - public override void BeginTask (string name, int totalWork) - { - base.BeginTask (name, totalWork); - statusMonitor.BeginTask (name, totalWork); - } - - public override void EndTask () - { - base.EndTask (); - statusMonitor.EndTask (); - } } }
\ No newline at end of file diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultPad.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultPad.cs index 961d59f6b1..0a9fe845e0 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultPad.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultPad.cs @@ -30,7 +30,8 @@ using System.Collections.Generic; using MonoDevelop.Ide.Gui; using MonoDevelop.Core; using MonoDevelop.Components.Commands; -using MonoDevelop.Ide.Commands;
+using MonoDevelop.Ide.Commands; +using System.Threading;
namespace MonoDevelop.Ide.FindInFiles { @@ -50,12 +51,12 @@ namespace MonoDevelop.Ide.FindInFiles } } - public IAsyncOperation AsyncOperation { + public CancellationTokenSource CancellationTokenSource { get { - return widget.AsyncOperation; + return widget.CancellationTokenSource; } set { - widget.AsyncOperation = value; + widget.CancellationTokenSource = value; } } public bool FocusPad { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultWidget.cs index 35c90f9a7c..5048ae13af 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultWidget.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultWidget.cs @@ -42,6 +42,7 @@ using MonoDevelop.Ide.Gui.Content; using MonoDevelop.Ide.Navigation; using MonoDevelop.Ide.Gui.Components; using MonoDevelop.Components; +using System.Threading; namespace MonoDevelop.Ide.FindInFiles { @@ -68,7 +69,7 @@ namespace MonoDevelop.Ide.FindInFiles set; } - public IAsyncOperation AsyncOperation { + public CancellationTokenSource CancellationTokenSource { get; set; } @@ -225,8 +226,8 @@ namespace MonoDevelop.Ide.FindInFiles void ButtonStopClicked (object sender, EventArgs e) { - if (AsyncOperation != null) - AsyncOperation.Cancel (); + if (CancellationTokenSource != null) + CancellationTokenSource.Cancel (); } void TreeviewSearchResultsRowActivated(object o, RowActivatedArgs args) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs index 3f78b656d2..a0794350f9 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs @@ -50,22 +50,17 @@ using MonoDevelop.Ide.Gui.Pads; using MonoDevelop.Projects.Extensions; using Mono.TextEditor; using System.Linq; +using MonoDevelop.Ide.Tasks; namespace MonoDevelop.Ide.Gui.Components { public partial class ExtensibleTreeView : CompactScrolledWindow { - internal const int TextColumn = 0; - internal const int OpenIconColumn = 1; - internal const int ClosedIconColumn = 2; - internal const int DataItemColumn = 3; - internal const int BuilderChainColumn = 4; - internal const int FilledColumn = 5; - internal const int ShowPopupColumn = 6; - internal const int OverlayBottomRightColumn = 7; - internal const int OverlayBottomLeftColumn = 8; - internal const int OverlayTopLeftColumn = 9; - internal const int OverlayTopRightColumn = 10; + internal const int NodeInfoColumn = 0; + internal const int DataItemColumn = 1; + internal const int BuilderChainColumn = 2; + internal const int FilledColumn = 3; + internal const int ShowPopupColumn = 4; NodeBuilder[] builders; Dictionary<Type, NodeBuilder[]> builderChains = new Dictionary<Type, NodeBuilder[]> (); @@ -156,15 +151,8 @@ namespace MonoDevelop.Ide.Gui.Components builderContext = new TreeBuilderContext (this); SetBuilders (builders, options); - /* - 0 -- Text - 1 -- Icon (Open) - 2 -- Icon (Closed) - 3 -- Node Data - 4 -- Builder chain - 5 -- Expanded - */ - store = new Gtk.TreeStore (typeof(string), typeof(Xwt.Drawing.Image), typeof(Xwt.Drawing.Image), typeof(object), typeof(object), typeof(bool), typeof(bool), typeof(Xwt.Drawing.Image), typeof(Xwt.Drawing.Image), typeof(Xwt.Drawing.Image), typeof(Xwt.Drawing.Image)); + + store = new Gtk.TreeStore (typeof(NodeInfo), typeof(object), typeof(object), typeof(bool), typeof(bool)); tree.Model = store; tree.Selection.Mode = Gtk.SelectionMode.Multiple; @@ -180,13 +168,6 @@ namespace MonoDevelop.Ide.Gui.Components pix_render = new ZoomableCellRendererPixbuf (); pix_render.Xpad = 0; complete_column.PackStart (pix_render, false); - complete_column.AddAttribute (pix_render, "image", OpenIconColumn); - complete_column.AddAttribute (pix_render, "image-expander-open", OpenIconColumn); - complete_column.AddAttribute (pix_render, "image-expander-closed", ClosedIconColumn); - complete_column.AddAttribute (pix_render, "overlay-image-bottom-left", OverlayBottomLeftColumn); - complete_column.AddAttribute (pix_render, "overlay-image-bottom-right", OverlayBottomRightColumn); - complete_column.AddAttribute (pix_render, "overlay-image-top-left", OverlayTopLeftColumn); - complete_column.AddAttribute (pix_render, "overlay-image-top-right", OverlayTopRightColumn); text_render = new CustomCellRendererText (this); text_render.Ypad = 0; @@ -194,10 +175,10 @@ namespace MonoDevelop.Ide.Gui.Components text_render.EditingStarted += HandleEditingStarted; text_render.Edited += HandleOnEdit; text_render.EditingCanceled += HandleOnEditCancelled; - complete_column.PackStart (text_render, true); - complete_column.AddAttribute (text_render, "text-markup", TextColumn); - complete_column.AddAttribute (text_render, "show-popup-button", ShowPopupColumn); + + complete_column.SetCellDataFunc (pix_render, SetIconCellData); + complete_column.SetCellDataFunc (text_render, SetTextCellData); tree.AppendColumn (complete_column); @@ -214,20 +195,11 @@ namespace MonoDevelop.Ide.Gui.Components tree.MotionNotifyEvent += HandleMotionNotifyEvent; tree.LeaveNotifyEvent += HandleLeaveNotifyEvent; - if (GtkGestures.IsSupported) { - tree.AddGestureMagnifyHandler ((sender, args) => { - Zoom += Zoom * (args.Magnification / 4d); - }); - } - for (int n=3; n<16; n++) { Gtk.Rc.ParseString ("style \"MonoDevelop.ExtensibleTreeView_" + n + "\" {\n GtkTreeView::expander-size = " + n + "\n }\n"); Gtk.Rc.ParseString ("widget \"*.MonoDevelop.ExtensibleTreeView_" + n + "\" style \"MonoDevelop.ExtensibleTreeView_" + n + "\"\n"); } - if (!string.IsNullOrEmpty (Id)) - Zoom = PropertyService.Get<double> ("MonoDevelop.Ide.ExtensibleTreeView.Zoom." + Id, 1d); - this.Add (tree); this.ShowAll (); @@ -264,6 +236,34 @@ namespace MonoDevelop.Ide.Gui.Components } #endif + void SetIconCellData (Gtk.TreeViewColumn col, Gtk.CellRenderer renderer, Gtk.TreeModel model, Gtk.TreeIter it) + { + var info = (NodeInfo)model.GetValue (it, NodeInfoColumn); + var cell = (ZoomableCellRendererPixbuf)renderer; + + cell.Image = info.Icon != null && info.Icon != CellRendererImage.NullImage && info.DisabledStyle ? info.Icon.WithAlpha (0.5) : info.Icon; + cell.ImageExpanderOpen = cell.Image; + cell.ImageExpanderClosed = info.ClosedIcon != null && info.ClosedIcon != CellRendererImage.NullImage && info.DisabledStyle ? info.ClosedIcon.WithAlpha (0.5) : info.ClosedIcon; + cell.OverlayBottomLeft = info.OverlayBottomLeft; + cell.OverlayBottomRight = info.OverlayBottomRight; + cell.OverlayTopLeft = info.OverlayTopLeft; + cell.OverlayTopRight = info.OverlayTopRight; + } + + void SetTextCellData (Gtk.TreeViewColumn col, Gtk.CellRenderer renderer, Gtk.TreeModel model, Gtk.TreeIter it) + { + var info = (NodeInfo)model.GetValue (it, NodeInfoColumn); + var cell = (CustomCellRendererText)renderer; + + if (info.DisabledStyle) + cell.TextMarkup = "<span foreground='gray'>" + info.Label + "</span>"; + else + cell.TextMarkup = info.Label; + + cell.StatusIcon = info.StatusIconInternal; + cell.ShowPopupButton = (bool)model.GetValue (it, ShowPopupColumn); + } + public void UpdateBuilders (NodeBuilder[] builders, TreePadOption[] options) { // Save the current state @@ -343,7 +343,7 @@ namespace MonoDevelop.Ide.Gui.Components var dragObjects = new object [navs.Length]; for (int n=0; n<navs.Length; n++) dragObjects [n] = navs [n].DataItem; - icon = (Xwt.Drawing.Image) store.GetValue (navs[0].CurrentPosition._iter, OpenIconColumn); + icon = ((NodeInfo) store.GetValue (navs[0].CurrentPosition._iter, NodeInfoColumn)).Icon; return dragObjects; } @@ -422,20 +422,74 @@ namespace MonoDevelop.Ide.Gui.Components [GLib.ConnectBefore] void HandleMotionNotifyEvent (object o, Gtk.MotionNotifyEventArgs args) { - if (ShowSelectionPopupButton) { - text_render.PointerPosition = new Gdk.Point ((int)args.Event.XRoot, (int)args.Event.YRoot); - Gtk.TreePath path; - if (tree.GetPathAtPos ((int)args.Event.X, (int)args.Event.Y, out path)) { - var area = tree.GetCellArea (path, tree.Columns[0]); + Gtk.TreePath path; + int cx, cy; + Gtk.TreeViewColumn col; + bool popupShown = false; + + if (tree.GetPathAtPos ((int)args.Event.X, (int)args.Event.Y, out path, out col, out cx, out cy)) { + if (ShowSelectionPopupButton) { + text_render.PointerPosition = new Gdk.Point ((int)args.Event.XRoot, (int)args.Event.YRoot); + var area = tree.GetCellArea (path, tree.Columns [0]); tree.QueueDrawArea (area.X, area.Y, area.Width, area.Height); } + + Gtk.TreeIter it; + if (store.GetIter (out it, path)) { + var info = (NodeInfo)store.GetValue (it, NodeInfoColumn); + if (info.StatusIconInternal != CellRendererImage.NullImage && info.StatusIconInternal != null) { + var cellArea = tree.GetCellArea (path, tree.Columns [0]); + int sp, w; + col.CellGetPosition (text_render, out sp, out w); + cellArea.X += sp; + cellArea.Width = w; + var rect = text_render.GetStatusIconArea (tree, cellArea); + if (cx >= rect.X && cx <= rect.Right) { + ShowStatusMessage (it, rect, info); + popupShown = true; + } + } + } + } + if (!popupShown) + HideStatusMessage (); + } + + bool statusMessageVisible; + Gtk.TreeIter statusIconIter; + TooltipPopoverWindow statusPopover; + + void ShowStatusMessage (Gtk.TreeIter it, Gdk.Rectangle rect, NodeInfo info) + { + if (statusMessageVisible && store.GetPath (it).Equals (store.GetPath (statusIconIter))) + return; + if (statusPopover != null) + statusPopover.Destroy (); + statusMessageVisible = true; + statusIconIter = it; + + statusPopover = new TooltipPopoverWindow { + ShowArrow = true, + Text = info.StatusMessage, + Severity = info.StatusSeverity + }; + rect.Y += 2; + statusPopover.ShowPopup (this, rect, PopupPosition.Bottom); + } + + void HideStatusMessage () + { + if (statusMessageVisible) { + statusMessageVisible = false; + statusPopover.Destroy (); + statusPopover = null; } } [GLib.ConnectBefore] void HandleLeaveNotifyEvent (object o, Gtk.LeaveNotifyEventArgs args) { - + HideStatusMessage (); } void HandleMenuHidden (object sender, EventArgs e) @@ -960,92 +1014,12 @@ namespace MonoDevelop.Ide.Gui.Components public event EventHandler CurrentItemActivated; - #region Zoom - - const double ZOOM_FACTOR = 1.1f; - const int ZOOM_MIN_POW = -4; - const int ZOOM_MAX_POW = 8; - static readonly double ZOOM_MIN = System.Math.Pow (ZOOM_FACTOR, ZOOM_MIN_POW); - static readonly double ZOOM_MAX = System.Math.Pow (ZOOM_FACTOR, ZOOM_MAX_POW); - double zoom; - + [Obsolete ("Not supported anymore")] public double Zoom { - get { - return zoom; - } - set { - value = System.Math.Min (ZOOM_MAX, System.Math.Max (ZOOM_MIN, value)); - if (value > ZOOM_MAX || value < ZOOM_MIN) - return; - //snap to one, if within 0.001d - if ((System.Math.Abs (value - 1d)) < 0.001d) { - value = 1d; - } - if (zoom != value) { - zoom = value; - OnZoomChanged (value); - } - } - } - - void OnZoomChanged (double value) - { - pix_render.Zoom = value; - text_render.Zoom = value; - - int expanderSize = (int) (12 * Zoom); - if (expanderSize < 3) expanderSize = 3; - if (expanderSize > 15) expanderSize = 15; - if (expanderSize != 12) - tree.Name = "MonoDevelop.ExtensibleTreeView_" + expanderSize; - else - tree.Name = ""; - tree.ColumnsAutosize (); - if (!string.IsNullOrEmpty (Id)) { - PropertyService.Set ("MonoDevelop.Ide.ExtensibleTreeView.Zoom." + Id, Zoom); - } + get { return 1d; } + set { } } - [CommandHandler (ViewCommands.ZoomIn)] - public void ZoomIn () - { - int oldPow = (int)System.Math.Round (System.Math.Log (zoom) / System.Math.Log (ZOOM_FACTOR)); - Zoom = System.Math.Pow (ZOOM_FACTOR, oldPow + 1); - } - - [CommandHandler (ViewCommands.ZoomOut)] - public void ZoomOut () - { - int oldPow = (int)System.Math.Round (System.Math.Log (zoom) / System.Math.Log (ZOOM_FACTOR)); - Zoom = System.Math.Pow (ZOOM_FACTOR, oldPow - 1); - } - - [CommandHandler (ViewCommands.ZoomReset)] - public void ZoomReset () - { - Zoom = 1d; - } - - [CommandUpdateHandler (ViewCommands.ZoomIn)] - protected void UpdateZoomIn (CommandInfo cinfo) - { - cinfo.Enabled = zoom < ZOOM_MAX - 0.000001d; - } - - [CommandUpdateHandler (ViewCommands.ZoomOut)] - protected void UpdateZoomOut (CommandInfo cinfo) - { - cinfo.Enabled = zoom > ZOOM_MIN + 0.000001d; - } - - [CommandUpdateHandler (ViewCommands.ZoomReset)] - protected void UpdateZoomReset (CommandInfo cinfo) - { - cinfo.Enabled = zoom != 1d; - } - - #endregion Zoom - [CommandHandler (EditCommands.Copy)] public void CopyCurrentItem () { @@ -1202,6 +1176,11 @@ namespace MonoDevelop.Ide.Gui.Components } } + NodeInfo GetNodeInfo (Gtk.TreeIter it) + { + return (NodeInfo)store.GetValue (it, NodeInfoColumn); + } + public void StartLabelEditInternal() { if (editingText) @@ -1234,7 +1213,9 @@ namespace MonoDevelop.Ide.Gui.Components node.ExpandToNode (); //make sure the parent of the node that is being edited is expanded string nodeName = node.NodeName; - store.SetValue (iter, ExtensibleTreeView.TextColumn, nodeName); + + GetNodeInfo (iter).Label = nodeName; + store.EmitRowChanged (store.GetPath (iter), iter); // Get and validate the initial text selection int nameLength = nodeName != null ? nodeName.Length : 0, @@ -1937,24 +1918,6 @@ namespace MonoDevelop.Ide.Gui.Components } } - protected override bool OnScrollEvent (Gdk.EventScroll evnt) - { - var modifier = !Platform.IsMac? Gdk.ModifierType.ControlMask - //Mac window manager already uses control-scroll, so use command - //Command might be either meta or mod1, depending on GTK version - : (Gdk.ModifierType.MetaMask | Gdk.ModifierType.Mod1Mask); - - if ((evnt.State & modifier) !=0) { - if (evnt.Direction == Gdk.ScrollDirection.Up) - ZoomIn (); - else if (evnt.Direction == Gdk.ScrollDirection.Down) - ZoomOut (); - - return true; - } - return base.OnScrollEvent (evnt); - } - protected virtual void OnNodeActivated (object sender, Gtk.RowActivatedArgs args) { ActivateCurrentItem (); @@ -2253,7 +2216,6 @@ namespace MonoDevelop.Ide.Gui.Components class CustomCellRendererText: Gtk.CellRendererText { - double zoom; Pango.Layout layout; Pango.FontDescription scaledFont, customFont; @@ -2266,6 +2228,8 @@ namespace MonoDevelop.Ide.Gui.Components Gdk.Rectangle buttonAllocation; string markup; + const int StatusIconSpacing = 4; + public bool Pushed { get; set; } //using this instead of FontDesc property, FontDesc seems to be broken @@ -2298,28 +2262,22 @@ namespace MonoDevelop.Ide.Gui.Components [GLib.Property ("show-popup-button")] public bool ShowPopupButton { get; set; } + [GLib.Property ("status-icon")] + public Xwt.Drawing.Image StatusIcon { get; set; } + public CustomCellRendererText (ExtensibleTreeView parent) { this.parent = parent; } - protected override void Render (Gdk.Drawable window, Gtk.Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, Gtk.CellRendererState flags) - { - Gtk.StateType st = Gtk.StateType.Normal; - if ((flags & Gtk.CellRendererState.Prelit) != 0) - st = Gtk.StateType.Prelight; - if ((flags & Gtk.CellRendererState.Focused) != 0) - st = Gtk.StateType.Normal; - if ((flags & Gtk.CellRendererState.Insensitive) != 0) - st = Gtk.StateType.Insensitive; - if ((flags & Gtk.CellRendererState.Selected) != 0) - st = widget.HasFocus ? Gtk.StateType.Selected : Gtk.StateType.Active; + void SetupLayout (Gtk.Widget widget) + { if (scaledFont == null) { if (scaledFont != null) scaledFont.Dispose (); scaledFont = (customFont ?? parent.Style.FontDesc).Copy (); - scaledFont.Size = (int)(customFont.Size * Zoom); + scaledFont.Size = customFont.Size; if (layout != null) layout.FontDescription = scaledFont; } @@ -2332,6 +2290,23 @@ namespace MonoDevelop.Ide.Gui.Components } layout.SetMarkup (TextMarkup); + } + + const int iconMode = 0; + + protected override void Render (Gdk.Drawable window, Gtk.Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, Gtk.CellRendererState flags) + { + Gtk.StateType st = Gtk.StateType.Normal; + if ((flags & Gtk.CellRendererState.Prelit) != 0) + st = Gtk.StateType.Prelight; + if ((flags & Gtk.CellRendererState.Focused) != 0) + st = Gtk.StateType.Normal; + if ((flags & Gtk.CellRendererState.Insensitive) != 0) + st = Gtk.StateType.Insensitive; + if ((flags & Gtk.CellRendererState.Selected) != 0) + st = widget.HasFocus ? Gtk.StateType.Selected : Gtk.StateType.Active; + + SetupLayout (widget); int w, h; layout.GetPixelSize (out w, out h); @@ -2339,9 +2314,22 @@ namespace MonoDevelop.Ide.Gui.Components int tx = cell_area.X + (int)Xpad; int ty = cell_area.Y + (cell_area.Height - h) / 2; + bool hasStatusIcon = StatusIcon != CellRendererImage.NullImage && StatusIcon != null; + + if (hasStatusIcon && iconMode != 2) { + var x = iconMode == 1 ? tx : tx + w + StatusIconSpacing; + using (var ctx = Gdk.CairoHelper.Create (window)) { + ctx.DrawImage (widget, StatusIcon, x, cell_area.Y + (cell_area.Height - StatusIcon.Height) / 2); + } + if (iconMode == 1) + tx += (int)StatusIcon.Width + StatusIconSpacing; + } + window.DrawLayout (widget.Style.TextGC (st), tx, ty, layout); - if (ShowPopupButton) { + hasStatusIcon &= iconMode == 2; + + if (ShowPopupButton || hasStatusIcon) { if (!bound) { bound = true; ((Gtk.ScrolledWindow)widget.Parent).Hadjustment.ValueChanged += delegate { @@ -2352,7 +2340,8 @@ namespace MonoDevelop.Ide.Gui.Components }; } - if ((flags & Gtk.CellRendererState.Selected) != 0) { + var selected = (flags & Gtk.CellRendererState.Selected) != 0; + if (selected || hasStatusIcon) { var icon = Pushed ? popupIconDown : popupIcon; var dy = (cell_area.Height - (int)icon.Height) / 2 - 1; var y = cell_area.Y + dy; @@ -2393,25 +2382,47 @@ namespace MonoDevelop.Ide.Gui.Components icon = popupIconHover; using (var ctx = Gdk.CairoHelper.Create (window)) { - ctx.DrawImage (widget, icon, x, y); + if (ShowPopupButton && selected) { + if (hasStatusIcon) + x -= (int) icon.Width + StatusIconSpacing; + ctx.DrawImage (widget, icon, x, y); + if (hasStatusIcon) + x += (int) icon.Width + StatusIconSpacing; + } + if (hasStatusIcon) { + ctx.DrawImage (widget, StatusIcon, x, y); + } } } } } - public double Zoom { - get { - return zoom; - } - set { - if (scaledFont != null) { - scaledFont.Dispose (); - scaledFont = null; - } - zoom = value; + public Gdk.Rectangle GetStatusIconArea (Gtk.Widget widget, Gdk.Rectangle cell_area) + { + SetupLayout (widget); + + int w, h; + layout.GetPixelSize (out w, out h); + + int tx = cell_area.X + (int)Xpad; + if (iconMode == 0) { + var x = tx + w + StatusIconSpacing; + return new Gdk.Rectangle (x, cell_area.Y, (int) StatusIcon.Width, (int) cell_area.Height); + } else if (iconMode == 1) { + var x = tx; + return new Gdk.Rectangle (x, cell_area.Y, (int) StatusIcon.Width, (int) cell_area.Height); + } else { + return new Gdk.Rectangle (cell_area.Width - (int) StatusIcon.Width, cell_area.Y, (int) StatusIcon.Width, (int) cell_area.Height); } } + public override void GetSize (Gtk.Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height) + { + base.GetSize (widget, ref cell_area, out x_offset, out y_offset, out width, out height); + if (StatusIcon != CellRendererImage.NullImage && StatusIcon != null) + width += (int) StatusIcon.Width + StatusIconSpacing; + } + public bool PointerInButton (int px, int py) { return buttonScreenRect.Contains (px, py); @@ -2492,8 +2503,6 @@ namespace MonoDevelop.Ide.Gui.Components class ZoomableCellRendererPixbuf: CellRendererImage { - double zoom = 1f; - Dictionary<Xwt.Drawing.Image,Xwt.Drawing.Image> resizedCache = new Dictionary<Xwt.Drawing.Image, Xwt.Drawing.Image> (); Xwt.Drawing.Image overlayBottomLeft; @@ -2501,17 +2510,6 @@ namespace MonoDevelop.Ide.Gui.Components Xwt.Drawing.Image overlayTopLeft; Xwt.Drawing.Image overlayTopRight; - public double Zoom { - get { return zoom; } - set { - if (zoom != value) { - zoom = value; - resizedCache.Clear (); - Notify ("image"); - } - } - } - public override Xwt.Drawing.Image Image { get { return base.Image; @@ -2586,20 +2584,7 @@ namespace MonoDevelop.Ide.Gui.Components if (value == null || value == CellRendererImage.NullImage) return null; - if (zoom == 1) - return value; - - Xwt.Drawing.Image resized; - if (resizedCache.TryGetValue (value, out resized)) - return resized; - - int w = (int) (zoom * (double) value.Width); - int h = (int) (zoom * (double) value.Height); - if (w == 0) w = 1; - if (h == 0) h = 1; - resized = value.WithSize (w, h); - resizedCache [value] = resized; - return resized; + return value; } public override void GetSize (Gtk.Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ITreeNavigator.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ITreeNavigator.cs index 67b56ba78a..f9d60de665 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ITreeNavigator.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ITreeNavigator.cs @@ -37,6 +37,7 @@ namespace MonoDevelop.Ide.Gui.Components string NodeName { get; } object GetParentDataItem (Type type, bool includeCurrent); + T GetParentDataItem<T> (bool includeCurrent); bool Selected { get; set; } bool Expanded { get; set; } void ExpandToNode (); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/LogView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/LogView.cs index b8944e730f..c6acdc9f9d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/LogView.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/LogView.cs @@ -36,6 +36,7 @@ using System.IO; using System.Text.RegularExpressions; using MonoDevelop.Ide.Fonts; using MonoDevelop.Components.Commands; +using System.Threading; namespace MonoDevelop.Ide.Gui.Components { @@ -430,14 +431,12 @@ namespace MonoDevelop.Ide.Gui.Components } } - public class LogViewProgressMonitor : NullProgressMonitor, IDebugConsole + public class LogViewProgressMonitor : ProgressMonitor, IDebugConsole { LogView outputPad; event EventHandler stopRequested; - LogTextWriter logger = new LogTextWriter (); LogTextWriter internalLogger = new LogTextWriter (); - LogTextWriter errorLogger = new LogTextWriter(); NotSupportedTextReader inputReader = new NotSupportedTextReader (); public LogView LogView { @@ -448,31 +447,47 @@ namespace MonoDevelop.Ide.Gui.Components { outputPad = pad; outputPad.Clear (); - logger.TextWritten += outputPad.WriteText; internalLogger.TextWritten += outputPad.WriteConsoleLogText; - errorLogger.TextWritten += outputPad.WriteError; + CancellationToken.Register (OnCancelRequested); } - - public override void BeginTask (string name, int totalWork) + + public void Cancel () + { + CancellationTokenSource.Cancel (); + } + + protected override void OnWriteLog (string message) + { + outputPad.WriteText (message); + base.OnWriteLog (message); + } + + protected override void OnWriteErrorLog (string message) + { + outputPad.WriteText (message); + base.OnWriteErrorLog (message); + } + + protected override void OnBeginTask (string name, int totalWork, int stepWork) { if (outputPad == null) throw GetDisposedException (); outputPad.BeginTask (name, totalWork); - base.BeginTask (name, totalWork); + base.OnBeginTask (name, totalWork, stepWork); } - - public override void EndTask () + + protected override void OnEndTask (string name, int totalWork, int stepWork) { if (outputPad == null) throw GetDisposedException (); outputPad.EndTask (); - base.EndTask (); + base.OnEndTask (name, totalWork, stepWork); } - - protected override void OnCompleted () + + public override void Dispose () { if (outputPad == null) throw GetDisposedException (); outputPad.WriteText ("\n"); - foreach (string msg in Messages) + foreach (string msg in SuccessMessages) outputPad.WriteText (msg + "\n"); foreach (string msg in Warnings) @@ -481,9 +496,8 @@ namespace MonoDevelop.Ide.Gui.Components foreach (ProgressError msg in Errors) outputPad.WriteError (msg.Message + "\n"); - base.OnCompleted (); - outputPad = null; + base.Dispose (); } Exception GetDisposedException () @@ -491,17 +505,12 @@ namespace MonoDevelop.Ide.Gui.Components return new InvalidOperationException ("Output progress monitor already disposed."); } - protected override void OnCancelRequested () + void OnCancelRequested () { - base.OnCancelRequested (); if (stopRequested != null) stopRequested (this, null); } - public override TextWriter Log { - get { return logger; } - } - TextWriter IConsole.Log { get { return internalLogger; } } @@ -511,11 +520,11 @@ namespace MonoDevelop.Ide.Gui.Components } TextWriter IConsole.Out { - get { return logger; } + get { return base.Log; } } TextWriter IConsole.Error { - get { return errorLogger; } + get { return base.ErrorLog; } } void IDebugConsole.Debug (int level, string category, string message) @@ -531,6 +540,15 @@ namespace MonoDevelop.Ide.Gui.Components add { stopRequested += value; } remove { stopRequested -= value; } } + + protected override void OnCompleted () + { + base.OnCompleted (); + if (Completed != null) + Completed (this, EventArgs.Empty); + } + + public event EventHandler Completed; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/NodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/NodeBuilder.cs index cf548cbad2..eaa6bb08a8 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/NodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/NodeBuilder.cs @@ -29,6 +29,8 @@ using System; using MonoDevelop.Core; +using MonoDevelop.Components; +using MonoDevelop.Ide.Tasks; namespace MonoDevelop.Ide.Gui.Components { @@ -154,6 +156,32 @@ namespace MonoDevelop.Ide.Gui.Components public class NodeInfo { + public NodeInfo () + { + Reset (); + } + + public void Reset () + { + Label = string.Empty; + Icon = CellRendererImage.NullImage; + ClosedIcon = CellRendererImage.NullImage; + OverlayBottomLeft = CellRendererImage.NullImage; + OverlayBottomRight = CellRendererImage.NullImage; + OverlayTopLeft = CellRendererImage.NullImage; + OverlayTopRight = CellRendererImage.NullImage; + StatusIcon = CellRendererImage.NullImage; + StatusMessage = null; + StatusSeverity = null; + DisabledStyle = false; + } + + internal static readonly NodeInfo Empty = new NodeInfo (); + + internal bool IsShared { + get { return this == Empty; } + } + public string Label { get; set; } public Xwt.Drawing.Image Icon { get; set; } public Xwt.Drawing.Image ClosedIcon { get; set; } @@ -161,5 +189,29 @@ namespace MonoDevelop.Ide.Gui.Components public Xwt.Drawing.Image OverlayBottomRight { get; set; } public Xwt.Drawing.Image OverlayTopLeft { get; set; } public Xwt.Drawing.Image OverlayTopRight { get; set; } + public Xwt.Drawing.Image StatusIcon { get; set; } + public string StatusMessage { get; set; } + public TaskSeverity? StatusSeverity { get; set; } + public bool DisabledStyle { get; set; } + + internal Xwt.Drawing.Image StatusIconInternal { + get { + if (StatusIcon != null && StatusIcon != CellRendererImage.NullImage) + return StatusIcon; + if (StatusSeverity.HasValue) { + switch (StatusSeverity.Value) { + case TaskSeverity.Error: + return ImageService.GetIcon ("md-project-status-error"); + case TaskSeverity.Warning: + return ImageService.GetIcon ("md-project-status-warning"); + case TaskSeverity.Information: + return ImageService.GetIcon ("md-project-status-information"); + case TaskSeverity.Comment: + return ImageService.GetIcon ("md-project-status-information"); + } + } + return CellRendererImage.NullImage; + } + } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ProjectSelectorWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ProjectSelectorWidget.cs index 713bae12e9..87453d351b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ProjectSelectorWidget.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ProjectSelectorWidget.cs @@ -37,9 +37,9 @@ namespace MonoDevelop.Ide.Gui.Components { TreeStore store; bool showCheckboxes; - IBuildTarget rootItem; - IBuildTarget currentSelection; - HashSet<IBuildTarget> activeItems = new HashSet<IBuildTarget> (); + WorkspaceObject rootItem; + WorkspaceObject currentSelection; + HashSet<WorkspaceObject> activeItems = new HashSet<WorkspaceObject> (); HashSet<Type> selectableTypes = new HashSet<Type> (); public event EventHandler SelectionChanged; @@ -75,7 +75,7 @@ namespace MonoDevelop.Ide.Gui.Components { TreeIter it; if (tree.Selection.GetSelected (out it)) - currentSelection = (IBuildTarget) store.GetValue (it, 2); + currentSelection = (WorkspaceObject) store.GetValue (it, 2); else currentSelection = null; @@ -83,7 +83,7 @@ namespace MonoDevelop.Ide.Gui.Components SelectionChanged (this, EventArgs.Empty); } - public IBuildTarget SelectedItem { + public WorkspaceObject SelectedItem { get { if (currentSelection != null && selectableTypes.Count > 0 && !selectableTypes.Any (t => t.IsAssignableFrom (currentSelection.GetType ()))) return null; @@ -96,12 +96,12 @@ namespace MonoDevelop.Ide.Gui.Components } } - public IEnumerable<IBuildTarget> ActiveItems { + public IEnumerable<WorkspaceObject> ActiveItems { get { return activeItems; } set { - activeItems = new HashSet<IBuildTarget> (); + activeItems = new HashSet<WorkspaceObject> (); activeItems.UnionWith (value); SetSelection (currentSelection, activeItems); } @@ -125,7 +125,7 @@ namespace MonoDevelop.Ide.Gui.Components public bool CascadeCheckboxSelection { get; set; } - public IBuildTarget RootItem { + public WorkspaceObject RootItem { get { return this.rootItem; } @@ -137,7 +137,7 @@ namespace MonoDevelop.Ide.Gui.Components void Fill () { - IBuildTarget sel = SelectedItem; + WorkspaceObject sel = SelectedItem; store.Clear (); if (rootItem is RootWorkspace) { foreach (var item in ((RootWorkspace)rootItem).Items) @@ -150,7 +150,7 @@ namespace MonoDevelop.Ide.Gui.Components } } - void AddEntry (TreeIter iter, IBuildTarget item) + void AddEntry (TreeIter iter, WorkspaceObject item) { if (!IsVisible (item)) return; @@ -178,21 +178,21 @@ namespace MonoDevelop.Ide.Gui.Components if (selected) tree.ExpandToPath (store.GetPath (iter)); - foreach (IBuildTarget ce in GetChildren (item)) + foreach (WorkspaceObject ce in GetChildren (item)) AddEntry (iter, ce); } - void SetSelection (IBuildTarget selected, HashSet<IBuildTarget> active) + void SetSelection (WorkspaceObject selected, HashSet<WorkspaceObject> active) { TreeIter it; if (store.GetIterFirst (out it)) SetSelection (it, selected, active); } - bool SetSelection (TreeIter it, IBuildTarget selected, HashSet<IBuildTarget> active) + bool SetSelection (TreeIter it, WorkspaceObject selected, HashSet<WorkspaceObject> active) { do { - IBuildTarget item = (IBuildTarget) store.GetValue (it, 2); + WorkspaceObject item = (WorkspaceObject) store.GetValue (it, 2); if (selected != null && item == selected) { tree.Selection.SelectIter (it); tree.ExpandToPath (store.GetPath (it)); @@ -220,13 +220,13 @@ namespace MonoDevelop.Ide.Gui.Components { TreeIter iter; store.GetIterFromString (out iter, args.Path); - IBuildTarget ob = (IBuildTarget) store.GetValue (iter, 2); + var ob = (WorkspaceObject) store.GetValue (iter, 2); if (activeItems.Contains (ob)) { activeItems.Remove (ob); if (CascadeCheckboxSelection) { foreach (var i in GetAllChildren (ob)) activeItems.Remove (i); - SetSelection (iter, null, new HashSet<IBuildTarget> ()); + SetSelection (iter, null, new HashSet<WorkspaceObject> ()); } else { store.SetValue (iter, 3, false); } @@ -245,13 +245,13 @@ namespace MonoDevelop.Ide.Gui.Components ActiveChanged (this, EventArgs.Empty); } - IEnumerable<IBuildTarget> GetAllChildren (IBuildTarget item) + IEnumerable<WorkspaceObject> GetAllChildren (WorkspaceObject item) { - IEnumerable<IBuildTarget> res = GetChildren (item); + var res = GetChildren (item); return res.Concat (res.SelectMany (i => GetAllChildren (i))); } - IEnumerable<IBuildTarget> GetChildren (IBuildTarget item) + IEnumerable<WorkspaceObject> GetChildren (WorkspaceObject item) { if (item is SolutionFolder) { return ((SolutionFolder)item).Items; @@ -260,20 +260,20 @@ namespace MonoDevelop.Ide.Gui.Components } else if (item is Workspace) { return ((Workspace)item).Items; } else - return new IBuildTarget [0]; + return new WorkspaceObject [0]; } - protected bool IsVisible (IBuildTarget item) + protected bool IsVisible (WorkspaceObject item) { return true; } - protected bool IsCheckboxVisible (IBuildTarget item) + protected bool IsCheckboxVisible (WorkspaceObject item) { if (!ShowCheckboxes) return false; if (selectableTypes.Count > 0) - return selectableTypes.Any (t => t.IsAssignableFrom (item.GetType ())); + return selectableTypes.Any (t => t.IsInstanceOfType (item)); return true; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/TransactedTreeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/TransactedTreeBuilder.cs index 7f26bb49af..7c45c3181d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/TransactedTreeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/TransactedTreeBuilder.cs @@ -124,6 +124,11 @@ namespace MonoDevelop.Ide.Gui.Components } } + public T GetParentDataItem<T> (bool includeCurrent) + { + return (T)GetParentDataItem (typeof(T), includeCurrent); + } + public object GetParentDataItem (Type type, bool includeCurrent) { if (includeCurrent && type.IsInstanceOfType (DataItem)) @@ -659,7 +664,8 @@ namespace MonoDevelop.Ide.Gui.Components void UpdateNode (TreeNode n, NodeBuilder[] chain, NodeAttributes ats, object dataObject) { - n.NodeInfo = TreeBuilder.GetNodeInfo (tree, this, chain, dataObject); + var ni = new NodeInfo (); + n.NodeInfo = TreeBuilder.GetNodeInfo (ni, tree, this, chain, dataObject); if (chain != null && chain.Length > 0) n.Name = ((TypeNodeBuilder)chain[0]).GetNodeName (this, n.DataItem); @@ -834,17 +840,11 @@ namespace MonoDevelop.Ide.Gui.Components LoggingService.LogError ("Found invalid iter for node. " + node.DataItem);
return;
} - tree.Store.SetValue (node.NodeIter, ExtensibleTreeView.TextColumn, node.NodeInfo.Label); - tree.Store.SetValue (node.NodeIter, ExtensibleTreeView.OpenIconColumn, node.NodeInfo.Icon ?? CellRendererImage.NullImage); - tree.Store.SetValue (node.NodeIter, ExtensibleTreeView.ClosedIconColumn, node.NodeInfo.ClosedIcon ?? CellRendererImage.NullImage); - tree.Store.SetValue (node.NodeIter, ExtensibleTreeView.OverlayBottomRightColumn, node.NodeInfo.OverlayBottomRight ?? CellRendererImage.NullImage); - tree.Store.SetValue (node.NodeIter, ExtensibleTreeView.OverlayBottomLeftColumn, node.NodeInfo.OverlayBottomLeft ?? CellRendererImage.NullImage); - tree.Store.SetValue (node.NodeIter, ExtensibleTreeView.OverlayTopLeftColumn, node.NodeInfo.OverlayTopLeft ?? CellRendererImage.NullImage); - tree.Store.SetValue (node.NodeIter, ExtensibleTreeView.OverlayTopRightColumn, node.NodeInfo.OverlayTopRight ?? CellRendererImage.NullImage); + tree.Store.SetValue (node.NodeIter, ExtensibleTreeView.NodeInfoColumn, node.NodeInfo); } if (node.Children != null) { foreach (TreeNode cn in node.Children) { - Gtk.TreeIter it = tree.Store.AppendValues (node.NodeIter, cn.NodeInfo.Label, cn.NodeInfo.Icon, cn.NodeInfo.ClosedIcon, cn.DataItem, cn.BuilderChain, cn.Filled, false, cn.NodeInfo.OverlayBottomRight, cn.NodeInfo.OverlayBottomLeft, cn.NodeInfo.OverlayTopLeft, cn.NodeInfo.OverlayTopRight); + Gtk.TreeIter it = tree.Store.AppendValues (node.NodeIter, cn.NodeInfo, cn.DataItem, cn.BuilderChain, cn.Filled, false); if (!cn.Filled) tree.Store.AppendNode (it); // Dummy node // The OnNodeAdded event was already fired when the node was added. There is no need to fire it again. diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/TreeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/TreeBuilder.cs index 6f064e368f..8c810ff21f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/TreeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/TreeBuilder.cs @@ -187,9 +187,9 @@ namespace MonoDevelop.Ide.Gui.Components if (!currentIter.Equals (Gtk.TreeIter.Zero)) { if (!Filled) continue; - it = store.InsertWithValues (currentIter, 0, "", null, null, dataObject, chain, false); + it = store.InsertWithValues (currentIter, 0, NodeInfo.Empty, dataObject, chain, false); } else { - it = store.AppendValues ("", null, null, dataObject, chain, false); + it = store.AppendValues (NodeInfo.Empty, dataObject, chain, false); } pad.RegisterNode (it, dataObject, chain, true); @@ -219,10 +219,10 @@ namespace MonoDevelop.Ide.Gui.Components Gtk.TreeIter it; if (!currentIter.Equals (Gtk.TreeIter.Zero)) { if (!Filled) return; - it = store.AppendValues (currentIter, "", null, null, dataObject, chain, false); + it = store.AppendValues (currentIter, NodeInfo.Empty, dataObject, chain, false); } else - it = store.AppendValues ("", null, null, dataObject, chain, false); + it = store.AppendValues (NodeInfo.Empty, dataObject, chain, false); pad.RegisterNode (it, dataObject, chain, true); @@ -277,16 +277,26 @@ namespace MonoDevelop.Ide.Gui.Components void UpdateNode (NodeBuilder[] chain, NodeAttributes ats, object dataObject) { - var ni = GetNodeInfo (pad, this, chain, dataObject); - SetNodeInfo (currentIter, ats, ni); + bool isNew = false; + + var ni = (NodeInfo)store.GetValue (currentIter, ExtensibleTreeView.NodeInfoColumn); + if (ni == null || ni.IsShared) { + ni = new NodeInfo (); + isNew = true; + } + else + ni.Reset (); + + GetNodeInfo (ni, pad, this, chain, dataObject); + + if (isNew) + store.SetValue (currentIter, ExtensibleTreeView.NodeInfoColumn, ni); + else + store.EmitRowChanged (store.GetPath (currentIter), currentIter); } - internal static NodeInfo GetNodeInfo (ExtensibleTreeView tree, ITreeBuilder tb, NodeBuilder[] chain, object dataObject) + internal static NodeInfo GetNodeInfo (NodeInfo nodeInfo, ExtensibleTreeView tree, ITreeBuilder tb, NodeBuilder[] chain, object dataObject) { - NodeInfo nodeInfo = new NodeInfo () { - Label = string.Empty - }; - NodePosition pos = tb.CurrentPosition; foreach (NodeBuilder builder in chain) { @@ -317,18 +327,6 @@ namespace MonoDevelop.Ide.Gui.Components return nodeInfo; } - void SetNodeInfo (Gtk.TreeIter it, NodeAttributes ats, NodeInfo nodeInfo) - { - store.SetValue (it, ExtensibleTreeView.TextColumn, nodeInfo.Label); - store.SetValue (it, ExtensibleTreeView.OpenIconColumn, nodeInfo.Icon ?? CellRendererImage.NullImage); - store.SetValue (it, ExtensibleTreeView.ClosedIconColumn, nodeInfo.ClosedIcon ?? CellRendererImage.NullImage); - store.SetValue (it, ExtensibleTreeView.OverlayBottomLeftColumn, nodeInfo.OverlayBottomLeft ?? CellRendererImage.NullImage); - store.SetValue (it, ExtensibleTreeView.OverlayBottomRightColumn, nodeInfo.OverlayBottomRight ?? CellRendererImage.NullImage); - store.SetValue (it, ExtensibleTreeView.OverlayTopLeftColumn, nodeInfo.OverlayTopLeft ?? CellRendererImage.NullImage); - store.SetValue (it, ExtensibleTreeView.OverlayTopRightColumn, nodeInfo.OverlayTopRight ?? CellRendererImage.NullImage); - pad.Tree.QueueDraw (); - } - void CreateChildren (NodeBuilder[] chain, object dataObject) { Gtk.TreeIter it = currentIter; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/TreeNodeNavigator.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/TreeNodeNavigator.cs index c08e37e4f2..b69fa16661 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/TreeNodeNavigator.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/TreeNodeNavigator.cs @@ -358,7 +358,7 @@ namespace MonoDevelop.Ide.Gui.Components object data = DataItem; NodeBuilder[] chain = BuilderChain; if (chain != null && chain.Length > 0) return ((TypeNodeBuilder)chain[0]).GetNodeName (this, data); - else return GetStoreValue (ExtensibleTreeView.TextColumn) as string; + else return GetStoreNodeInfo ().Label; } } @@ -369,6 +369,11 @@ namespace MonoDevelop.Ide.Gui.Components } } + public T GetParentDataItem<T> (bool includeCurrent) + { + return (T)GetParentDataItem (typeof(T), includeCurrent); + } + public object GetParentDataItem (Type type, bool includeCurrent) { if (includeCurrent && type.IsInstanceOfType (DataItem)) @@ -401,6 +406,11 @@ namespace MonoDevelop.Ide.Gui.Components { return store.GetValue (currentIter, column); } + + NodeInfo GetStoreNodeInfo () + { + return (NodeInfo) store.GetValue (currentIter, 0); + } } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/FileSelectorDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/FileSelectorDialog.cs index 2d63a444e0..59b927b4aa 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/FileSelectorDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/FileSelectorDialog.cs @@ -114,11 +114,11 @@ namespace MonoDevelop.Ide.Gui.Dialogs return -1; else if (encodingMenu.History < firstEncIndex || encodingMenu.History == selectOption) return -1; - return SelectedEncodings.ConversionEncodings [encodingMenu.History - firstEncIndex]; + return TextEncoding.ConversionEncodings [encodingMenu.History - firstEncIndex].CodePage; } set { - for (uint n=0; n < SelectedEncodings.ConversionEncodings.Length; n++) { - if (SelectedEncodings.ConversionEncodings [n] == value) { + for (uint n=0; n < TextEncoding.ConversionEncodings.Length; n++) { + if (TextEncoding.ConversionEncodings [n].CodePage == value) { encodingMenu.SetHistory (n + (uint)firstEncIndex); Menu menu = (Menu)encodingMenu.Menu; RadioMenuItem rm = (RadioMenuItem) menu.Children [n + firstEncIndex]; @@ -164,8 +164,8 @@ namespace MonoDevelop.Ide.Gui.Dialogs } else firstEncIndex = 0; - foreach (var codePage in SelectedEncodings.ConversionEncodings) { - var enc = Encoding.GetEncoding (codePage); + foreach (var textEncoding in TextEncoding.ConversionEncodings) { + var enc = Encoding.GetEncoding (textEncoding.CodePage); RadioMenuItem mitem = new RadioMenuItem (enc.EncodingName + " (" + enc.WebName + ")"); menu.Append (mitem); if (defaultActivated == null) { @@ -190,7 +190,7 @@ namespace MonoDevelop.Ide.Gui.Dialogs encodingMenu.SetHistory (0); - selectOption = firstEncIndex + SelectedEncodings.ConversionEncodings.Length + 1; + selectOption = firstEncIndex + TextEncoding.ConversionEncodings.Length + 1; } void EncodingChanged (object s, EventArgs args) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/GtkAlertDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/GtkAlertDialog.cs index 89f0ef9835..0721f8bff6 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/GtkAlertDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/GtkAlertDialog.cs @@ -100,7 +100,12 @@ namespace MonoDevelop.Ide.Gui.Dialogs primaryText = message.Text; secondaryText = message.SecondaryText; } - + + if (!message.UseMarkup) { + primaryText = GLib.Markup.EscapeText (primaryText); + secondaryText = GLib.Markup.EscapeText (secondaryText); + } + if (!string.IsNullOrEmpty (message.Icon)) { image = new ImageView (); image.Yalign = 0.00f; @@ -110,14 +115,14 @@ namespace MonoDevelop.Ide.Gui.Dialogs } StringBuilder markup = new StringBuilder (@"<span weight=""bold"" size=""larger"">"); - markup.Append (GLib.Markup.EscapeText (primaryText)); + markup.Append (primaryText); markup.Append ("</span>"); if (!String.IsNullOrEmpty (secondaryText)) { if (!String.IsNullOrEmpty (primaryText)) { markup.AppendLine (); markup.AppendLine (); } - markup.Append (GLib.Markup.EscapeText (secondaryText)); + markup.Append (secondaryText); } label.Markup = markup.ToString (); label.Selectable = true; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ItemOptionsDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ItemOptionsDialog.cs index 43475f204d..2be7c597ce 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ItemOptionsDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ItemOptionsDialog.cs @@ -29,6 +29,7 @@ using System; using Mono.Addins; using MonoDevelop.Projects.Extensions; using MonoDevelop.Ide.Gui.Dialogs; +using MonoDevelop.Projects; namespace MonoDevelop.Ide.Gui.Dialogs { @@ -48,6 +49,8 @@ namespace MonoDevelop.Ide.Gui.Dialogs base.InitializeContext (extensionContext); extensionContext.RegisterCondition ("ItemType", new ItemTypeCondition (DataObject.GetType ())); extensionContext.RegisterCondition ("ActiveLanguage", new ProjectLanguageCondition (DataObject)); + if (DataObject is Project) + extensionContext.RegisterCondition ("ItemType", new FlavorTypeCondition ((Project)DataObject)); } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ItemOptionsPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ItemOptionsPanel.cs index f4f9b40ab3..fb478e3985 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ItemOptionsPanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ItemOptionsPanel.cs @@ -34,10 +34,10 @@ namespace MonoDevelop.Ide.Gui.Dialogs { public abstract class ItemOptionsPanel: OptionsPanel { - SolutionEntityItem solutionItem; + SolutionItem solutionItem; WorkspaceItem workspaceItem; - public SolutionEntityItem ConfiguredSolutionItem { + public SolutionItem ConfiguredSolutionItem { get { return solutionItem; } @@ -76,7 +76,7 @@ namespace MonoDevelop.Ide.Gui.Dialogs { base.Initialize (dialog, dataObject); - solutionItem = dataObject as SolutionEntityItem; + solutionItem = dataObject as SolutionItem; if (solutionItem != null) workspaceItem = solutionItem.ParentSolution; else diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/MultiConfigItemOptionsDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/MultiConfigItemOptionsDialog.cs index ff956b9d6f..c59f7092d3 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/MultiConfigItemOptionsDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/MultiConfigItemOptionsDialog.cs @@ -136,9 +136,9 @@ namespace MonoDevelop.Ide.Gui.Dialogs data.Configurations.Add (copy); } if (entry is Solution) { - foreach (SolutionItem e in ((Solution)entry).Items) { - if (e is SolutionEntityItem) - data.children.Add (ConfigurationData.Build ((SolutionEntityItem) e)); + foreach (SolutionFolderItem e in ((Solution)entry).Items) { + if (e is SolutionItem) + data.children.Add (ConfigurationData.Build ((SolutionItem) e)); } } return data; @@ -177,7 +177,7 @@ namespace MonoDevelop.Ide.Gui.Dialogs data.Update (modifiedObjects); // If configurations have been renamed, update the references in the solution - SolutionEntityItem item = entry as SolutionEntityItem; + SolutionItem item = entry as SolutionItem; if (item != null && renameData.Count > 0) { Solution sol = item.ParentSolution; if (sol != null) { @@ -211,9 +211,9 @@ namespace MonoDevelop.Ide.Gui.Dialogs foreach (ConfigurationData data in children) { SolutionConfigurationEntry ce; if (sourceName != null) - ce = cc.GetEntryForItem ((SolutionEntityItem)data.Entry); + ce = cc.GetEntryForItem ((SolutionItem)data.Entry); else - ce = cc.AddItem ((SolutionEntityItem) data.Entry); + ce = cc.AddItem ((SolutionItem) data.Entry); if (createChildConfigurations) { ce.ItemConfiguration = name; if (data.Configurations [name] == null) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/MultiTaskProgressDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/MultiTaskProgressDialog.cs index 8151852824..453fa20070 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/MultiTaskProgressDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/MultiTaskProgressDialog.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; using Gtk; using MonoDevelop.Core; +using System.Threading; namespace MonoDevelop.Ide.Gui.Dialogs { @@ -46,7 +47,7 @@ namespace MonoDevelop.Ide.Gui.Dialogs int ident = 0; List<TextTag> tags = new List<TextTag> (); Stack<string> indents = new Stack<string> (); - IAsyncOperation asyncOperation; + CancellationTokenSource asyncOperation; CellRendererText textRenderer; CellRendererProgress progressRenderer; @@ -99,7 +100,7 @@ namespace MonoDevelop.Ide.Gui.Dialogs Resize (w, 1); } - public IAsyncOperation AsyncOperation { + public CancellationTokenSource CancellationTokenSource { get { return asyncOperation; } set { asyncOperation = value; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ProgressDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ProgressDialog.cs index 0d39dfe617..52d41f001d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ProgressDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ProgressDialog.cs @@ -28,6 +28,7 @@ using System; using Gtk; using System.Collections.Generic; using MonoDevelop.Core; +using System.Threading; namespace MonoDevelop.Ide.Gui.Dialogs { @@ -40,9 +41,8 @@ namespace MonoDevelop.Ide.Gui.Dialogs int ident = 0; List<TextTag> tags = new List<TextTag> (); Stack<string> indents = new Stack<string> (); - IAsyncOperation asyncOperation; - public event EventHandler OperationCancelled; - + CancellationTokenSource cancellationTokenSource; + public ProgressDialog (bool allowCancel, bool showDetails): this (null, allowCancel, showDetails) { } @@ -74,9 +74,9 @@ namespace MonoDevelop.Ide.Gui.Dialogs tags.Add (tag); } - public IAsyncOperation AsyncOperation { - get { return asyncOperation; } - set { asyncOperation = value; } + public CancellationTokenSource CancellationTokenSource { + get { return cancellationTokenSource; } + set { cancellationTokenSource = value; } } public string Message { @@ -168,11 +168,8 @@ namespace MonoDevelop.Ide.Gui.Dialogs protected void OnBtnCancelClicked (object sender, EventArgs e) { - if (asyncOperation != null) - asyncOperation.Cancel (); - - if (OperationCancelled != null) - OperationCancelled (this, null); + if (cancellationTokenSource != null) + cancellationTokenSource.Cancel (); } bool UpdateSize () diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/SelectEncodingsDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/SelectEncodingsDialog.cs index 1bd10c36ef..7bd95d1488 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/SelectEncodingsDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/SelectEncodingsDialog.cs @@ -32,40 +32,10 @@ using Gtk; using MonoDevelop.Core; using System.Text; using System.Collections.Generic; +using MonoDevelop.Projects.Text; namespace MonoDevelop.Ide { - public static class SelectedEncodings - { - static int[] conversionEncodings = null; - public static int[] ConversionEncodings { - get { - if (conversionEncodings == null) { - string propertyEncodings = PropertyService.Get ("MonoDevelop.Ide.SelectEncodingsDialog.ConversionEncodings", string.Join (",", DefaultEncodings)); - try { - conversionEncodings = propertyEncodings.Split (',').Select (e => int.Parse (e.Trim ())).ToArray (); - } catch (Exception) { - conversionEncodings = DefaultEncodings; - } - } - - return conversionEncodings; - } - set { - conversionEncodings = value; - PropertyService.Set ("MonoDevelop.Ide.SelectEncodingsDialog.ConversionEncodings", string.Join (",", value)); - Console.WriteLine ("set to:" + string.Join (",", value)); - } - } - - const int ISO_8859_15 = 28605; - public readonly static int[] DefaultEncodings = new int[] { - Encoding.UTF8.CodePage, - ISO_8859_15, - Encoding.Unicode.CodePage - }; - } - internal partial class SelectEncodingsDialog: Gtk.Dialog { ListStore storeAvail; @@ -86,13 +56,12 @@ namespace MonoDevelop.Ide listSelected.AppendColumn ("Encoding", new Gtk.CellRendererText (), "text", 1); foreach (var e in Encoding.GetEncodings ()) { - // if (!((IList)TextEncoding.ConversionEncodings).Contains (e)) var enc = e.GetEncoding (); storeAvail.AppendValues (enc.EncodingName, enc.WebName, e.CodePage); } - foreach (var e in SelectedEncodings.ConversionEncodings) { - var enc = Encoding.GetEncoding (e); + foreach (var e in TextEncoding.ConversionEncodings) { + var enc = Encoding.GetEncoding (e.CodePage); storeSelected.AppendValues (enc.EncodingName, enc.WebName, enc.CodePage); } } catch (Exception ex) { @@ -115,7 +84,7 @@ namespace MonoDevelop.Ide list.Add (enc); } while (storeSelected.IterNext (ref iter)); } - SelectedEncodings.ConversionEncodings = list.ToArray (); + TextEncoding.ConversionEncodings = list.Select ((id) => TextEncoding.GetEncoding (id)).ToArray (); } protected void OnAddClicked (object ob, EventArgs args) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/TextStylePolicyPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/TextStylePolicyPanel.cs index b2bd294637..4135b233d5 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/TextStylePolicyPanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/TextStylePolicyPanel.cs @@ -67,8 +67,8 @@ namespace MonoDevelop.Ide.Gui.OptionPanels //NOTE: order corresponds to EolMarker enum values lineEndingCombo.AppendText (GettextCatalog.GetString ("Native")); - lineEndingCombo.AppendText (GettextCatalog.GetString ("Mac")); - lineEndingCombo.AppendText (GettextCatalog.GetString ("Unix")); + lineEndingCombo.AppendText (GettextCatalog.GetString ("Mac Classic")); + lineEndingCombo.AppendText (GettextCatalog.GetString ("Unix / Mac")); lineEndingCombo.AppendText (GettextCatalog.GetString ("Microsoft Windows")); // Using "Windows" is too short, otherwise the translation get's confused. Mike } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/CombineNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/CombineNodeBuilder.cs index 9944f0f4b3..59cb4ab063 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/CombineNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/CombineNodeBuilder.cs @@ -69,17 +69,17 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad { SolutionFolder combine = (SolutionFolder) dataObject; if (builder.Options ["ShowProjects"]) { - foreach (SolutionItem entry in combine.Items) + foreach (SolutionFolderItem entry in combine.Items) builder.AddChild (entry); } else { AddClasses (builder, combine); } } - void AddClasses (ITreeBuilder builder, SolutionItem entry) + void AddClasses (ITreeBuilder builder, SolutionFolderItem entry) { if (entry is SolutionFolder) { - foreach (SolutionItem e in ((SolutionFolder)entry).Items) + foreach (SolutionFolderItem e in ((SolutionFolder)entry).Items) AddClasses (builder, e); } else if (entry is Project) { ProjectNodeBuilder.BuildChildNodes (builder, entry as Project); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/SolutionNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/SolutionNodeBuilder.cs index b33c3a69d5..5ce1af0112 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/SolutionNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/SolutionNodeBuilder.cs @@ -82,7 +82,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad { Solution solution = dataObject as Solution; int count = 0; - foreach (SolutionItem e in solution.GetAllSolutionItems ()) + foreach (SolutionFolderItem e in solution.GetAllSolutionItems ()) if (!(e is SolutionFolder)) count++; @@ -104,7 +104,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad public override void BuildChildNodes (ITreeBuilder ctx, object dataObject) { Solution solution = (Solution) dataObject; - foreach (SolutionItem entry in solution.RootFolder.Items) + foreach (SolutionFolderItem entry in solution.RootFolder.Items) ctx.AddChild (entry); } @@ -177,7 +177,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad Solution sol = (Solution) CurrentNode.DataItem; sol.Name = newName; - IdeApp.Workspace.Save(); + IdeApp.Workspace.SaveAsync(); } public override DragOperation CanDragNode () @@ -187,7 +187,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad public override bool CanDropNode (object dataObject, DragOperation operation) { - return dataObject is SolutionItem; + return dataObject is SolutionFolderItem; } public override void OnNodeDrop (object dataObject, DragOperation operation) @@ -211,7 +211,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad if (res == AlertButton.Remove) { parent.Items.Remove (solution); solution.Dispose (); - IdeApp.Workspace.Save(); + IdeApp.Workspace.SaveAsync(); } } @@ -226,17 +226,17 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad public void AddNewProjectToSolution () { Solution solution = (Solution) CurrentNode.DataItem; - SolutionItem ce = IdeApp.ProjectOperations.CreateProject (solution.RootFolder); + SolutionFolderItem ce = IdeApp.ProjectOperations.CreateProject (solution.RootFolder); if (ce == null) return; Tree.AddNodeInsertCallback (ce, new TreeNodeCallback (OnEntryInserted)); CurrentNode.Expanded = true; } [CommandHandler (ProjectCommands.AddProject)] - public void AddProjectToCombine() + public async void AddProjectToCombine() { Solution solution = (Solution) CurrentNode.DataItem; - SolutionItem ce = IdeApp.ProjectOperations.AddSolutionItem (solution.RootFolder); + SolutionFolderItem ce = await IdeApp.ProjectOperations.AddSolutionItem (solution.RootFolder); if (ce == null) return; Tree.AddNodeInsertCallback (ce, new TreeNodeCallback (OnEntryInserted)); CurrentNode.Expanded = true; @@ -246,7 +246,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad public void AddFolder() { Solution solution = (Solution) CurrentNode.DataItem; - SolutionItem ce = new SolutionFolder (); + var ce = new SolutionFolder (); ce.Name = GettextCatalog.GetString ("New Folder"); solution.RootFolder.Items.Add (ce); Tree.AddNodeInsertCallback (ce, OnFolderInserted); @@ -257,7 +257,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad public void OnReload () { Solution solution = (Solution) CurrentNode.DataItem; - using (IProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { + using (ProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { solution.ParentWorkspace.ReloadItem (m, solution); } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs index f958a36b42..03fa015e0d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs @@ -184,9 +184,9 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad return false; } - public override void OnMultipleNodeDrop (object[] dataObjects, DragOperation operation) + public override async void OnMultipleNodeDrop (object[] dataObjects, DragOperation operation) { - var projectsToSave = new HashSet<SolutionEntityItem> (); + var projectsToSave = new HashSet<SolutionItem> (); var groupedFiles = new HashSet<ProjectFile> (); foreach (var pf in dataObjects.OfType<ProjectFile> ()) { @@ -197,10 +197,10 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad foreach (object dataObject in dataObjects) DropNode (projectsToSave, dataObject, groupedFiles, operation); - IdeApp.ProjectOperations.Save (projectsToSave); + await IdeApp.ProjectOperations.SaveAsync (projectsToSave); } - void DropNode (HashSet<SolutionEntityItem> projectsToSave, object dataObject, HashSet<ProjectFile> groupedFiles, DragOperation operation) + void DropNode (HashSet<SolutionItem> projectsToSave, object dataObject, HashSet<ProjectFile> groupedFiles, DragOperation operation) { FilePath targetDirectory = GetFolderPath (CurrentNode.DataItem); FilePath source; @@ -373,7 +373,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } [CommandHandler (ProjectCommands.AddFiles)] - public void AddFilesToProject() + public async void AddFilesToProject() { Project project = (Project) CurrentNode.GetParentDataItem (typeof(Project), true); var targetRoot = ((FilePath) GetFolderPath (CurrentNode.DataItem)).CanonicalPath; @@ -398,18 +398,18 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad IdeApp.ProjectOperations.AddFilesToProject (project, files, baseDirectory, overrideAction); - IdeApp.ProjectOperations.Save (project); + await IdeApp.ProjectOperations.SaveAsync (project); } [CommandHandler (ProjectCommands.AddNewFiles)] - public void AddNewFileToProject() + public async void AddNewFileToProject() { Project project = (Project) CurrentNode.GetParentDataItem (typeof(Project), true); IdeApp.ProjectOperations.CreateProjectFile (project, GetFolderPath (CurrentNode.DataItem)); - IdeApp.ProjectOperations.Save (project); CurrentNode.Expanded = true; if (IdeApp.Workbench.ActiveDocument != null) IdeApp.Workbench.ActiveDocument.Window.SelectWindow (); + await IdeApp.ProjectOperations.SaveAsync (project); } void OnFileInserted (ITreeNavigator nav) @@ -420,7 +420,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad ///<summary>Imports files and folders from a target folder into the current folder</summary> [CommandHandler (ProjectCommands.AddFilesFromFolder)] - public void AddFilesFromFolder () + public async void AddFilesFromFolder () { var project = (Project) CurrentNode.GetParentDataItem (typeof(Project), true); var targetRoot = ((FilePath) GetFolderPath (CurrentNode.DataItem)).CanonicalPath; @@ -447,12 +447,12 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad var added = IdeApp.ProjectOperations.AddFilesToProject (project, srcFiles.ToArray (), targetFiles.ToArray (), null).Any (); if (added) - IdeApp.ProjectOperations.Save (project); + await IdeApp.ProjectOperations.SaveAsync (project); } ///<summary>Adds an existing folder to the current folder</summary> [CommandHandler (ProjectCommands.AddExistingFolder)] - public void AddExistingFolder () + public async void AddExistingFolder () { var project = (Project) CurrentNode.GetParentDataItem (typeof(Project), true); var selectedFolder = ((FilePath) GetFolderPath (CurrentNode.DataItem)).CanonicalPath; @@ -504,11 +504,11 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } if (changedProject) - IdeApp.ProjectOperations.Save (project); + await IdeApp.ProjectOperations.SaveAsync (project); } [CommandHandler (ProjectCommands.NewFolder)] - public void AddNewFolder () + public async void AddNewFolder () { Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; @@ -529,10 +529,11 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad ProjectFile newFolder = new ProjectFile (directoryName); newFolder.Subtype = Subtype.Directory; project.Files.Add (newFolder); - IdeApp.ProjectOperations.Save (project); CurrentNode.Expanded = true; Tree.AddNodeInsertCallback (new ProjectFolder (directoryName, project), new TreeNodeCallback (OnFileInserted)); + + await IdeApp.ProjectOperations.SaveAsync (project); } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/PortableFrameworkSubsetNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/PortableFrameworkSubsetNodeBuilder.cs index 50e91608c8..799791c97f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/PortableFrameworkSubsetNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/PortableFrameworkSubsetNodeBuilder.cs @@ -34,9 +34,9 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad { class PortableFrameworkSubset { - public PortableDotNetProject Project { get; private set; } + public DotNetProject Project { get; private set; } - public PortableFrameworkSubset (PortableDotNetProject project) + public PortableFrameworkSubset (DotNetProject project) { this.Project = project; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs index 5725c9dcb4..d4c2328ea6 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs @@ -168,7 +168,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad selectionLength = Path.GetFileNameWithoutExtension(name).Length; } - public override void RenameItem (string newName) + public async override void RenameItem (string newName) { ProjectFile newProjectFile = null; var file = (ProjectFile) CurrentNode.DataItem; @@ -201,7 +201,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad FileService.RenameFile (oldPath, newName); } if (file.Project != null) - IdeApp.ProjectOperations.Save (file.Project); + await IdeApp.ProjectOperations.SaveAsync (file.Project); } } catch (ArgumentException) { // new file name with wildcard (*, ?) characters in it MessageService.ShowWarning (GettextCatalog.GetString ("The name you have chosen contains illegal characters. Please choose a different name.")); @@ -239,7 +239,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad return pf != null && pf != target && !pf.HasChildren && target.DependsOn == null; } - void Drop (ProjectFile pf, DragOperation operation, HashSet<SolutionEntityItem> projectsToSave) + void Drop (ProjectFile pf, DragOperation operation, HashSet<SolutionItem> projectsToSave) { var target = (ProjectFile) CurrentNode.DataItem; var targetDirectory = target.FilePath.ParentDirectory; @@ -277,12 +277,12 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public override void OnMultipleNodeDrop (object[] dataObjects, DragOperation operation) { - var projectsToSave = new HashSet<SolutionEntityItem> (); + var projectsToSave = new HashSet<SolutionItem> (); foreach (var dataObject in dataObjects) Drop ((ProjectFile) dataObject, operation, projectsToSave); - IdeApp.ProjectOperations.Save (projectsToSave); + IdeApp.ProjectOperations.SaveAsync (projectsToSave); } public override bool CanDeleteItem () @@ -294,7 +294,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad [AllowMultiSelection] public override void DeleteMultipleItems () { - var projects = new Set<SolutionEntityItem> (); + var projects = new Set<SolutionItem> (); var files = new List<ProjectFile> (); bool hasChildren = false; @@ -357,7 +357,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad FileService.DeleteFile (file.Name); } - IdeApp.ProjectOperations.Save (projects); + IdeApp.ProjectOperations.SaveAsync (projects); } [CommandUpdateHandler (EditCommands.Delete)] @@ -412,7 +412,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad [AllowMultiSelection] public void OnSetBuildAction (object ob) { - Set<SolutionEntityItem> projects = new Set<SolutionEntityItem> (); + Set<SolutionItem> projects = new Set<SolutionItem> (); string action = (string)ob; foreach (ITreeNavigator node in CurrentNodes) { @@ -420,7 +420,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad file.BuildAction = action; projects.Add (file.Project); } - IdeApp.ProjectOperations.Save (projects); + IdeApp.ProjectOperations.SaveAsync (projects); } [CommandUpdateHandler (FileCommands.SetBuildAction)] @@ -486,7 +486,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } } - Set<SolutionEntityItem> projects = new Set<SolutionEntityItem> (); + Set<SolutionItem> projects = new Set<SolutionItem> (); foreach (ITreeNavigator node in CurrentNodes) { ProjectFile file = (ProjectFile) node.DataItem; @@ -498,7 +498,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } } - IdeApp.ProjectOperations.Save (projects); + IdeApp.ProjectOperations.SaveAsync (projects); } [CommandUpdateHandler (FileCommands.CopyToOutputDirectory)] diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolder.cs index ed643cf77a..934f2dd923 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolder.cs @@ -39,15 +39,15 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public class ProjectFolder: IDisposable, IFolderItem {
FilePath absolutePath; - IWorkspaceObject parentWorkspaceObject; + WorkspaceObject parentWorkspaceObject; object parent; bool trackChanges; - public ProjectFolder (FilePath absolutePath, IWorkspaceObject parentWorkspaceObject): this (absolutePath, parentWorkspaceObject, null) + public ProjectFolder (FilePath absolutePath, WorkspaceObject parentWorkspaceObject): this (absolutePath, parentWorkspaceObject, null) { }
- public ProjectFolder (FilePath absolutePath, IWorkspaceObject parentWorkspaceObject, object parent) + public ProjectFolder (FilePath absolutePath, WorkspaceObject parentWorkspaceObject, object parent) { this.parent = parent; this.parentWorkspaceObject = parentWorkspaceObject; @@ -80,7 +80,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad get { return absolutePath.FileName; } } - public IWorkspaceObject ParentWorkspaceObject { + public WorkspaceObject ParentWorkspaceObject { get { return parentWorkspaceObject; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs index 88b8be8058..0552cb6020 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs @@ -149,7 +149,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad return ((ProjectFolder)dataObject).Path; } - public override void RenameItem (string newName) + public async override void RenameItem (string newName) { ProjectFolder folder = (ProjectFolder) CurrentNode.DataItem as ProjectFolder; string oldFoldername = folder.Path; @@ -159,13 +159,23 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad try { if (!FileService.IsValidPath (newFoldername)) { MessageService.ShowWarning (GettextCatalog.GetString ("The name you have chosen contains illegal characters. Please choose a different name.")); - } else if (File.Exists (newFoldername) || Directory.Exists (newFoldername)) { + return; + } + if (File.Exists (newFoldername)) { MessageService.ShowWarning (GettextCatalog.GetString ("File or directory name is already in use. Please choose a different one.")); - } else { - FileService.RenameDirectory (oldFoldername, newName); - if (folder.Project != null) - IdeApp.ProjectOperations.Save (folder.Project); + return; } + // Don't use Directory.Exists because we want to check for the exact case in case-insensitive file systems + var di = Directory.GetDirectories (Path.GetDirectoryName (newFoldername), Path.GetFileName (newFoldername)).FirstOrDefault (); + if (di != null) { + MessageService.ShowWarning (GettextCatalog.GetString ("File or directory name is already in use. Please choose a different one.")); + return; + } + + FileService.RenameDirectory (oldFoldername, newName); + if (folder.Project != null) + await IdeApp.ProjectOperations.SaveAsync (folder.Project); + } catch (System.ArgumentException) { // new file name with wildcard (*, ?) characters in it MessageService.ShowWarning (GettextCatalog.GetString ("The name you have chosen contains illegal characters. Please choose a different name.")); } catch (System.IO.IOException ex) { @@ -176,7 +186,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public override void DeleteMultipleItems () { - var projects = new Set<SolutionEntityItem> (); + var projects = new Set<SolutionItem> (); var folders = new List<ProjectFolder> (); foreach (ITreeNavigator node in CurrentNodes) folders.Add ((ProjectFolder) node.DataItem); @@ -263,7 +273,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } } } - IdeApp.ProjectOperations.Save (projects); + IdeApp.ProjectOperations.SaveAsync (projects); } static void DeleteFolder (ProjectFolder folder) @@ -289,7 +299,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad [AllowMultiSelection] public void IncludeToProject () { - Set<SolutionEntityItem> projects = new Set<SolutionEntityItem> (); + Set<SolutionItem> projects = new Set<SolutionItem> (); foreach (ITreeNavigator node in CurrentNodes) { Project project = node.GetParentDataItem (typeof(Project), true) as Project; if (node.HasChildren ()) { @@ -309,7 +319,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } } } - IdeApp.ProjectOperations.Save (projects); + IdeApp.ProjectOperations.SaveAsync (projects); } [CommandUpdateHandler (ProjectCommands.IncludeToProject)] diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs index db967f8f2d..b598ed4865 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs @@ -39,6 +39,7 @@ using MonoDevelop.Components.Commands; using MonoDevelop.Ide.Gui.Components; using MonoDevelop.Ide.Gui.Dialogs; using System.Linq; +using MonoDevelop.Ide.Tasks; namespace MonoDevelop.Ide.Gui.Pads.ProjectPad { @@ -114,27 +115,30 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad Project p = dataObject as Project; string escapedProjectName = GLib.Markup.EscapeText (p.Name); - string iconName; - + if (p is DotNetProject && ((DotNetProject)p).LanguageBinding == null) { - iconName = Gtk.Stock.DialogError; - nodeInfo.Label = GettextCatalog.GetString ("{0} <span foreground='red' size='small'>(Unknown language '{1}')</span>", escapedProjectName, ((DotNetProject)p).LanguageName); + nodeInfo.Icon = Context.GetIcon (Stock.Project); + nodeInfo.Label = escapedProjectName; + nodeInfo.StatusSeverity = TaskSeverity.Error; + nodeInfo.StatusMessage = GettextCatalog.GetString ("Unknown language '{0}'", ((DotNetProject)p).LanguageName); + nodeInfo.DisabledStyle = true; + return; } else if (p is UnknownProject) { var up = (UnknownProject)p; - nodeInfo.OverlayBottomLeft = ImageService.GetIcon (Stock.Warning).WithSize (10, 10); - nodeInfo.Label = "<span foreground='gray'>" + escapedProjectName + " <small>(" + GLib.Markup.EscapeText (up.LoadError.TrimEnd ('.')) + ")</small></span>"; - nodeInfo.Icon = Context.GetIcon (p.StockIcon).WithAlpha (0.5); + nodeInfo.StatusSeverity = TaskSeverity.Warning; + nodeInfo.StatusMessage = up.UnsupportedProjectMessage.TrimEnd ('.'); + nodeInfo.Label = escapedProjectName; + nodeInfo.DisabledStyle = true; + nodeInfo.Icon = Context.GetIcon (p.StockIcon); return; - } else { - iconName = p.StockIcon; - if (p.ParentSolution != null && p.ParentSolution.SingleStartup && p.ParentSolution.StartupItem == p) - nodeInfo.Label = "<b>" + escapedProjectName + "</b>"; - else - nodeInfo.Label = escapedProjectName; } - - nodeInfo.Icon = Context.GetIcon (iconName); - + + nodeInfo.Icon = Context.GetIcon (p.StockIcon); + if (p.ParentSolution != null && p.ParentSolution.SingleStartup && p.ParentSolution.StartupItem == p) + nodeInfo.Label = "<b>" + escapedProjectName + "</b>"; + else + nodeInfo.Label = escapedProjectName; + // Gray out the project name if it is not selected in the current build configuration SolutionConfiguration conf = p.ParentSolution.GetConfiguration (IdeApp.Workspace.ActiveConfiguration); @@ -142,13 +146,14 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad bool noMapping = conf == null || (ce = conf.GetEntryForItem (p)) == null; bool missingConfig = false; if (p.SupportsBuild () && (noMapping || !ce.Build || (missingConfig = p.Configurations [ce.ItemConfiguration] == null))) { - var ticon = Context.GetComposedIcon (nodeInfo.Icon, "project-no-build"); - if (ticon == null) - ticon = Context.CacheComposedIcon (nodeInfo.Icon, "project-no-build", nodeInfo.Icon.WithAlpha (0.5)); - nodeInfo.Icon = ticon; - nodeInfo.Label = missingConfig - ? "<span foreground='red'>" + nodeInfo.Label + " <small>(invalid configuration mapping)</small></span>" - : "<span foreground='gray'>" + nodeInfo.Label + " <small>(not built in active configuration)</small></span>"; + nodeInfo.DisabledStyle = true; + if (missingConfig) { + nodeInfo.StatusSeverity = TaskSeverity.Error; + nodeInfo.StatusMessage = GettextCatalog.GetString ("Invalid configuration mapping"); + } else { + nodeInfo.StatusSeverity = TaskSeverity.Information; + nodeInfo.StatusMessage = GettextCatalog.GetString ("Project not built in active configuration"); + } } } @@ -169,7 +174,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public override object GetParentObject (object dataObject) { - SolutionItem it = (SolutionItem) dataObject; + SolutionFolderItem it = (SolutionFolderItem) dataObject; if (it.ParentFolder == null) return null; @@ -374,12 +379,12 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } [CommandHandler (ProjectCommands.SetAsStartupProject)] - public void SetAsStartupProject () + public async void SetAsStartupProject () { Project project = CurrentNode.DataItem as Project; project.ParentSolution.SingleStartup = true; project.ParentSolution.StartupItem = project; - IdeApp.ProjectOperations.Save (project.ParentSolution); + await IdeApp.ProjectOperations.SaveAsync (project.ParentSolution); } public override void DeleteItem () @@ -389,11 +394,11 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } [CommandHandler (ProjectCommands.AddReference)] - public void AddReferenceToProject () + public async void AddReferenceToProject () { DotNetProject p = (DotNetProject) CurrentNode.DataItem; if (IdeApp.ProjectOperations.AddReferenceToProject (p)) - IdeApp.ProjectOperations.Save (p); + await IdeApp.ProjectOperations.SaveAsync (p); } [CommandUpdateHandler (ProjectCommands.AddReference)] @@ -406,7 +411,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad [AllowMultiSelection] public void OnReload () { - using (IProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { + using (ProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { m.BeginTask (null, CurrentNodes.Length); foreach (ITreeNavigator nav in CurrentNodes) { Project p = (Project) nav.DataItem; @@ -431,21 +436,21 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad [CommandHandler (ProjectCommands.Unload)] [AllowMultiSelection] - public void OnUnload () + public async void OnUnload () { HashSet<Solution> solutions = new HashSet<Solution> (); - using (IProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { + using (ProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { m.BeginTask (null, CurrentNodes.Length); foreach (ITreeNavigator nav in CurrentNodes) { Project p = (Project) nav.DataItem; p.Enabled = false; - p.ParentFolder.ReloadItem (m, p); + await p.ParentFolder.ReloadItem (m, p); m.Step (1); solutions.Add (p.ParentSolution); } m.EndTask (); } - IdeApp.ProjectOperations.Save (solutions); + await IdeApp.ProjectOperations.SaveAsync (solutions); } [CommandUpdateHandler (ProjectCommands.Unload)] diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectReferenceFolderNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectReferenceFolderNodeBuilder.cs index 178ce4413c..fc5373e319 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectReferenceFolderNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectReferenceFolderNodeBuilder.cs @@ -85,15 +85,18 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad ctx.AddChild (pref); // For portable libraries, add node that represents all framework assemblies - var project = ctx.GetParentDataItem (typeof(DotNetProject), false) as PortableDotNetProject; - if (project != null) + var project = (DotNetProject) ctx.GetParentDataItem (typeof(DotNetProject), false); + if (project != null && project.IsPortableLibrary) ctx.AddChild (new PortableFrameworkSubset (project)); } public override bool HasChildNodes (ITreeBuilder builder, object dataObject) { - return ((ProjectReferenceCollection) dataObject).Count > 0 - || builder.GetParentDataItem (typeof(DotNetProject), false) is PortableDotNetProject; + if (((ProjectReferenceCollection) dataObject).Count > 0) + return true; + + var p = (DotNetProject) builder.GetParentDataItem (typeof(DotNetProject), false); + return p != null && p.IsPortableLibrary; } public override int CompareObjects (ITreeNavigator thisNode, ITreeNavigator otherNode) @@ -129,7 +132,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad return dataObject is ProjectReference || dataObject is Project; } - public override void OnNodeDrop (object dataObject, DragOperation operation) + public async override void OnNodeDrop (object dataObject, DragOperation operation) { // It allows dropping either project references or projects. // Dropping a project creates a new project reference to that project @@ -146,7 +149,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad if (ProjectReferencesProject (p, project.Name)) return; p.References.Add (pr); - IdeApp.ProjectOperations.Save (p); + await IdeApp.ProjectOperations.SaveAsync (p); return; } @@ -175,8 +178,8 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } p2.References.Add (pref); - IdeApp.ProjectOperations.Save (p); - IdeApp.ProjectOperations.Save (p2); + await IdeApp.ProjectOperations.SaveAsync (p); + await IdeApp.ProjectOperations.SaveAsync (p2); } else { nav.MoveToParent (typeof(DotNetProject)); DotNetProject p = nav.DataItem as DotNetProject; @@ -194,7 +197,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad return; } p.References.Add ((ProjectReference) pref.Clone ()); - IdeApp.ProjectOperations.Save (p); + await IdeApp.ProjectOperations.SaveAsync (p); } } @@ -204,12 +207,12 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } [CommandHandler (ProjectCommands.AddReference)] - public void AddReferenceToProject () + public async void AddReferenceToProject () { DotNetProject p = (DotNetProject) CurrentNode.GetParentDataItem (typeof(DotNetProject), false); if (IdeApp.ProjectOperations.AddReferenceToProject (p)) { - IdeApp.ProjectOperations.Save (p); CurrentNode.Expanded = true; + await IdeApp.ProjectOperations.SaveAsync (p); } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectReferenceNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectReferenceNodeBuilder.cs index c86ce21f73..9a4ab8fb22 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectReferenceNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectReferenceNodeBuilder.cs @@ -37,6 +37,7 @@ using MonoDevelop.Ide.Commands; using MonoDevelop.Ide.Gui; using MonoDevelop.Components.Commands; using MonoDevelop.Ide.Gui.Components; +using MonoDevelop.Ide.Tasks; namespace MonoDevelop.Ide.Gui.Pads.ProjectPad { @@ -90,24 +91,12 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad nodeInfo.Label = GLib.Markup.EscapeText (nodeInfo.Label); if (!pref.IsValid) { - nodeInfo.Label = "<span color='red'>" + nodeInfo.Label + "</span>"; - nodeInfo.Icon = Context.GetIcon ("md-reference-warning"); + nodeInfo.StatusSeverity = TaskSeverity.Error; + nodeInfo.DisabledStyle = true; + nodeInfo.StatusMessage = pref.ValidationErrorMessage; } } - public override bool HasChildNodes (MonoDevelop.Ide.Gui.Components.ITreeBuilder builder, object dataObject) - { - ProjectReference pref = (ProjectReference) dataObject; - return !pref.IsValid; - } - - public override void BuildChildNodes (MonoDevelop.Ide.Gui.Components.ITreeBuilder treeBuilder, object dataObject) - { - ProjectReference pref = (ProjectReference) dataObject; - if (!pref.IsValid) - treeBuilder.AddChild (new TreeViewItem (pref.ValidationErrorMessage, Stock.Warning)); - } - public override void OnNodeAdded (object dataObject) { ProjectReference pref = (ProjectReference) dataObject; @@ -141,7 +130,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } } - public override void DeleteMultipleItems () + public async override void DeleteMultipleItems () { Dictionary<Project,Project> projects = new Dictionary<Project,Project> (); foreach (ITreeNavigator nav in CurrentNodes) { @@ -151,12 +140,12 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad projects [project] = project; } foreach (Project p in projects.Values) - IdeApp.ProjectOperations.Save (p); + await IdeApp.ProjectOperations.SaveAsync (p); } [CommandHandler (ProjectCommands.LocalCopyReference)] [AllowMultiSelection] - public void ChangeLocalReference () + public async void ChangeLocalReference () { var projects = new Dictionary<Project,Project> (); ProjectReference firstRef = null; @@ -173,7 +162,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad projects [project] = project; } foreach (Project p in projects.Values) - IdeApp.ProjectOperations.Save (p); + await IdeApp.ProjectOperations.SaveAsync (p); } [CommandUpdateHandler (ProjectCommands.LocalCopyReference)] @@ -195,7 +184,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad [CommandHandler (ProjectCommands.SpecificAssemblyVersion)] [AllowMultiSelection] - public void RequireSpecificAssemblyVersion () + public async void RequireSpecificAssemblyVersion () { var projects = new Dictionary<Project,Project> (); ProjectReference firstRef = null; @@ -212,7 +201,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad projects [project] = project; } foreach (Project p in projects.Values) - IdeApp.ProjectOperations.Save (p); + await IdeApp.ProjectOperations.SaveAsync (p); } [CommandUpdateHandler (ProjectCommands.SpecificAssemblyVersion)] diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectSolutionPad.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectSolutionPad.cs index cb8a60c75c..40c3f4753d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectSolutionPad.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectSolutionPad.cs @@ -66,7 +66,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad if (nav != null) { WorkspaceItem c = (WorkspaceItem) nav.GetParentDataItem (typeof(WorkspaceItem), true); IdeApp.ProjectOperations.CurrentSelectedWorkspaceItem = c; - SolutionItem ce = (SolutionItem) nav.GetParentDataItem (typeof(SolutionItem), true); + SolutionFolderItem ce = (SolutionFolderItem) nav.GetParentDataItem (typeof(SolutionFolderItem), true); IdeApp.ProjectOperations.CurrentSelectedSolutionItem = ce; IdeApp.ProjectOperations.CurrentSelectedItem = nav.DataItem; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ShowAllFilesBuilderExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ShowAllFilesBuilderExtension.cs index 0d9fe017ed..d7c3758ea4 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ShowAllFilesBuilderExtension.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ShowAllFilesBuilderExtension.cs @@ -357,7 +357,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad if (targetPath == source) targetPath = ProjectOperations.GetTargetCopyName (targetPath, false); - using (IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor (GettextCatalog.GetString("Copying files..."), Stock.StatusWorking, true)) + using (ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor (GettextCatalog.GetString("Copying files..."), Stock.StatusWorking, true)) { bool move = operation == DragOperation.Move; IdeApp.ProjectOperations.TransferFiles (monitor, null, source, targetProject, targetPath, move, false); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionFolderFileNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionFolderFileNodeBuilder.cs index a324c03715..497cd3a870 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionFolderFileNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionFolderFileNodeBuilder.cs @@ -113,7 +113,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } } - IdeApp.ProjectOperations.Save (modifiedSolutionsToSave); + IdeApp.ProjectOperations.SaveAsync (modifiedSolutionsToSave); } public override void ActivateItem () diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionFolderNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionFolderNodeBuilder.cs index 21aba0b470..27946ee746 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionFolderNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionFolderNodeBuilder.cs @@ -83,7 +83,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public override void BuildChildNodes (ITreeBuilder ctx, object dataObject) { SolutionFolder folder = (SolutionFolder) dataObject; - foreach (SolutionItem entry in folder.Items) + foreach (SolutionFolderItem entry in folder.Items) ctx.AddChild (entry); foreach (FilePath file in folder.Files) ctx.AddChild (new SolutionFolderFileNode (file, folder)); @@ -178,7 +178,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad CurrentNode.Expanded = !CurrentNode.Expanded; } - public override void RenameItem (string newName) + public async override void RenameItem (string newName) { if (newName.IndexOfAny (new char [] { '\'', '(', ')', '"', '{', '}', '|' } ) != -1) { MessageService.ShowError (GettextCatalog.GetString ("Solution name may not contain any of the following characters: {0}", "', (, ), \", {, }, |")); @@ -187,7 +187,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad SolutionFolder folder = (SolutionFolder) CurrentNode.DataItem; folder.Name = newName; - IdeApp.Workspace.Save(); + await IdeApp.Workspace.SaveAsync(); } public override DragOperation CanDragNode () @@ -199,15 +199,15 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad { if (dataObject is IFileItem) return true; - SolutionItem it = dataObject as SolutionItem; + SolutionFolderItem it = dataObject as SolutionFolderItem; return it != null && operation == DragOperation.Move; } - public override void OnNodeDrop (object dataObject, DragOperation operation) + public async override void OnNodeDrop (object dataObject, DragOperation operation) { SolutionFolder folder = (SolutionFolder) CurrentNode.DataItem; - if (dataObject is SolutionItem) { - SolutionItem it = (SolutionItem) dataObject; + if (dataObject is SolutionFolderItem) { + SolutionFolderItem it = (SolutionFolderItem) dataObject; if (!MessageService.Confirm (GettextCatalog.GetString ("Are you sure you want to move the item '{0}' to the solution folder '{1}'?", it.Name, folder.Name), AlertButton.Move)) return; @@ -218,7 +218,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad DropFile (folder, (IFileItem) dataObject, operation); } - IdeApp.ProjectOperations.Save (folder.ParentSolution); + await IdeApp.ProjectOperations.SaveAsync (folder.ParentSolution); } internal static void DropFile (SolutionFolder folder, IFileItem fileItem, DragOperation operation) @@ -250,7 +250,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad IdeApp.ProjectOperations.ShowOptions (folder); } - public override void DeleteItem () + public async override void DeleteItem () { SolutionFolder folder = CurrentNode.DataItem as SolutionFolder; SolutionFolder parent = folder.ParentFolder; @@ -261,7 +261,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad Solution sol = folder.ParentSolution; parent.Items.Remove (folder); folder.Dispose (); - IdeApp.ProjectOperations.Save (sol); + await IdeApp.ProjectOperations.SaveAsync (sol); } } @@ -269,7 +269,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public void AddNewProjectToSolutionFolder() { SolutionFolder folder = (SolutionFolder) CurrentNode.DataItem; - SolutionItem ce = IdeApp.ProjectOperations.CreateProject (folder); + SolutionFolderItem ce = IdeApp.ProjectOperations.CreateProject (folder); if (ce == null) return; Tree.AddNodeInsertCallback (ce, new TreeNodeCallback (OnEntryInserted)); CurrentNode.Expanded = true; @@ -279,10 +279,11 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public void AddProjectToSolutionFolder() { SolutionFolder folder = (SolutionFolder) CurrentNode.DataItem; - SolutionItem ce = IdeApp.ProjectOperations.AddSolutionItem (folder); - if (ce == null) return; - Tree.AddNodeInsertCallback (ce, new TreeNodeCallback (OnEntryInserted)); - CurrentNode.Expanded = true; + IdeApp.ProjectOperations.AddSolutionItem (folder).ContinueWith (t => { + if (t.Result == null) return; + Tree.AddNodeInsertCallback (t.Result, new TreeNodeCallback (OnEntryInserted)); + CurrentNode.Expanded = true; + }); } [CommandHandler (ProjectCommands.AddSolutionFolder)] @@ -300,7 +301,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad [AllowMultiSelection] public void OnReload () { - using (IProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { + using (ProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { m.BeginTask (null, CurrentNodes.Length); foreach (ITreeNavigator node in CurrentNodes) { SolutionFolder folder = (SolutionFolder) node.DataItem; @@ -334,12 +335,12 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad }*/ [CommandHandler (ProjectCommands.AddFiles)] - protected void OnAddFiles () + protected async void OnAddFiles () { SolutionFolder folder = (SolutionFolder) CurrentNode.DataItem; if (IdeApp.ProjectOperations.AddFilesToSolutionFolder (folder)) { CurrentNode.Expanded = true; - IdeApp.ProjectOperations.Save (folder.ParentSolution); + await IdeApp.ProjectOperations.SaveAsync (folder.ParentSolution); } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionNodeBuilder.cs index c144c2f2ac..a9f3447e79 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionNodeBuilder.cs @@ -101,7 +101,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public override void BuildChildNodes (ITreeBuilder ctx, object dataObject) { Solution solution = (Solution) dataObject; - foreach (SolutionItem entry in solution.RootFolder.Items) + foreach (SolutionFolderItem entry in solution.RootFolder.Items) ctx.AddChild (entry); foreach (FilePath file in solution.RootFolder.Files) ctx.AddChild (new SolutionFolderFileNode (file, solution.RootFolder)); @@ -142,7 +142,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad void OnStartupChanged (object sender, EventArgs args) { - foreach (SolutionEntityItem it in IdeApp.Workspace.GetAllSolutionItems<SolutionEntityItem> ()) { + foreach (SolutionItem it in IdeApp.Workspace.GetAllSolutionItems ()) { ITreeBuilder tb = Context.GetTreeBuilder (it); if (tb != null) tb.Update (); @@ -212,14 +212,14 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public override bool CanDropNode (object dataObject, DragOperation operation) { - return (dataObject is SolutionItem) || (dataObject is IFileItem); + return (dataObject is SolutionFolderItem) || (dataObject is IFileItem); } public override void OnNodeDrop (object dataObject, DragOperation operation) { Solution sol = CurrentNode.DataItem as Solution; - if (dataObject is SolutionItem) { - SolutionItem it = (SolutionItem) dataObject; + if (dataObject is SolutionFolderItem) { + SolutionFolderItem it = (SolutionFolderItem) dataObject; if (!MessageService.Confirm (GettextCatalog.GetString ("Are you sure you want to move the item '{0}' to the root node of the solution?", it.Name), AlertButton.Move)) return; @@ -229,7 +229,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad else { SolutionFolderNodeCommandHandler.DropFile (sol.DefaultSolutionFolder, (IFileItem) dataObject, operation); } - IdeApp.ProjectOperations.Save (sol); + IdeApp.ProjectOperations.SaveAsync (sol); } public override void ActivateMultipleItems () @@ -254,7 +254,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } } } - IdeApp.ProjectOperations.Save (items); + IdeApp.ProjectOperations.SaveAsync (items); } public override bool CanDeleteItem () @@ -267,7 +267,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public void AddNewProjectToSolution () { Solution solution = (Solution) CurrentNode.DataItem; - SolutionItem ce = IdeApp.ProjectOperations.CreateProject (solution.RootFolder); + SolutionFolderItem ce = IdeApp.ProjectOperations.CreateProject (solution.RootFolder); if (ce == null) return; Tree.AddNodeInsertCallback (ce, new TreeNodeCallback (OnEntryInserted)); CurrentNode.Expanded = true; @@ -277,17 +277,18 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public void AddProjectToCombine() { Solution solution = (Solution) CurrentNode.DataItem; - SolutionItem ce = IdeApp.ProjectOperations.AddSolutionItem (solution.RootFolder); - if (ce == null) return; - Tree.AddNodeInsertCallback (ce, new TreeNodeCallback (OnEntryInserted)); - CurrentNode.Expanded = true; + IdeApp.ProjectOperations.AddSolutionItem (solution.RootFolder).ContinueWith (t => { + if (t.Result == null) return; + Tree.AddNodeInsertCallback (t.Result, new TreeNodeCallback (OnEntryInserted)); + CurrentNode.Expanded = true; + }).RunSynchronously (); } [CommandHandler (ProjectCommands.AddSolutionFolder)] public void AddFolder() { Solution solution = (Solution) CurrentNode.DataItem; - SolutionItem ce = new SolutionFolder (); + var ce = new SolutionFolder (); ce.Name = GettextCatalog.GetString ("New Folder"); solution.RootFolder.Items.Add (ce); Tree.AddNodeInsertCallback (ce, OnFolderInserted); @@ -298,7 +299,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad [AllowMultiSelection] public void OnReload () { - using (IProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { + using (ProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { m.BeginTask (null, CurrentNodes.Length); foreach (ITreeNavigator node in CurrentNodes) { Solution solution = (Solution) node.DataItem; @@ -350,7 +351,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad { Solution sol = (Solution) CurrentNode.DataItem; if (IdeApp.ProjectOperations.AddFilesToSolutionFolder (sol.RootFolder)) - IdeApp.ProjectOperations.Save (sol); + IdeApp.ProjectOperations.SaveAsync (sol); } void OnEntryInserted (ITreeNavigator nav) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SystemFile.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SystemFile.cs index b604e9d7b9..7291a032fc 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SystemFile.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SystemFile.cs @@ -37,14 +37,14 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public class SystemFile: IFileItem {
FilePath absolutePath; - IWorkspaceObject parent; + WorkspaceObject parent; bool showTransparent; - public SystemFile (FilePath absolutePath, IWorkspaceObject parent): this (absolutePath, parent, true) + public SystemFile (FilePath absolutePath, WorkspaceObject parent): this (absolutePath, parent, true) { }
- public SystemFile (FilePath absolutePath, IWorkspaceObject parent, bool showTransparent) + public SystemFile (FilePath absolutePath, WorkspaceObject parent, bool showTransparent) { this.parent = parent; this.absolutePath = absolutePath; @@ -63,7 +63,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad get { return System.IO.Path.GetFileName (absolutePath); } } - public IWorkspaceObject ParentWorkspaceObject { + public WorkspaceObject ParentWorkspaceObject { get { return parent; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SystemFileNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SystemFileNodeBuilder.cs index f54b033a61..71551dd481 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SystemFileNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SystemFileNodeBuilder.cs @@ -149,8 +149,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad [AllowMultiSelection] public void IncludeFileToProject () { - Set<SolutionEntityItem> projects = new Set<SolutionEntityItem> (); - Set<Solution> solutions = new Set<Solution> (); + Set<IWorkspaceFileObject> projects = new Set<IWorkspaceFileObject> (); var nodesByProject = CurrentNodes.GroupBy (n => n.GetParentDataItem (typeof(Project), true) as Project); foreach (var projectGroup in nodesByProject) { @@ -166,21 +165,19 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad SolutionFolder folder = node.GetParentDataItem (typeof(SolutionFolder), true) as SolutionFolder; if (folder != null) { folder.Files.Add (file.Path); - solutions.Add (folder.ParentSolution); + projects.Add (folder.ParentSolution); } else { Solution sol = node.GetParentDataItem (typeof(Solution), true) as Solution; sol.RootFolder.Files.Add (file.Path); - solutions.Add (sol); + projects.Add (sol); } } } if (newFiles.Count > 0) project.AddFiles (newFiles); } - IdeApp.ProjectOperations.Save (projects); - foreach (Solution sol in solutions) - IdeApp.ProjectOperations.Save (sol); + IdeApp.ProjectOperations.SaveAsync (projects); } [CommandUpdateHandler (ProjectCommands.IncludeToProject)] diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/UnknownEntryNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/UnknownEntryNodeBuilder.cs index 5efe1b58e6..d831511d57 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/UnknownEntryNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/UnknownEntryNodeBuilder.cs @@ -36,6 +36,7 @@ using MonoDevelop.Ide.Commands; using MonoDevelop.Ide.Gui.Components; using System.Linq; using System.Collections.Generic; +using MonoDevelop.Ide.Tasks; namespace MonoDevelop.Ide.Gui.Pads.ProjectPad { @@ -64,8 +65,10 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad nodeInfo.Label = GettextCatalog.GetString ("<span foreground='grey'>{0} <span size='small'>(Unavailable)</span></span>", GLib.Markup.EscapeText (entry.Name)); } else if (entry.LoadError.Length > 0) { - nodeInfo.Icon = Context.GetIcon (Gtk.Stock.DialogError); - nodeInfo.Label = GettextCatalog.GetString ("{0} <span foreground='red' size='small'>(Load failed)</span>", GLib.Markup.EscapeText (entry.Name)); + nodeInfo.Icon = Context.GetIcon (MonoDevelop.Ide.Gui.Stock.Project).WithAlpha (0.5); + nodeInfo.Label = entry.Name; + nodeInfo.StatusSeverity = TaskSeverity.Error; + nodeInfo.StatusMessage = GettextCatalog.GetString ("Load failed: ") + entry.LoadError; } else { nodeInfo.Icon = Context.GetIcon (MonoDevelop.Ide.Gui.Stock.Project); var gicon = Context.GetComposedIcon (nodeInfo.Icon, "fade"); @@ -77,19 +80,6 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad nodeInfo.Label = GLib.Markup.EscapeText (entry.Name); } } - - public override bool HasChildNodes (ITreeBuilder builder, object dataObject) - { - UnknownSolutionItem entry = (UnknownSolutionItem) dataObject; - return !(entry is UnloadedSolutionItem) && entry.LoadError.Length > 0; - } - - public override void BuildChildNodes (ITreeBuilder treeBuilder, object dataObject) - { - UnknownSolutionItem entry = (UnknownSolutionItem) dataObject; - if (!(entry is UnloadedSolutionItem) && entry.LoadError.Length > 0) - treeBuilder.AddChild (new TreeViewItem (GLib.Markup.EscapeText (entry.LoadError))); - } public override string GetNodeName (ITreeNavigator thisNode, object dataObject) { @@ -104,7 +94,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public void OnReload () { var solutions = new HashSet<Solution> (); - using (IProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { + using (ProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { m.BeginTask (null, CurrentNodes.Length); foreach (ITreeNavigator node in CurrentNodes) { UnknownSolutionItem entry = (UnknownSolutionItem) node.DataItem; @@ -117,7 +107,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } m.EndTask (); } - IdeApp.ProjectOperations.Save (solutions); + IdeApp.ProjectOperations.SaveAsync (solutions); } [CommandUpdateHandler (ProjectCommands.Reload)] @@ -137,7 +127,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public void OnUnload () { HashSet<Solution> solutions = new HashSet<Solution> (); - using (IProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { + using (ProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { m.BeginTask (null, CurrentNodes.Length); foreach (ITreeNavigator nav in CurrentNodes) { UnknownSolutionItem p = (UnknownSolutionItem) nav.DataItem; @@ -148,7 +138,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad } m.EndTask (); } - IdeApp.ProjectOperations.Save (solutions); + IdeApp.ProjectOperations.SaveAsync (solutions); } [CommandUpdateHandler (ProjectCommands.Unload)] @@ -184,7 +174,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad if (yes) { cmb.Items.Remove (item); item.Dispose (); - IdeApp.ProjectOperations.Save (cmb.ParentSolution); + IdeApp.ProjectOperations.SaveAsync (cmb.ParentSolution); } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/WorkspaceNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/WorkspaceNodeBuilder.cs index 21292f6530..3c32d5b5cc 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/WorkspaceNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/WorkspaceNodeBuilder.cs @@ -182,7 +182,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad toSave.Add (ws); } } - IdeApp.ProjectOperations.Save (toSave); + IdeApp.ProjectOperations.SaveAsync (toSave); } public override void ActivateItem () @@ -205,7 +205,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad ws.Dispose (); } } - IdeApp.Workspace.Save(); + IdeApp.Workspace.SaveAsync (); } [CommandUpdateHandler (EditCommands.Delete)] @@ -225,37 +225,42 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public void AddNewSolutionToWorkspace () { Workspace ws = (Workspace) CurrentNode.DataItem; - WorkspaceItem ce = IdeApp.ProjectOperations.AddNewWorkspaceItem (ws); - if (ce == null) return; - Tree.AddNodeInsertCallback (ce, new TreeNodeCallback (OnEntryInserted)); - CurrentNode.Expanded = true; + IdeApp.ProjectOperations.AddNewWorkspaceItem (ws).ContinueWith (t => { + if (t.Result == null) + return; + Tree.AddNodeInsertCallback (t.Result, new TreeNodeCallback (OnEntryInserted)); + CurrentNode.Expanded = true; + }); } [CommandHandler (ProjectCommands.AddNewWorkspace)] public void AddNewWorkspaceToWorkspace () { Workspace ws = (Workspace) CurrentNode.DataItem; - WorkspaceItem ce = IdeApp.ProjectOperations.AddNewWorkspaceItem (ws, "MonoDevelop.Workspace"); - if (ce == null) return; - Tree.AddNodeInsertCallback (ce, new TreeNodeCallback (OnEntryInserted)); - CurrentNode.Expanded = true; + IdeApp.ProjectOperations.AddNewWorkspaceItem (ws, "MonoDevelop.Workspace").ContinueWith (t => { + if (t.Result == null) return; + Tree.AddNodeInsertCallback (t.Result, new TreeNodeCallback (OnEntryInserted)); + CurrentNode.Expanded = true; + }); } [CommandHandler (ProjectCommands.AddItem)] public void AddProjectToCombine() { Workspace ws = (Workspace) CurrentNode.DataItem; - WorkspaceItem ce = IdeApp.ProjectOperations.AddWorkspaceItem (ws); - if (ce == null) return; - Tree.AddNodeInsertCallback (ce, new TreeNodeCallback (OnEntryInserted)); - CurrentNode.Expanded = true; + IdeApp.ProjectOperations.AddWorkspaceItem (ws).ContinueWith (t => { + if (t.Result == null) + return; + Tree.AddNodeInsertCallback (t.Result, new TreeNodeCallback (OnEntryInserted)); + CurrentNode.Expanded = true; + }); } [CommandHandler (ProjectCommands.Reload)] [AllowMultiSelection] public void OnReload () { - using (IProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { + using (ProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { m.BeginTask (null, CurrentNodes.Length); foreach (ITreeNavigator node in CurrentNodes) { Workspace ws = (Workspace) node.DataItem; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/DefaultMonitorPad.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/DefaultMonitorPad.cs index e830428697..ae6609f565 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/DefaultMonitorPad.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/DefaultMonitorPad.cs @@ -51,7 +51,6 @@ namespace MonoDevelop.Ide.Gui.Pads ToggleButton buttonPin; Button buttonClear; bool progressStarted; - IAsyncOperation asyncOperation; LogViewProgressMonitor monitor; Pad statusSourcePad; @@ -114,7 +113,7 @@ namespace MonoDevelop.Ide.Gui.Pads set { this.statusSourcePad = value; } } - internal IProgressMonitor CurrentMonitor { + internal ProgressMonitor CurrentMonitor { get { return monitor; } } @@ -125,7 +124,7 @@ namespace MonoDevelop.Ide.Gui.Pads void OnButtonStopClick (object sender, EventArgs e) { - asyncOperation.Cancel (); + monitor.Cancel (); } void OnCombineOpen (object sender, EventArgs e) @@ -150,14 +149,13 @@ namespace MonoDevelop.Ide.Gui.Pads get { return !progressStarted && !buttonPin.Active; } } - public IProgressMonitor BeginProgress (string title) + public ProgressMonitor BeginProgress (string title) { progressStarted = true; logView.Clear (); monitor = logView.GetProgressMonitor (); - asyncOperation = monitor.AsyncOperation; - + DispatchService.GuiDispatch (delegate { window.HasNewData = false; window.HasErrors = false; @@ -165,7 +163,7 @@ namespace MonoDevelop.Ide.Gui.Pads buttonStop.Sensitive = true; }); - monitor.AsyncOperation.Completed += delegate { + monitor.Completed += delegate { EndProgress (); }; @@ -177,7 +175,7 @@ namespace MonoDevelop.Ide.Gui.Pads DispatchService.GuiDispatch (delegate { if (window != null) { window.IsWorking = false; - if (!asyncOperation.Success) + if (monitor.Errors.Length > 0) window.HasErrors = true; else window.HasNewData = true; @@ -190,8 +188,8 @@ namespace MonoDevelop.Ide.Gui.Pads if (monitor.Errors.Length > 0) { IdeApp.Workbench.StatusBar.ShowMessage (Stock.Error, monitor.Errors [monitor.Errors.Length - 1].Message); IdeApp.Workbench.StatusBar.SetMessageSourcePad (statusSourcePad); - } else if (monitor.Messages.Length > 0) { - IdeApp.Workbench.StatusBar.ShowMessage (monitor.Messages [monitor.Messages.Length - 1]); + } else if (monitor.SuccessMessages.Length > 0) { + IdeApp.Workbench.StatusBar.ShowMessage (monitor.SuccessMessages [monitor.SuccessMessages.Length - 1]); IdeApp.Workbench.StatusBar.SetMessageSourcePad (statusSourcePad); } else if (monitor.Warnings.Length > 0) { IdeApp.Workbench.StatusBar.ShowMessage (Stock.Warning, monitor.Warnings [monitor.Warnings.Length - 1]); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs index b77c434f5c..346ae1731b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs @@ -168,7 +168,7 @@ namespace MonoDevelop.Ide.Gui.Pads store = new Gtk.ListStore (typeof (Xwt.Drawing.Image), // image - type typeof (bool), // read? - typeof (Task)); // read? -- use Pango weight + typeof (UserTask)); // read? -- use Pango weight TreeModelFilterVisibleFunc filterFunct = new TreeModelFilterVisibleFunc (FilterTaskTypes); filter = new TreeModelFilter (store, null); @@ -225,7 +225,7 @@ namespace MonoDevelop.Ide.Gui.Pads sw.SizeAllocated += HandleSwSizeAllocated; // Load existing tasks - foreach (Task t in TaskService.Errors) { + foreach (UserTask t in TaskService.Errors) { AddTask (t); } @@ -249,7 +249,7 @@ namespace MonoDevelop.Ide.Gui.Pads } } - public IProgressMonitor GetBuildProgressMonitor () + public ProgressMonitor GetBuildProgressMonitor () { if (control == null) CreateControl (); @@ -266,7 +266,7 @@ namespace MonoDevelop.Ide.Gui.Pads if (!view.Model.GetIterFirst (out it)) return; do { - Task t = (Task) view.Model.GetValue (it, DataColumns.Task); + UserTask t = (UserTask) view.Model.GetValue (it, DataColumns.Task); if (t == TaskService.Errors.CurrentLocationTask) { view.Selection.SelectIter (it); view.ScrollToCell (view.Model.GetPath (it), view.Columns[0], false, 0, 0); @@ -421,13 +421,13 @@ namespace MonoDevelop.Ide.Gui.Pads return menu; } - Task SelectedTask + UserTask SelectedTask { get { TreeModel model; TreeIter iter; if (view.Selection.GetSelected (out model, out iter)) - return model.GetValue (iter, DataColumns.Task) as Task; + return model.GetValue (iter, DataColumns.Task) as UserTask; return null; // no one selected } } @@ -440,7 +440,7 @@ namespace MonoDevelop.Ide.Gui.Pads void OnTaskCopied (object o, EventArgs args) { - Task task = SelectedTask; + UserTask task = SelectedTask; if (task != null) { StringBuilder text = new StringBuilder (); if (!string.IsNullOrEmpty (task.FileName)) { @@ -480,7 +480,7 @@ namespace MonoDevelop.Ide.Gui.Pads bool GetSelectedErrorReference (out string reference) { - Task task = SelectedTask; + UserTask task = SelectedTask; if (task != null && !String.IsNullOrEmpty (task.Code)) { reference = task.Code; return true; @@ -496,7 +496,7 @@ namespace MonoDevelop.Ide.Gui.Pads if (view.Selection.GetSelected (out model, out iter)) { iter = filter.ConvertIterToChildIter (sort.ConvertIterToChildIter (iter)); store.SetValue (iter, DataColumns.Read, true); - Task task = store.GetValue (iter, DataColumns.Task) as Task; + UserTask task = store.GetValue (iter, DataColumns.Task) as UserTask; if (task != null) { TaskService.ShowStatus (task); task.JumpToPosition (); @@ -552,7 +552,7 @@ namespace MonoDevelop.Ide.Gui.Pads static void ToggleDataFunc (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { Gtk.CellRendererToggle toggleRenderer = (Gtk.CellRendererToggle)cell; - Task task = model.GetValue (iter, DataColumns.Task) as Task; + UserTask task = model.GetValue (iter, DataColumns.Task) as UserTask; if (task == null) return; toggleRenderer.Active = task.Completed; @@ -561,7 +561,7 @@ namespace MonoDevelop.Ide.Gui.Pads static void LineDataFunc (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { Gtk.CellRendererText textRenderer = (Gtk.CellRendererText)cell; - Task task = model.GetValue (iter, DataColumns.Task) as Task; + UserTask task = model.GetValue (iter, DataColumns.Task) as UserTask; if (task == null) return; SetText (textRenderer, model, iter, task, task.Line != 0 ? task.Line.ToString () : ""); @@ -570,7 +570,7 @@ namespace MonoDevelop.Ide.Gui.Pads static void DescriptionDataFunc (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { Gtk.CellRendererText textRenderer = (Gtk.CellRendererText)cell; - Task task = model.GetValue (iter, DataColumns.Task) as Task; + UserTask task = model.GetValue (iter, DataColumns.Task) as UserTask; if (task == null) return; SetText (textRenderer, model, iter, task, task.Description); @@ -579,7 +579,7 @@ namespace MonoDevelop.Ide.Gui.Pads static void FileDataFunc (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { Gtk.CellRendererText textRenderer = (Gtk.CellRendererText)cell; - Task task = model.GetValue (iter, DataColumns.Task) as Task; + UserTask task = model.GetValue (iter, DataColumns.Task) as UserTask; if (task == null) return; @@ -595,7 +595,7 @@ namespace MonoDevelop.Ide.Gui.Pads SetText (textRenderer, model, iter, task, fileName); } - static string GetPath (Task task) + static string GetPath (UserTask task) { if (task.WorkspaceObject != null) return FileService.AbsoluteToRelativePath (task.WorkspaceObject.BaseDirectory, task.FileName); @@ -606,27 +606,27 @@ namespace MonoDevelop.Ide.Gui.Pads static void ProjectDataFunc (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { Gtk.CellRendererText textRenderer = (Gtk.CellRendererText)cell; - Task task = model.GetValue (iter, DataColumns.Task) as Task; + UserTask task = model.GetValue (iter, DataColumns.Task) as UserTask; if (task == null) return; SetText (textRenderer, model, iter, task, GetProject(task)); } - static string GetProject (Task task) + static string GetProject (UserTask task) { - return (task != null && task.WorkspaceObject is SolutionItem)? task.WorkspaceObject.Name: string.Empty; + return (task != null && task.WorkspaceObject is SolutionFolderItem)? task.WorkspaceObject.Name: string.Empty; } static void PathDataFunc (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { Gtk.CellRendererText textRenderer = (Gtk.CellRendererText)cell; - Task task = model.GetValue (iter, DataColumns.Task) as Task; + UserTask task = model.GetValue (iter, DataColumns.Task) as UserTask; if (task == null) return; SetText (textRenderer, model, iter, task, GetPath (task)); } - static void SetText (CellRendererText textRenderer, TreeModel model, TreeIter iter, Task task, string text) + static void SetText (CellRendererText textRenderer, TreeModel model, TreeIter iter, UserTask task, string text) { textRenderer.Text = text; textRenderer.Weight = (int)((bool)model.GetValue (iter, DataColumns.Read) ? Pango.Weight.Normal : Pango.Weight.Bold); @@ -669,7 +669,7 @@ namespace MonoDevelop.Ide.Gui.Pads bool canShow = false; try { - Task task = store.GetValue (iter, DataColumns.Task) as Task; + UserTask task = store.GetValue (iter, DataColumns.Task) as UserTask; if (task == null) return true; if (task.Severity == TaskSeverity.Error && errorBtn.Active) canShow = true; @@ -713,10 +713,10 @@ namespace MonoDevelop.Ide.Gui.Pads AddTasks (e.Tasks); } - public void AddTasks (IEnumerable<Task> tasks) + public void AddTasks (IEnumerable<UserTask> tasks) { int n = 1; - foreach (Task t in tasks) { + foreach (UserTask t in tasks) { AddTaskInternal (t); if ((n++ % 100) == 0) { // Adding many tasks is a bit slow, so refresh the @@ -727,13 +727,13 @@ namespace MonoDevelop.Ide.Gui.Pads filter.Refilter (); } - public void AddTask (Task t) + public void AddTask (UserTask t) { AddTaskInternal (t); filter.Refilter (); } - void AddTaskInternal (Task t) + void AddTaskInternal (UserTask t) { if (tasks.Contains (t)) return; @@ -795,7 +795,7 @@ namespace MonoDevelop.Ide.Gui.Pads { Gtk.TreeIter iter; if (store.GetIterFromString (out iter, args.Path)) { - Task task = (Task)store.GetValue (iter, DataColumns.Task); + UserTask task = (UserTask)store.GetValue (iter, DataColumns.Task); task.Completed = !task.Completed; TaskService.FireTaskToggleEvent (this, new TaskEventArgs (task)); } @@ -803,8 +803,8 @@ namespace MonoDevelop.Ide.Gui.Pads static int SeverityIterSort(TreeModel model, TreeIter a, TreeIter z) { - Task aTask = model.GetValue(a, DataColumns.Task) as Task, - zTask = model.GetValue(z, DataColumns.Task) as Task; + UserTask aTask = model.GetValue(a, DataColumns.Task) as UserTask, + zTask = model.GetValue(z, DataColumns.Task) as UserTask; return (aTask != null && zTask != null) ? aTask.Severity.CompareTo(zTask.Severity) : @@ -813,8 +813,8 @@ namespace MonoDevelop.Ide.Gui.Pads static int ProjectIterSort (TreeModel model, TreeIter a, TreeIter z) { - Task aTask = model.GetValue (a, DataColumns.Task) as Task, - zTask = model.GetValue (z, DataColumns.Task) as Task; + UserTask aTask = model.GetValue (a, DataColumns.Task) as UserTask, + zTask = model.GetValue (z, DataColumns.Task) as UserTask; return (aTask != null && zTask != null) ? GetProject (aTask).CompareTo (GetProject (zTask)) : @@ -823,8 +823,8 @@ namespace MonoDevelop.Ide.Gui.Pads static int FileIterSort (TreeModel model, TreeIter a, TreeIter z) { - Task aTask = model.GetValue (a, DataColumns.Task) as Task, - zTask = model.GetValue (z, DataColumns.Task) as Task; + UserTask aTask = model.GetValue (a, DataColumns.Task) as UserTask, + zTask = model.GetValue (z, DataColumns.Task) as UserTask; return (aTask != null && zTask != null) ? aTask.FileName.CompareTo (zTask.FileName) : diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/BackgroundProgressMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/BackgroundProgressMonitor.cs index 4fa2e70f60..25aac3297a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/BackgroundProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/BackgroundProgressMonitor.cs @@ -33,7 +33,7 @@ using Gtk; namespace MonoDevelop.Ide.Gui { - class BackgroundProgressMonitor: SimpleProgressMonitor + class BackgroundProgressMonitor: ProgressMonitor { string title; StatusBarIcon icon; @@ -56,10 +56,10 @@ namespace MonoDevelop.Ide.Gui if (icon == null) return; string tip; - if (Tracker.UnknownWork) - tip = string.Format ("{0}\n{1}", title, Tracker.CurrentTask); + if (ProgressIsUnknown) + tip = string.Format ("{0}\n{1}", title, CurrentTaskName); else - tip = string.Format ("{0} ({1}%)\n{2}", title, (int)(Tracker.GlobalWork * 100), Tracker.CurrentTask); + tip = string.Format ("{0} ({1}%)\n{2}", title, (int)(Progress * 100), CurrentTaskName); Application.Invoke (delegate { if (icon != null) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs index aaf11e4ef7..ede3dfd33b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs @@ -451,8 +451,6 @@ namespace MonoDevelop.Ide.Gui return; } - RegisterPad (content); - if (item != null) { if (show) item.Visible = true; @@ -1292,6 +1290,8 @@ namespace MonoDevelop.Ide.Gui void AddPad (PadCodon padCodon, string placement, DockItemStatus defaultStatus) { + RegisterPad (padCodon); + PadWindow window = new PadWindow (this, padCodon); window.Icon = padCodon.Icon; padWindows [padCodon] = window; @@ -1331,9 +1331,6 @@ namespace MonoDevelop.Ide.Gui else window.NotifyContentHidden (); }; - - if (!padContentCollection.Contains (padCodon)) - padContentCollection.Add (padCodon); } void UpdatePad (object source, EventArgs args) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DockItemToolbarLoader.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DockItemToolbarLoader.cs index 1efcf2e3c7..a8e41c92ed 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DockItemToolbarLoader.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DockItemToolbarLoader.cs @@ -75,7 +75,7 @@ namespace MonoDevelop.Ide.Gui { Widget w = CreateWidget (entry); if (w is Button) { - buttons.Add (new ToolButtonStatus (entry.CommandId, (Gtk.Button) w)); + buttons.Add (new ToolButtonStatus (entry.CommandId, (Gtk.Button)w, entry.DispayType)); ((Gtk.Button) w).Clicked += delegate { IdeApp.CommandService.DispatchCommand (entry.CommandId, null, initialTarget, CommandSource.MainToolbar); }; @@ -141,11 +141,16 @@ namespace MonoDevelop.Ide.Gui string stockId; Button button; object cmdId; + CommandEntryDisplayType displayType; - public ToolButtonStatus (object cmdId, Button button) + public ToolButtonStatus (object cmdId, Button button, CommandEntryDisplayType displayType = CommandEntryDisplayType.Default) { this.cmdId = cmdId; this.button = button; + if (displayType == CommandEntryDisplayType.Default)//Simplefies code in rest of class + this.displayType = CommandEntryDisplayType.IconHasPriority; + else + this.displayType = displayType; } public void Update (CommandTargetRoute targetRoute) @@ -155,10 +160,12 @@ namespace MonoDevelop.Ide.Gui bool hasAccel = string.IsNullOrEmpty (cmdInfo.AccelKey); bool hasIcon = !cmdInfo.Icon.IsNull; string desc = cmdInfo.Description; - + bool displayText = !(displayType == CommandEntryDisplayType.IconHasPriority && hasIcon) && + displayType != CommandEntryDisplayType.IconOnly; + //If the button only has an icon it's not always clear what it does. In such cases, use the label as a //fallback tooltip. Also do this if there's an accelerator, so the user can see what it is. - if (string.IsNullOrEmpty (desc) && (hasIcon || hasAccel)) + if (string.IsNullOrEmpty (desc) && (!displayText || hasAccel)) desc = cmdInfo.Text; if (lastDesc != desc) { @@ -172,10 +179,11 @@ namespace MonoDevelop.Ide.Gui lastDesc = desc; } - if (!hasIcon && button.Label != cmdInfo.Text) + if (displayText && button.Label != cmdInfo.Text) { button.Label = cmdInfo.Text; - - if (cmdInfo.Icon != stockId) { + } + + if (displayType != CommandEntryDisplayType.TextOnly && cmdInfo.Icon != stockId) { stockId = cmdInfo.Icon; button.Image = new Gtk.Image (cmdInfo.Icon, Gtk.IconSize.Menu); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs index b7e118ea1d..dd0f91da87 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs @@ -462,53 +462,6 @@ namespace MonoDevelop.Ide.Gui UpdateParseDocument (); } - public bool IsBuildTarget - { - get - { - if (this.IsViewOnly) - return false; - if (Window.ViewContent.ContentName != null) - return Services.ProjectService.CanCreateSingleFileProject(Window.ViewContent.ContentName); - - return false; - } - } - - public IAsyncOperation Build () - { - return IdeApp.ProjectOperations.BuildFile (Window.ViewContent.ContentName); - } - - public IAsyncOperation Rebuild () - { - return Build (); - } - - public void Clean () - { - } - - public IAsyncOperation Run () - { - return Run (Runtime.ProcessService.DefaultExecutionHandler); - } - - public IAsyncOperation Run (IExecutionHandler handler) - { - return IdeApp.ProjectOperations.ExecuteFile (Window.ViewContent.ContentName, handler); - } - - public bool CanRun () - { - return CanRun (Runtime.ProcessService.DefaultExecutionHandler); - } - - public bool CanRun (IExecutionHandler handler) - { - return IsBuildTarget && Window.ViewContent.ContentName != null && IdeApp.ProjectOperations.CanExecuteFile (Window.ViewContent.ContentName, handler); - } - public bool Close () { return ((SdiWorkspaceWindow)Window).CloseWindow (false, true); @@ -740,7 +693,7 @@ namespace MonoDevelop.Ide.Gui TypeSystemService.ProjectContentWrapper currentWrapper; internal void SetProject (Project project) { - if (Window.ViewContent.Project == project) + if (Window == null || Window.ViewContent == null || Window.ViewContent.Project == project) return; DetachExtensionChain (); ISupportsProjectReload pr = GetContent<ISupportsProjectReload> (); @@ -768,9 +721,7 @@ namespace MonoDevelop.Ide.Gui var wrapper = TypeSystemService.GetProjectContentWrapper (project); wrapper.Loaded += HandleInLoadChanged; currentWrapper = wrapper; - RunWhenLoaded (delegate { - currentWrapper.RequestLoad (); - }); + currentWrapper.RequestLoad (); } StartReparseThread (); } @@ -825,7 +776,7 @@ namespace MonoDevelop.Ide.Gui get { if (currentWrapper == null) return false; - return !currentWrapper.IsLoaded || !currentWrapper.ReferencesConnected; + return !currentWrapper.IsLoaded; } } @@ -845,42 +796,49 @@ namespace MonoDevelop.Ide.Gui } uint parseTimeout = 0; + object reparseLock = new object(); internal void StartReparseThread () { - // Don't directly parse the document because doing it at every key press is - // very inefficient. Do it after a small delay instead, so several changes can - // be parsed at the same time. - string currentParseFile = FileName; - if (string.IsNullOrEmpty (currentParseFile)) - return; - CancelParseTimeout (); - if (IsProjectContextInUpdate) - return; - parseTimeout = GLib.Timeout.Add (ParseDelay, delegate { - var editor = Editor; - if (editor == null || IsProjectContextInUpdate) { - parseTimeout = 0; - return false; + lock (reparseLock) { + if (currentWrapper != null) + currentWrapper.EnsureReferencesAreLoaded (); + + // Don't directly parse the document because doing it at every key press is + // very inefficient. Do it after a small delay instead, so several changes can + // be parsed at the same time. + string currentParseFile = FileName; + if (string.IsNullOrEmpty (currentParseFile)) + return; + CancelParseTimeout (); + if (IsProjectContextInUpdate) { + return; } - string currentParseText = editor.Text; - string mimeType = editor.Document.MimeType; - ThreadPool.QueueUserWorkItem (delegate { - if (IsProjectContextInUpdate) - return; - TypeSystemService.AddSkippedFile (currentParseFile); - var currentParsedDocument = TypeSystemService.ParseFile (Project, currentParseFile, mimeType, currentParseText); - Application.Invoke (delegate { - // this may be called after the document has closed, in that case the OnDocumentParsed event shouldn't be invoked. - if (isClosed) + parseTimeout = GLib.Timeout.Add (ParseDelay, delegate { + var editor = Editor; + if (editor == null || IsProjectContextInUpdate) { + parseTimeout = 0; + return false; + } + string currentParseText = editor.Text; + string mimeType = editor.Document.MimeType; + ThreadPool.QueueUserWorkItem (delegate { + if (IsProjectContextInUpdate) { return; - - this.parsedDocument = currentParsedDocument; - OnDocumentParsed (EventArgs.Empty); + } + TypeSystemService.AddSkippedFile (currentParseFile); + var currentParsedDocument = TypeSystemService.ParseFile (Project, currentParseFile, mimeType, currentParseText); + Application.Invoke (delegate { + // this may be called after the document has closed, in that case the OnDocumentParsed event shouldn't be invoked. + if (isClosed) + return; + this.parsedDocument = currentParsedDocument; + OnDocumentParsed (EventArgs.Empty); + }); }); + parseTimeout = 0; + return false; }); - parseTimeout = 0; - return false; - }); + } } /// <summary> diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs index 6f4aa11a6d..566581443b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs @@ -37,6 +37,7 @@ using MonoDevelop.Core.Execution; using MonoDevelop.Core.ProgressMonitoring; using MonoDevelop.Ide.FindInFiles; using MonoDevelop.Components.Docking; +using System.Threading; namespace MonoDevelop.Ide.Gui { @@ -51,22 +52,22 @@ namespace MonoDevelop.Ide.Gui { } - public IProgressMonitor GetBuildProgressMonitor () + public ProgressMonitor GetBuildProgressMonitor () { return GetBuildProgressMonitor (GettextCatalog.GetString ("Building...")); } - public IProgressMonitor GetCleanProgressMonitor () + public ProgressMonitor GetCleanProgressMonitor () { return GetBuildProgressMonitor (GettextCatalog.GetString ("Cleaning...")); } - public IProgressMonitor GetRebuildProgressMonitor () + public ProgressMonitor GetRebuildProgressMonitor () { return GetBuildProgressMonitor (GettextCatalog.GetString ("Rebuilding...")); } - private IProgressMonitor GetBuildProgressMonitor (string statusText) + private ProgressMonitor GetBuildProgressMonitor (string statusText) { Pad pad = IdeApp.Workbench.GetPad<ErrorListPad> (); ErrorListPad errorPad = (ErrorListPad) pad.Content; @@ -75,27 +76,27 @@ namespace MonoDevelop.Ide.Gui return mon; } - public IProgressMonitor GetRunProgressMonitor () + public ProgressMonitor GetRunProgressMonitor () { return GetOutputProgressMonitor ("MonoDevelop.Ide.ApplicationOutput", GettextCatalog.GetString ("Application Output"), Stock.RunProgramIcon, true, true); } - public IProgressMonitor GetToolOutputProgressMonitor (bool bringToFront) + public ProgressMonitor GetToolOutputProgressMonitor (bool bringToFront, CancellationTokenSource cs = null) { return GetOutputProgressMonitor ("MonoDevelop.Ide.ToolOutput", GettextCatalog.GetString ("Tool Output"), Stock.RunProgramIcon, bringToFront, true); } - public IProgressMonitor GetLoadProgressMonitor (bool lockGui) + public ProgressMonitor GetLoadProgressMonitor (bool lockGui) { return GetStatusProgressMonitor (GettextCatalog.GetString ("Loading..."), Stock.StatusSolutionOperation, true, false, lockGui); } - public IProgressMonitor GetProjectLoadProgressMonitor (bool lockGui) + public ProgressMonitor GetProjectLoadProgressMonitor (bool lockGui) { return new GtkProjectLoadProgressMonitor (GetLoadProgressMonitor (lockGui)); } - public IProgressMonitor GetSaveProgressMonitor (bool lockGui) + public ProgressMonitor GetSaveProgressMonitor (bool lockGui) { return GetStatusProgressMonitor (GettextCatalog.GetString ("Saving..."), Stock.StatusSolutionOperation, true, false, lockGui); } @@ -108,32 +109,32 @@ namespace MonoDevelop.Ide.Gui /******************************/ - public IProgressMonitor GetStatusProgressMonitor (string title, IconId icon, bool showErrorDialogs) + public ProgressMonitor GetStatusProgressMonitor (string title, IconId icon, bool showErrorDialogs) { return new StatusProgressMonitor (title, icon, showErrorDialogs, true, false, null); } - public IProgressMonitor GetStatusProgressMonitor (string title, IconId icon, bool showErrorDialogs, bool showTaskTitle, bool lockGui) + public ProgressMonitor GetStatusProgressMonitor (string title, IconId icon, bool showErrorDialogs, bool showTaskTitle, bool lockGui) { return new StatusProgressMonitor (title, icon, showErrorDialogs, showTaskTitle, lockGui, null); } - public IProgressMonitor GetStatusProgressMonitor (string title, IconId icon, bool showErrorDialogs, bool showTaskTitle, bool lockGui, Pad statusSourcePad) + public ProgressMonitor GetStatusProgressMonitor (string title, IconId icon, bool showErrorDialogs, bool showTaskTitle, bool lockGui, Pad statusSourcePad) { return new StatusProgressMonitor (title, icon, showErrorDialogs, showTaskTitle, lockGui, statusSourcePad); } - public IProgressMonitor GetBackgroundProgressMonitor (string title, IconId icon) + public ProgressMonitor GetBackgroundProgressMonitor (string title, IconId icon) { return new BackgroundProgressMonitor (title, icon); } - public IProgressMonitor GetOutputProgressMonitor (string title, IconId icon, bool bringToFront, bool allowMonitorReuse) + public ProgressMonitor GetOutputProgressMonitor (string title, IconId icon, bool bringToFront, bool allowMonitorReuse) { return GetOutputProgressMonitor (null, title, icon, bringToFront, allowMonitorReuse); } - public IProgressMonitor GetOutputProgressMonitor (string id, string title, IconId icon, bool bringToFront, bool allowMonitorReuse) + public ProgressMonitor GetOutputProgressMonitor (string id, string title, IconId icon, bool bringToFront, bool allowMonitorReuse) { Pad pad = CreateMonitorPad (id, title, icon, bringToFront, allowMonitorReuse, true); pad.Visible = true; @@ -150,7 +151,7 @@ namespace MonoDevelop.Ide.Gui /// For example, if you have a monitor 'm' created with a call to GetOutputProgressMonitor, /// GetPadForMonitor (m) will return the output pad. /// </remarks> - public Pad GetPadForMonitor (IProgressMonitor monitor) + public Pad GetPadForMonitor (ProgressMonitor monitor) { foreach (Pad pad in outputMonitors) { DefaultMonitorPad p = (DefaultMonitorPad) pad.Content; @@ -236,12 +237,12 @@ namespace MonoDevelop.Ide.Gui pad.Destroy (); } - public ISearchProgressMonitor GetSearchProgressMonitor (bool bringToFront) + public SearchProgressMonitor GetSearchProgressMonitor (bool bringToFront) { return GetSearchProgressMonitor (bringToFront, false); } - public ISearchProgressMonitor GetSearchProgressMonitor (bool bringToFront, bool focusPad) + public SearchProgressMonitor GetSearchProgressMonitor (bool bringToFront, bool focusPad) { Pad pad = null; string title = GettextCatalog.GetString ("Search Results"); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProjectLoadProgressMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProjectLoadProgressMonitor.cs index 783e6b97a7..d48c48479d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProjectLoadProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProjectLoadProgressMonitor.cs @@ -29,21 +29,18 @@ using MonoDevelop.Projects.Extensions; namespace MonoDevelop.Ide.Gui { - public class GtkProjectLoadProgressMonitor : WrappedProgressMonitor, IProjectLoadProgressMonitor + public class GtkProjectLoadProgressMonitor : ProjectLoadProgressMonitor { MigrationType? Migration { get; set; } - public MonoDevelop.Projects.Solution CurrentSolution { get; set; } - - public GtkProjectLoadProgressMonitor (IProgressMonitor monitor) - : base (monitor) + public GtkProjectLoadProgressMonitor (ProgressMonitor monitor) { - + AddSlaveMonitor (monitor); } - public MigrationType ShouldMigrateProject () + public override MigrationType ShouldMigrateProject () { if (!IdeApp.IsInitialized) return MigrationType.Ignore; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/SdiWorkspaceWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/SdiWorkspaceWindow.cs index 5e93f19676..f008cf6790 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/SdiWorkspaceWindow.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/SdiWorkspaceWindow.cs @@ -670,7 +670,8 @@ namespace MonoDevelop.Ide.Gui void HandlePathChange (object sender, MonoDevelop.Ide.Gui.Content.DocumentPathChangedEventArgs args) { var pathDoc = (MonoDevelop.Ide.Gui.Content.IPathedDocument) sender; - pathBar.SetPath (pathDoc.CurrentPath); + if (pathBar != null) + pathBar.SetPath (pathDoc.CurrentPath); // pathBar.SetActive (pathDoc.SelectedIndex); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/StatusProgressMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/StatusProgressMonitor.cs index df4fd5efbe..9c53d67eb7 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/StatusProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/StatusProgressMonitor.cs @@ -34,7 +34,7 @@ using MonoDevelop.Core; namespace MonoDevelop.Ide.Gui { - internal class StatusProgressMonitor: BaseProgressMonitor + internal class StatusProgressMonitor: ProgressMonitor { string icon; bool showErrorDialogs; @@ -62,20 +62,20 @@ namespace MonoDevelop.Ide.Gui protected override void OnProgressChanged () { if (showTaskTitles) - statusBar.ShowMessage (icon, CurrentTask); - if (!UnknownWork) - statusBar.SetProgressFraction (GlobalWork); - RunPendingEvents (); + statusBar.ShowMessage (icon, CurrentTaskName); + if (!ProgressIsUnknown) + statusBar.SetProgressFraction (Progress); + DispatchService.RunPendingEvents (); } public void UpdateStatusBar () { if (showTaskTitles) - statusBar.ShowMessage (icon, CurrentTask); + statusBar.ShowMessage (icon, CurrentTaskName); else statusBar.ShowMessage (icon, title); - if (!UnknownWork) - statusBar.SetProgressFraction (GlobalWork); + if (!ProgressIsUnknown) + statusBar.SetProgressFraction (Progress); else statusBar.SetProgressFraction (0); } @@ -87,22 +87,22 @@ namespace MonoDevelop.Ide.Gui statusBar.EndProgress (); try { - if (Errors.Count > 0 || Warnings.Count > 0) { - if (Errors.Count > 0) { - statusBar.ShowError (Errors [Errors.Count - 1]); - } else if (SuccessMessages.Count == 0) { - statusBar.ShowWarning (Warnings [Warnings.Count - 1]); + if (Errors.Length > 0 || Warnings.Length > 0) { + if (Errors.Length > 0) { + statusBar.ShowError (Errors [Errors.Length - 1].Message); + } else if (SuccessMessages.Length == 0) { + statusBar.ShowWarning (Warnings [Warnings.Length - 1]); } base.OnCompleted (); if (showErrorDialogs) - ShowResultDialog (); + this.ShowResultDialog (); return; } - if (SuccessMessages.Count > 0) - statusBar.ShowMessage (MonoDevelop.Ide.Gui.Stock.StatusSuccess, SuccessMessages [SuccessMessages.Count - 1]); + if (SuccessMessages.Length > 0) + statusBar.ShowMessage (MonoDevelop.Ide.Gui.Stock.StatusSuccess, SuccessMessages [SuccessMessages.Length - 1]); } finally { statusBar.StatusSourcePad = statusSourcePad; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs index e5fa795274..d2d14a42dd 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs @@ -133,6 +133,14 @@ namespace MonoDevelop.Ide.Gui public static readonly int PagerTriangleSize = 6; public static readonly int PagerHeight = 16; + public static readonly Cairo.Color ErrorBackgroundColor = CairoExtensions.ParseColor ("E27267"); + public static readonly Cairo.Color WarningBackgroundColor = CairoExtensions.ParseColor ("F6C61E"); + public static readonly Cairo.Color InformationBackgroundColor = CairoExtensions.ParseColor ("709DC9"); + + public static readonly Cairo.Color ErrorTextColor = CairoExtensions.ParseColor ("ffffff"); + public static readonly Cairo.Color WarningTextColor = CairoExtensions.ParseColor ("6D5607"); + public static readonly Cairo.Color InformationTextColor = CairoExtensions.ParseColor ("ffffff"); + public static class ParamaterWindows { public static readonly Cairo.Color GradientStartColor = CairoExtensions.ParseColor ("fffee6"); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs index be65157287..de309fd3d1 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs @@ -70,7 +70,7 @@ namespace MonoDevelop.Ide.Gui public event EventHandler GuiLocked; public event EventHandler GuiUnlocked; - internal void Initialize (IProgressMonitor monitor) + internal void Initialize (ProgressMonitor monitor) { monitor.BeginTask (GettextCatalog.GetString ("Initializing Main Window"), 4); try { @@ -98,6 +98,15 @@ namespace MonoDevelop.Ide.Gui CheckFileStatus (); }; + IdeApp.ProjectOperations.StartBuild += delegate { + SaveFileStatus (); + }; + + IdeApp.ProjectOperations.EndBuild += delegate { + // The file status checks outputs as well. + CheckFileStatus (); + }; + pads = null; // Make sure we get an up to date pad list. monitor.Step (1); } finally { @@ -279,16 +288,18 @@ namespace MonoDevelop.Ide.Gui public void LockGui () { - IdeApp.CommandService.LockAll (); - if (GuiLocked != null) - GuiLocked (this, EventArgs.Empty); + if (IdeApp.CommandService.LockAll ()) { + if (GuiLocked != null) + GuiLocked (this, EventArgs.Empty); + } } public void UnlockGui () { - IdeApp.CommandService.UnlockAll (); - if (GuiUnlocked != null) - GuiUnlocked (this, EventArgs.Empty); + if (IdeApp.CommandService.UnlockAll ()) { + if (GuiUnlocked != null) + GuiUnlocked (this, EventArgs.Empty); + } } public void SaveAll () @@ -347,9 +358,9 @@ namespace MonoDevelop.Ide.Gui public Pad ShowPad (IPadContent padContent, string id, string label, string defaultPlacement, DockItemStatus defaultStatus, IconId icon) { return ShowPad (new PadCodon (padContent, id, label, defaultPlacement, defaultStatus, icon)); - }
+ } - [Obsolete("Use OpenDocument (FilePath fileName, Project project, bool bringToFront)")]
+ [Obsolete("Use OpenDocument (FilePath fileName, Project project, bool bringToFront)")] public Document OpenDocument (FilePath fileName, bool bringToFront) { return OpenDocument (fileName, bringToFront ? OpenDocumentOptions.Default : OpenDocumentOptions.Default & ~OpenDocumentOptions.BringToFront); @@ -359,15 +370,15 @@ namespace MonoDevelop.Ide.Gui public Document OpenDocument (FilePath fileName, OpenDocumentOptions options = OpenDocumentOptions.Default) { return OpenDocument (fileName, -1, -1, options, null, null); - }
+ } - [Obsolete("Use OpenDocument (FilePath fileName, Project project, Encoding encoding, OpenDocumentOptions options = OpenDocumentOptions.Default)")]
+ [Obsolete("Use OpenDocument (FilePath fileName, Project project, Encoding encoding, OpenDocumentOptions options = OpenDocumentOptions.Default)")] public Document OpenDocument (FilePath fileName, Encoding encoding, OpenDocumentOptions options = OpenDocumentOptions.Default) { return OpenDocument (fileName, -1, -1, options, encoding, null); - }
+ } - [Obsolete("Use OpenDocument (FilePath fileName, Project project, int line, int column, OpenDocumentOptions options = OpenDocumentOptions.Default)")]
+ [Obsolete("Use OpenDocument (FilePath fileName, Project project, int line, int column, OpenDocumentOptions options = OpenDocumentOptions.Default)")] public Document OpenDocument (FilePath fileName, int line, int column, OpenDocumentOptions options = OpenDocumentOptions.Default) { return OpenDocument (fileName, line, column, options, null, null); @@ -495,7 +506,7 @@ namespace MonoDevelop.Ide.Gui } } Counters.OpenDocumentTimer.Trace ("Initializing monitor"); - IProgressMonitor pm = ProgressMonitors.GetStatusProgressMonitor ( + ProgressMonitor pm = ProgressMonitors.GetStatusProgressMonitor ( GettextCatalog.GetString ("Opening {0}", info.Project != null ? info.FileName.ToRelative (info.Project.ParentSolution.BaseDirectory) : info.FileName), @@ -521,7 +532,7 @@ namespace MonoDevelop.Ide.Gui } } - IViewContent BatchOpenDocument (IProgressMonitor monitor, FilePath fileName, Project project, int line, int column, DockNotebook dockNotebook) + IViewContent BatchOpenDocument (ProgressMonitor monitor, FilePath fileName, Project project, int line, int column, DockNotebook dockNotebook) { if (string.IsNullOrEmpty (fileName)) return null; @@ -818,7 +829,7 @@ namespace MonoDevelop.Ide.Gui return project; } - void RealOpenFile (IProgressMonitor monitor, FileOpenInformation openFileInfo) + void RealOpenFile (ProgressMonitor monitor, FileOpenInformation openFileInfo) { FilePath fileName; @@ -1009,7 +1020,7 @@ namespace MonoDevelop.Ide.Gui FilePath baseDir = args.Item.BaseDirectory; var floatingWindows = new List<DockWindow> (); - using (IProgressMonitor pm = ProgressMonitors.GetStatusProgressMonitor (GettextCatalog.GetString ("Loading workspace documents"), Stock.StatusSolutionOperation, true)) { + using (ProgressMonitor pm = ProgressMonitors.GetStatusProgressMonitor (GettextCatalog.GetString ("Loading workspace documents"), Stock.StatusSolutionOperation, true)) { var docList = prefs.Files.Distinct (new DocumentUserPrefsFilenameComparer ()).OrderBy (d => d.NotebookId).ToList (); OpenDocumentsInContainer (pm, baseDir, docViews, docList, workbench.TabControl.Container); @@ -1063,14 +1074,14 @@ namespace MonoDevelop.Ide.Gui } } - void OpenDocumentsInContainer (IProgressMonitor pm, FilePath baseDir, List<Tuple<IViewContent,string>> docViews, List<DocumentUserPrefs> list, DockNotebookContainer container) + void OpenDocumentsInContainer (ProgressMonitor pm, FilePath baseDir, List<Tuple<IViewContent,string>> docViews, List<DocumentUserPrefs> list, DockNotebookContainer container) { int currentNotebook = -1; DockNotebook nb = container.GetFirstNotebook (); foreach (var doc in list) { string fileName = baseDir.Combine (doc.FileName).FullPath; - if (File.Exists (fileName)) { + if (GetDocument(fileName) == null && File.Exists (fileName)) { if (doc.NotebookId != currentNotebook) { if (currentNotebook != -1 || nb == null) nb = container.InsertRight (null); @@ -1170,8 +1181,8 @@ namespace MonoDevelop.Ide.Gui ThreadPool.QueueUserWorkItem (delegate { lock (fileStatusLock) { -// DateTime t = DateTime.Now;
- if (fileStatus == null)
+// DateTime t = DateTime.Now; + if (fileStatus == null) return; List<FilePath> modified = new List<FilePath> (); foreach (FileData fd in fileStatus) { @@ -1276,7 +1287,7 @@ namespace MonoDevelop.Ide.Gui return fileName; } set { - fileName = value.CanonicalPath; + fileName = ResolveSymbolicLink (value.CanonicalPath); if (fileName.IsNullOrEmpty) LoggingService.LogError ("FileName == null\n" + Environment.StackTrace); } @@ -1328,6 +1339,36 @@ namespace MonoDevelop.Ide.Gui this.Options &= ~OpenDocumentOptions.BringToFront; } } + + static FilePath ResolveSymbolicLink (FilePath fileName) + { + if (fileName.IsEmpty) + return fileName; + try { + var alreadyVisted = new HashSet<FilePath> (); + while (true) { + if (alreadyVisted.Contains (fileName)) { + LoggingService.LogError ("Cyclic links detected: " + fileName); + return FilePath.Empty; + } + alreadyVisted.Add (fileName); + var linkInfo = new Mono.Unix.UnixSymbolicLinkInfo (fileName); + if (linkInfo.IsSymbolicLink && linkInfo.HasContents) { + FilePath contentsPath = linkInfo.ContentsPath; + if (contentsPath.IsAbsolute) { + fileName = linkInfo.ContentsPath; + } else { + fileName = fileName.ParentDirectory.Combine (contentsPath); + } + fileName = fileName.CanonicalPath; + continue; + } + return ResolveSymbolicLink (fileName.ParentDirectory).Combine (fileName.FileName).CanonicalPath; + } + } catch (Exception) { + return fileName; + } + } } class LoadFileWrapper @@ -1336,10 +1377,10 @@ namespace MonoDevelop.Ide.Gui Project project; FileOpenInformation fileInfo; DefaultWorkbench workbench; - IProgressMonitor monitor; + ProgressMonitor monitor; IViewContent newContent; - public LoadFileWrapper (IProgressMonitor monitor, DefaultWorkbench workbench, IViewDisplayBinding binding, FileOpenInformation fileInfo) + public LoadFileWrapper (ProgressMonitor monitor, DefaultWorkbench workbench, IViewDisplayBinding binding, FileOpenInformation fileInfo) { this.monitor = monitor; this.workbench = workbench; @@ -1347,7 +1388,7 @@ namespace MonoDevelop.Ide.Gui this.binding = binding; } - public LoadFileWrapper (IProgressMonitor monitor, DefaultWorkbench workbench, IViewDisplayBinding binding, Project project, FileOpenInformation fileInfo) + public LoadFileWrapper (ProgressMonitor monitor, DefaultWorkbench workbench, IViewDisplayBinding binding, Project project, FileOpenInformation fileInfo) : this (monitor, workbench, binding, fileInfo) { this.project = project; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/BaseProgressMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/BaseProgressMonitor.cs index a7359939a2..348ce2aa23 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/BaseProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/BaseProgressMonitor.cs @@ -38,317 +38,27 @@ using MonoDevelop.Ide.Gui.Dialogs; namespace MonoDevelop.Ide.ProgressMonitoring { - public class BaseProgressMonitor: GuiSyncObject, IProgressMonitor, IAsyncOperation + public static class ProgressHelper { - class MbrWrapper { - public ManualResetEvent waitEvent; - - //workaround for "** ERROR **: file icall.c: line 2419 (ves_icall_InternalExecute): assertion failed" bug when - //handling the CancelRequested event - public event MonitorHandler cancelRequestedEvent; - - public void RaiseEvent (IProgressMonitor monitor) { - if (cancelRequestedEvent != null) - cancelRequestedEvent (monitor); - } - } - - MbrWrapper c = new MbrWrapper (); - ProgressTracker progressTracker; - LogTextWriter logger; - bool canceled; - bool runningPendingEvents; - - event OperationHandler completedEvent; - - StringCollection errorsMessages = new StringCollection (); - StringCollection successMessages = new StringCollection (); - StringCollection warningMessages = new StringCollection (); - Exception errorException; - - public BaseProgressMonitor () - { - progressTracker = new ProgressTracker (); - logger = new LogTextWriter (); - logger.TextWritten += new LogTextEventHandler (WriteLogInternal); - } - - [FreeDispatch] - public object SyncRoot { - [FreeDispatch] - get { - // Dont return 'this'. Locking on proxies doesn't look like a good idea. - return progressTracker; - } - } - - [AsyncDispatch] - public virtual void BeginTask (string name, int totalWork) - { - progressTracker.BeginTask (name, totalWork); - OnProgressChanged (); - } - - [AsyncDispatch] - public virtual void BeginStepTask (string name, int totalWork, int stepSize) - { - progressTracker.BeginStepTask (name, totalWork, stepSize); - OnProgressChanged (); - } - - [AsyncDispatch] - public virtual void EndTask () - { - progressTracker.EndTask (); - } - - [AsyncDispatch] - public virtual void Step (int work) - { - progressTracker.Step (work); - OnProgressChanged (); - } - - public TextWriter Log { - [FreeDispatch] - get { - return logger; - } - } - - [FreeDispatch] - public virtual void ReportSuccess (string message) - { - successMessages.Add (message); - } - - [FreeDispatch] - public virtual void ReportWarning (string message) - { - warningMessages.Add (message); - } - - [FreeDispatch] - public virtual void ReportError (string message, Exception ex) - { - if (message == null && ex != null) { - var userEx = ex as UserException; - if (userEx != null) - message = string.Format ("{0}{1}{1}{2}", userEx.Message, Environment.NewLine, userEx.Details); - else - message = ex.Message; - } else if (message != null && ex != null) { - if (!message.EndsWith (".")) message += "."; - message += " " + ex.Message; - } - - errorsMessages.Add (message); - if (ex != null) { - LoggingService.LogError (ex.ToString ()); - errorException = ex; - } - } - - [FreeDispatch] - public virtual bool IsCancelRequested { - [FreeDispatch] - get { return canceled; } - } - - [AsyncDispatch] - public virtual void Dispose() - { - DispatchService.RunPendingEvents (); - - lock (progressTracker) { - progressTracker.Done (); - if (c.waitEvent != null) - c.waitEvent.Set (); - } - try { - OnCompleted (); - } catch (Exception ex) { - string msg = "Unhandled exception in monitor cancel event handler"; - LoggingService.LogError (msg, ex); - MessageService.ShowException (ex, msg); - } - } - - [FreeDispatch] - public IAsyncOperation AsyncOperation - { - [FreeDispatch] - get { return this; } - } - - [FreeDispatch] - void IAsyncOperation.Cancel () - { - OnCancelRequested (); - } - - [FreeDispatch] - void IAsyncOperation.WaitForCompleted () - { - if (IsCompleted) return; - - if (DispatchService.IsGuiThread) { - while (!IsCompleted) { - DispatchService.RunPendingEvents (); - Thread.Sleep (100); - } - } else { - lock (progressTracker) { - if (!progressTracker.InProgress) return; - if (c.waitEvent == null) - c.waitEvent = new ManualResetEvent (false); - } - c.waitEvent.WaitOne (); - } - } - - [FreeDispatch] - bool IAsyncOperation.Success { - [FreeDispatch] - get { return errorsMessages.Count == 0; } - } - - [FreeDispatch] - bool IAsyncOperation.SuccessWithWarnings { - [FreeDispatch] - get { return errorsMessages.Count == 0 && warningMessages.Count > 0; } - } - - public bool IsCompleted { - [FreeDispatch] - get { return !progressTracker.InProgress; } - } - - public event OperationHandler Completed { - add { - bool alreadyCompleted = false; - lock (progressTracker) { - completedEvent += value; - alreadyCompleted = !progressTracker.InProgress; - } - if (alreadyCompleted) value (this); - } - remove { - lock (progressTracker) { - completedEvent -= value; - } - } - } - - public event MonitorHandler CancelRequested { - [FreeDispatch] - add { - bool alreadyCanceled = false; - lock (progressTracker) { - c.cancelRequestedEvent += value; - alreadyCanceled = canceled; - } - if (alreadyCanceled) value (this); - } - [FreeDispatch] - remove { - lock (progressTracker) { - c.cancelRequestedEvent -= value; - } - } - } - - public Exception ErrorException { - get { return errorException; } - } - - public StringCollection Errors { - get { return errorsMessages; } - } - - public StringCollection SuccessMessages { - get { return successMessages; } - } - - public StringCollection Warnings { - get { return warningMessages; } - } - - protected string CurrentTask { - get { return progressTracker.CurrentTask; } - } - - protected double CurrentTaskWork { - get { return progressTracker.CurrentTaskWork; } - } - - protected double GlobalWork { - get { return progressTracker.GlobalWork; } - } - - protected bool UnknownWork { - get { return progressTracker.UnknownWork; } - } - - protected virtual void OnCompleted () - { - if (completedEvent != null) - completedEvent (AsyncOperation); - } - - protected virtual void OnCancelRequested () - { - lock (progressTracker) { - canceled = true; - } - - c.RaiseEvent(this); - } - - [AsyncDispatch] - void WriteLogInternal (string text) - { - OnWriteLog (text); - } - - protected virtual void OnWriteLog (string text) - { - } - - protected virtual void OnProgressChanged () - { - } - - protected void RunPendingEvents () - { - if (!runningPendingEvents) { - try { - runningPendingEvents = true; - DispatchService.RunPendingEvents (); - } finally { - runningPendingEvents = false; - } - } - } - - protected void ShowResultDialog () + public static void ShowResultDialog (this ProgressMonitor monitor) { - if (Errors.Count == 1 && Warnings.Count == 0) { - if (ErrorException != null) - MessageService.ShowException (ErrorException, Errors[0]); + if (monitor.Errors.Length == 1 && !monitor.HasWarnings) { + var error = monitor.Errors [0]; + if (error.Exception != null) + MessageService.ShowException (error.Exception, error.Message); else - MessageService.ShowError (Errors[0]); + MessageService.ShowError (error.Message); } - else if (Errors.Count == 0 && Warnings.Count == 1) { - MessageService.ShowWarning (Warnings[0]); + else if (!monitor.HasErrors && monitor.Warnings.Length == 1) { + MessageService.ShowWarning (monitor.Warnings[0]); } - else if (Errors.Count > 0 || Warnings.Count > 0) { + else if (monitor.HasErrors || monitor.HasWarnings) { var resultDialog = new MultiMessageDialog () { Modal = true, }; - foreach (string m in Errors) - resultDialog.AddError (m); - foreach (string m in Warnings) + foreach (var m in monitor.Errors) + resultDialog.AddError (m.Message); + foreach (var m in monitor.Warnings) resultDialog.AddWarning (m); MessageService.ShowCustomDialog (resultDialog); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/MessageDialogProgressMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/MessageDialogProgressMonitor.cs index 8a5304d435..c26cb908e9 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/MessageDialogProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/MessageDialogProgressMonitor.cs @@ -34,7 +34,7 @@ namespace MonoDevelop.Ide.ProgressMonitoring { // Progress monitor that reports errors and warnings in message dialogs. - public class MessageDialogProgressMonitor: BaseProgressMonitor + public class MessageDialogProgressMonitor: ProgressMonitor { ProgressDialog dialog; bool hideWhenDone; @@ -64,77 +64,64 @@ namespace MonoDevelop.Ide.ProgressMonitoring dialog.Message = ""; MessageService.PlaceDialog (dialog, MessageService.RootWindow); dialog.Show (); - dialog.AsyncOperation = AsyncOperation; - dialog.OperationCancelled += delegate { - OnCancelRequested (); - }; - RunPendingEvents (); + dialog.CancellationTokenSource = CancellationTokenSource; + DispatchService.RunPendingEvents (); this.hideWhenDone = hideWhenDone; this.showDetails = showDetails; } } - + protected override void OnWriteLog (string text) { if (dialog != null) { dialog.WriteText (text); - RunPendingEvents (); + DispatchService.RunPendingEvents (); } } protected override void OnProgressChanged () { if (dialog != null) { - dialog.Message = CurrentTask; - dialog.Progress = GlobalWork; - RunPendingEvents (); - } - } - - public override void BeginTask (string name, int totalWork) - { - if (dialog != null) { - dialog.BeginTask (name); + dialog.Message = CurrentTaskName; + dialog.Progress = Progress; + DispatchService.RunPendingEvents (); } - base.BeginTask (name, totalWork); } - public override void BeginStepTask (string name, int totalWork, int stepSize) + protected override void OnBeginTask (string name, int totalWork, int stepWork) { if (dialog != null) { dialog.BeginTask (name); } - base.BeginStepTask (name, totalWork, stepSize); } - - public override void EndTask () + + protected override void OnEndTask (string name, int totalWork, int stepWork) { if (dialog != null) { dialog.EndTask (); } - base.EndTask (); - RunPendingEvents (); + base.OnEndTask (name, totalWork, stepWork); + DispatchService.RunPendingEvents (); } - - public override void ReportWarning (string message) + + protected override void OnWarningReported (string message) { - base.ReportWarning (message); if (dialog != null) { dialog.WriteText (GettextCatalog.GetString ("WARNING: ") + message + "\n"); - RunPendingEvents (); + DispatchService.RunPendingEvents (); } + base.OnWarningReported (message); } - - public override void ReportError (string message, Exception ex) + + protected override void OnErrorReported (string message, Exception exception) { - base.ReportError (message, ex); - if (dialog != null) { - dialog.WriteText (GettextCatalog.GetString ("ERROR: ") + Errors [Errors.Count - 1] + "\n"); - RunPendingEvents (); + dialog.WriteText (GettextCatalog.GetString ("ERROR: ") + Errors [Errors.Length - 1] + "\n"); + DispatchService.RunPendingEvents (); } + base.OnErrorReported (message, exception); } - + protected override void OnCompleted () { DispatchService.GuiDispatch (new MessageHandler (ShowDialogs)); @@ -144,7 +131,7 @@ namespace MonoDevelop.Ide.ProgressMonitoring void ShowDialogs () { if (dialog != null) { - dialog.ShowDone (Warnings.Count > 0, Errors.Count > 0); + dialog.ShowDone (Warnings.Length > 0, Errors.Length > 0); if (hideWhenDone) dialog.Destroy (); } @@ -152,7 +139,7 @@ namespace MonoDevelop.Ide.ProgressMonitoring if (showDetails) return; - ShowResultDialog (); + this.ShowResultDialog (); } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/MultiTaskDialogProgressMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/MultiTaskDialogProgressMonitor.cs index 75ab2adfe4..8e24e95f31 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/MultiTaskDialogProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/MultiTaskDialogProgressMonitor.cs @@ -39,7 +39,7 @@ namespace MonoDevelop.Ide.ProgressMonitoring { - public class MultiTaskDialogProgressMonitor : BaseProgressMonitor + public class MultiTaskDialogProgressMonitor : ProgressMonitor { StringCollection errorsMessages = new StringCollection (); StringCollection warningMessages = new StringCollection (); @@ -75,7 +75,7 @@ namespace MonoDevelop.Ide.ProgressMonitoring }; MessageService.PlaceDialog (dialog, parent); Mono.TextEditor.GtkWorkarounds.PresentWindowWithNotification (dialog); - dialog.AsyncOperation = AsyncOperation; + dialog.CancellationTokenSource = CancellationTokenSource; DispatchService.RunPendingEvents (); this.showDetails = showDetails; } @@ -106,46 +106,39 @@ namespace MonoDevelop.Ide.ProgressMonitoring protected override void OnProgressChanged () { if (dialog != null) { - dialog.SetProgress (CurrentTaskWork); + dialog.SetProgress (Progress); DispatchService.RunPendingEvents (); } } - public override void BeginTask (string name, int totalWork) + protected override void OnBeginTask (string name, int totalWork, int stepWork) { if (dialog != null) { dialog.BeginTask (name); } - base.BeginTask (name, totalWork); + base.OnBeginTask (name, totalWork, stepWork); } - - public override void BeginStepTask (string name, int totalWork, int stepSize) - { - if (dialog != null) { - dialog.BeginTask (name); - } - base.BeginStepTask (name, totalWork, stepSize); - } - - public override void EndTask () + + protected override void OnEndTask (string name, int totalWork, int stepWork) { if (dialog != null) { dialog.EndTask (); } - base.EndTask (); DispatchService.RunPendingEvents (); + base.OnEndTask (name, totalWork, stepWork); } - - public override void ReportWarning (string message) + + protected override void OnWarningReported (string message) { if (dialog != null) { dialog.WriteText (GettextCatalog.GetString ("WARNING: ") + message + "\n"); DispatchService.RunPendingEvents (); } warningMessages.Add (message); + base.OnWarningReported (message); } - - public override void ReportError (string message, Exception ex) + + protected override void OnErrorReported (string message, Exception ex) { if (message == null && ex != null) message = ex.Message; @@ -153,17 +146,18 @@ namespace MonoDevelop.Ide.ProgressMonitoring if (!message.EndsWith (".")) message += "."; message += " " + ex.Message; } - + errorsMessages.Add (message); if (ex != null) { LoggingService.LogError (ex.ToString ()); errorException = ex; } - + if (dialog != null) { dialog.WriteText (GettextCatalog.GetString ("ERROR: ") + message + "\n"); DispatchService.RunPendingEvents (); } + base.OnErrorReported (message, ex); } protected override void OnCompleted () diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/ProgressBarMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/ProgressBarMonitor.cs deleted file mode 100644 index 81a3602f34..0000000000 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/ProgressBarMonitor.cs +++ /dev/null @@ -1,90 +0,0 @@ -// -// ProgressBarMonitor.cs -// -// Author: -// Lluis Sanchez Gual <lluis@novell.com> -// -// Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Linq; -using MonoDevelop.Core; - -namespace MonoDevelop.Ide.ProgressMonitoring -{ - [System.ComponentModel.ToolboxItem(true)] - public partial class ProgressBarMonitor : Gtk.Bin - { - public ProgressBarMonitor () - { - this.Build (); - } - - public bool AllowCancel { - get { return buttonCancel.Visible; } - set { buttonCancel.Visible = value; } - } - - public bool ShowErrorsDialog { get; set; } - - public IProgressMonitor CreateProgressMonitor () - { - return new InternalProgressBarMonitor (this); - } - - class InternalProgressBarMonitor: BaseProgressMonitor - { - ProgressBarMonitor widget; - - public InternalProgressBarMonitor (ProgressBarMonitor widget) - { - this.widget = widget; - widget.buttonCancel.Clicked += OnCancelClicked; - } - - void OnCancelClicked (object sender, EventArgs e) - { - AsyncOperation.Cancel (); - } - - protected override void OnProgressChanged () - { - widget.progressBar.Fraction = GlobalWork; - RunPendingEvents (); - } - - protected override void OnCompleted () - { - base.OnCompleted (); - if (!AsyncOperation.Success && widget.ShowErrorsDialog) { - string err = string.Join ("\n", Errors.Cast<string> ().ToArray ()); - MessageService.ShowError (GettextCatalog.GetString ("Add-in installation failed"), err); - } - } - - public override void Dispose () - { - widget.buttonCancel.Clicked -= OnCancelClicked; - base.Dispose (); - } - } - } -} - diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/BaseDirectoryPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/BaseDirectoryPanel.cs index 09d95ab8a5..7b487bab59 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/BaseDirectoryPanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/BaseDirectoryPanel.cs @@ -35,7 +35,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels public class BaseDirectoryPanel: IOptionsPanel { BaseDirectoryPanelWidget widget; - IWorkspaceObject obj; + WorkspaceObject obj; public BaseDirectoryPanel() { @@ -43,7 +43,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels public void Initialize (OptionsDialog dialog, object dataObject) { - obj = dataObject as IWorkspaceObject; + obj = dataObject as WorkspaceObject; } public Gtk.Widget CreatePanelWidget () @@ -69,7 +69,10 @@ namespace MonoDevelop.Ide.Projects.OptionPanels public void ApplyChanges () { - obj.BaseDirectory = widget.BaseDirectory; + if (obj is WorkspaceItem) + ((WorkspaceItem)obj).BaseDirectory = widget.BaseDirectory; + else if (obj is SolutionFolderItem) + ((SolutionFolderItem)obj).BaseDirectory = widget.BaseDirectory; } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CodeFormattingPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CodeFormattingPanel.cs index d05c486556..e81655f224 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CodeFormattingPanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CodeFormattingPanel.cs @@ -59,7 +59,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels provider = PolicyService.GetUserDefaultPolicySet (); policyContainer = provider.Policies; - if (!(dataObject is SolutionItem) && !(dataObject is Solution)) { + if (!(dataObject is SolutionFolderItem) && !(dataObject is Solution)) { globalMimeTypes = new List<string> (); string userTypes = PropertyService.Get<string> ("MonoDevelop.Projects.GlobalPolicyMimeTypes", ""); globalMimeTypes.AddRange (userTypes.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); @@ -214,8 +214,8 @@ namespace MonoDevelop.Ide.Projects.OptionPanels HashSet<string> types = new HashSet<string> (); if (DataObject is Solution) GetItemMimeTypes (types, ((Solution)DataObject).RootFolder); - else if (DataObject is SolutionItem) - GetItemMimeTypes (types, (SolutionItem)DataObject); + else if (DataObject is SolutionFolderItem) + GetItemMimeTypes (types, (SolutionFolderItem)DataObject); else { types.Add ("application/xml"); foreach (MimeTypeOptionsPanelNode node in AddinManager.GetExtensionNodes ("/MonoDevelop/ProjectModel/Gui/MimeTypePolicyPanels")) { @@ -232,10 +232,10 @@ namespace MonoDevelop.Ide.Projects.OptionPanels return globalMimeTypes != null && globalMimeTypes.Contains (type); } - void GetItemMimeTypes (HashSet<string> types, SolutionItem item) + void GetItemMimeTypes (HashSet<string> types, SolutionFolderItem item) { if (item is SolutionFolder) { - foreach (SolutionItem it in ((SolutionFolder)item).Items) + foreach (SolutionFolderItem it in ((SolutionFolder)item).Items) GetItemMimeTypes (types, it); } else if (item is Project) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CombineConfigurationPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CombineConfigurationPanel.cs index 3a6e6709bb..c250af9a4f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CombineConfigurationPanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CombineConfigurationPanel.cs @@ -75,7 +75,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels this.parentDialog = parentDialog; this.solution = solution; - store = new ListStore (typeof(string), typeof(bool), typeof(SolutionEntityItem)); + store = new ListStore (typeof(string), typeof(bool), typeof(SolutionItem)); configsList.Model = store; configsList.HeadersVisible = true; @@ -104,7 +104,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels configuration = config; store.Clear (); - foreach (var it in solution.GetAllSolutionItems ().OfType<SolutionEntityItem> ().Where (s => s.SupportsBuild ())) { + foreach (var it in solution.GetAllSolutionItems ().OfType<SolutionItem> ().Where (s => s.SupportsBuild ())) { var ce = config.GetEntryForItem (it); store.AppendValues (it.Name, ce != null && ce.Build, it); } @@ -112,7 +112,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels void OnSetConfigurationsData (Gtk.TreeViewColumn treeColumn, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { - var item = (SolutionEntityItem) store.GetValue (iter, ProjectCol); + var item = (SolutionItem) store.GetValue (iter, ProjectCol); ConfigurationData data = parentDialog.ConfigurationData.FindConfigurationData (item); CellRendererComboBox comboCell = (CellRendererComboBox) cell; @@ -126,7 +126,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels comboCell.Markup = escaped; } - string GetSelectedConfiguration (SolutionEntityItem item) + string GetSelectedConfiguration (SolutionItem item) { var entry = configuration.GetEntryForItem (item); return entry != null ? entry.ItemConfiguration : (item.DefaultConfiguration != null ? item.DefaultConfiguration.Id : ""); @@ -136,7 +136,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels { TreeIter iter; if (store.GetIter (out iter, new TreePath (args.Path))) { - var item = (SolutionEntityItem) store.GetValue (iter, ProjectCol); + var item = (SolutionItem) store.GetValue (iter, ProjectCol); var entry = configuration.GetEntryForItem (item); if (entry == null) { entry = CreateDefaultMapping (item); @@ -147,7 +147,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels } } - SolutionConfigurationEntry CreateDefaultMapping (SolutionEntityItem item) + SolutionConfigurationEntry CreateDefaultMapping (SolutionItem item) { var conf = GetSelectedConfiguration (item); var entry = configuration.AddItem (item); @@ -159,7 +159,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels { TreeIter iter; if (store.GetIter (out iter, new TreePath (args.Path))) { - var item = (SolutionEntityItem) store.GetValue (iter, ProjectCol); + var item = (SolutionItem) store.GetValue (iter, ProjectCol); var entry = configuration.GetEntryForItem (item); if (entry == null) { entry = CreateDefaultMapping (item); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CustomCommandPanelWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CustomCommandPanelWidget.cs index 347b6bd900..1470bf39dc 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CustomCommandPanelWidget.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CustomCommandPanelWidget.cs @@ -38,7 +38,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels { CustomCommandCollection commands; CustomCommandWidget lastSlot; - SolutionEntityItem entry; + SolutionItem entry; ConfigurationSelector configSelector; CustomCommandType[] supportedTypes; @@ -48,7 +48,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels label3.LabelProp = MonoDevelop.Core.BrandingService.BrandApplicationName (label3.LabelProp); } - public void Load (SolutionEntityItem entry, CustomCommandCollection commands, ConfigurationSelector configSelector, CustomCommandType[] supportedTypes) + public void Load (SolutionItem entry, CustomCommandCollection commands, ConfigurationSelector configSelector, CustomCommandType[] supportedTypes) { this.entry = entry; this.commands = commands; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CustomCommandWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CustomCommandWidget.cs index 139aa03ff7..5cb485755e 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CustomCommandWidget.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CustomCommandWidget.cs @@ -39,7 +39,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels internal partial class CustomCommandWidget : Gtk.Bin { CustomCommand cmd; - IWorkspaceObject entry; + WorkspaceObject entry; bool updating; CustomCommandType[] supportedTypes; @@ -56,7 +56,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels GettextCatalog.GetString ("Custom Command") }; - public CustomCommandWidget (IWorkspaceObject entry, CustomCommand cmd, ConfigurationSelector configSelector, CustomCommandType[] supportedTypes) + public CustomCommandWidget (WorkspaceObject entry, CustomCommand cmd, ConfigurationSelector configSelector, CustomCommandType[] supportedTypes) { this.Build(); this.supportedTypes = supportedTypes; @@ -77,8 +77,8 @@ namespace MonoDevelop.Ide.Projects.OptionPanels this.WidgetFlags |= Gtk.WidgetFlags.NoShowAll; StringTagModelDescription tagModel; - if (entry is SolutionItem) - tagModel = ((SolutionItem)entry).GetStringTagModelDescription (configSelector); + if (entry is SolutionFolderItem) + tagModel = ((SolutionFolderItem)entry).GetStringTagModelDescription (configSelector); else if (entry is WorkspaceItem) tagModel = ((WorkspaceItem)entry).GetStringTagModelDescription (); else diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/NamespaceSynchronisationPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/NamespaceSynchronisationPanel.cs index b78bf266f7..bb48e5a476 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/NamespaceSynchronisationPanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/NamespaceSynchronisationPanel.cs @@ -53,7 +53,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels return slnFolder.GetAllItems<DotNetProject> ().Any (); // Global options case - return !(item is IWorkspaceObject); + return !(item is WorkspaceObject); } public override Widget CreatePanelWidget () @@ -105,7 +105,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels foreach (DotNetProject prj in ((SolutionFolder)DataObject).GetAllItems<DotNetProject> ()) prj.UpdateResourceHandler (migrateIds); } else if (ConfiguredSolution != null) { - foreach (DotNetProject prj in ConfiguredSolution.GetAllSolutionItems<DotNetProject> ()) + foreach (DotNetProject prj in ConfiguredSolution.GetAllItems<DotNetProject> ()) prj.UpdateResourceHandler (migrateIds); } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/PortableRuntimeOptionsPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/PortableRuntimeOptionsPanel.cs index 6a4169cc9e..2819785204 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/PortableRuntimeOptionsPanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/PortableRuntimeOptionsPanel.cs @@ -43,7 +43,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels public override Widget CreatePanelWidget () { - return (widget = new PortableRuntimeOptionsPanelWidget ((PortableDotNetProject) ConfiguredProject, ItemConfigurations)); + return (widget = new PortableRuntimeOptionsPanelWidget ((DotNetProject) ConfiguredProject, ItemConfigurations)); } public override void ApplyChanges () @@ -60,7 +60,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels readonly SortedDictionary<string, List<SupportedFramework>> supportedFrameworks; readonly List<OptionCombo> options; - PortableDotNetProject project; + DotNetProject project; TargetFramework target; HBox warningHBox; Label warning; @@ -103,7 +103,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels } } - public PortableRuntimeOptionsPanelWidget (PortableDotNetProject project, IEnumerable<ItemConfiguration> configurations) + public PortableRuntimeOptionsPanelWidget (DotNetProject project, IEnumerable<ItemConfiguration> configurations) { this.target = project.TargetFramework; this.project = project; @@ -667,7 +667,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels { if (target != null && target != project.TargetFramework) { project.TargetFramework = target; - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/StartupOptionsPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/StartupOptionsPanel.cs index 49c15e72d6..8686b5be7f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/StartupOptionsPanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/StartupOptionsPanel.cs @@ -41,15 +41,15 @@ namespace MonoDevelop.Ide.Projects.OptionPanels { Solution sol; ListStore listStore; - List<SolutionEntityItem> startupItems; + List<SolutionItem> startupItems; public StartupOptionsPanelWidget (Solution sol) { this.Build(); this.sol = sol; - startupItems = new List<SolutionEntityItem> (); - foreach (SolutionEntityItem it in sol.GetAllSolutionItems<SolutionEntityItem> ()) { + startupItems = new List<SolutionItem> (); + foreach (SolutionItem it in sol.GetAllItems<SolutionItem> ()) { // Include in the list if it can run in any of the existing execution modes and configurations foreach (IExecutionModeSet mset in Runtime.ProcessService.GetExecutionModes ()) { bool matched = false; @@ -69,7 +69,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels } } - listStore = new ListStore (typeof(SolutionItem), typeof(bool), typeof(string)); + listStore = new ListStore (typeof(SolutionFolderItem), typeof(bool), typeof(string)); treeItems.Model = listStore; CellRendererToggle crt = new CellRendererToggle (); @@ -78,7 +78,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels if (startupItems.Count > 0) { for (int n=0; n<startupItems.Count; n++) { - SolutionEntityItem it = startupItems [n]; + SolutionItem it = startupItems [n]; comboItems.AppendText (it.Name); listStore.AppendValues (it, sol.MultiStartupItems.Contains (it), it.Name); if (sol.StartupItem == it) @@ -175,7 +175,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels if (listStore.GetIterFirst (out it)) { do { if ((bool) listStore.GetValue (it, 1)) - sol.MultiStartupItems.Add ((SolutionEntityItem) listStore.GetValue (it, 0)); + sol.MultiStartupItems.Add ((SolutionItem) listStore.GetValue (it, 0)); } while (listStore.IterNext (ref it)); } sol.StartupItem = null; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ApplyPolicyDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ApplyPolicyDialog.cs index a934ed107b..0d3bd7a4ab 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ApplyPolicyDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ApplyPolicyDialog.cs @@ -106,7 +106,12 @@ namespace MonoDevelop.Ide.Projects void UpdateContentLabels () { - PolicySet pset = GetPolicySet (false); + PolicySet pset = null; + try { + pset = GetPolicySet (false); + } catch (Exception ex) { + LoggingService.LogError ("Policy file could not be loaded", ex); + } tree.SetPolicies (pset); if (tree.HasPolicies) { buttonOk.Sensitive = true; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs index 6e4f9d456e..652a333b2f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs @@ -66,7 +66,7 @@ namespace MonoDevelop.Ide.Projects PackStart (chooser, true, true, 0); HeaderBox hbox = new HeaderBox (1, 0, 0, 0); - hbox.GradientBackround = true; + hbox.GradientBackground = true; hbox.SetPadding (6,6,6,6); HBox box = new HBox (); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/CombineEntryFeatureSelector.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/CombineEntryFeatureSelector.cs index 55e7fbe1f6..05f39a51c5 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/CombineEntryFeatureSelector.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/CombineEntryFeatureSelector.cs @@ -41,7 +41,7 @@ namespace MonoDevelop.Ide.Projects { List<ISolutionItemFeature> selectedFeatures = new List<ISolutionItemFeature> (); List<Gtk.Widget> selectedEditors = new List<Gtk.Widget> (); - SolutionItem entry; + SolutionFolderItem entry; SolutionFolder parentCombine; VBox box = new VBox (); Gdk.Cursor handCursor; @@ -55,7 +55,7 @@ namespace MonoDevelop.Ide.Projects box.Show (); } - public void Fill (SolutionFolder parentCombine, SolutionItem entry, ISolutionItemFeature[] features) + public void Fill (SolutionFolder parentCombine, SolutionFolderItem entry, ISolutionItemFeature[] features) { selectedFeatures.Clear (); selectedEditors.Clear (); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ConfirmProjectDeleteDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ConfirmProjectDeleteDialog.cs index 83b1c22d89..b9944dc13e 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ConfirmProjectDeleteDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ConfirmProjectDeleteDialog.cs @@ -109,10 +109,10 @@ namespace MonoDevelop.Ide.Projects } } - if (item is SolutionItem) { - var sol = ((SolutionItem)item).ParentSolution; + if (item is SolutionFolderItem) { + var sol = ((SolutionFolderItem)item).ParentSolution; var bdir = item.BaseDirectory; - if (sol.GetItemFiles (false).Any (f => f.IsChildPathOf (bdir)) || sol.GetAllSolutionItems<SolutionEntityItem> ().Any (it => it != item && it.GetItemFiles (true).Any (f => f.IsChildPathOf (bdir)))) { + if (sol.GetItemFiles (false).Any (f => f.IsChildPathOf (bdir)) || sol.GetAllItems<SolutionItem> ().Any (it => it != item && it.GetItemFiles (true).Any (f => f.IsChildPathOf (bdir)))) { radioDeleteAll.Sensitive = false; labelProjectDir.Text = GettextCatalog.GetString ("Project directory can't be deleted since it contains files from other projects or solutions"); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/DefaultPolicyOptionsDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/DefaultPolicyOptionsDialog.cs index eaac1af0c3..5485501f36 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/DefaultPolicyOptionsDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/DefaultPolicyOptionsDialog.cs @@ -115,7 +115,7 @@ namespace MonoDevelop.Ide.Projects align.Add (topBar); HeaderBox ebox = new HeaderBox (); - ebox.GradientBackround = true; + ebox.GradientBackground = true; ebox.SetMargins (0, 1, 0, 0); ebox.Add (align); @@ -251,14 +251,14 @@ namespace MonoDevelop.Ide.Projects try { dlg.Title = GettextCatalog.GetString ("Apply to Project"); dlg.RootItem = IdeApp.Workspace; - dlg.SelectedItem = IdeApp.ProjectOperations.CurrentSelectedBuildTarget; - dlg.SelectableItemTypes = new Type[] { typeof(Solution), typeof(SolutionItem) }; + dlg.SelectedItem = IdeApp.ProjectOperations.CurrentSelectedObject; + dlg.SelectableItemTypes = new Type[] { typeof(Solution), typeof(SolutionFolderItem) }; if (MessageService.RunCustomDialog (dlg, this) == (int) Gtk.ResponseType.Ok) { ((IPolicyProvider)dlg.SelectedItem).Policies.Import (currentSet, true); if (dlg.SelectedItem is IWorkspaceFileObject) - IdeApp.ProjectOperations.Save ((IWorkspaceFileObject)dlg.SelectedItem); + IdeApp.ProjectOperations.SaveAsync (dlg.SelectedItem); else - IdeApp.ProjectOperations.Save (((SolutionItem)dlg.SelectedItem).ParentSolution); + IdeApp.ProjectOperations.SaveAsync (((SolutionFolderItem)dlg.SelectedItem).ParentSolution); } } finally { dlg.Destroy (); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ExportProjectPolicyDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ExportProjectPolicyDialog.cs index 576b13aa4f..58ba8e6c44 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ExportProjectPolicyDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ExportProjectPolicyDialog.cs @@ -42,8 +42,8 @@ namespace MonoDevelop.Ide.Projects this.policyProvider = policyProvider; fileEntry.DefaultPath = DefaultFileDialogPolicyDir; - if (policyProvider is SolutionItem) - fileEntry.Path = ((SolutionItem)policyProvider).Name + ".mdpolicy"; + if (policyProvider is SolutionFolderItem) + fileEntry.Path = ((SolutionFolderItem)policyProvider).Name + ".mdpolicy"; else if (policyProvider is Solution) fileEntry.Path = ((Solution)policyProvider).Name + ".mdpolicy"; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/FeatureSelectorDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/FeatureSelectorDialog.cs index 1eab8d9141..45ebf05e4a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/FeatureSelectorDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/FeatureSelectorDialog.cs @@ -36,7 +36,7 @@ namespace MonoDevelop.Ide.Projects public partial class FeatureSelectorDialog : Gtk.Dialog { - public FeatureSelectorDialog (SolutionFolder parentCombine, SolutionItem entry) + public FeatureSelectorDialog (SolutionFolder parentCombine, SolutionFolderItem entry) { this.Build(); featureList.Fill (parentCombine, entry, SolutionItemFeatures.GetFeatures (parentCombine, entry)); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ImportProjectPolicyDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ImportProjectPolicyDialog.cs index 548cf4a916..25f7a20099 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ImportProjectPolicyDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ImportProjectPolicyDialog.cs @@ -35,7 +35,7 @@ namespace MonoDevelop.Ide.Projects { this.Build (); selector.RootItem = IdeApp.Workspace; - selector.SelectedItem = IdeApp.ProjectOperations.CurrentSelectedBuildTarget; + selector.SelectedItem = IdeApp.ProjectOperations.CurrentSelectedObject; selector.SelectableItemTypes = new Type[] { typeof(IPolicyProvider) }; UpdateOk (); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewFileDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewFileDialog.cs index 61600ffd88..aa81747da7 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewFileDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewFileDialog.cs @@ -481,7 +481,7 @@ namespace MonoDevelop.Ide.Projects } if (project != null) - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project).RunSynchronously (); if (OnOked != null) OnOked (null, null); @@ -595,19 +595,19 @@ namespace MonoDevelop.Ide.Projects infoLabel.Text = string.Empty; labelTemplateTitle.Text = string.Empty; - ReadOnlyCollection<Project> projects = null; + Project[] projects = null; if (parentProject == null) - projects = IdeApp.Workspace.GetAllProjects (); + projects = IdeApp.Workspace.GetAllProjects ().ToArray (); - if (projects != null && projects.Count > 0) { + if (projects != null && projects.Length > 0) { Project curProject = IdeApp.ProjectOperations.CurrentSelectedProject; boxProject.Visible = true; projectAddCheckbox.Active = curProject != null; projectAddCheckbox.Toggled += new EventHandler (AddToProjectToggled); - projectNames = new string[projects.Count]; - projectRefs = new Project[projects.Count]; + projectNames = new string[projects.Length]; + projectRefs = new Project[projects.Length]; int i = 0; bool singleSolution = IdeApp.Workspace.Items.Count == 1 && IdeApp.Workspace.Items[0] is Solution; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectDialog.cs index 7b5279036d..6ca65e22c6 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectDialog.cs @@ -63,10 +63,10 @@ namespace MonoDevelop.Ide.Projects { bool newSolution; string lastName = ""; ProjectTemplate selectedItem; - SolutionItem currentEntry; + SolutionFolderItem currentEntry; SolutionFolder parentFolder; CombineEntryFeatureSelector featureList; - IWorkspaceFileObject newItem; + WorkspaceObject newItem; Category recentCategory; List<string> recentTemplates = new List<string> (); bool disposeNewItem = true; @@ -288,7 +288,7 @@ namespace MonoDevelop.Ide.Projects { } } - public IWorkspaceObject NewItem { + public WorkspaceObject NewItem { get { return newItem; } @@ -317,7 +317,7 @@ namespace MonoDevelop.Ide.Projects { lbl_will_save_in.Text = GettextCatalog.GetString("Project will be saved at") + " " + ProjectLocation; } - void OpenEvent (object sender, EventArgs e) + async void OpenEvent (object sender, EventArgs e) { if (!btn_new.Sensitive) return; @@ -334,11 +334,11 @@ namespace MonoDevelop.Ide.Projects { parentSolution = item as Solution; if (parentSolution != null) { if (parentSolution.RootFolder.Items.Count > 0) - currentEntry = parentSolution.RootFolder.Items [0] as SolutionItem; + currentEntry = parentSolution.RootFolder.Items [0] as SolutionFolderItem; parentFolder = parentSolution.RootFolder; } } else { - SolutionItem item = (SolutionItem) newItem; + SolutionFolderItem item = (SolutionFolderItem) newItem; parentSolution = parentFolder.ParentSolution; currentEntry = item; } @@ -369,11 +369,11 @@ namespace MonoDevelop.Ide.Projects { if (!newSolution) { // Make sure the new item is saved before adding. In this way the // version control add-in will be able to put it under version control. - if (currentEntry is SolutionEntityItem) { + if (currentEntry is SolutionItem) { // Inherit the file format from the solution - SolutionEntityItem eitem = (SolutionEntityItem) currentEntry; + SolutionItem eitem = (SolutionItem) currentEntry; eitem.FileFormat = parentFolder.ParentSolution.FileFormat; - IdeApp.ProjectOperations.Save (eitem); + await IdeApp.ProjectOperations.SaveAsync (eitem); } parentFolder.AddItem (currentEntry, true); } @@ -382,19 +382,16 @@ namespace MonoDevelop.Ide.Projects { featureList.ApplyFeatures (); if (parentFolder != null) - IdeApp.ProjectOperations.Save (parentFolder.ParentSolution); + await IdeApp.ProjectOperations.SaveAsync (parentFolder.ParentSolution); else - IdeApp.ProjectOperations.Save (newItem); + await IdeApp.ProjectOperations.SaveAsync (newItem); if (openSolution) { - var op = selectedItem.OpenCreatedSolution (); - op.Completed += delegate { - if (op.Success) { - var sol = IdeApp.Workspace.GetAllSolutions ().FirstOrDefault (); - if (sol != null) - InstallProjectTemplatePackages (sol); - } - }; + if (await selectedItem.OpenCreatedSolution ()) { + var sol = IdeApp.Workspace.GetAllSolutions ().FirstOrDefault (); + if (sol != null) + InstallProjectTemplatePackages (sol); + } } else { // The item is not a solution being opened, so it is going to be added to @@ -487,6 +484,8 @@ namespace MonoDevelop.Ide.Projects { newItem = item.CreateWorkspaceItem (cinfo); else newItem = item.CreateProject (parentFolder, cinfo); + if (newItem == null) + return false; } catch (UserException ex) { MessageService.ShowError (ex.Message, ex.Details); return false; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/PackageReferencePanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/PackageReferencePanel.cs index 34bfd45dc6..ad2aa73f1a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/PackageReferencePanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/PackageReferencePanel.cs @@ -135,7 +135,7 @@ namespace MonoDevelop.Ide.Projects { store.Clear (); - bool isPcl = configureProject is PortableDotNetProject; + bool isPcl = configureProject.IsPortableLibrary; foreach (SystemAssembly systemAssembly in targetContext.GetAssemblies (targetVersion)) { if (systemAssembly.Package.IsFrameworkPackage && (isPcl || systemAssembly.Name == "mscorlib")) @@ -178,7 +178,7 @@ namespace MonoDevelop.Ide.Projects Dictionary<DotNetProject,bool> references = new Dictionary<DotNetProject, bool> (); - foreach (Project projectEntry in openSolution.GetAllSolutionItems<Project>()) { + foreach (Project projectEntry in openSolution.GetAllItems<Project>()) { if (projectEntry == configureProject) continue; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectFileSelectorDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectFileSelectorDialog.cs index 2d7450a840..90cb6deab4 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectFileSelectorDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectFileSelectorDialog.cs @@ -322,7 +322,7 @@ namespace MonoDevelop.Ide.Projects IdeApp.ProjectOperations.AddFilesToProject (project, fileDialog.SelectedFiles, baseDirectory, buildAction); - IdeApp.ProjectOperations.Save (project); + IdeApp.ProjectOperations.SaveAsync (project); UpdateFileList (sender, e); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectOptionsDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectOptionsDialog.cs index 438e0ba79a..57da87b1a3 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectOptionsDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectOptionsDialog.cs @@ -43,7 +43,7 @@ namespace MonoDevelop.Ide.Projects /// </summary> public class ProjectOptionsDialog : MultiConfigItemOptionsDialog { - public ProjectOptionsDialog (Gtk.Window parentWindow, SolutionEntityItem project) : base (parentWindow, project) + public ProjectOptionsDialog (Gtk.Window parentWindow, SolutionItem project) : base (parentWindow, project) { this.Title = GettextCatalog.GetString ("Project Options") + " - " + project.Name; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectReferencePanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectReferencePanel.cs index edf0032940..268ef500c7 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectReferencePanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectReferencePanel.cs @@ -180,7 +180,7 @@ namespace MonoDevelop.Ide.Projects { Dictionary<DotNetProject,bool> references = new Dictionary<DotNetProject, bool> (); - foreach (Project projectEntry in openSolution.GetAllSolutionItems<Project>()) { + foreach (Project projectEntry in openSolution.GetAllItems<Project>()) { if (projectEntry == configureProject) continue; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectSelectorDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectSelectorDialog.cs index 21c9816b5e..1d0c4f6dd4 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectSelectorDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ProjectSelectorDialog.cs @@ -56,12 +56,12 @@ namespace MonoDevelop.Ide.Projects } } - public IBuildTarget SelectedItem { + public WorkspaceObject SelectedItem { get { return selector.SelectedItem; } set { selector.SelectedItem = value; } } - public IEnumerable<IBuildTarget> ActiveItems { + public IEnumerable<WorkspaceObject> ActiveItems { get { return selector.ActiveItems; } set { selector.ActiveItems = value; } } @@ -76,7 +76,7 @@ namespace MonoDevelop.Ide.Projects set { selector.CascadeCheckboxSelection = value; } } - public IBuildTarget RootItem { + public WorkspaceObject RootItem { get { return selector.RootItem; } set { selector.RootItem = value; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs index c3cd89c632..4e2cc5fb17 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs @@ -231,7 +231,7 @@ namespace MonoDevelop.Ide.Projects selectedHeader.Remove (w); HeaderBox header = new HeaderBox (1, 0, 1, 1); header.SetPadding (6, 6, 6, 6); - header.GradientBackround = true; + header.GradientBackground = true; header.Add (w); selectedHeader.Add (header); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.StandardHeader/StandardHeaderService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.StandardHeader/StandardHeaderService.cs index c34f26b240..f3692a002d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.StandardHeader/StandardHeaderService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.StandardHeader/StandardHeaderService.cs @@ -42,7 +42,7 @@ namespace MonoDevelop.Ide.StandardHeader { public static class StandardHeaderService { - public static string GetHeader (SolutionItem policyParent, string fileName, bool newFile) + public static string GetHeader (SolutionFolderItem policyParent, string fileName, bool newFile) { StandardHeaderPolicy headerPolicy = policyParent != null ? policyParent.Policies.Get<StandardHeaderPolicy> () : MonoDevelop.Projects.Policies.PolicyService.GetDefaultPolicy<StandardHeaderPolicy> (); TextStylePolicy textPolicy = policyParent != null ? policyParent.Policies.Get<TextStylePolicy> ("text/plain") : MonoDevelop.Projects.Policies.PolicyService.GetDefaultPolicy<TextStylePolicy> ("text/plain"); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksView.cs index 74fbae57bc..78bdd57192 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksView.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksView.cs @@ -94,7 +94,7 @@ namespace MonoDevelop.Ide.Tasks typeof (string), // desc typeof (string), // file typeof (string), // path - typeof (Task), // task + typeof (UserTask), // task typeof (Gdk.Color), // foreground color typeof (int)); // font weight @@ -143,7 +143,7 @@ namespace MonoDevelop.Ide.Tasks PropertyService.PropertyChanged += DispatchService.GuiDispatch<EventHandler<PropertyChangedEventArgs>> (OnPropertyUpdated); // Initialize with existing tags. - foreach (Task t in comments) + foreach (UserTask t in comments) AddGeneratedTask (t); view.Destroyed += delegate { @@ -197,7 +197,7 @@ namespace MonoDevelop.Ide.Tasks void LoadWorkspaceItemContents (WorkspaceItem wob) { - foreach (var sln in wob.GetAllSolutions ()) + foreach (var sln in wob.GetAllItems<Solution> ()) LoadSolutionContents (sln); } @@ -247,7 +247,7 @@ namespace MonoDevelop.Ide.Tasks void OnWorkspaceItemUnloaded (object sender, WorkspaceItemEventArgs e) { - foreach (var sln in e.Item.GetAllSolutions ()) + foreach (var sln in e.Item.GetAllItems<Solution>()) loadedSlns.Remove (sln); comments.RemoveItemTasks (e.Item, true); } @@ -276,7 +276,7 @@ namespace MonoDevelop.Ide.Tasks fileName = fileName.FullPath; - List<Task> newTasks = new List<Task> (); + List<UserTask> newTasks = new List<UserTask> (); if (tagComments != null) { foreach (Tag tag in tagComments) { TaskPriority priority; @@ -297,13 +297,13 @@ namespace MonoDevelop.Ide.Tasks } } - Task t = new Task (fileName, desc, tag.Region.BeginColumn, tag.Region.BeginLine, + UserTask t = new UserTask (fileName, desc, tag.Region.BeginColumn, tag.Region.BeginLine, TaskSeverity.Information, priority, wob); newTasks.Add (t); } } - List<Task> oldTasks = new List<Task> (comments.GetFileTasks (fileName)); + List<UserTask> oldTasks = new List<UserTask> (comments.GetFileTasks (fileName)); for (int i = 0; i < newTasks.Count; ++i) { for (int j = 0; j < oldTasks.Count; ++j) { @@ -339,11 +339,11 @@ namespace MonoDevelop.Ide.Tasks void GeneratedTaskAdded (object sender, TaskEventArgs e) { - foreach (Task t in e.Tasks) + foreach (UserTask t in e.Tasks) AddGeneratedTask (t); } - void AddGeneratedTask (Task t) + void AddGeneratedTask (UserTask t) { FilePath tmpPath = t.FileName; if (t.WorkspaceObject != null) @@ -354,25 +354,25 @@ namespace MonoDevelop.Ide.Tasks void GeneratedTaskRemoved (object sender, TaskEventArgs e) { - foreach (Task t in e.Tasks) + foreach (UserTask t in e.Tasks) RemoveGeneratedTask (t); } - void RemoveGeneratedTask (Task t) + void RemoveGeneratedTask (UserTask t) { TreeIter iter = FindTask (store, t); if (!iter.Equals (TreeIter.Zero)) store.Remove (ref iter); } - static TreeIter FindTask (ListStore store, Task task) + static TreeIter FindTask (ListStore store, UserTask task) { TreeIter iter; if (!store.GetIterFirst (out iter)) return TreeIter.Zero; do { - Task t = store.GetValue (iter, (int)Columns.Task) as Task; + UserTask t = store.GetValue (iter, (int)Columns.Task) as UserTask; if (t == task) return iter; } @@ -466,7 +466,7 @@ namespace MonoDevelop.Ide.Tasks void OnGenTaskCopied (object o, EventArgs args) { - Task task = SelectedTask; + UserTask task = SelectedTask; if (task != null) { clipboard = Clipboard.Get (Gdk.Atom.Intern ("CLIPBOARD", false)); clipboard.Text = task.ToString (); @@ -475,14 +475,14 @@ namespace MonoDevelop.Ide.Tasks } } - Task SelectedTask + UserTask SelectedTask { get { TreeModel model; TreeIter iter; if (view.Selection.GetSelected (out model, out iter)) { - return (Task)model.GetValue (iter, (int)Columns.Task); + return (UserTask)model.GetValue (iter, (int)Columns.Task); } else return null; // no one selected } @@ -490,7 +490,7 @@ namespace MonoDevelop.Ide.Tasks void OnGenTaskJumpto (object o, EventArgs args) { - Task task = SelectedTask; + UserTask task = SelectedTask; if (task != null) task.JumpToPosition (); } @@ -502,7 +502,7 @@ namespace MonoDevelop.Ide.Tasks void OnGenTaskDelete (object o, EventArgs args) { - Task task = SelectedTask; + UserTask task = SelectedTask; if (task != null && ! String.IsNullOrEmpty (task.FileName)) { Document doc = IdeApp.Workbench.OpenDocument (task.FileName, Math.Max (1, task.Line), Math.Max (1, task.Column)); if (doc != null && doc.HasProject && doc.Project is DotNetProject) { @@ -618,7 +618,7 @@ namespace MonoDevelop.Ide.Tasks { do { - Task task = (Task) store.GetValue (iter, (int)Columns.Task); + UserTask task = (UserTask) store.GetValue (iter, (int)Columns.Task); store.SetValue (iter, (int)Columns.Foreground, GetColorByPriority (task.Priority)); } while (store.IterNext (ref iter)); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskService.cs index e29aefd2d3..6432322c8b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskService.cs @@ -104,7 +104,7 @@ namespace MonoDevelop.Ide.Tasks /// <summary> /// Shows a description of the task in the status bar /// </summary> - public static void ShowStatus (Task t) + public static void ShowStatus (UserTask t) { if (t == null) IdeApp.Workbench.StatusBar.ShowMessage (GettextCatalog.GetString ("No more errors or warnings")); @@ -125,8 +125,8 @@ namespace MonoDevelop.Ide.Tasks // Load User Tasks from xml file if (File.Exists (fileToLoad)) { XmlDataSerializer serializer = new XmlDataSerializer (new DataContext ()); - List<Task> ts = (List<Task>) serializer.Deserialize (fileToLoad, typeof(List<Task>)); - foreach (Task t in ts) { + List<UserTask> ts = (List<UserTask>) serializer.Deserialize (fileToLoad, typeof(List<UserTask>)); + foreach (UserTask t in ts) { t.WorkspaceObject = e.Item; userTasks.Add (t); } @@ -157,11 +157,11 @@ namespace MonoDevelop.Ide.Tasks return combinePath.Combine (item.FileName.FileNameWithoutExtension + ".usertasks"); } - internal static void SaveUserTasks (IWorkspaceObject item) + internal static void SaveUserTasks (WorkspaceObject item) { string fileToSave = GetUserTasksFilename ((WorkspaceItem)item); try { - List<Task> utasks = new List<Task> (userTasks.GetItemTasks (item, true)); + List<UserTask> utasks = new List<UserTask> (userTasks.GetItemTasks (item, true)); if (utasks.Count == 0) { if (File.Exists (fileToSave)) File.Delete (fileToSave); @@ -177,7 +177,7 @@ namespace MonoDevelop.Ide.Tasks public static event EventHandler<TaskEventArgs> JumpedToTask; - internal static void InformJumpToTask (Task task) + internal static void InformJumpToTask (UserTask task) { EventHandler<TaskEventArgs> handler = JumpedToTask; if (handler != null) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskStore.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskStore.cs index bb41f90835..3415d4392b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskStore.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskStore.cs @@ -45,18 +45,18 @@ using MonoDevelop.Ide.TextEditing; namespace MonoDevelop.Ide.Tasks
{
- public class TaskStore: IEnumerable<Task>, ILocationList
+ public class TaskStore: IEnumerable<UserTask>, ILocationList
{
int taskUpdateCount; - List<Task> tasks = new List<Task> (); - Dictionary<FilePath,Task[]> taskIndex = new Dictionary<FilePath, Task[]> (); + List<UserTask> tasks = new List<UserTask> (); + Dictionary<FilePath,UserTask[]> taskIndex = new Dictionary<FilePath, UserTask[]> (); public event TaskEventHandler TasksAdded; public event TaskEventHandler TasksRemoved; public event TaskEventHandler TasksChanged; - List<Task> tasksAdded; - List<Task> tasksRemoved; + List<UserTask> tasksAdded; + List<UserTask> tasksRemoved; public TaskStore ()
{
@@ -64,13 +64,13 @@ namespace MonoDevelop.Ide.Tasks IdeApp.Workspace.FileRemovedFromProject += ProjectFileRemoved; TextEditorService.LineCountChangesCommitted += delegate (object sender, TextFileEventArgs args) { - foreach (Task task in GetFileTasks (args.TextFile.Name.FullPath)) + foreach (UserTask task in GetFileTasks (args.TextFile.Name.FullPath)) task.SavedLine = -1; }; TextEditorService.LineCountChangesReset += delegate (object sender, TextFileEventArgs args) { - Task[] ctasks = GetFileTasks (args.TextFile.Name.FullPath); - foreach (Task task in ctasks) { + UserTask[] ctasks = GetFileTasks (args.TextFile.Name.FullPath); + foreach (UserTask task in ctasks) { if (task.SavedLine != -1) { task.Line = task.SavedLine; task.SavedLine = -1; @@ -82,8 +82,8 @@ namespace MonoDevelop.Ide.Tasks TextEditorService.LineCountChanged += delegate (object sender, LineCountEventArgs args) { if (args.TextFile == null || args.TextFile.Name.IsNullOrEmpty) return; - Task[] ctasks = GetFileTasks (args.TextFile.Name.FullPath); - foreach (Task task in ctasks) { + UserTask[] ctasks = GetFileTasks (args.TextFile.Name.FullPath); + foreach (UserTask task in ctasks) { if (task.Line > args.LineNumber || (task.Line == args.LineNumber && task.Column >= args.Column)) { if (task.SavedLine == -1) task.SavedLine = task.Line; @@ -94,17 +94,17 @@ namespace MonoDevelop.Ide.Tasks }; } - public void Add (Task task) + public void Add (UserTask task) { tasks.Add (task); OnTaskAdded (task); } - public void AddRange (IEnumerable<Task> newTasks) + public void AddRange (IEnumerable<UserTask> newTasks) { BeginTaskUpdates (); try { - foreach (Task t in newTasks) { + foreach (UserTask t in newTasks) { tasks.Add (t); OnTaskAdded (t); } @@ -113,11 +113,11 @@ namespace MonoDevelop.Ide.Tasks } } - public void RemoveRange (IEnumerable<Task> tasks) + public void RemoveRange (IEnumerable<UserTask> tasks) { BeginTaskUpdates (); try { - foreach (Task t in tasks) { + foreach (UserTask t in tasks) { if (this.tasks.Remove (t)) OnTaskRemoved (t); } @@ -126,22 +126,22 @@ namespace MonoDevelop.Ide.Tasks } } - public void RemoveItemTasks (IWorkspaceObject parent) + public void RemoveItemTasks (WorkspaceObject parent) { - RemoveRange (new List<Task> (GetItemTasks (parent))); + RemoveRange (new List<UserTask> (GetItemTasks (parent))); } - public void RemoveItemTasks (IWorkspaceObject parent, bool checkHierarchy) + public void RemoveItemTasks (WorkspaceObject parent, bool checkHierarchy) { - RemoveRange (new List<Task> (GetItemTasks (parent, checkHierarchy))); + RemoveRange (new List<UserTask> (GetItemTasks (parent, checkHierarchy))); } public void RemoveFileTasks (FilePath file) { - RemoveRange (new List<Task> (GetFileTasks (file))); + RemoveRange (new List<UserTask> (GetFileTasks (file))); } - public void Remove (Task task) + public void Remove (UserTask task) { if (tasks.Remove (task)) OnTaskRemoved (task); @@ -151,9 +151,9 @@ namespace MonoDevelop.Ide.Tasks { try { BeginTaskUpdates (); - List<Task> toRemove = tasks; - tasks = new List<Task> (); - foreach (Task t in toRemove) + List<UserTask> toRemove = tasks; + tasks = new List<UserTask> (); + foreach (UserTask t in toRemove) OnTaskRemoved (t); } finally { EndTaskUpdates (); @@ -164,8 +164,8 @@ namespace MonoDevelop.Ide.Tasks { try { BeginTaskUpdates (); - List<Task> toRemove = new List<Task> (GetOwnerTasks (owner)); - foreach (Task t in toRemove) + List<UserTask> toRemove = new List<UserTask> (GetOwnerTasks (owner)); + foreach (UserTask t in toRemove) Remove (t); } finally { EndTaskUpdates (); @@ -176,7 +176,7 @@ namespace MonoDevelop.Ide.Tasks get { return tasks.Count; } } - public IEnumerator<Task> GetEnumerator () + public IEnumerator<UserTask> GetEnumerator () { return tasks.GetEnumerator (); } @@ -186,31 +186,31 @@ namespace MonoDevelop.Ide.Tasks return ((IEnumerable)tasks).GetEnumerator (); } - public IEnumerable<Task> GetOwnerTasks (object owner) + public IEnumerable<UserTask> GetOwnerTasks (object owner) { - foreach (Task t in tasks) { + foreach (UserTask t in tasks) { if (t.Owner == owner) yield return t; } } - public Task[] GetFileTasks (FilePath file) + public UserTask[] GetFileTasks (FilePath file) { - Task[] ta; + UserTask[] ta; if (taskIndex.TryGetValue (file, out ta)) return ta; else - return new Task [0]; + return new UserTask [0]; } - public IEnumerable<Task> GetItemTasks (IWorkspaceObject parent) + public IEnumerable<UserTask> GetItemTasks (WorkspaceObject parent) { return GetItemTasks (parent, true); } - public IEnumerable<Task> GetItemTasks (IWorkspaceObject parent, bool checkHierarchy) + public IEnumerable<UserTask> GetItemTasks (WorkspaceObject parent, bool checkHierarchy) { - foreach (Task t in tasks) { + foreach (UserTask t in tasks) { if (t.BelongsToItem (parent, checkHierarchy)) yield return t; } @@ -220,16 +220,16 @@ namespace MonoDevelop.Ide.Tasks { if (taskUpdateCount++ != 0) return; - tasksAdded = new List<Task> (); - tasksRemoved = new List<Task> (); + tasksAdded = new List<UserTask> (); + tasksRemoved = new List<UserTask> (); } public void EndTaskUpdates () { if (--taskUpdateCount != 0) return; - List<Task> oldAdded = tasksAdded; - List<Task> oldRemoved = tasksRemoved; + List<UserTask> oldAdded = tasksAdded; + List<UserTask> oldRemoved = tasksRemoved; tasksAdded = null; tasksRemoved = null; if (oldRemoved.Count > 0) @@ -238,7 +238,7 @@ namespace MonoDevelop.Ide.Tasks NotifyTasksAdded (oldAdded); } - void NotifyTasksAdded (IEnumerable<Task> ts) + void NotifyTasksAdded (IEnumerable<UserTask> ts) { try { if (TasksAdded != null) @@ -248,7 +248,7 @@ namespace MonoDevelop.Ide.Tasks } } - void NotifyTasksChanged (IEnumerable<Task> ts) + void NotifyTasksChanged (IEnumerable<UserTask> ts) { try { if (TasksChanged != null) @@ -258,7 +258,7 @@ namespace MonoDevelop.Ide.Tasks } } - void NotifyTasksRemoved (IEnumerable<Task> ts) + void NotifyTasksRemoved (IEnumerable<UserTask> ts) { try { if (TasksRemoved != null) @@ -268,28 +268,28 @@ namespace MonoDevelop.Ide.Tasks } } - internal void OnTaskAdded (Task t) + internal void OnTaskAdded (UserTask t) { if (t.FileName != FilePath.Null) { - Task[] ta; + UserTask[] ta; if (taskIndex.TryGetValue (t.FileName, out ta)) { Array.Resize (ref ta, ta.Length + 1); ta [ta.Length - 1] = t; } else { - ta = new Task [] { t }; + ta = new UserTask [] { t }; } taskIndex [t.FileName] = ta; } if (tasksAdded != null) tasksAdded.Add (t); else - NotifyTasksAdded (new Task [] { t }); + NotifyTasksAdded (new UserTask [] { t }); } - internal void OnTaskRemoved (Task t) + internal void OnTaskRemoved (UserTask t) { if (t.FileName != FilePath.Null) { - Task[] ta; + UserTask[] ta; if (taskIndex.TryGetValue (t.FileName, out ta)) { if (ta.Length == 1) { if (ta [0] == t) @@ -297,7 +297,7 @@ namespace MonoDevelop.Ide.Tasks } else { int i = Array.IndexOf (ta, t); if (i != -1) { - Task[] newTa = new Task [ta.Length - 1]; + UserTask[] newTa = new UserTask [ta.Length - 1]; Array.Copy (ta, 0, newTa, 0, i); Array.Copy (ta, i+1, newTa, i, ta.Length - i - 1); taskIndex [t.FileName] = newTa; @@ -308,7 +308,7 @@ namespace MonoDevelop.Ide.Tasks if (tasksRemoved != null) tasksRemoved.Add (t); else - NotifyTasksRemoved (new Task [] { t }); + NotifyTasksRemoved (new UserTask [] { t }); } void ProjectFileRemoved (object sender, ProjectFileEventArgs args) @@ -316,7 +316,7 @@ namespace MonoDevelop.Ide.Tasks BeginTaskUpdates (); try { foreach (ProjectFileEventInfo e in args) { - foreach (Task curTask in new List<Task> (GetFileTasks (e.ProjectFile.FilePath))) { + foreach (UserTask curTask in new List<UserTask> (GetFileTasks (e.ProjectFile.FilePath))) { Remove (curTask); } } @@ -330,8 +330,8 @@ namespace MonoDevelop.Ide.Tasks BeginTaskUpdates (); try { foreach (ProjectFileRenamedEventInfo e in args) { - Task[] ctasks = GetFileTasks (e.OldName); - foreach (Task curTask in ctasks) + UserTask[] ctasks = GetFileTasks (e.OldName); + foreach (UserTask curTask in ctasks) curTask.FileName = e.NewName; taskIndex.Remove (e.OldName); taskIndex [e.NewName] = ctasks; @@ -345,7 +345,7 @@ namespace MonoDevelop.Ide.Tasks #region ILocationList implementation - Task currentLocationTask; + UserTask currentLocationTask; TaskSeverity iteratingSeverity; public void ResetLocationList () @@ -356,7 +356,7 @@ namespace MonoDevelop.Ide.Tasks public event EventHandler CurrentLocationTaskChanged; - public Task CurrentLocationTask { + public UserTask CurrentLocationTask { get { return currentLocationTask; } set { currentLocationTask = value; @@ -371,9 +371,9 @@ namespace MonoDevelop.Ide.Tasks class TaskNavigationPoint : TextFileNavigationPoint { - Task task; + UserTask task; - public TaskNavigationPoint (Task task) : base (task.FileName, task.Line, task.Column) + public TaskNavigationPoint (UserTask task) : base (task.FileName, task.Line, task.Column) { this.task = task; } @@ -405,7 +405,7 @@ namespace MonoDevelop.Ide.Tasks (iteratingSeverity != tasks [n].Severity || !IsProjectTaskFile (tasks [n]))) n++; - Task ct = n != -1 && n < tasks.Count ? tasks [n] : null; + UserTask ct = n != -1 && n < tasks.Count ? tasks [n] : null; if (ct == null) { if (iteratingSeverity != TaskSeverity.Comment) { iteratingSeverity++; @@ -428,7 +428,7 @@ namespace MonoDevelop.Ide.Tasks } } - public static bool IsProjectTaskFile (Task t) + public static bool IsProjectTaskFile (UserTask t) { if (t.FileName.IsNullOrEmpty) return false; @@ -461,7 +461,7 @@ namespace MonoDevelop.Ide.Tasks while (n != -1 && n < tasks.Count && (iteratingSeverity != tasks [n].Severity || string.IsNullOrEmpty (tasks [n].FileName))) n--; - Task ct = n != -1 && n < tasks.Count ? tasks [n] : null; + UserTask ct = n != -1 && n < tasks.Count ? tasks [n] : null; if (ct == null) { if (iteratingSeverity != TaskSeverity.Error) { iteratingSeverity--; @@ -484,7 +484,7 @@ namespace MonoDevelop.Ide.Tasks } } - int IndexOfTask (Task t) + int IndexOfTask (UserTask t) { for (int n=0; n<tasks.Count; n++) { if (tasks [n] == t) @@ -504,18 +504,18 @@ namespace MonoDevelop.Ide.Tasks public class TaskEventArgs : EventArgs { - IEnumerable<Task> tasks; + IEnumerable<UserTask> tasks; - public TaskEventArgs (Task task) : this (new Task[] { task }) + public TaskEventArgs (UserTask task) : this (new UserTask[] { task }) { } - public TaskEventArgs (IEnumerable<Task> tasks) + public TaskEventArgs (IEnumerable<UserTask> tasks) { this.tasks = tasks; } - public IEnumerable<Task> Tasks + public IEnumerable<UserTask> Tasks { get { return tasks; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/Task.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/UserTask.cs index 09bd276157..9af6389931 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/Task.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/UserTask.cs @@ -37,7 +37,7 @@ using MonoDevelop.Core.Serialization; namespace MonoDevelop.Ide.Tasks { - public class Task + public class UserTask { [ItemProperty] FilePath file; @@ -64,25 +64,25 @@ namespace MonoDevelop.Ide.Tasks bool completed; object owner; - IWorkspaceObject parentObject; + WorkspaceObject parentObject; internal int SavedLine; - public Task (FilePath file, string description, int column, int line, TaskSeverity severity) + public UserTask (FilePath file, string description, int column, int line, TaskSeverity severity) : this (file, description, column, line, severity, TaskPriority.Normal, null, null) { } - public Task (FilePath file, string description, int column, int line, TaskSeverity severity, TaskPriority priority) + public UserTask (FilePath file, string description, int column, int line, TaskSeverity severity, TaskPriority priority) : this (file, description, column, line, severity, priority, null, null) { } - public Task (FilePath file, string description, int column, int line, TaskSeverity severity, TaskPriority priority, IWorkspaceObject parent) + public UserTask (FilePath file, string description, int column, int line, TaskSeverity severity, TaskPriority priority, WorkspaceObject parent) : this (file, description, column, line, severity, priority, parent, null) { } - public Task (FilePath file, string description, int column, int line, TaskSeverity severity, TaskPriority priority, IWorkspaceObject parent, object owner) + public UserTask (FilePath file, string description, int column, int line, TaskSeverity severity, TaskPriority priority, WorkspaceObject parent, object owner) { this.file = file; this.description = description; @@ -94,19 +94,19 @@ namespace MonoDevelop.Ide.Tasks this.parentObject = parent; } - public Task () + public UserTask () { } - public Task (BuildError error) + public UserTask (BuildError error) : this (error, null) { } - public Task (BuildError error, object owner) + public UserTask (BuildError error, object owner) { - parentObject = error.SourceTarget; + parentObject = error.SourceTarget as WorkspaceObject; file = error.FileName; this.owner = owner; description = error.ErrorText; @@ -179,7 +179,7 @@ namespace MonoDevelop.Ide.Tasks } } - public IWorkspaceObject WorkspaceObject { + public WorkspaceObject WorkspaceObject { get { return parentObject; } @@ -224,17 +224,17 @@ namespace MonoDevelop.Ide.Tasks TaskService.InformJumpToTask (this); } - public bool BelongsToItem (IWorkspaceObject item, bool checkHierarchy) + public bool BelongsToItem (WorkspaceObject item, bool checkHierarchy) { if (!checkHierarchy) return item == parentObject; - IWorkspaceObject cit = parentObject; + WorkspaceObject cit = parentObject; do { if (cit == item) return true; - if (cit is SolutionItem) { - SolutionItem si = (SolutionItem) cit; + if (cit is SolutionFolderItem) { + SolutionFolderItem si = (SolutionFolderItem) cit; if (si.ParentFolder != null) cit = si.ParentFolder; else diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/UserTasksView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/UserTasksView.cs index f0a97916a8..8757665453 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/UserTasksView.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/UserTasksView.cs @@ -72,7 +72,7 @@ namespace MonoDevelop.Ide.Tasks typeof (string), // priority typeof (bool), // completed typeof (string), // desc - typeof (Task), // user task + typeof (UserTask), // user task typeof (Gdk.Color), // foreground color typeof (int)); // font style @@ -157,7 +157,7 @@ namespace MonoDevelop.Ide.Tasks view.ScrollToPoint (0, 0); store.Clear (); - foreach (Task task in TaskService.UserTasks) { + foreach (UserTask task in TaskService.UserTasks) { store.AppendValues (GettextCatalog.GetString (Enum.GetName (typeof (TaskPriority), task.Priority)), task.Completed, task.Description, task, GetColorByPriority (task.Priority), task.Completed ? (int)Pango.Weight.Light : (int)Pango.Weight.Bold); } ValidateButtons (); @@ -188,7 +188,7 @@ namespace MonoDevelop.Ide.Tasks { do { - Task task = (Task) store.GetValue (iter, (int)Columns.UserTask); + UserTask task = (UserTask) store.GetValue (iter, (int)Columns.UserTask); store.SetValue (iter, (int)Columns.Foreground, GetColorByPriority (task.Priority)); } while (store.IterNext (ref iter)); } @@ -208,7 +208,7 @@ namespace MonoDevelop.Ide.Tasks void NewUserTaskClicked (object obj, EventArgs e) { - Task task = new Task (); + UserTask task = new UserTask (); task.WorkspaceObject = IdeApp.ProjectOperations.CurrentSelectedWorkspaceItem; updating = true; TaskService.UserTasks.Add (task); @@ -228,7 +228,7 @@ namespace MonoDevelop.Ide.Tasks TreeIter iter; if (store.GetIter (out iter, view.Selection.GetSelectedRows ()[0])) { - Task task = (Task) store.GetValue (iter, (int)Columns.UserTask); + UserTask task = (UserTask) store.GetValue (iter, (int)Columns.UserTask); updating = true; TaskService.UserTasks.Remove (task); updating = false; @@ -242,7 +242,7 @@ namespace MonoDevelop.Ide.Tasks { Gtk.TreeIter iter; if (store.GetIterFromString (out iter, args.Path)) { - Task task = (Task) store.GetValue (iter, (int)Columns.UserTask); + UserTask task = (UserTask) store.GetValue (iter, (int)Columns.UserTask); if (args.Active == 0) { task.Priority = TaskPriority.High; @@ -286,7 +286,7 @@ namespace MonoDevelop.Ide.Tasks Gtk.TreeIter iter; if (store.GetIterFromString (out iter, args.Path)) { bool val = (bool)store.GetValue (iter, (int)Columns.Completed); - Task task = (Task) store.GetValue (iter, (int)Columns.UserTask); + UserTask task = (UserTask) store.GetValue (iter, (int)Columns.UserTask); task.Completed = !val; store.SetValue (iter, (int)Columns.Completed, !val); store.SetValue (iter, (int)Columns.Bold, task.Completed ? (int)Pango.Weight.Light : (int)Pango.Weight.Bold); @@ -310,7 +310,7 @@ namespace MonoDevelop.Ide.Tasks { Gtk.TreeIter iter; if (store.GetIterFromString (out iter, args.Path)) { - Task task = (Task) store.GetValue (iter, (int)Columns.UserTask); + UserTask task = (UserTask) store.GetValue (iter, (int)Columns.UserTask); task.Description = args.NewText; store.SetValue (iter, (int)Columns.Description, args.NewText); TaskService.SaveUserTasks (task.WorkspaceObject); @@ -355,13 +355,13 @@ namespace MonoDevelop.Ide.Tasks void OnUserTaskCopied (object o, EventArgs args) { - Task task; + UserTask task; TreeModel model; TreeIter iter; if (view.Selection.GetSelected (out model, out iter)) { - task = (Task) model.GetValue (iter, (int)Columns.UserTask); + task = (UserTask) model.GetValue (iter, (int)Columns.UserTask); } else return; // no one selected diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/CodeDomFileDescriptionTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/CodeDomFileDescriptionTemplate.cs index f4f064c1cd..3a57928536 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/CodeDomFileDescriptionTemplate.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/CodeDomFileDescriptionTemplate.cs @@ -115,7 +115,7 @@ namespace MonoDevelop.Ide.Templates } } - int offset = doc.GetLine (realStartLine).Offset; + int offset = doc.GetLine (Math.Max(Mono.TextEditor.DocumentLocation.MinLine, realStartLine)).Offset; return doc.GetTextAt (offset, doc.TextLength - offset); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/CodeTranslationFileDescriptionTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/CodeTranslationFileDescriptionTemplate.cs index f641faee66..0a669a7b17 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/CodeTranslationFileDescriptionTemplate.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/CodeTranslationFileDescriptionTemplate.cs @@ -134,7 +134,7 @@ namespace MonoDevelop.Ide.Templates return txt.Substring (i+1); } - public override void ModifyTags (SolutionItem policyParent, Project project, string language, string identifier, string fileName, ref Dictionary<string,string> tags) + public override void ModifyTags (SolutionFolderItem policyParent, Project project, string language, string identifier, string fileName, ref Dictionary<string,string> tags) { //prevent parser breakage from missing tags, which SingleFile only provides for DotNetProject //if ((project as DotNetProject) == null) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/DirectoryTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/DirectoryTemplate.cs index 6f91811444..9992402f8c 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/DirectoryTemplate.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/DirectoryTemplate.cs @@ -87,7 +87,7 @@ namespace MonoDevelop.Ide.Templates t.Show (); } - public override bool AddToProject (SolutionItem policyParent, Project project, + public override bool AddToProject (SolutionFolderItem policyParent, Project project, string language, string directory, string name) { bool addedSomething = false; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileDescriptionTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileDescriptionTemplate.cs index 181afb93cf..bb103f722c 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileDescriptionTemplate.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileDescriptionTemplate.cs @@ -75,7 +75,7 @@ namespace MonoDevelop.Ide.Templates public abstract string Name { get; } public abstract void Load (XmlElement filenode, FilePath baseDirectory); - public abstract bool AddToProject (SolutionItem policyParent, Project project, string language, string directory, string name); + public abstract bool AddToProject (SolutionFolderItem policyParent, Project project, string language, string directory, string name); public abstract void Show (); public virtual bool IsValidName (string name, string language) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplate.cs index dd3fc5d476..93ab834b62 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplate.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplate.cs @@ -294,7 +294,7 @@ namespace MonoDevelop.Ide.Templates return null; } - public virtual bool Create (SolutionItem policyParent, Project project, string directory, string language, string name) + public virtual bool Create (SolutionFolderItem policyParent, Project project, string directory, string language, string name) { if (!String.IsNullOrEmpty(WizardPath)) { //Properties customizer = new Properties(); @@ -342,7 +342,7 @@ namespace MonoDevelop.Ide.Templates return mimeType; } - public virtual bool CanCreateUnsavedFiles (FileDescriptionTemplate newfile, SolutionItem policyParent, Project project, string directory, string language, string name) + public virtual bool CanCreateUnsavedFiles (FileDescriptionTemplate newfile, SolutionFolderItem policyParent, Project project, string directory, string language, string name) { if (project != null) { return true; @@ -361,7 +361,7 @@ namespace MonoDevelop.Ide.Templates } } - protected virtual bool CreateFile (FileDescriptionTemplate newfile, SolutionItem policyParent, Project project, string directory, string language, string name) + protected virtual bool CreateFile (FileDescriptionTemplate newfile, SolutionFolderItem policyParent, Project project, string directory, string language, string name) { if (project != null) { if (newfile.AddToProject (policyParent, project, language, directory, name)) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplateReference.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplateReference.cs index 97dd1c0f92..0e09e343a9 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplateReference.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplateReference.cs @@ -69,7 +69,7 @@ namespace MonoDevelop.Ide.Templates get { return name;} } - public override bool AddToProject (SolutionItem policyParent, Project project, string language, string directory, string entryName) + public override bool AddToProject (SolutionFolderItem policyParent, Project project, string language, string directory, string entryName) { string[,] customTags = new string[,] { {"ProjectName", project.Name}, diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ISolutionItemDescriptor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ISolutionItemDescriptor.cs index 9012f7b9ba..13d6804573 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ISolutionItemDescriptor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ISolutionItemDescriptor.cs @@ -34,7 +34,7 @@ namespace MonoDevelop.Ide.Templates { internal interface ISolutionItemDescriptor { - SolutionEntityItem CreateItem (ProjectCreateInformation projectCreateInformation, string defaultLanguage); - void InitializeItem (SolutionItem policyParent, ProjectCreateInformation projectCreateInformation, string defaultLanguage, SolutionEntityItem item); + SolutionItem CreateItem (ProjectCreateInformation projectCreateInformation, string defaultLanguage); + void InitializeItem (SolutionFolderItem policyParent, ProjectCreateInformation projectCreateInformation, string defaultLanguage, SolutionItem item); } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ISolutionItemFeature.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ISolutionItemFeature.cs index dcd4ace676..f328a3472f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ISolutionItemFeature.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ISolutionItemFeature.cs @@ -75,7 +75,7 @@ namespace MonoDevelop.Ide.Templates /// The provided item, parent folder and parent solution may or may not have a file name, and even if they /// have, they may not be saved to disk. parentFolder can be null. /// </remarks> - FeatureSupportLevel GetSupportLevel (SolutionFolder parentFolder, SolutionItem item); + FeatureSupportLevel GetSupportLevel (SolutionFolder parentFolder, SolutionFolderItem item); /// <summary> /// Short title of the feature @@ -103,7 +103,7 @@ namespace MonoDevelop.Ide.Templates /// The provided item, parent folder and parent solution may or may not have a file name, and even if they /// have, they may not be saved to disk. /// </remarks> - Gtk.Widget CreateFeatureEditor (SolutionFolder parentFolder, SolutionItem entry); + Gtk.Widget CreateFeatureEditor (SolutionFolder parentFolder, SolutionFolderItem entry); /// <summary> /// Validates the configuration of the feature @@ -128,7 +128,7 @@ namespace MonoDevelop.Ide.Templates /// The provided item, parent folder and parent solution may or may not have a file name, and even if they /// have, they may not be saved to disk. /// </remarks> - string Validate (SolutionFolder parentFolder, SolutionItem entry, Gtk.Widget editor); + string Validate (SolutionFolder parentFolder, SolutionFolderItem entry, Gtk.Widget editor); /// <summary> /// Applies the feature to a project @@ -146,12 +146,12 @@ namespace MonoDevelop.Ide.Templates /// The provided item, parent folder and parent solution may or may not have a file name, and even if they /// have, they may not be saved to disk. /// </remarks> - void ApplyFeature (SolutionFolder parentFolder, SolutionItem entry, Gtk.Widget editor); + void ApplyFeature (SolutionFolder parentFolder, SolutionFolderItem entry, Gtk.Widget editor); } internal class SolutionItemFeatures { - public static ISolutionItemFeature[] GetFeatures (SolutionFolder parentCombine, SolutionItem entry) + public static ISolutionItemFeature[] GetFeatures (SolutionFolder parentCombine, SolutionFolderItem entry) { List<ISolutionItemFeature> list = new List<ISolutionItemFeature> (); foreach (ISolutionItemFeature e in AddinManager.GetExtensionObjects ("/MonoDevelop/Ide/ProjectFeatures", typeof(ISolutionItemFeature), true)) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectDescriptor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectDescriptor.cs index ce49a15daa..196289b82d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectDescriptor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectDescriptor.cs @@ -117,12 +117,12 @@ namespace MonoDevelop.Ide.Templates return projectDescriptor; } - public SolutionEntityItem CreateItem (ProjectCreateInformation projectCreateInformation, string defaultLanguage) + public SolutionItem CreateItem (ProjectCreateInformation projectCreateInformation, string defaultLanguage) { if (string.IsNullOrEmpty (projectOptions.GetAttribute ("language")) && !string.IsNullOrEmpty (defaultLanguage)) projectOptions.SetAttribute ("language", defaultLanguage); - if (!Services.ProjectService.CanCreateProject (type)) { + if (!Services.ProjectService.CanCreateProject (type, projectCreateInformation, projectOptions)) { LoggingService.LogError ("Could not create project of type '" + type + "'. Project skipped"); return null; } @@ -130,7 +130,7 @@ namespace MonoDevelop.Ide.Templates return project; } - public void InitializeItem (SolutionItem policyParent, ProjectCreateInformation projectCreateInformation, string defaultLanguage, SolutionEntityItem item) + public void InitializeItem (SolutionFolderItem policyParent, ProjectCreateInformation projectCreateInformation, string defaultLanguage, SolutionItem item) { MonoDevelop.Projects.Project project = item as MonoDevelop.Projects.Project; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplate.cs index 9640135723..796235af41 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplate.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplate.cs @@ -46,6 +46,7 @@ using MonoDevelop.Ide.Codons; using MonoDevelop.Projects; using MonoDevelop.Ide.Gui; using System.Linq; +using System.Threading.Tasks; namespace MonoDevelop.Ide.Templates { @@ -217,17 +218,18 @@ namespace MonoDevelop.Ide.Templates } //methods - public IAsyncOperation OpenCreatedSolution () + public Task<bool> OpenCreatedSolution () { - IAsyncOperation asyncOperation = IdeApp.Workspace.OpenWorkspaceItem (createdSolutionName); - asyncOperation.Completed += delegate { - if (asyncOperation.Success) { + var asyncOperation = IdeApp.Workspace.OpenWorkspaceItem (createdSolutionName); + return asyncOperation.ContinueWith (t => { + if (t.Result) { foreach (string action in actions) { IdeApp.Workbench.OpenDocument (Path.Combine (createdProjectInformation.ProjectBasePath, action)); } + return true; } - }; - return asyncOperation; + return false; + }); } public WorkspaceItem CreateWorkspaceItem (ProjectCreateInformation cInfo) @@ -241,13 +243,13 @@ namespace MonoDevelop.Ide.Templates return workspaceItemInfo.WorkspaceItem; } - public SolutionEntityItem CreateProject (SolutionItem policyParent, ProjectCreateInformation cInfo) + public SolutionItem CreateProject (SolutionFolderItem policyParent, ProjectCreateInformation cInfo) { if (solutionDescriptor.EntryDescriptors.Length == 0) throw new InvalidOperationException ("Solution template doesn't have any project templates"); ISolutionItemDescriptor descriptor = solutionDescriptor.EntryDescriptors [0]; - SolutionEntityItem solutionEntryItem = descriptor.CreateItem (cInfo, this.languagename); + SolutionItem solutionEntryItem = descriptor.CreateItem (cInfo, this.languagename); descriptor.InitializeItem (policyParent, cInfo, this.languagename, solutionEntryItem); SavePackageReferences (solutionEntryItem, descriptor); @@ -257,7 +259,7 @@ namespace MonoDevelop.Ide.Templates return solutionEntryItem; } - void SavePackageReferences (SolutionEntityItem solutionEntryItem, ISolutionItemDescriptor descriptor) + void SavePackageReferences (SolutionItem solutionEntryItem, ISolutionItemDescriptor descriptor) { packageReferencesForCreatedProjects = new List<PackageReferencesForCreatedProject> (); if ((solutionEntryItem is Project) && (descriptor is ProjectDescriptor)) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ResourceFileDescriptionTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ResourceFileDescriptionTemplate.cs index e2cb831041..b52003c6ca 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ResourceFileDescriptionTemplate.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ResourceFileDescriptionTemplate.cs @@ -53,7 +53,7 @@ namespace MonoDevelop.Ide.Templates } } - public override bool AddToProject (SolutionItem policyParent, Project project, string language, string directory, string name) + public override bool AddToProject (SolutionFolderItem policyParent, Project project, string language, string directory, string name) { ProjectFile file = template.AddFileToProject (policyParent, project, language, directory, name); if (file != null) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SingleFileDescriptionTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SingleFileDescriptionTemplate.cs index b9a2a6ffa0..701850e4e7 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SingleFileDescriptionTemplate.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SingleFileDescriptionTemplate.cs @@ -104,12 +104,12 @@ namespace MonoDevelop.Ide.Templates set { addStandardHeader = value; } } - public sealed override bool AddToProject (SolutionItem policyParent, Project project, string language, string directory, string name) + public sealed override bool AddToProject (SolutionFolderItem policyParent, Project project, string language, string directory, string name) { return AddFileToProject (policyParent, project, language, directory, name) != null; } - public ProjectFile AddFileToProject (SolutionItem policyParent, Project project, string language, string directory, string name) + public ProjectFile AddFileToProject (SolutionFolderItem policyParent, Project project, string language, string directory, string name) { generatedFile = SaveFile (policyParent, project, language, directory, name); if (generatedFile != null) { @@ -187,7 +187,7 @@ namespace MonoDevelop.Ide.Templates // Creates a file and saves it to disk. Returns the path to the new file // All parameters are optional (can be null) - public string SaveFile (SolutionItem policyParent, Project project, string language, string baseDirectory, string entryName) + public string SaveFile (SolutionFolderItem policyParent, Project project, string language, string baseDirectory, string entryName) { string file = GetFileName (policyParent, project, language, baseDirectory, entryName); @@ -221,7 +221,7 @@ namespace MonoDevelop.Ide.Templates // Returns the name of the file that this template generates. // All parameters are optional (can be null) - public virtual string GetFileName (SolutionItem policyParent, Project project, string language, string baseDirectory, string entryName) + public virtual string GetFileName (SolutionFolderItem policyParent, Project project, string language, string baseDirectory, string entryName) { if (string.IsNullOrEmpty (entryName) && !string.IsNullOrEmpty (defaultName)) entryName = defaultName; @@ -257,7 +257,7 @@ namespace MonoDevelop.Ide.Templates // Returns a stream with the content of the file. // project and language parameters are optional - public virtual Stream CreateFileContent (SolutionItem policyParent, Project project, string language, string fileName, string identifier) + public virtual Stream CreateFileContent (SolutionFolderItem policyParent, Project project, string language, string fileName, string identifier) { Dictionary<string, string> tags = new Dictionary<string, string> (); ModifyTags (policyParent, project, language, identifier, fileName, ref tags); @@ -326,7 +326,7 @@ namespace MonoDevelop.Ide.Templates // We supply defaults whenever it is possible, to avoid having unsubstituted tags. However, // do not substitute blanks when a sensible default cannot be guessed, because they result //in less obvious errors. - public virtual void ModifyTags (SolutionItem policyParent, Project project, string language, + public virtual void ModifyTags (SolutionFolderItem policyParent, Project project, string language, string identifier, string fileName, ref Dictionary<string,string> tags) { DotNetProject netProject = project as DotNetProject; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SolutionDescriptor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SolutionDescriptor.cs index 02c0eb2e38..e70f9e5f30 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SolutionDescriptor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SolutionDescriptor.cs @@ -151,7 +151,7 @@ namespace MonoDevelop.Ide.Templates var solutionItemDesc = entryDescriptors[i]; - SolutionEntityItem info = solutionItemDesc.CreateItem (entryProjectCI, defaultLanguage); + SolutionItem info = solutionItemDesc.CreateItem (entryProjectCI, defaultLanguage); if (info == null) continue; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SolutionItemDescriptor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SolutionItemDescriptor.cs index a0a04fc553..9a5eba1eeb 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SolutionItemDescriptor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SolutionItemDescriptor.cs @@ -60,7 +60,7 @@ namespace MonoDevelop.Ide.Templates template = element; } - public SolutionEntityItem CreateItem (ProjectCreateInformation projectCreateInformation, string defaultLanguage) + public SolutionItem CreateItem (ProjectCreateInformation projectCreateInformation, string defaultLanguage) { Type type = addin.GetType (typeName, false); @@ -69,7 +69,7 @@ namespace MonoDevelop.Ide.Templates return null; } - SolutionEntityItem item = (SolutionEntityItem) Activator.CreateInstance (type); + SolutionItem item = (SolutionItem) Activator.CreateInstance (type); item.InitializeFromTemplate (template); string newProjectName = StringParserService.Parse (name, new string[,] { @@ -82,7 +82,7 @@ namespace MonoDevelop.Ide.Templates return item; } - public void InitializeItem (SolutionItem policyParent, ProjectCreateInformation projectCreateInformation, string defaultLanguage, SolutionEntityItem item) + public void InitializeItem (SolutionFolderItem policyParent, ProjectCreateInformation projectCreateInformation, string defaultLanguage, SolutionItem item) { } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/TextFileDescriptionTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/TextFileDescriptionTemplate.cs index 4092840eaf..eb56927303 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/TextFileDescriptionTemplate.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/TextFileDescriptionTemplate.cs @@ -95,7 +95,7 @@ namespace MonoDevelop.Ide.Templates contentSrcFile = contentSrcFile.ToAbsolute (baseDirectory); } - public override Stream CreateFileContent (SolutionItem policyParent, Project project, string language, + public override Stream CreateFileContent (SolutionFolderItem policyParent, Project project, string language, string fileName, string identifier) { return File.OpenRead (contentSrcFile); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/AmbienceService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/AmbienceService.cs index 27d7d7169d..794144d931 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/AmbienceService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/AmbienceService.cs @@ -432,7 +432,6 @@ namespace MonoDevelop.Ide.TypeSystem StringBuilder ret = new StringBuilder (70); StringBuilder parameterBuilder = new StringBuilder (); StringBuilder exceptions = new StringBuilder (); - exceptions.AppendLine (options.FormatHeading (GettextCatalog.GetString ("Exceptions:"))); // ret.Append ("<small>"); int paramCount = 0, exceptionCount = 0, summaryEnd = -1; @@ -509,6 +508,8 @@ namespace MonoDevelop.Ide.TypeSystem parameterBuilder.Append ("</b>"); parameterBuilder.Append (":</i> "); parameterBuilder.Append (body); + } else { + return null; } break; case "value": diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ParsedDocument.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ParsedDocument.cs index a47d916d7a..0fdb4a13cd 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ParsedDocument.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ParsedDocument.cs @@ -272,7 +272,7 @@ namespace MonoDevelop.Ide.TypeSystem public DefaultParsedDocument (string fileName) : base (fileName) { - + Flags |= ParsedDocumentFlags.NonSerializable; } #region IUnresolvedFile implementation diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs index 4a935785de..783044f2b7 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs @@ -48,6 +48,7 @@ using System.Text; using ICSharpCode.NRefactory.Completion; using System.Diagnostics; using MonoDevelop.Projects.SharedAssetsProjects; +using Mono.CSharp.Nullable; namespace MonoDevelop.Ide.TypeSystem { @@ -159,7 +160,7 @@ namespace MonoDevelop.Ide.TypeSystem public static class TypeSystemService { - const string CurrentVersion = "1.1.5"; + const string CurrentVersion = "1.1.8"; static readonly List<TypeSystemParserNode> parsers; static string[] filesSkippedInParseThread = new string[0]; @@ -255,7 +256,7 @@ namespace MonoDevelop.Ide.TypeSystem if (project != null) CheckProjectOutput (project, true); - pr.Value.ReconnectAssemblyReferences (); + pr.Value.referencesConnected = false; } } @@ -269,6 +270,8 @@ namespace MonoDevelop.Ide.TypeSystem var fileName = project.GetOutputFileName (IdeApp.Workspace.ActiveConfiguration); var wrapper = GetProjectContentWrapper (project); + if (wrapper == null) + return; bool update = wrapper.UpdateTrackedOutputAssembly (fileName); if (autoUpdate && update) { wrapper.ReconnectAssemblyReferences (); @@ -372,7 +375,7 @@ namespace MonoDevelop.Ide.TypeSystem wrapper = null; } if (wrapper != null && (result.Flags & ParsedDocumentFlags.NonSerializable) != ParsedDocumentFlags.NonSerializable) { - var oldFile = wrapper.Content.GetFile (fileName); + var oldFile = wrapper._content.GetFile (fileName); wrapper.UpdateContent (c => c.AddOrUpdateFiles (result.ParsedFile)); UpdateProjectCommentTasks (wrapper, result); if (oldFile != null) @@ -387,7 +390,7 @@ namespace MonoDevelop.Ide.TypeSystem continue; // Use the project context because file lookup is faster there than in the project class. var pcnt = cnt.Value; - var file = pcnt.Content.GetFile (fileName); + var file = pcnt._content.GetFile (fileName); if (file != null) { var newResult = parser.Parse (false, fileName, new StringReader (content), pcnt.Project); pcnt.UpdateContent (c => c.AddOrUpdateFiles (newResult.ParsedFile)); @@ -431,7 +434,7 @@ namespace MonoDevelop.Ide.TypeSystem var result = parser.Parse (true, fileName, content); lock (projectWrapperUpdateLock) { if (wrapper != null && (result.Flags & ParsedDocumentFlags.NonSerializable) != ParsedDocumentFlags.NonSerializable) { - var oldFile = wrapper.Content.GetFile (fileName); + var oldFile = wrapper._content.GetFile (fileName); wrapper.UpdateContent (c => c.AddOrUpdateFiles (result.ParsedFile)); UpdateProjectCommentTasks (wrapper, result); if (oldFile != null) @@ -943,42 +946,22 @@ namespace MonoDevelop.Ide.TypeSystem readonly Dictionary<Type, object> extensionObjects = new Dictionary<Type, object> (); List<ProjectContentWrapper> referencedWrappers = new List<ProjectContentWrapper>(); List<UnresolvedAssemblyProxy> referencedAssemblies = new List<UnresolvedAssemblyProxy>(); - IProjectContent _content; - bool referencesConnected; - - public bool ReferencesConnected { - get { - return GetReferencesConnected (this, new HashSet<ProjectContentWrapper> ()); - } - } + internal IProjectContent _content; + internal bool referencesConnected; + /* static bool GetReferencesConnected (ProjectContentWrapper pcw, HashSet<ProjectContentWrapper> wrapper) { if (wrapper.Contains (pcw)) return true; wrapper.Add (pcw); return pcw.referencesConnected && pcw.referencedWrappers.All (w => GetReferencesConnected (w, wrapper)); - } - - public bool IsLoaded { - get { - return GetIsLoaded (this, new HashSet<ProjectContentWrapper> ()); - } - } - - static bool GetIsLoaded (ProjectContentWrapper pcw, HashSet<ProjectContentWrapper> wrapper) - { - if (wrapper.Contains (pcw)) - return true; - wrapper.Add (pcw); - return !pcw.InLoad && pcw.referencedWrappers.All (w => GetIsLoaded (w, wrapper)); - } + }*/ public IProjectContent Content { get { if (!referencesConnected) { - referencesConnected = true; - ReconnectAssemblyReferences (); + EnsureReferencesAreLoaded (); } return _content; } @@ -1050,12 +1033,14 @@ namespace MonoDevelop.Ide.TypeSystem public void RunWhenLoaded (Action<IProjectContent> act) { lock (updateContentLock) { - if (Content is LazyProjectLoader) { - if (loadActions != null) { - loadActions.Clear (); - loadActions.Add (act); + var lazyProjectLoader = _content as LazyProjectLoader; + if (loadActions != null) { + lock (loadActions) { + if (lazyProjectLoader != null && !lazyProjectLoader.ContextTask.IsCompleted) { + loadActions.Add (act); + return; + } } - return; } } act (Content); @@ -1073,29 +1058,43 @@ namespace MonoDevelop.Ide.TypeSystem continue; cleared.Add (cur); cur.compilation = null; - foreach (var project in cur.ReferencedProjects) - stack.Push (GetProjectContentWrapper (project)); + foreach (var project in cur.ReferencedProjects) { + var projectContentWrapper = GetProjectContentWrapper (project); + if (projectContentWrapper != null) + stack.Push (projectContentWrapper); + } } } readonly object updateContentLock = new object (); + void RunLoadActions () + { + if (loadActions == null) + return; + Action<IProjectContent>[] actions; + lock (loadActions) { + actions = loadActions.ToArray (); + loadActions = null; + } + foreach (var action in actions) + action (Content); + } + public void UpdateContent (Func<IProjectContent, IProjectContent> updateFunc) { + LazyProjectLoader lazyProjectLoader; lock (updateContentLock) { - var lazyProjectLoader = Content as LazyProjectLoader; + lazyProjectLoader = Content as LazyProjectLoader; if (lazyProjectLoader != null) { lazyProjectLoader.ContextTask.Wait (); - if (loadActions != null) { - var action = loadActions.FirstOrDefault (); - loadActions = null; - if (action != null) - action (Content); - } } Content = updateFunc (Content); ClearCachedCompilations (); WasChanged = true; + if (lazyProjectLoader != null && !(Content is LazyProjectLoader)) { + RunLoadActions (); + } } } @@ -1144,6 +1143,8 @@ namespace MonoDevelop.Ide.TypeSystem { lock (loadOperationLocker) { loadOperationDepth++; + if (loadOperationDepth == 1) + UpdateLoadState (); } } @@ -1153,13 +1154,15 @@ namespace MonoDevelop.Ide.TypeSystem if (loadOperationDepth > 0) { loadOperationDepth--; } + if (loadOperationDepth == 0) + UpdateLoadState (); } - OnLoad (EventArgs.Empty); } - bool inLoad; - public bool InLoad { + + bool isLoaded; + public bool IsLoaded { get { - return inLoad; + return isLoaded; } } @@ -1174,52 +1177,38 @@ namespace MonoDevelop.Ide.TypeSystem void UpdateLoadState () { - inLoad = loadOperationDepth > 0 || referencedWrappers.Any (w => w.InLoad) || referencedAssemblies.Any (a => a.InLoad); + bool wasLoaded = isLoaded; + isLoaded = loadOperationDepth == 0 && referencesConnected && !referencedAssemblies.Any (a => a.InLoad); + if (isLoaded && !wasLoaded) + OnLoad (EventArgs.Empty); } internal void RequestLoad () { - UpdateLoadState (); - if (!InLoad) - return; + BeginLoadOperation (); + EnsureReferencesAreLoaded (); CancelLoad (); src = new CancellationTokenSource (); var token = src.Token; - Task.Factory.StartNew (delegate { - var s = new Stack<ProjectContentWrapper> (); - s.Push (this); - var w = new HashSet<ProjectContentWrapper> (); - while (s.Count > 0) { - var wrapper = s.Pop (); - if (token.IsCancellationRequested) - return; - if (w.Contains (wrapper)) - continue; - w.Add (wrapper); - - foreach (var asm in wrapper.referencedAssemblies.ToArray ()) { + //Task.Factory.StartNew (delegate { + try { + foreach (var asm in referencedAssemblies.ToArray ()) { if (token.IsCancellationRequested) - return; + break; var ctxLoader = asm.CtxLoader; if (ctxLoader != null) ctxLoader.EnsureAssemblyLoaded (); } - foreach (var rw in wrapper.referencedWrappers.ToArray ()) { - if (token.IsCancellationRequested) - return; - s.Push (rw); - } + } finally { + EndLoadOperation (); } - }); + //}); } public event EventHandler Loaded; protected virtual void OnLoad (EventArgs e) { - UpdateLoadState (); - if (InLoad) - return; var handler = Loaded; if (handler != null) handler (this, e); @@ -1244,7 +1233,8 @@ namespace MonoDevelop.Ide.TypeSystem if (project == null) throw new ArgumentNullException ("project"); this.Project = project; - this.Content = new LazyProjectLoader (this); + var lazyProjectLoader = new LazyProjectLoader (this); + this.Content = lazyProjectLoader; } public IEnumerable<Project> ReferencedProjects { @@ -1263,18 +1253,29 @@ namespace MonoDevelop.Ide.TypeSystem return contextTask; } } - + object contentLock = new object (); + IProjectContent contentWithReferences; public IProjectContent Content { get { - if (References != null) - return contextTask.Result.AddAssemblyReferences (References); - return contextTask.Result; + lock (contentLock) { + if (References != null) { + return contentWithReferences ?? (contentWithReferences = contextTask.Result.AddAssemblyReferences (References)); + } + return contextTask.Result; + } } } + List<IAssemblyReference> references; public List<IAssemblyReference> References { - get; - set; + get { + return references; + } + set { + lock (contentLock) { + references = value; + } + } } public LazyProjectLoader (ProjectContentWrapper wrapper) @@ -1504,106 +1505,127 @@ namespace MonoDevelop.Ide.TypeSystem } return false; } - public void ReconnectAssemblyReferences () + + List<UnresolvedAssemblyProxy> LoadReferencedAssemblies (DotNetProject netProject) { - var netProject = Project as DotNetProject; - if (netProject == null) - return; - CancelLoad (); + var newReferencedAssemblies = new List<UnresolvedAssemblyProxy> (); try { - var contexts = new List<IAssemblyReference> (); - var nonCyclicCache = new HashSet<Project> (); - foreach (var referencedWrapper in referencedWrappers) { - referencedWrapper.Loaded -= HandleReferencedProjectInLoadChange; - } - var newReferencedWrappers = new List<ProjectContentWrapper>(); - foreach (var referencedProject in ReferencedProjects) { - ProjectContentWrapper wrapper; - if (projectContents.TryGetValue (referencedProject, out wrapper)) { - if (HasCyclicRefs (wrapper, nonCyclicCache)) - continue; - wrapper.Loaded += HandleReferencedProjectInLoadChange; - newReferencedWrappers.Add (wrapper); - contexts.Add (new UnresolvedAssemblyDecorator (wrapper)); + foreach (string file in netProject.GetReferencedAssemblies (IdeApp.IsInitialized ? IdeApp.Workspace.ActiveConfiguration : ConfigurationSelector.Default, false)) { + string fileName; + if (!Path.IsPathRooted (file)) { + fileName = Path.Combine (Path.GetDirectoryName (netProject.FileName), file); + } + else { + fileName = Path.GetFullPath (file); + } + var ctx = LoadAssemblyContext (fileName); + if (ctx != null) { + newReferencedAssemblies.Add (ctx); + ctx.Loaded += HandleReferencedProjectInLoadChange; + } + else { + LoggingService.LogWarning ("TypeSystemService: Can't load assembly context for:" + file); } } - this.referencedWrappers = newReferencedWrappers; + } + catch (Exception e) { + LoggingService.LogError ("Error while getting assembly references", e); + } + return newReferencedAssemblies; + } - UnresolvedAssemblyProxy ctx; - // Add mscorlib reference + object assemblyReconnectLock = new object(); - var config = IdeApp.Workspace != null ? netProject.GetConfiguration (IdeApp.Workspace.ActiveConfiguration) as DotNetProjectConfiguration : null; - bool noStdLib = false; - if (config != null) { - var parameters = config.CompilationParameters as DotNetConfigurationParameters; - if (parameters != null) { - noStdLib = parameters.NoStdLib; + public void EnsureReferencesAreLoaded () + { + lock (assemblyReconnectLock) { + if (referencesConnected) + return; + compilation = null; + referencesConnected = true; + var netProject = Project as DotNetProject; + if (netProject == null) + return; + try { + var contexts = new List<IAssemblyReference> (); + var nonCyclicCache = new HashSet<Project> (); + foreach (var referencedWrapper in referencedWrappers) { + referencedWrapper.Loaded -= HandleReferencedProjectInLoadChange; } - } - - if (!noStdLib && netProject.TargetRuntime != null && netProject.TargetRuntime.AssemblyContext != null) { - var corLibRef = netProject.TargetRuntime.AssemblyContext.GetAssemblyForVersion ( - typeof(object).Assembly.FullName, - null, - netProject.TargetFramework - ); - if (corLibRef != null) { - ctx = LoadAssemblyContext (corLibRef.Location); - if (ctx != null) - contexts.Add (ctx); + var newReferencedWrappers = new List<ProjectContentWrapper> (); + foreach (var referencedProject in ReferencedProjects) { + ProjectContentWrapper wrapper; + if (projectContents.TryGetValue (referencedProject, out wrapper)) { + if (HasCyclicRefs (wrapper, nonCyclicCache)) + continue; + wrapper.Loaded += HandleReferencedProjectInLoadChange; + newReferencedWrappers.Add (wrapper); + contexts.Add (new UnresolvedAssemblyDecorator (wrapper)); + } } - } - // Get the assembly references throught the project, since it may have custom references - foreach (var asm in referencedAssemblies) { - asm.Loaded += HandleReferencedProjectInLoadChange; - } - var newReferencedAssemblies = new List<UnresolvedAssemblyProxy>(); - try { - foreach (string file in netProject.GetReferencedAssemblies (IdeApp.IsInitialized ? IdeApp.Workspace.ActiveConfiguration : ConfigurationSelector.Default, false)) { - string fileName; - if (!Path.IsPathRooted (file)) { - fileName = Path.Combine (Path.GetDirectoryName (netProject.FileName), file); - } else { - fileName = Path.GetFullPath (file); + this.referencedWrappers = newReferencedWrappers; + UnresolvedAssemblyProxy ctx; + // Add mscorlib reference + var config = IdeApp.Workspace != null ? netProject.GetConfiguration (IdeApp.Workspace.ActiveConfiguration) as DotNetProjectConfiguration : null; + bool noStdLib = false; + if (config != null) { + var parameters = config.CompilationParameters as DotNetCompilerParameters; + if (parameters != null) { + noStdLib = parameters.NoStdLib; } - ctx = LoadAssemblyContext (fileName); - if (ctx != null) { - newReferencedAssemblies.Add (ctx); - ctx.Loaded += HandleReferencedProjectInLoadChange; - contexts.Add (ctx); - } else { - LoggingService.LogWarning ("TypeSystemService: Can't load assembly context for:" + file); + } + if (!noStdLib && netProject.TargetRuntime != null && netProject.TargetRuntime.AssemblyContext != null) { + var corLibRef = netProject.TargetRuntime.AssemblyContext.GetAssemblyForVersion (typeof(object).Assembly.FullName, null, netProject.TargetFramework); + if (corLibRef != null) { + ctx = LoadAssemblyContext (corLibRef.Location); + if (ctx != null) + contexts.Add (ctx); } } + // Get the assembly references throught the project, since it may have custom references + foreach (var asm in referencedAssemblies) { + asm.Loaded += HandleReferencedProjectInLoadChange; + } + var newReferencedAssemblies = LoadReferencedAssemblies (netProject); + contexts.AddRange (newReferencedAssemblies); + referencedAssemblies = newReferencedAssemblies; + bool changed = WasChanged; + var lazyProjectLoader = Content as LazyProjectLoader; + if (lazyProjectLoader != null) { + lazyProjectLoader.References = contexts; + } + else { + UpdateContent (c => c.RemoveAssemblyReferences (Content.AssemblyReferences).AddAssemblyReferences (contexts)); + } + WasChanged = changed; } catch (Exception e) { - LoggingService.LogError ("Error while getting assembly references", e); - } - referencedAssemblies = newReferencedAssemblies; - bool changed = WasChanged; - var lazyProjectLoader = Content as LazyProjectLoader; - if (lazyProjectLoader != null) { - lazyProjectLoader.References = contexts; - } else { - UpdateContent (c => c.RemoveAssemblyReferences (Content.AssemblyReferences)); - UpdateContent (c => c.AddAssemblyReferences (contexts)); - } - WasChanged = changed; - } catch (Exception e) { - if (netProject.TargetRuntime == null) { - LoggingService.LogError ("Target runtime was null: " + Project.Name); - } else if (netProject.TargetRuntime.AssemblyContext == null) { - LoggingService.LogError ("Target runtime assembly context was null: " + Project.Name); + if (netProject.TargetRuntime == null) { + LoggingService.LogError ("Target runtime was null: " + Project.Name); + } else if (netProject.TargetRuntime.AssemblyContext == null) { + LoggingService.LogError ("Target runtime assembly context was null: " + Project.Name); + } + LoggingService.LogError ("Error while reloading all references of project: " + Project.Name, e); + } finally { + UpdateLoadState (); } - LoggingService.LogError ("Error while reloading all references of project: " + Project.Name, e); - } finally { + } + } + object reconnectLock = new object(); + public void ReconnectAssemblyReferences () + { + var netProject = Project as DotNetProject; + if (netProject == null) + return; + lock (reconnectLock) { + CancelLoad (); + this.referencesConnected = false; RequestLoad (); - OnLoad (EventArgs.Empty); } } void HandleReferencedProjectInLoadChange (object sender, EventArgs e) { - OnLoad (EventArgs.Empty); + UpdateLoadState (); } internal void Unload () @@ -1643,7 +1665,6 @@ namespace MonoDevelop.Ide.TypeSystem project.FileRenamedInProject += OnFileRenamed; project.Modified += OnProjectModified; - if (dotNetProject != null) { StartFrameworkLookup (dotNetProject); } @@ -1686,7 +1707,7 @@ namespace MonoDevelop.Ide.TypeSystem foreach (ProjectFileEventInfo fargs in args) { var wrapper = projectContents [project]; var fileName = fargs.ProjectFile.Name; - var file = wrapper.Content.GetFile (fileName); + var file = wrapper._content.GetFile (fileName); if (file == null) continue; wrapper.UpdateContent (c => c.RemoveFiles (fileName)); @@ -1703,7 +1724,7 @@ namespace MonoDevelop.Ide.TypeSystem var project = (Project)sender; foreach (ProjectFileRenamedEventInfo fargs in args) { var content = projectContents [project]; - var file = content.Content.GetFile (fargs.OldName); + var file = content._content.GetFile (fargs.OldName); if (file == null) continue; content.UpdateContent (c => c.RemoveFiles (fargs.OldName)); @@ -1763,7 +1784,7 @@ namespace MonoDevelop.Ide.TypeSystem TrackFileChanges = true; } - internal static void UnloadProject (Project project) + internal static void UnloadProject (Project project, bool skipProjectSerialization = false) { if (DecLoadCount (project) != 0) return; @@ -1779,7 +1800,8 @@ namespace MonoDevelop.Ide.TypeSystem return; projectContents.Remove (project); } - StoreProjectCache (project, wrapper); + if (!skipProjectSerialization) + StoreProjectCache (project, wrapper); OnProjectUnloaded (new ProjectUnloadEventArgs (project, wrapper)); wrapper.Unload (); } @@ -1809,10 +1831,10 @@ namespace MonoDevelop.Ide.TypeSystem if (project != null) { var wrapper = LoadProject (project); if (wrapper != null) { - wrapper.ReconnectAssemblyReferences (); var files = wrapper.Project.Files.ToArray (); Task.Factory.StartNew (delegate { CheckModifiedFiles (wrapper.Project, files, wrapper); + wrapper.RequestLoad (); }); } } @@ -2020,6 +2042,11 @@ namespace MonoDevelop.Ide.TypeSystem } #endregion + + public override string ToString () + { + return string.Format ("[UnresolvedAssemblyProxy: FileName={0}]", FileName); + } } internal class LazyAssemblyLoader : IUnresolvedAssembly @@ -2242,11 +2269,13 @@ namespace MonoDevelop.Ide.TypeSystem this.cache = cache; } + IUnresolvedAssembly LoadAssembly () { var assemblyPath = cache != null ? Path.Combine (cache, "assembly.data") : null; + var assemblyTag = cache != null ? Path.Combine (cache, "assembly.tag") : null; try { - if (assemblyPath != null && File.Exists (assemblyPath)) { + if (assemblyPath != null && assemblyTag != null && File.Exists (assemblyPath) && File.Exists (assemblyTag)) { var deserializedAssembly = DeserializeObject <IUnresolvedAssembly> (assemblyPath); if (deserializedAssembly != null) { return deserializedAssembly; @@ -2268,13 +2297,7 @@ namespace MonoDevelop.Ide.TypeSystem if (cache != null) { var writeTime = File.GetLastWriteTimeUtc (fileName); SerializeObject (assemblyPath, result); - if (File.Exists (assemblyPath)) { - try { - File.SetCreationTimeUtc (assemblyPath, writeTime); - } catch (Exception e) { - LoggingService.LogError ("Can't set creation time for: " + assemblyPath, e); - } - } + SerializeObject (assemblyTag, new AssemblyTag (writeTime)); } return result; } @@ -2380,6 +2403,8 @@ namespace MonoDevelop.Ide.TypeSystem if (project == null) throw new ArgumentNullException ("project"); var content = GetProjectContentWrapper (project); + if (content == null) + return null; return content.Content; } @@ -2388,6 +2413,8 @@ namespace MonoDevelop.Ide.TypeSystem if (project == null) throw new ArgumentNullException ("project"); var content = GetProjectContentWrapper (project); + if (content == null) + return null; return content.Compilation; } @@ -2532,7 +2559,12 @@ namespace MonoDevelop.Ide.TypeSystem ProjectContentWrapper content; if (projectContents.TryGetValue (project, out content)) return content; - return new ProjectContentWrapper (project); + // in case of outdated projects try to get the most recent project wrapper. + foreach (var cnt in projectContents) { + if (cnt.Key.FileName == project.FileName) + return cnt.Value; + } + return null; } public static IProjectContent GetContext (FilePath file, string mimeType, string text) @@ -2569,7 +2601,7 @@ namespace MonoDevelop.Ide.TypeSystem } class InternalProgressMonitor - : NullProgressMonitor + : ProgressMonitor { public InternalProgressMonitor () { @@ -2582,9 +2614,9 @@ namespace MonoDevelop.Ide.TypeSystem } } - internal static IProgressMonitor GetParseProgressMonitor () + internal static ProgressMonitor GetParseProgressMonitor () { - var mon = ParseProgressMonitorFactory != null ? ParseProgressMonitorFactory.CreateProgressMonitor () : new NullProgressMonitor (); + var mon = ParseProgressMonitorFactory != null ? ParseProgressMonitorFactory.CreateProgressMonitor () : new ProgressMonitor (); return new AggregatedProgressMonitor (mon, new InternalProgressMonitor ()); } @@ -2596,7 +2628,7 @@ namespace MonoDevelop.Ide.TypeSystem public ProjectContentWrapper Context; public IEnumerable<ProjectFile> FileList; // public Action<string, IProgressMonitor> ParseCallback; - public void Run (IProgressMonitor monitor, CancellationToken token) + public void Run (ProgressMonitor monitor, CancellationToken token) { TypeSystemParserNode node = null; TypeSystemParser parser = null; @@ -2635,7 +2667,7 @@ namespace MonoDevelop.Ide.TypeSystem tags.UpdateTags (Context.Project, parsedDocument.FileName, parsedDocument.TagComments); if (token.IsCancellationRequested) return; - parsedFiles.Add (Tuple.Create (parsedDocument, Context.Content.GetFile (fileName))); + parsedFiles.Add (Tuple.Create (parsedDocument, Context._content.GetFile (fileName))); } Context.UpdateContent (c => c.AddOrUpdateFiles (parsedFiles.Select (p => p.Item1.ParsedFile))); foreach (var file in parsedFiles) { @@ -2643,11 +2675,12 @@ namespace MonoDevelop.Ide.TypeSystem return; if (file.Item2 != null) Context.InformFileRemoved (new ParsedFileEventArgs (file.Item2)); - Context.InformFileAdded (new ParsedFileEventArgs (file.Item1.ParsedFile)); + var parsedDocument = file.Item1; + if ((parsedDocument.Flags & ParsedDocumentFlags.NonSerializable) != ParsedDocumentFlags.NonSerializable) + Context.InformFileAdded (new ParsedFileEventArgs (parsedDocument.ParsedFile)); } } finally { - if (!token.IsCancellationRequested) - Context.EndLoadOperation (); + Context.EndLoadOperation (); } } } @@ -2781,28 +2814,31 @@ namespace MonoDevelop.Ide.TypeSystem static bool IsFileModified (ProjectFile file, IUnresolvedFile parsedFile) { - if (parsedFile == null) + if (parsedFile == null || !parsedFile.LastWriteTime.HasValue) return true; try { - return File.GetLastWriteTimeUtc (file.FilePath) > parsedFile.LastWriteTime; + return File.GetLastWriteTimeUtc (file.FilePath) != parsedFile.LastWriteTime; } catch (Exception) { - return false; + return true; } } static void CheckModifiedFiles (Project project, ProjectFile[] projectFiles, ProjectContentWrapper content, CancellationToken token = default (CancellationToken)) { - if (token.IsCancellationRequested) + if (token.IsCancellationRequested) { return; + } +// Console.WriteLine ("add modified file check for :" + project.Name); content.RunWhenLoaded (delegate(IProjectContent cnt) { try { +// Console.WriteLine ("check for " + project.Name); content.BeginLoadOperation (); var modifiedFiles = new List<ProjectFile> (); var oldFileNewFile = new List<Tuple<ProjectFile, IUnresolvedFile>> (); - foreach (var file in projectFiles) { - if (token.IsCancellationRequested) + if (token.IsCancellationRequested) { return; + } if (file.BuildAction == null) continue; // if the file is already inside the content a parser exists for it, if not check if it can be parsed. @@ -2827,8 +2863,9 @@ namespace MonoDevelop.Ide.TypeSystem // check if file needs to be removed from project content foreach (var file in cnt.Files) { - if (token.IsCancellationRequested) + if (token.IsCancellationRequested) { return; + } if (project.GetProjectFile (file.FileName) == null) { content.UpdateContent (c => c.RemoveFiles (file.FileName)); content.InformFileRemoved (new ParsedFileEventArgs (file)); @@ -2836,37 +2873,54 @@ namespace MonoDevelop.Ide.TypeSystem tags.RemoveFile (project, file.FileName); } } - if (token.IsCancellationRequested) + if (token.IsCancellationRequested) { return; - if (modifiedFiles.Count > 0) + } + if (modifiedFiles.Count > 0) { QueueParseJob (content, modifiedFiles); + WaitForParseJob (); + } } catch (Exception e) { LoggingService.LogError ("Exception in check modified files.", e); } finally { content.EndLoadOperation (); } - }); } + /// <summary> + /// Used to store meta data information about the assembly. + /// </summary> + [Serializable] + class AssemblyTag + { + public DateTime LastWriteTimeUTC { get; set; } + + public AssemblyTag (DateTime lastWriteTimeUTC) + { + this.LastWriteTimeUTC = lastWriteTimeUTC; + } + } + static void CheckModifiedFile (UnresolvedAssemblyProxy context) { try { string cache = GetCacheDirectory (context.FileName); if (cache == null) return; - var assemblyDataDirectory = Path.Combine (cache, "assembly.data"); + var assemblyDataDirectory = Path.Combine (cache, "assembly.tag"); var writeTime = File.GetLastWriteTimeUtc (context.FileName); - var cacheTime = File.Exists (assemblyDataDirectory) ? File.GetCreationTimeUtc (assemblyDataDirectory) : writeTime; - if (writeTime != cacheTime) { + var cacheTime = File.Exists (assemblyDataDirectory) ? DeserializeObject<AssemblyTag> (assemblyDataDirectory) : new AssemblyTag (writeTime); + if (writeTime != cacheTime.LastWriteTimeUTC) { cache = GetCacheDirectory (context.FileName); if (cache != null) { - context.CtxLoader = new LazyAssemblyLoader (context.FileName, cache); try { - // File is reloaded by the lazy loader + // Files will be reloaded by the lazy loader File.Delete (assemblyDataDirectory); + File.Delete (Path.Combine (cache, "assembly.data")); } catch { } + context.CtxLoader = new LazyAssemblyLoader (context.FileName, cache); } } } catch (Exception e) { @@ -2899,7 +2953,7 @@ namespace MonoDevelop.Ide.TypeSystem static void ConsumeParsingQueue () { int pending = 0; - IProgressMonitor monitor = null; + ProgressMonitor monitor = null; var token = loadCancellationSource.Token; StartParseOperation (); try { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs index ff6916aee4..2fa1435196 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs @@ -33,6 +33,7 @@ using MonoDevelop.Ide.ProgressMonitoring; using Mono.Addins; using MonoDevelop.Core.Setup; using Mono.TextEditor; +using System.Threading.Tasks; namespace MonoDevelop.Ide.Updater { @@ -42,27 +43,34 @@ namespace MonoDevelop.Ide.Updater AddinRepositoryEntry[] updates; static StatusBarIcon updateIcon; internal static AddinsUpdateHandler Instance; - IProgressMonitor updateMonitor; + + ProgressMonitor updateMonitor; + Task currentTask = Task.FromResult (0); public AddinsUpdateHandler () { Instance = this; } - public void CheckUpdates (IProgressMonitor monitor, bool automatic) + public async Task CheckUpdates (ProgressMonitor monitor, bool automatic) { updateMonitor = monitor; try { if (UpdateService.UpdateLevel == UpdateLevel.Test) Runtime.AddinSetupService.RegisterMainRepository (UpdateLevel.Test, true); - using (ProgressStatusMonitor pm = new ProgressStatusMonitor (monitor)) { - Runtime.AddinSetupService.Repositories.UpdateAllRepositories (pm); - updates = Runtime.AddinSetupService.Repositories.GetAvailableUpdates (); - if (updates.Length > 0) - DispatchService.GuiDispatch (new MessageHandler (WarnAvailableUpdates)); - } + + currentTask = Task.Factory.StartNew (delegate { + using (ProgressStatusMonitor pm = new ProgressStatusMonitor (monitor)) { + Runtime.AddinSetupService.Repositories.UpdateAllRepositories (pm); + updates = Runtime.AddinSetupService.Repositories.GetAvailableUpdates (); + } + }); + await currentTask; + if (updates.Length > 0) + WarnAvailableUpdates (); } finally { updateMonitor = null; + currentTask = null; } } @@ -92,26 +100,20 @@ namespace MonoDevelop.Ide.Updater } } - public static void ShowManager () + public async static void ShowManager () { - IProgressMonitor m = Instance != null ? Instance.updateMonitor : null; - if (m != null && !m.AsyncOperation.IsCompleted) { - AggregatedProgressMonitor monitor = new AggregatedProgressMonitor (m); + Task t = Instance != null ? Instance.currentTask : null; + + if (t != null && t.IsCompleted) { + AggregatedProgressMonitor monitor = new AggregatedProgressMonitor (Instance.updateMonitor); monitor.AddSlaveMonitor (new MessageDialogProgressMonitor (true, true, false)); - monitor.AsyncOperation.WaitForCompleted (); + await t; } HideAlert (); AddinManagerWindow.Run (IdeApp.Workbench.RootWindow); } - internal void QueryAddinUpdates () - { - IProgressMonitor monitor = updateMonitor; - if (monitor != null) - monitor.AsyncOperation.WaitForCompleted (); - } - public static void HideAlert () { if (updateIcon != null) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/IUpdateHandler.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/IUpdateHandler.cs index 5b912d6dc4..a4fc5d1889 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/IUpdateHandler.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/IUpdateHandler.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; using MonoDevelop.Core; +using System.Threading.Tasks; namespace MonoDevelop.Ide.Updater { @@ -40,7 +41,7 @@ namespace MonoDevelop.Ide.Updater /// 'True' if the check has been automatically started by MD (e.g. when MD starts). /// 'False' if the check was started explicitly by the user. /// </param> - void CheckUpdates (IProgressMonitor monitor, bool automatic); + Task CheckUpdates (ProgressMonitor monitor, bool automatic); } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateService.cs index 5c4855320f..5ba90f08ef 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateService.cs @@ -30,6 +30,7 @@ using System; using Mono.Addins; using MonoDevelop.Core.ProgressMonitoring; using System.Threading; +using System.Threading.Tasks; namespace MonoDevelop.Ide.Updater { @@ -128,22 +129,18 @@ namespace MonoDevelop.Ide.Updater CheckForUpdates (false); } - static void CheckForUpdates (bool automatic) + static async void CheckForUpdates (bool automatic) { PropertyService.Set ("MonoDevelop.Ide.AddinUpdater.LastCheck", DateTime.Now); PropertyService.SaveProperties (); var handlers = AddinManager.GetExtensionObjects ("/MonoDevelop/Ide/Updater/UpdateHandlers"); - IProgressMonitor mon = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor ("Looking for updates", "md-updates"); + ProgressMonitor mon = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor ("Looking for updates", "md-updates"); - Thread t = new Thread (delegate () { - CheckUpdates (mon, handlers, automatic); - }); - t.Name = "Addin updater"; - t.Start (); + await CheckUpdates (mon, handlers, automatic); } - static void CheckUpdates (IProgressMonitor monitor, object[] handlers, bool automatic) + static async Task CheckUpdates (ProgressMonitor monitor, object[] handlers, bool automatic) { using (monitor) { // The handler to use is the last one declared in the extension point @@ -151,7 +148,7 @@ namespace MonoDevelop.Ide.Updater return; try { IUpdateHandler uh = (IUpdateHandler) handlers [handlers.Length - 1]; - uh.CheckUpdates (monitor, automatic); + await uh.CheckUpdates (monitor, automatic); } catch (Exception ex) { LoggingService.LogError ("Updates check failed for handler of type '" + handlers [handlers.Length - 1].GetType () + "'", ex); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageFrame.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageFrame.cs index 3810acfda0..22b2b3ec76 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageFrame.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageFrame.cs @@ -58,6 +58,26 @@ namespace MonoDevelop.Ide.WelcomePage Add (box); Show (); UpdateProjectBar (); + + IdeApp.Workbench.GuiLocked += HandleGuiLocked; + IdeApp.Workbench.GuiUnlocked += HandleGuiUnlocked; + } + + protected override void OnDestroyed () + { + base.OnDestroyed (); + IdeApp.Workbench.GuiLocked -= HandleGuiLocked; + IdeApp.Workbench.GuiUnlocked -= HandleGuiUnlocked; + } + + void HandleGuiUnlocked (object sender, EventArgs e) + { + Sensitive = true; + } + + void HandleGuiLocked (object sender, EventArgs e) + { + Sensitive = false; } public void UpdateProjectBar () @@ -109,7 +129,7 @@ namespace MonoDevelop.Ide.WelcomePage public WelcomePageProjectBar () { SetPadding (3, 3, 12, 12); - GradientBackround = true; + GradientBackground = true; HBox box = new HBox (false, 6); box.PackStart (messageLabel = new Gtk.Label () { Xalign = 0 }, true, true, 0); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj index a0626abe0f..b12fae6a81 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj @@ -1964,6 +1964,24 @@ <EmbeddedResource Include="icons\light\catchpoint-disabled-16%402x.png"> <LogicalName>catchpoint-disabled-light-16@2x.png</LogicalName> </EmbeddedResource> + <EmbeddedResource Include="icons\light\project-status-information-16.png"> + <LogicalName>project-status-information-light-16.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\light\project-status-information-16%402x.png"> + <LogicalName>project-status-information-light-16@2x.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\light\project-status-warning-16.png"> + <LogicalName>project-status-warning-light-16.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\light\project-status-warning-16%402x.png"> + <LogicalName>project-status-warning-light-16@2x.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\light\project-status-error-16.png"> + <LogicalName>project-status-error-light-16.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\light\project-status-error-16%402x.png"> + <LogicalName>project-status-error-light-16@2x.png</LogicalName> + </EmbeddedResource> </ItemGroup> <ItemGroup> <Compile Include="MonoDevelop.Ide.Commands\CustomStringTagProvider.cs" /> @@ -1978,7 +1996,6 @@ <Compile Include="MonoDevelop.Ide.Gui\DisplayBindingService.cs" /> <Compile Include="MonoDevelop.Ide.Gui\BackgroundProgressMonitor.cs" /> <Compile Include="MonoDevelop.Ide.Gui\StatusProgressMonitor.cs" /> - <Compile Include="MonoDevelop.Ide.Tasks\Task.cs" /> <Compile Include="MonoDevelop.Ide.Tasks\TaskService.cs" /> <Compile Include="MonoDevelop.Ide.Codons\ContextPadCodon.cs" /> <Compile Include="MonoDevelop.Ide.Codons\WorkbenchContextCodon.cs" /> @@ -2567,8 +2584,6 @@ <Compile Include="gtk-gui\MonoDevelop.Ide.Projects.ProjectSelectorDialog.cs" /> <Compile Include="MonoDevelop.Ide.Projects\ImportProjectPolicyDialog.cs" /> <Compile Include="gtk-gui\MonoDevelop.Ide.Projects.ImportProjectPolicyDialog.cs" /> - <Compile Include="MonoDevelop.Ide.ProgressMonitoring\ProgressBarMonitor.cs" /> - <Compile Include="gtk-gui\MonoDevelop.Ide.ProgressMonitoring.ProgressBarMonitor.cs" /> <Compile Include="MonoDevelop.Ide.Projects\AddExternalFileDialog.cs" /> <Compile Include="gtk-gui\MonoDevelop.Ide.Projects.AddExternalFileDialog.cs" /> <Compile Include="MonoDevelop.Ide.Gui.Components\PriorityList.cs" /> @@ -2724,7 +2739,6 @@ <Compile Include="MonoDevelop.Ide.TypeSystem\MonoDevelopProjectContent.cs" /> <Compile Include="MonoDevelop.Components.Commands\ICommandDelegator.cs" /> <Compile Include="MonoDevelop.Ide.CustomTools\ResXFileCodeGenerator.cs" /> - <Compile Include="MonoDevelop.Ide.CustomTools\ThreadAsyncOperation.cs" /> <Compile Include="MonoDevelop.Components\CellRendererImage.cs" /> <Compile Include="MonoDevelop.Components\ImageView.cs" /> <Compile Include="MonoDevelop.Ide.Projects\IdeFileSystemExtensionExtension.cs" /> @@ -2773,6 +2787,7 @@ <Compile Include="MonoDevelop.Components\Mac\NSViewContainer.cs" /> <Compile Include="MonoDevelop.Components\Mac\GtkEmbed.cs" /> <Compile Include="MonoDevelop.Components\Mac\WidgetWithNativeWindow.cs" /> + <Compile Include="MonoDevelop.Ide.Tasks\UserTask.cs" /> </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs index 6d95ef090a..860bc2f017 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs @@ -33,6 +33,7 @@ using System.IO; using MonoDevelop.Components; using MonoDevelop.Components.MainToolbar; using MonoDevelop.Ide.Fonts; +using System.Threading.Tasks; namespace MonoDevelop.Ide { @@ -101,10 +102,7 @@ namespace MonoDevelop.Ide get { return PlatformService.Name; } } - /// <summary> - /// Used in the text editor. Valid values are found in MonoDevelop.SourceEditor.ControlLeftRightMode in the - /// source editor project. - /// </summary> + [Obsolete] public static string DefaultControlLeftRightBehavior { get { return PlatformService.DefaultControlLeftRightBehavior; @@ -164,6 +162,31 @@ namespace MonoDevelop.Ide return true; } + public async static Task<bool> GetFileIsTextAsync (string file, string mimeType = null) + { + if (mimeType == null) { + mimeType = GetMimeTypeForUri (file); + } + + if (mimeType != "application/octet-stream") { + return GetMimeTypeIsText (mimeType); + } + + return await Task<bool>.Factory.StartNew (delegate { + if (!File.Exists (file)) + return false; + + using (var f = File.OpenRead (file)) { + var buf = new byte[8192]; + var read = f.Read (buf, 0, buf.Length); + for (int i = 0; i < read; i++) + if (buf [i] == 0) + return false; + } + return true; + }); + } + public static bool GetMimeTypeIsSubtype (string subMimeType, string baseMimeType) { return PlatformService.GetMimeTypeIsSubtype (subMimeType, baseMimeType); @@ -319,5 +342,20 @@ namespace MonoDevelop.Ide { return PlatformService.IsModalDialogRunning (); } + + internal static void AddChildWindow (Gtk.Window parent, Gtk.Window child) + { + PlatformService.AddChildWindow (parent, child); + } + + internal static void RemoveChildWindow (Gtk.Window parent, Gtk.Window child) + { + PlatformService.RemoveChildWindow (parent, child); + } + + internal static void PlaceWindow (Gtk.Window window, int x, int y, int width, int height) + { + PlatformService.PlaceWindow (window, x, y, width, height); + } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DispatchService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DispatchService.cs index eb2d62fa3d..4512d16973 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DispatchService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DispatchService.cs @@ -36,6 +36,7 @@ using MonoDevelop.Core; using MonoDevelop.Ide.Gui; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace MonoDevelop.Ide { @@ -69,17 +70,54 @@ namespace MonoDevelop.Ide DispatchDebug = Environment.GetEnvironmentVariable ("MONODEVELOP_DISPATCH_DEBUG") != null; } - public static void GuiDispatch (MessageHandler cb) + public static Task<T> GuiDispatch<T> (Func<T> cb) { + TaskCompletionSource<T> ts = new TaskCompletionSource<T> (); if (IsGuiThread) { - cb (); - return; + try { + ts.SetResult (cb ()); + } catch (Exception ex) { + ts.SetException (ex); + } + return ts.Task; + } + + QueueMessage (new GenericMessageContainer (() => { + try { + ts.SetResult (cb ()); + } catch (Exception ex) { + ts.SetException (ex); + } + }, false)); + + return ts.Task; + } + + public static Task GuiDispatch (Action cb) + { + TaskCompletionSource<bool> ts = new TaskCompletionSource<bool> (); + if (IsGuiThread) { + try { + cb (); + ts.SetResult (true); + } catch (Exception ex) { + ts.SetException (ex); + } + return ts.Task; } - QueueMessage (new GenericMessageContainer (cb, false)); + QueueMessage (new GenericMessageContainer (() => { + try { + cb (); + } finally { + ts.SetResult (true); + } + }, false)); + + return ts.Task; } - public static void GuiDispatch (StatefulMessageHandler cb, object state) + internal static void GuiDispatch (StatefulMessageHandler cb, object state) { if (IsGuiThread) { cb (state); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/HelpOperations.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/HelpOperations.cs index fa8670ff7a..3d9f30aa81 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/HelpOperations.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/HelpOperations.cs @@ -54,7 +54,7 @@ namespace MonoDevelop.Ide if (Platform.IsMac) { var url = topic != null ? "monodoc://" + System.Web.HttpUtility.UrlEncode (topic) : null; - var mdapp = new FilePath (typeof (HelpOperations).Assembly.Location).ParentDirectory.Combine ("..", "..", "..", "MonoDoc.app").FullPath; + var mdapp = new FilePath (typeof (HelpOperations).Assembly.Location).ParentDirectory.Combine ("..", "..", "..", "..", "MacOS", "MonoDoc.app").FullPath; if (Directory.Exists (mdapp)) { builder.AddQuoted ("-a", mdapp, url, "--args"); AddDirArgs (builder); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs index 648180e7c6..3f06680c1a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs @@ -164,7 +164,7 @@ namespace MonoDevelop.Ide } } - public static void Initialize (IProgressMonitor monitor) + public static void Initialize (ProgressMonitor monitor) { Counters.Initialization.Trace ("Creating Workbench"); workbench = new Workbench (); @@ -225,7 +225,7 @@ namespace MonoDevelop.Ide TypeSystemService.TrackFileChanges = true; TypeSystemService.ParseProgressMonitorFactory = new ParseProgressMonitorFactory (); - Customizer.Initialize (); + Customizer.OnIdeInitialized (); // Startup commands Counters.Initialization.Trace ("Running Startup Commands"); @@ -291,7 +291,7 @@ namespace MonoDevelop.Ide if ((bool)PropertyService.Get("SharpDevelop.LoadPrevProjectOnStartup", false)) { var proj = DesktopService.RecentFiles.GetProjects ().FirstOrDefault (); if (proj != null) { - IdeApp.Workspace.OpenWorkspaceItem (proj.FileName).WaitForCompleted (); + IdeApp.Workspace.OpenWorkspaceItem (proj.FileName); } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs index c43f740ea8..a02a1b2d95 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs @@ -75,6 +75,9 @@ namespace MonoDevelop.Ide LoggingService.LogInfo ("Starting {0} {1}", BrandingService.ApplicationName, IdeVersionInfo.MonoDevelopVersion); LoggingService.LogInfo ("Running on {0}", IdeVersionInfo.GetRuntimeInfo ()); + IdeApp.Customizer = options.IdeCustomizer ?? new IdeCustomizer (); + IdeApp.Customizer.Initialize (); + Counters.Initialization.BeginTiming (); if (options.PerfLog) { @@ -149,8 +152,7 @@ namespace MonoDevelop.Ide Counters.Initialization.Trace ("Initializing Runtime"); Runtime.Initialize (true); - - IdeApp.Customizer = options.IdeCustomizer ?? new IdeCustomizer (); + IdeApp.Customizer.OnCoreInitialized (); Counters.Initialization.Trace ("Initializing theme"); @@ -162,7 +164,7 @@ namespace MonoDevelop.Ide if (theme != DefaultTheme) Gtk.Settings.Default.ThemeName = theme; - IProgressMonitor monitor = new MonoDevelop.Core.ProgressMonitoring.ConsoleProgressMonitor (); + ProgressMonitor monitor = new MonoDevelop.Core.ProgressMonitoring.ConsoleProgressMonitor (); monitor.BeginTask (GettextCatalog.GetString ("Starting {0}", BrandingService.ApplicationName), 2); @@ -222,7 +224,10 @@ namespace MonoDevelop.Ide return 1; reportedFailures = errorsList.Count; } - + + if (!CheckSCPlugin ()) + return 1; + // no alternative for Application.ThreadException? // Application.ThreadException += new ThreadExceptionEventHandler(ShowErrorBox); @@ -277,12 +282,17 @@ namespace MonoDevelop.Ide AddinManager.AddExtensionNodeHandler("/MonoDevelop/Ide/InitCompleteHandlers", OnExtensionChanged); StartLockupTracker (); IdeApp.Run (); + + IdeApp.Customizer.OnIdeShutdown (); // unloading services if (null != socket_filename) File.Delete (socket_filename); lockupCheckRunning = false; Runtime.Shutdown (); + + IdeApp.Customizer.OnCoreShutdown (); + InstrumentationService.Stop (); AddinManager.AddinLoadError -= OnAddinError; @@ -297,6 +307,8 @@ namespace MonoDevelop.Ide { if (Platform.IsWindows) return; + if (!string.Equals (Environment.GetEnvironmentVariable ("MD_LOCKUP_TRACKER"), "ON", StringComparison.OrdinalIgnoreCase)) + return; GLib.Timeout.Add (2000, () => { lastIdle = DateTime.Now; return true; @@ -537,6 +549,35 @@ namespace MonoDevelop.Ide } } + bool CheckSCPlugin () + { + if (Platform.IsMac && Directory.Exists ("/Library/Contextual Menu Items/SCFinderPlugin.plugin")) { + string message = "SCPlugin not supported"; + string detail = "MonoDevelop has detected that SCPlugin (scplugin.tigris.org) is installed. " + + "SCPlugin is a Subversion extension for Finder that is known to cause crashes in MonoDevelop and" + + "other applications running on Mac OSX 10.9 (Mavericks) or upper. Please uninstall SCPlugin " + + "before proceeding."; + var close = new AlertButton (BrandingService.BrandApplicationName (GettextCatalog.GetString ("Close MonoDevelop"))); + var info = new AlertButton (GettextCatalog.GetString ("More Information")); + var cont = new AlertButton (GettextCatalog.GetString ("Continue Anyway")); + while (true) { + var res = MessageService.GenericAlert (Gtk.Stock.DialogWarning, message, BrandingService.BrandApplicationName (detail), info, cont, close); + if (res == close) { + LoggingService.LogInternalError ("SCPlugin detected", new Exception ("SCPlugin detected. Closing.")); + return false; + } + if (res == info) + DesktopService.ShowUrl ("https://bugzilla.xamarin.com/show_bug.cgi?id=21755"); + if (res == cont) { + bool exists = Directory.Exists ("/Library/Contextual Menu Items/SCFinderPlugin.plugin"); + LoggingService.LogInternalError ("SCPlugin detected", new Exception ("SCPlugin detected. Continuing " + (exists ? "Installed." : "Uninstalled."))); + return true; + } + } + } + return true; + } + static void SetupExceptionManager () { System.Threading.Tasks.TaskScheduler.UnobservedTaskException += (sender, e) => { @@ -569,9 +610,9 @@ namespace MonoDevelop.Ide { ulong hash = 0; for (int i = 0; i < input.Length; i++) { - unchecked {
- hash = ((ulong)input[i]) + (hash << 6) + (hash << 16) - hash;
- }
+ unchecked { + hash = ((ulong)input[i]) + (hash << 6) + (hash << 16) - hash; + } } return (int)(hash % 1000); @@ -585,6 +626,8 @@ namespace MonoDevelop.Ide LoggingService.Initialize (options.RedirectOutput); + if (customizer == null) + customizer = LoadBrandingCustomizer (); options.IdeCustomizer = customizer; int ret = -1; @@ -623,6 +666,30 @@ namespace MonoDevelop.Ide return ret; } + + static IdeCustomizer LoadBrandingCustomizer () + { + var pathsString = BrandingService.GetString ("CustomizerAssemblyPath"); + if (string.IsNullOrEmpty (pathsString)) + return null; + + var paths = pathsString.Split (new [] {';'}, StringSplitOptions.RemoveEmptyEntries); + var type = BrandingService.GetString ("CustomizerType"); + if (!string.IsNullOrEmpty (type)) { + foreach (var path in paths) { + var file = BrandingService.GetFile (path.Replace ('/',Path.DirectorySeparatorChar)); + if (File.Exists (file)) { + Assembly asm = Assembly.LoadFrom (file); + var t = asm.GetType (type, true); + var c = Activator.CreateInstance (t) as IdeCustomizer; + if (c == null) + throw new InvalidOperationException ("Customizer class specific in the branding file is not an IdeCustomizer subclass"); + return c; + } + } + } + return null; + } } public class MonoDevelopOptions diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs index 98c65d8c83..20a66ccdca 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs @@ -585,6 +585,7 @@ namespace MonoDevelop.Ide int result = addins.IndexOf (addin); if (result == -1) { result = addins.Count; + addins.Add (addin); addinIcons.Add (new Dictionary<string, string> ()); } return result; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs index 578f09c53e..63625527ec 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs @@ -514,6 +514,7 @@ namespace MonoDevelop.Ide public bool AllowApplyToAll { get; set; } public int DefaultButton { get; set; } public CancellationToken CancellationToken { get; private set; } + public bool UseMarkup { get; set; } public void AddOption (string id, string text, bool setByDefault) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs index 35c90fc7e8..5662fac7e4 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs @@ -40,7 +40,6 @@ using MonoDevelop.Core; using MonoDevelop.Core.Execution; using MonoDevelop.Core.ProgressMonitoring; using MonoDevelop.Ide.ProgressMonitoring; -using MonoDevelop.Ide.Tasks; using MonoDevelop.Ide.Gui.Dialogs; using MonoDevelop.Ide.Gui; using MonoDevelop.Ide.Projects; @@ -53,6 +52,10 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation; using System.Text; using MonoDevelop.Ide.TypeSystem; using ICSharpCode.NRefactory.TypeSystem; +using System.Threading.Tasks; +using System.Threading; +using ExecutionContext = MonoDevelop.Projects.ExecutionContext; +using MonoDevelop.Ide.Tasks; namespace MonoDevelop.Ide { @@ -61,14 +64,14 @@ namespace MonoDevelop.Ide /// </summary> public class ProjectOperations { - IAsyncOperation currentBuildOperation = NullAsyncOperation.Success; - IAsyncOperation currentRunOperation = NullAsyncOperation.Success; + AsyncOperation<BuildResult> currentBuildOperation = new AsyncOperation<BuildResult> (Task.FromResult (BuildResult.Success), null); + AsyncOperation currentRunOperation = AsyncOperation.CompleteOperation; IBuildTarget currentBuildOperationOwner; IBuildTarget currentRunOperationOwner; SelectReferenceDialog selDialog = null; - SolutionItem currentSolutionItem = null; + SolutionFolderItem currentSolutionItem = null; WorkspaceItem currentWorkspaceItem = null; object currentItem; @@ -99,12 +102,18 @@ namespace MonoDevelop.Ide public IBuildTarget CurrentSelectedBuildTarget { get { - if (currentSolutionItem != null) - return currentSolutionItem; - return currentWorkspaceItem; + if (currentSolutionItem is IBuildTarget) + return (IBuildTarget) currentSolutionItem; + return currentWorkspaceItem as IBuildTarget; } } + public WorkspaceObject CurrentSelectedObject { + get { + return (WorkspaceObject)currentSolutionItem ?? (WorkspaceObject) currentWorkspaceItem; + } + } + public WorkspaceItem CurrentSelectedWorkspaceItem { get { return currentWorkspaceItem; @@ -119,7 +128,7 @@ namespace MonoDevelop.Ide } } - public SolutionItem CurrentSelectedSolutionItem { + public SolutionFolderItem CurrentSelectedSolutionItem { get { if (currentSolutionItem == null && CurrentSelectedSolution != null) return CurrentSelectedSolution.RootFolder; @@ -127,7 +136,7 @@ namespace MonoDevelop.Ide } internal set { if (value != currentSolutionItem) { - SolutionItem oldValue = currentSolutionItem; + SolutionFolderItem oldValue = currentSolutionItem; currentSolutionItem = value; if (oldValue is Project || value is Project) OnCurrentProjectChanged (new ProjectEventArgs(currentSolutionItem as Project)); @@ -153,29 +162,31 @@ namespace MonoDevelop.Ide } } - public IAsyncOperation CurrentBuildOperation { + public AsyncOperation CurrentBuildOperation { get { return currentBuildOperation; } } - public IAsyncOperation CurrentRunOperation { + public AsyncOperation CurrentRunOperation { get { return currentRunOperation; } set { - currentRunOperation = value ?? NullAsyncOperation.Success; + currentRunOperation = value ?? AsyncOperation.CompleteOperation; OnCurrentRunOperationChanged (EventArgs.Empty); } } - public bool IsBuilding (IBuildTarget target) + public bool IsBuilding (WorkspaceObject ob) { - return !currentBuildOperation.IsCompleted && ContainsTarget (target, currentBuildOperationOwner); + var owner = currentBuildOperationOwner as WorkspaceObject; + return owner != null && !currentBuildOperation.IsCompleted && ContainsTarget (ob, owner); } - public bool IsRunning (IBuildTarget target) + public bool IsRunning (WorkspaceObject target) { - return !currentRunOperation.IsCompleted && ContainsTarget (target, currentRunOperationOwner); + var owner = currentRunOperationOwner as WorkspaceObject; + return owner != null && !currentRunOperation.IsCompleted && ContainsTarget (target, owner); } - internal static bool ContainsTarget (IBuildTarget owner, IBuildTarget target) + internal static bool ContainsTarget (WorkspaceObject owner, WorkspaceObject target) { if (owner == target) return true; @@ -314,10 +325,10 @@ namespace MonoDevelop.Ide public void RenameItem (IWorkspaceFileObject item, string newName) { ProjectOptionsDialog.RenameItem (item, newName); - if (item is SolutionItem) { - Save (((SolutionItem)item).ParentSolution); + if (item is SolutionFolderItem) { + SaveAsync (((SolutionFolderItem)item).ParentSolution); } else { - IdeApp.Workspace.Save (); + IdeApp.Workspace.SaveAsync (); IdeApp.Workspace.SavePreferences (); } } @@ -333,7 +344,7 @@ namespace MonoDevelop.Ide try { if (MessageService.RunCustomDialog (dlg) == (int) Gtk.ResponseType.Ok) { - using (IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetToolOutputProgressMonitor (true)) { + using (ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetToolOutputProgressMonitor (true)) { Services.ProjectService.Export (monitor, item.FileName, dlg.TargetFolder, dlg.Format); } } @@ -342,29 +353,29 @@ namespace MonoDevelop.Ide } } - public void Save (IEnumerable<SolutionEntityItem> entries) + public async Task SaveAsync (IEnumerable<SolutionItem> entries) { List<IWorkspaceFileObject> items = new List<IWorkspaceFileObject> (); foreach (IWorkspaceFileObject it in entries) items.Add (it); - Save (items); + await SaveAsync (items); } - public void Save (SolutionEntityItem entry) + public async Task SaveAsync (SolutionItem entry) { if (!entry.FileFormat.CanWrite (entry)) { IWorkspaceFileObject itemContainer = GetContainer (entry); if (SelectValidFileFormat (itemContainer)) - Save (itemContainer); + await SaveAsync (itemContainer); return; } if (!AllowSave (entry)) return; - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true); try { - entry.Save (monitor); + await entry.SaveAsync (monitor); monitor.ReportSuccess (GettextCatalog.GetString ("Project saved.")); } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("Save failed."), ex); @@ -373,7 +384,7 @@ namespace MonoDevelop.Ide } } - public void Save (Solution item) + public async Task SaveAsync (Solution item) { if (!item.FileFormat.CanWrite (item)) { if (!SelectValidFileFormat (item)) @@ -383,9 +394,9 @@ namespace MonoDevelop.Ide if (!AllowSave (item)) return; - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true); try { - item.Save (monitor); + await item.SaveAsync (monitor); monitor.ReportSuccess (GettextCatalog.GetString ("Solution saved.")); } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("Save failed."), ex); @@ -394,7 +405,7 @@ namespace MonoDevelop.Ide } } - public void Save (IEnumerable<IWorkspaceFileObject> items) + public async Task SaveAsync (IEnumerable<IWorkspaceFileObject> items) { int count = items.Count (); if (count == 0) @@ -418,7 +429,7 @@ namespace MonoDevelop.Ide } } if (fixedItems.Count > 0) - Save (fixedItems); + await SaveAsync (fixedItems); if (failedItems.Count > 0 || fixedItems.Count > 0) { // Some file format changes were required, and some items were saved. @@ -432,14 +443,17 @@ namespace MonoDevelop.Ide items = notSavedEntries; } - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true); try { + var tasks = new List<Task> (); monitor.BeginTask (null, count); foreach (IWorkspaceFileObject item in items) { if (AllowSave (item)) - item.Save (monitor); - monitor.Step (1); + tasks.Add (item.SaveAsync (monitor).ContinueWith (t => monitor.Step(1))); + else + monitor.Step (1); } + await Task.WhenAll (tasks); monitor.EndTask (); monitor.ReportSuccess (GettextCatalog.GetString ("Items saved.")); } catch (Exception ex) { @@ -449,26 +463,35 @@ namespace MonoDevelop.Ide } } - public void Save (IWorkspaceFileObject item) + public Task SaveAsync (WorkspaceObject item) + { + if (item is IWorkspaceFileObject) + return SaveAsync ((IWorkspaceFileObject)item); + if (item.ParentObject != null) + return SaveAsync (item.ParentObject); + return Task.FromResult (0); + } + + async Task SaveAsync (IWorkspaceFileObject item) { - if (item is SolutionEntityItem) - Save ((SolutionEntityItem) item); + if (item is SolutionItem) + await SaveAsync ((SolutionItem) item); else if (item is Solution) - Save ((Solution)item); + await SaveAsync ((Solution)item); if (!item.FileFormat.CanWrite (item)) { IWorkspaceFileObject ci = GetContainer (item); if (SelectValidFileFormat (ci)) - Save (ci); + await SaveAsync (ci); return; } if (!AllowSave (item)) return; - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true); try { - item.Save (monitor); + await item.SaveAsync (monitor); monitor.ReportSuccess (GettextCatalog.GetString ("Item saved.")); } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("Save failed."), ex); @@ -500,7 +523,7 @@ namespace MonoDevelop.Ide if (item.ItemFilesChanged) return true; if (item is WorkspaceItem) { - foreach (SolutionEntityItem eitem in ((WorkspaceItem)item).GetAllSolutionItems<SolutionEntityItem> ()) + foreach (SolutionItem eitem in ((WorkspaceItem)item).GetAllItems<SolutionItem> ()) if (eitem.ItemFilesChanged) return true; } @@ -509,7 +532,7 @@ namespace MonoDevelop.Ide IWorkspaceFileObject GetContainer (IWorkspaceFileObject item) { - SolutionEntityItem si = item as SolutionEntityItem; + SolutionItem si = item as SolutionItem; if (si != null && si.ParentSolution != null && !si.ParentSolution.FileFormat.SupportsMixedFormats) return si.ParentSolution; else @@ -541,15 +564,15 @@ namespace MonoDevelop.Ide } } - public void ShowOptions (IWorkspaceObject entry) + public void ShowOptions (WorkspaceObject entry) { ShowOptions (entry, null); } - public void ShowOptions (IWorkspaceObject entry, string panelId) + public void ShowOptions (WorkspaceObject entry, string panelId) { - if (entry is SolutionEntityItem) { - var selectedProject = (SolutionEntityItem) entry; + if (entry is SolutionItem) { + var selectedProject = (SolutionItem) entry; var optionsDialog = new ProjectOptionsDialog (IdeApp.Workbench.RootWindow, selectedProject); var conf = selectedProject.GetConfiguration (IdeApp.Workspace.ActiveConfiguration); @@ -562,11 +585,11 @@ namespace MonoDevelop.Ide if (MessageService.RunCustomDialog (optionsDialog) == (int)Gtk.ResponseType.Ok) { foreach (object ob in optionsDialog.ModifiedObjects) { if (ob is Solution) { - Save ((Solution)ob); + SaveAsync ((Solution)ob); return; } } - Save (selectedProject); + SaveAsync (selectedProject); IdeApp.Workspace.SavePreferences (); IdeApp.Workbench.ReparseOpenDocuments (); } @@ -582,7 +605,7 @@ namespace MonoDevelop.Ide if (panelId != null) optionsDialog.SelectPanel (panelId); if (MessageService.RunCustomDialog (optionsDialog) == (int) Gtk.ResponseType.Ok) { - Save (solution); + SaveAsync (solution); IdeApp.Workspace.SavePreferences (solution); } } finally { @@ -596,11 +619,11 @@ namespace MonoDevelop.Ide optionsDialog.SelectPanel (panelId); if (MessageService.RunCustomDialog (optionsDialog) == (int) Gtk.ResponseType.Ok) { if (entry is IWorkspaceFileObject) - Save ((IWorkspaceFileObject) entry); + SaveAsync ((IWorkspaceFileObject) entry); else { - SolutionItem si = entry as SolutionItem; + SolutionFolderItem si = entry as SolutionFolderItem; if (si.ParentSolution != null) - Save (si.ParentSolution); + SaveAsync (si.ParentSolution); } IdeApp.Workspace.SavePreferences (); } @@ -623,19 +646,19 @@ namespace MonoDevelop.Ide MessageService.ShowCustomDialog (pd); } - public WorkspaceItem AddNewWorkspaceItem (Workspace parentWorkspace) + public Task<WorkspaceItem> AddNewWorkspaceItem (Workspace parentWorkspace) { return AddNewWorkspaceItem (parentWorkspace, null); } - public WorkspaceItem AddNewWorkspaceItem (Workspace parentWorkspace, string defaultItemId) + public async Task<WorkspaceItem> AddNewWorkspaceItem (Workspace parentWorkspace, string defaultItemId) { NewProjectDialog npdlg = new NewProjectDialog (null, false, parentWorkspace.BaseDirectory); npdlg.SelectTemplate (defaultItemId); try { if (MessageService.RunCustomDialog (npdlg) == (int) Gtk.ResponseType.Ok && npdlg.NewItem != null) { parentWorkspace.Items.Add ((WorkspaceItem) npdlg.NewItem); - Save (parentWorkspace); + await SaveAsync ((IWorkspaceFileObject)parentWorkspace); return (WorkspaceItem) npdlg.NewItem; } } finally { @@ -644,7 +667,7 @@ namespace MonoDevelop.Ide return null; } - public WorkspaceItem AddWorkspaceItem (Workspace parentWorkspace) + public async Task<WorkspaceItem> AddWorkspaceItem (Workspace parentWorkspace) { WorkspaceItem res = null; @@ -659,7 +682,7 @@ namespace MonoDevelop.Ide if (dlg.Run ()) { try { - res = AddWorkspaceItem (parentWorkspace, dlg.SelectedFile); + res = await AddWorkspaceItem (parentWorkspace, dlg.SelectedFile); } catch (Exception ex) { MessageService.ShowException (ex, GettextCatalog.GetString ("The file '{0}' could not be loaded.", dlg.SelectedFile)); } @@ -668,24 +691,24 @@ namespace MonoDevelop.Ide return res; } - public WorkspaceItem AddWorkspaceItem (Workspace parentWorkspace, string itemFileName) + public async Task<WorkspaceItem> AddWorkspaceItem (Workspace parentWorkspace, string itemFileName) { - using (IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { - WorkspaceItem it = Services.ProjectService.ReadWorkspaceItem (monitor, itemFileName); + using (ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { + WorkspaceItem it = await Services.ProjectService.ReadWorkspaceItem (monitor, itemFileName); if (it != null) { parentWorkspace.Items.Add (it); - Save (parentWorkspace); + await SaveAsync ((IWorkspaceFileObject)parentWorkspace); } return it; } } - public SolutionItem CreateProject (SolutionFolder parentFolder) + public SolutionFolderItem CreateProject (SolutionFolder parentFolder) { string basePath = parentFolder != null ? parentFolder.BaseDirectory : null; NewProjectDialog npdlg = new NewProjectDialog (parentFolder, false, basePath); if (MessageService.ShowCustomDialog (npdlg) == (int)Gtk.ResponseType.Ok) { - var item = npdlg.NewItem as SolutionItem; + var item = npdlg.NewItem as SolutionFolderItem; if ((item is Project) && ProjectCreated != null) ProjectCreated (this, new ProjectCreatedEventArgs (item as Project)); return item; @@ -693,9 +716,9 @@ namespace MonoDevelop.Ide return null; } - public SolutionItem AddSolutionItem (SolutionFolder parentFolder) + public async Task<SolutionFolderItem> AddSolutionItem (SolutionFolder parentFolder) { - SolutionItem res = null; + SolutionFolderItem res = null; var dlg = new SelectFileDialog () { Action = Gtk.FileChooserAction.Open, @@ -713,27 +736,27 @@ namespace MonoDevelop.Ide } try { - res = AddSolutionItem (parentFolder, dlg.SelectedFile); + res = await AddSolutionItem (parentFolder, dlg.SelectedFile); } catch (Exception ex) { MessageService.ShowException (ex, GettextCatalog.GetString ("The file '{0}' could not be loaded.", dlg.SelectedFile)); } } if (res != null) - IdeApp.Workspace.Save (); + await IdeApp.Workspace.SaveAsync (); return res; } - public SolutionItem AddSolutionItem (SolutionFolder folder, string entryFileName) + public async Task<SolutionFolderItem> AddSolutionItem (SolutionFolder folder, string entryFileName) { AddEntryEventArgs args = new AddEntryEventArgs (folder, entryFileName); if (AddingEntryToCombine != null) AddingEntryToCombine (this, args); if (args.Cancel) return null; - using (IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { - return folder.AddItem (monitor, args.FileName, true); + using (ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { + return await folder.AddItem (monitor, args.FileName, true); } } @@ -788,12 +811,12 @@ namespace MonoDevelop.Ide } } - public void RemoveSolutionItem (SolutionItem item) + public void RemoveSolutionItem (SolutionFolderItem item) { string question = GettextCatalog.GetString ("Do you really want to remove project '{0}' from '{1}'?", item.Name, item.ParentFolder.Name); string secondaryText = GettextCatalog.GetString ("The Remove option remove the project from the solution, but it will not physically delete any file from disk."); - SolutionEntityItem prj = item as SolutionEntityItem; + SolutionItem prj = item as SolutionItem; if (prj == null) { if (MessageService.Confirm (question, AlertButton.Remove) && IdeApp.Workspace.RequestItemUnload (item)) RemoveItemFromSolution (prj); @@ -814,7 +837,7 @@ namespace MonoDevelop.Ide RemoveItemFromSolution (prj); List<FilePath> files = dlg.GetFilesToDelete (); - using (IProgressMonitor monitor = new MessageDialogProgressMonitor (true)) { + using (ProgressMonitor monitor = new MessageDialogProgressMonitor (true)) { monitor.BeginTask (GettextCatalog.GetString ("Deleting Files..."), files.Count); foreach (FilePath file in files) { try { @@ -839,14 +862,14 @@ namespace MonoDevelop.Ide } } - void RemoveItemFromSolution (SolutionItem prj) + void RemoveItemFromSolution (SolutionFolderItem prj) { foreach (var doc in IdeApp.Workbench.Documents.Where (d => d.Project == prj).ToArray ()) doc.Close (); Solution sol = prj.ParentSolution; prj.ParentFolder.Items.Remove (prj); prj.Dispose (); - IdeApp.ProjectOperations.Save (sol); + IdeApp.ProjectOperations.SaveAsync (sol); } /// <summary> @@ -889,44 +912,43 @@ namespace MonoDevelop.Ide return entry.CanExecute (context, IdeApp.Workspace.ActiveConfiguration); } - public IAsyncOperation Execute (IBuildTarget entry) + public AsyncOperation Execute (IBuildTarget entry) { return Execute (entry, Runtime.ProcessService.DefaultExecutionHandler); } - public IAsyncOperation Execute (IBuildTarget entry, IExecutionHandler handler) + public AsyncOperation Execute (IBuildTarget entry, IExecutionHandler handler) { ExecutionContext context = new ExecutionContext (handler, IdeApp.Workbench.ProgressMonitors, IdeApp.Workspace.ActiveExecutionTarget); return Execute (entry, context); } - public IAsyncOperation Execute (IBuildTarget entry, ExecutionContext context) + public AsyncOperation Execute (IBuildTarget entry, ExecutionContext context) { if (currentRunOperation != null && !currentRunOperation.IsCompleted) return currentRunOperation; - NullProgressMonitor monitor = new NullProgressMonitor (); + var cs = new CancellationTokenSource (); + ProgressMonitor monitor = new ProgressMonitor (cs); - DispatchService.ThreadDispatch (delegate { - ExecuteSolutionItemAsync (monitor, entry, context); - }); - CurrentRunOperation = monitor.AsyncOperation; + var t = ExecuteSolutionItemAsync (monitor, entry, context); + + var op = new AsyncOperation (t, cs); + CurrentRunOperation = op; currentRunOperationOwner = entry; - currentRunOperation.Completed += delegate { - DispatchService.GuiDispatch (() => { - var error = monitor.Errors.FirstOrDefault (); - if (error != null) - IdeApp.Workbench.StatusBar.ShowError (error.Message); - currentRunOperationOwner = null; - }); - }; + t.ContinueWith (ta => { + var error = monitor.Errors.FirstOrDefault (); + if (error != null) + IdeApp.Workbench.StatusBar.ShowError (error.Message); + currentRunOperationOwner = null; + }); return currentRunOperation; } - void ExecuteSolutionItemAsync (IProgressMonitor monitor, IBuildTarget entry, ExecutionContext context) + async Task ExecuteSolutionItemAsync (ProgressMonitor monitor, IBuildTarget entry, ExecutionContext context) { try { OnBeforeStartProject (); - entry.Execute (monitor, context, IdeApp.Workspace.ActiveConfiguration); + await entry.Execute (monitor, context, IdeApp.Workspace.ActiveConfiguration); } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("Execution failed."), ex); LoggingService.LogError ("Execution failed", ex); @@ -934,22 +956,59 @@ namespace MonoDevelop.Ide monitor.Dispose (); } } - - public IAsyncOperation Clean (IBuildTarget entry) + + public bool CanExecuteFile (string file, IExecutionHandler handler) + { + ExecutionContext context = new ExecutionContext (handler, IdeApp.Workbench.ProgressMonitors, IdeApp.Workspace.ActiveExecutionTarget); + return CanExecuteFile (file, context); + } + + public bool CanExecuteFile (string file, ExecutionContext context) + { + var cmd = Runtime.ProcessService.CreateCommand (file); + if (context.ExecutionHandler.CanExecute (cmd)) + return true; + return false; + } + + public AsyncOperation ExecuteFile (string file, IExecutionHandler handler) + { + ExecutionContext context = new ExecutionContext (handler, IdeApp.Workbench.ProgressMonitors, IdeApp.Workspace.ActiveExecutionTarget); + return ExecuteFile (file, context); + } + + public AsyncOperation ExecuteFile (string file, ExecutionContext context) + { + var cmd = Runtime.ProcessService.CreateCommand (file); + if (context.ExecutionHandler.CanExecute (cmd)) + return context.ExecutionHandler.Execute (cmd, context.ConsoleFactory.CreateConsole (true)); + else { + MessageService.ShowError(GettextCatalog.GetString ("No runnable executable found.")); + return AsyncOperation.CompleteOperation; + } + } + + public AsyncOperation Clean (IBuildTarget entry) { if (currentBuildOperation != null && !currentBuildOperation.IsCompleted) return currentBuildOperation; ITimeTracker tt = Counters.BuildItemTimer.BeginTiming ("Cleaning " + entry.Name); try { - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetCleanProgressMonitor (); + var cs = new CancellationTokenSource (); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetCleanProgressMonitor ().WithCancellationSource (cs); + OnStartClean (monitor, tt); - DispatchService.ThreadDispatch (() => CleanAsync (entry, monitor, tt, false)); - - currentBuildOperation = monitor.AsyncOperation; - currentBuildOperationOwner = entry; - currentBuildOperation.Completed += delegate { + + var t = CleanAsync (entry, monitor, tt, false); + + t = t.ContinueWith (ta => { currentBuildOperationOwner = null; - }; + return ta.Result; + }); + + var op = new AsyncOperation<BuildResult> (t, cs); + currentBuildOperation = op; + currentBuildOperationOwner = entry; } catch { tt.End (); @@ -959,17 +1018,12 @@ namespace MonoDevelop.Ide return currentBuildOperation; } - void CleanAsync (IBuildTarget entry, IProgressMonitor monitor, ITimeTracker tt, bool isRebuilding) + async Task<BuildResult> CleanAsync (IBuildTarget entry, ProgressMonitor monitor, ITimeTracker tt, bool isRebuilding) { + BuildResult res = null; try { tt.Trace ("Cleaning item"); - SolutionItem it = entry as SolutionItem; - if (it != null) { - it.Clean (monitor, IdeApp.Workspace.ActiveConfiguration); - } - else { - entry.RunTarget (monitor, ProjectService.CleanTarget, IdeApp.Workspace.ActiveConfiguration); - } + res = await entry.Clean (monitor, IdeApp.Workspace.ActiveConfiguration); } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("Clean failed."), ex); } finally { @@ -978,14 +1032,15 @@ namespace MonoDevelop.Ide if (isRebuilding) { if (EndClean != null) { - DispatchService.GuiSyncDispatch (() => OnEndClean (monitor, tt)); + OnEndClean (monitor, tt); } } else { - DispatchService.GuiDispatch (() => CleanDone (monitor, entry, tt)); + CleanDone (monitor, entry, tt); } + return res; } - void CleanDone (IProgressMonitor monitor, IBuildTarget entry, ITimeTracker tt) + void CleanDone (ProgressMonitor monitor, IBuildTarget entry, ITimeTracker tt) { tt.Trace ("Begin reporting clean result"); try { @@ -1000,139 +1055,60 @@ namespace MonoDevelop.Ide } } - public IAsyncOperation BuildFile (string file) - { - Project tempProject = MonoDevelop.Projects.Services.ProjectService.CreateSingleFileProject (file); - if (tempProject != null) { - IAsyncOperation aop = Build (tempProject); - aop.Completed += delegate { tempProject.Dispose (); }; - return aop; - } else { - MessageService.ShowError (GettextCatalog.GetString ("The file {0} can't be compiled.", file)); - return NullAsyncOperation.Failure; - } - } - - public IAsyncOperation ExecuteFile (string file) - { - Project tempProject = MonoDevelop.Projects.Services.ProjectService.CreateSingleFileProject (file); - if (tempProject != null) { - IAsyncOperation aop = Execute (tempProject); - aop.Completed += delegate { tempProject.Dispose (); }; - return aop; - } else { - MessageService.ShowError(GettextCatalog.GetString ("No runnable executable found.")); - return NullAsyncOperation.Failure; - } - } - - public bool CanExecuteFile (string file) - { - return CanExecuteFile (file, Runtime.ProcessService.DefaultExecutionHandler); - } - - public bool CanExecuteFile (string file, IExecutionHandler handler) - { - ExecutionContext context = new ExecutionContext (handler, IdeApp.Workbench.ProgressMonitors, IdeApp.Workspace.ActiveExecutionTarget); - return CanExecuteFile (file, context); - } - - public bool CanExecuteFile (string file, ExecutionContext context) + public AsyncOperation<BuildResult> Rebuild (IBuildTarget entry) { - Project tempProject = MonoDevelop.Projects.Services.ProjectService.CreateSingleFileProject (file); - if (tempProject != null) { - bool res = CanExecute (tempProject, context); - tempProject.Dispose (); - return res; - } - else { - var cmd = Runtime.ProcessService.CreateCommand (file); - if (context.ExecutionHandler.CanExecute (cmd)) - return true; - } - return false; - } - - public IAsyncOperation ExecuteFile (string file, IExecutionHandler handler) - { - ExecutionContext context = new ExecutionContext (handler, IdeApp.Workbench.ProgressMonitors, IdeApp.Workspace.ActiveExecutionTarget); - return ExecuteFile (file, context); - } - - public IAsyncOperation ExecuteFile (string file, ExecutionContext context) - { - Project tempProject = MonoDevelop.Projects.Services.ProjectService.CreateSingleFileProject (file); - if (tempProject != null) { - IAsyncOperation aop = Execute (tempProject, context); - aop.Completed += delegate { tempProject.Dispose (); }; - return aop; - } else { - MessageService.ShowError(GettextCatalog.GetString ("No runnable executable found.")); - return NullAsyncOperation.Failure; - } + if (currentBuildOperation != null && !currentBuildOperation.IsCompleted) return currentBuildOperation; + + var cs = new CancellationTokenSource (); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetRebuildProgressMonitor ().WithCancellationSource (cs); + + var t = RebuildAsync (entry, monitor); + t = t.ContinueWith (ta => { + currentBuildOperationOwner = null; + return ta.Result; + }); + + var op = new AsyncOperation<BuildResult> (t, cs); + + return currentBuildOperation = op; } - public IAsyncOperation Rebuild (IBuildTarget entry) + async Task<BuildResult> RebuildAsync (IBuildTarget entry, ProgressMonitor monitor) { - if (currentBuildOperation != null && !currentBuildOperation.IsCompleted) return currentBuildOperation; - ITimeTracker tt = Counters.BuildItemTimer.BeginTiming ("Rebuilding " + entry.Name); try { - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetRebuildProgressMonitor (); OnStartClean (monitor, tt); - DispatchService.ThreadDispatch (delegate { - CleanAsync (entry, monitor, tt, true); - if (monitor.AsyncOperation.IsCompleted && !monitor.AsyncOperation.Success) { - tt.End (); - monitor.Dispose (); - return; - } - if (StartBuild != null) { - DispatchService.GuiSyncDispatch (() => BeginBuild (monitor, tt, true)); - } - BuildSolutionItemAsync (entry, monitor, tt); - }, null); - currentBuildOperation = monitor.AsyncOperation; - currentBuildOperationOwner = entry; - currentBuildOperation.Completed += delegate { currentBuildOperationOwner = null; }; - } catch { + var res = await CleanAsync (entry, monitor, tt, true); + if (res.HasErrors) { + tt.End (); + monitor.Dispose (); + return res; + } + if (StartBuild != null) { + BeginBuild (monitor, tt, true); + } + return await BuildSolutionItemAsync (entry, monitor, tt); + } finally { tt.End (); - throw; } - return currentBuildOperation; } - -// bool errorPadInitialized = false; - public IAsyncOperation Build (IBuildTarget entry) + + public AsyncOperation<BuildResult> Build (IBuildTarget entry, CancellationToken? cancellationToken = null) { if (currentBuildOperation != null && !currentBuildOperation.IsCompleted) return currentBuildOperation; - /* - if (!errorPadInitialized) { - try { - Pad errorsPad = IdeApp.Workbench.GetPad<MonoDevelop.Ide.Gui.Pads.ErrorListPad> (); - errorsPad.Window.PadHidden += delegate { - content.IsOpenedAutomatically = false; - }; - - Pad monitorPad = IdeApp.Workbench.Pads.FirstOrDefault (pad => pad.Content == ((OutputProgressMonitor)((AggregatedProgressMonitor)monitor).MasterMonitor).OutputPad); - monitorPad.Window.PadHidden += delegate { - monitorPad.IsOpenedAutomatically = false; - }; - } finally { - errorPadInitialized = true; - } - } - */ - + ITimeTracker tt = Counters.BuildItemTimer.BeginTiming ("Building " + entry.Name); try { - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBuildProgressMonitor (); + var cs = new CancellationTokenSource (); + if (cancellationToken != null) + cs = CancellationTokenSource.CreateLinkedTokenSource (cs.Token, cancellationToken.Value); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBuildProgressMonitor ().WithCancellationSource (cs); BeginBuild (monitor, tt, false); - DispatchService.ThreadDispatch (() => BuildSolutionItemAsync (entry, monitor, tt)); - currentBuildOperation = monitor.AsyncOperation; + var t = BuildSolutionItemAsync (entry, monitor, tt); + currentBuildOperation = new AsyncOperation<BuildResult> (t, cs); currentBuildOperationOwner = entry; - currentBuildOperation.Completed += delegate { currentBuildOperationOwner = null; }; + t.ContinueWith ((ta) => currentBuildOperationOwner = null); } catch { tt.End (); throw; @@ -1140,7 +1116,7 @@ namespace MonoDevelop.Ide return currentBuildOperation; } - void BuildSolutionItemAsync (IBuildTarget entry, IProgressMonitor monitor, ITimeTracker tt) + async Task<BuildResult> BuildSolutionItemAsync (IBuildTarget entry, ProgressMonitor monitor, ITimeTracker tt) { BuildResult result = null; try { @@ -1152,11 +1128,7 @@ namespace MonoDevelop.Ide if (result.ErrorCount == 0) { tt.Trace ("Building item"); - SolutionItem it = entry as SolutionItem; - if (it != null) - result = it.Build (monitor, IdeApp.Workspace.ActiveConfiguration, true); - else - result = entry.RunTarget (monitor, ProjectService.BuildTarget, IdeApp.Workspace.ActiveConfiguration); + result = await entry.Build (monitor, IdeApp.Workspace.ActiveConfiguration, true); } } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("Build failed."), ex); @@ -1166,10 +1138,10 @@ namespace MonoDevelop.Ide } finally { tt.Trace ("Done building"); } - DispatchService.GuiDispatch ( - delegate { - BuildDone (monitor, result, entry, tt); // BuildDone disposes the monitor - }); + + BuildDone (monitor, result, entry, tt); // BuildDone disposes the monitor + + return result; } // Note: This must run in the main thread @@ -1213,28 +1185,28 @@ namespace MonoDevelop.Ide switch (action) { case BeforeCompileAction.Nothing: break; - case BeforeCompileAction.PromptForSave: DispatchService.GuiSyncDispatch (delegate { PromptForSave (result); }); break; - case BeforeCompileAction.SaveAllFiles: DispatchService.GuiSyncDispatch (delegate { SaveAllFiles (result); }); break; + case BeforeCompileAction.PromptForSave: PromptForSave (result); break; + case BeforeCompileAction.SaveAllFiles: SaveAllFiles (result); break; default: System.Diagnostics.Debug.Assert (false); break; } return result; } - void BeginBuild (IProgressMonitor monitor, ITimeTracker tt, bool isRebuilding) + void BeginBuild (ProgressMonitor monitor, ITimeTracker tt, bool isRebuilding) { tt.Trace ("Start build event"); if (!isRebuilding) { - TaskService.Errors.ClearByOwner (this); + MonoDevelop.Ide.Tasks.TaskService.Errors.ClearByOwner (this); } if (StartBuild != null) { StartBuild (this, new BuildEventArgs (monitor, true)); } } - void BuildDone (IProgressMonitor monitor, BuildResult result, IBuildTarget entry, ITimeTracker tt) + void BuildDone (ProgressMonitor monitor, BuildResult result, IBuildTarget entry, ITimeTracker tt) { - Task[] tasks = null; + UserTask[] tasks = null; tt.Trace ("Begin reporting build result"); try { if (result != null) { @@ -1243,9 +1215,9 @@ namespace MonoDevelop.Ide monitor.Log.WriteLine (GettextCatalog.GetString ("---------------------- Done ----------------------")); tt.Trace ("Updating task service"); - tasks = new Task [result.Errors.Count]; + tasks = new UserTask [result.Errors.Count]; for (int n=0; n<tasks.Length; n++) { - tasks [n] = new Task (result.Errors [n]); + tasks [n] = new UserTask (result.Errors [n]); tasks [n].Owner = this; } @@ -1258,7 +1230,7 @@ namespace MonoDevelop.Ide string errorString = GettextCatalog.GetPluralString("{0} error", "{0} errors", result.ErrorCount, result.ErrorCount); string warningString = GettextCatalog.GetPluralString("{0} warning", "{0} warnings", result.WarningCount, result.WarningCount); - if (monitor.IsCancelRequested) { + if (monitor.CancellationToken.IsCancellationRequested) { monitor.ReportError (GettextCatalog.GetString ("Build canceled."), null); } else if (result.ErrorCount == 0 && result.WarningCount == 0 && lastResult.FailedBuildCount == 0) { monitor.ReportSuccess (GettextCatalog.GetString ("Build successful.")); @@ -1270,7 +1242,7 @@ namespace MonoDevelop.Ide monitor.ReportError(GettextCatalog.GetString("Build failed."), null); } tt.Trace ("End build event"); - OnEndBuild (monitor, lastResult.FailedBuildCount == 0, lastResult, entry as SolutionItem); + OnEndBuild (monitor, lastResult.FailedBuildCount == 0, lastResult, entry as SolutionFolderItem); } else { tt.Trace ("End build event"); OnEndBuild (monitor, false); @@ -1301,7 +1273,7 @@ namespace MonoDevelop.Ide } catch {} if (tasks != null) { - Task jumpTask = null; + UserTask jumpTask = null; switch (IdeApp.Preferences.JumpToFirstErrorOrWarning) { case JumpToFirst.Error: jumpTask = tasks.FirstOrDefault (t => t.Severity == TaskSeverity.Error && TaskStore.IsProjectTaskFile (t)); @@ -1421,7 +1393,7 @@ namespace MonoDevelop.Ide bool dialogShown = false; bool supportsLinking = !(project is MonoDevelop.Projects.SharedAssetsProjects.SharedAssetsProject); - IProgressMonitor monitor = null; + ProgressMonitor monitor = null; if (files.Length > 10) { monitor = new MessageDialogProgressMonitor (true); @@ -1586,7 +1558,7 @@ namespace MonoDevelop.Ide return true; } - public void TransferFiles (IProgressMonitor monitor, Project sourceProject, FilePath sourcePath, Project targetProject, + public void TransferFiles (ProgressMonitor monitor, Project sourceProject, FilePath sourcePath, Project targetProject, FilePath targetPath, bool removeFromSource, bool copyOnlyProjectFiles) { // When transfering directories, targetPath is the directory where the source @@ -1871,7 +1843,7 @@ namespace MonoDevelop.Ide } } - void OnEndBuild (IProgressMonitor monitor, bool success, BuildResult result = null, SolutionItem item = null) + void OnEndBuild (ProgressMonitor monitor, bool success, BuildResult result = null, SolutionFolderItem item = null) { if (EndBuild == null) return; @@ -1888,7 +1860,7 @@ namespace MonoDevelop.Ide EndBuild (this, args); } - void OnStartClean (IProgressMonitor monitor, ITimeTracker tt) + void OnStartClean (ProgressMonitor monitor, ITimeTracker tt) { tt.Trace ("Start clean event"); TaskService.Errors.ClearByOwner (this); @@ -1897,7 +1869,7 @@ namespace MonoDevelop.Ide } } - void OnEndClean (IProgressMonitor monitor, ITimeTracker tt) + void OnEndClean (ProgressMonitor monitor, ITimeTracker tt) { tt.Trace ("End clean event"); if (EndClean != null) { @@ -1926,7 +1898,7 @@ namespace MonoDevelop.Ide CurrentSelectedSolutionItem = null; if (ContainsTarget (args.Item, currentWorkspaceItem)) CurrentSelectedWorkspaceItem = null; - if ((currentItem is IBuildTarget) && ContainsTarget (args.Item, ((IBuildTarget)currentItem))) + if ((currentItem is IBuildTarget) && ContainsTarget (args.Item, ((WorkspaceObject)currentItem))) CurrentSelectedItem = null; } @@ -1972,7 +1944,7 @@ namespace MonoDevelop.Ide class ParseProgressMonitorFactory: IProgressMonitorFactory { - public IProgressMonitor CreateProgressMonitor () + public ProgressMonitor CreateProgressMonitor () { return new BackgroundProgressMonitor (GettextCatalog.GetString ("Code completion database generation"), "md-parser"); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs index 2a26de38a5..3816ddc78b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs @@ -43,10 +43,11 @@ using MonoDevelop.Core.Instrumentation; using MonoDevelop.Ide.Gui; using MonoDevelop.Ide.Projects; using MonoDevelop.Core.Execution; +using System.Threading.Tasks; namespace MonoDevelop.Ide { - public class RootWorkspace: IBuildTarget, IWorkspaceObject + public class RootWorkspace: WorkspaceObject, IBuildTarget { WorkspaceItemCollection items; // IParserDatabase parserDatabase; @@ -151,8 +152,8 @@ namespace MonoDevelop.Ide get { return Runtime.SystemAssemblyService.DefaultRuntime; } - set {
- useDefaultRuntime = false;
+ set { + useDefaultRuntime = false; Runtime.SystemAssemblyService.DefaultRuntime = value; } } @@ -160,8 +161,8 @@ namespace MonoDevelop.Ide public bool UseDefaultRuntime { get { return useDefaultRuntime; } set { - if (useDefaultRuntime != value) {
- useDefaultRuntime = value;
+ if (useDefaultRuntime != value) { + useDefaultRuntime = value; if (value) Runtime.SystemAssemblyService.DefaultRuntime = IdeApp.Preferences.DefaultTargetRuntime; } @@ -172,97 +173,43 @@ namespace MonoDevelop.Ide get { return Items.Count > 0; } } - IDictionary IExtendedDataItem.ExtendedProperties { - get { - throw new NotSupportedException ("Root namespace can't have extended properties."); - } + protected override string OnGetName () + { + return "MonoDevelop Workspace"; } - string IWorkspaceObject.Name { - get { - return "MonoDevelop Workspace"; - } - set { - throw new NotSupportedException ("Can't change the name of the root workspace."); - } + protected override string OnGetBaseDirectory () + { + return IdeApp.ProjectOperations.ProjectsDefaultPath; } - public FilePath BaseDirectory { - get { - return IdeApp.ProjectOperations.ProjectsDefaultPath; - } - } - - FilePath IWorkspaceObject.BaseDirectory { - get { - return BaseDirectory; - } - set { - throw new NotSupportedException (); - } - } - - FilePath IWorkspaceObject.ItemDirectory { - get { - return BaseDirectory; - } - } - -#region Model queries - - public SolutionEntityItem FindSolutionItem (string fileName) + protected override string OnGetItemDirectory () { - foreach (WorkspaceItem it in Items) { - SolutionEntityItem si = it.FindSolutionItem (fileName); - if (si != null) - return si; - } - return null; + return BaseDirectory; } - - public ReadOnlyCollection<SolutionItem> GetAllSolutionItems () + + protected override IEnumerable<WorkspaceObject> OnGetChildren () { - return GetAllSolutionItems<SolutionItem> (); + return Items; } + +#region Model queries - public virtual ReadOnlyCollection<T> GetAllSolutionItems<T> () where T: SolutionItem + public IEnumerable<SolutionItem> GetAllSolutionItems () { - List<T> list = new List<T> (); - foreach (WorkspaceItem it in Items) { - list.AddRange (it.GetAllSolutionItems<T> ()); - } - return list.AsReadOnly (); + return GetAllItems<SolutionItem> (); } - public ReadOnlyCollection<Project> GetAllProjects () + public IEnumerable<Project> GetAllProjects () { - return GetAllSolutionItems<Project> (); + return GetAllItems<Project> (); } - public ReadOnlyCollection<Solution> GetAllSolutions () + public IEnumerable<Solution> GetAllSolutions () { return GetAllItems<Solution> (); } - public ReadOnlyCollection<T> GetAllItems<T> () where T:WorkspaceItem - { - List<T> list = new List<T> (); - foreach (WorkspaceItem it in Items) - GetAllItems<T> (list, it); - return list.AsReadOnly (); - } - - void GetAllItems<T> (List<T> list, WorkspaceItem item) where T: WorkspaceItem - { - if (item is T) - list.Add ((T) item); - - if (item is Workspace) { - foreach (WorkspaceItem citem in ((Workspace)item).Items) - GetAllItems<T> (list, citem); - } - } - [Obsolete("Use GetProjectsContainingFile() (plural) instead")] public Project GetProjectContainingFile (string fileName) { @@ -287,11 +234,11 @@ namespace MonoDevelop.Ide #region Build and run operations - public void Save () + public async Task SaveAsync () { - IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true); try { - Save (monitor); + await SaveAsync (monitor); monitor.ReportSuccess (GettextCatalog.GetString ("Workspace saved.")); } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("Save failed."), ex); @@ -300,35 +247,6 @@ namespace MonoDevelop.Ide } } - public IAsyncOperation Build () - { - return IdeApp.ProjectOperations.Build (this); - } - - public void Clean () - { - IdeApp.ProjectOperations.Clean (this); - } - - public IAsyncOperation Execute () - { - if (IdeApp.ProjectOperations.CurrentSelectedSolution != null) - return IdeApp.ProjectOperations.Execute (IdeApp.ProjectOperations.CurrentSelectedSolution); - else { - MessageService.ShowError (GettextCatalog.GetString ("No solution has been selected"), GettextCatalog.GetString ("The solution to be executed must be selected in the solution pad.")); - return null; - } - } - - public bool CanExecute () - { - if (IdeApp.ProjectOperations.CurrentSelectedSolution != null) - return IdeApp.ProjectOperations.CanExecute (IdeApp.ProjectOperations.CurrentSelectedSolution); - else { - return false; - } - } - bool IBuildTarget.CanExecute (ExecutionContext context, ConfigurationSelector configuration) { if (IdeApp.ProjectOperations.CurrentSelectedSolution != null) @@ -338,27 +256,23 @@ namespace MonoDevelop.Ide } } - public void Dispose () - { - } - - public void Save (IProgressMonitor monitor) + public async Task SaveAsync (ProgressMonitor monitor) { monitor.BeginTask (GettextCatalog.GetString ("Saving Workspace..."), Items.Count); List<WorkspaceItem> items = new List<WorkspaceItem> (Items); foreach (WorkspaceItem it in items) { - it.Save (monitor); + await it.SaveAsync (monitor); monitor.Step (1); } monitor.EndTask (); } - BuildResult IBuildTarget.RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration) + async Task<BuildResult> IBuildTarget.Build (ProgressMonitor monitor, ConfigurationSelector configuration, bool buildReferences) { BuildResult result = null; - List<WorkspaceItem> items = new List<WorkspaceItem> (Items); - foreach (WorkspaceItem it in items.Where (i => i.SupportsTarget (target))) { - BuildResult res = it.RunTarget (monitor, target, configuration); + var items = Items.OfType<IBuildTarget> ().ToList (); + foreach (var it in items) { + BuildResult res = await it.Build (monitor, configuration, buildReferences); if (res != null) { if (result == null) result = new BuildResult (); @@ -368,25 +282,26 @@ namespace MonoDevelop.Ide return result; } - bool IBuildTarget.SupportsTarget (string target) + async Task<BuildResult> IBuildTarget.Clean (ProgressMonitor monitor, ConfigurationSelector configuration) { - foreach (WorkspaceItem it in Items.ToArray ()) { - if (it.SupportsTarget (target)) - return true; + BuildResult result = null; + var items = Items.OfType<IBuildTarget> ().ToList (); + foreach (var it in items) { + BuildResult res = await it.Clean (monitor, configuration); + if (res != null) { + if (result == null) + result = new BuildResult (); + result.Append (res); + } } - return false; + return result; } - public void Execute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) + public Task Execute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { - Solution sol = IdeApp.ProjectOperations.CurrentSelectedSolution; - if (sol == null) { - ReadOnlyCollection<Solution> sols = GetAllSolutions (); - if (sols.Count > 0) - sol = sols [0]; - } + Solution sol = IdeApp.ProjectOperations.CurrentSelectedSolution ?? GetAllSolutions ().FirstOrDefault (); if (sol != null) - sol.Execute (monitor, context, configuration); + return sol.Execute (monitor, context, configuration); else throw new UserException (GettextCatalog.GetString ("No solution has been selected.")); } @@ -499,7 +414,7 @@ namespace MonoDevelop.Ide if (RequestItemUnload (item)) { if (closeItemFiles) { - var projects = item.GetAllProjects (); + var projects = item.GetAllItems<Project> (); foreach (Document doc in IdeApp.Workbench.Documents.Where (d => d.Project != null && projects.Contains (d.Project)).ToArray ()) { if (!doc.Close ()) return; @@ -510,7 +425,7 @@ namespace MonoDevelop.Ide } } - public bool RequestItemUnload (IBuildTarget item) + public bool RequestItemUnload (WorkspaceObject item) { if (ItemUnloading != null) { try { @@ -523,19 +438,24 @@ namespace MonoDevelop.Ide } return true; } - - public IAsyncOperation OpenWorkspaceItem (string filename) + + bool openingItem; + + public Task<bool> OpenWorkspaceItem (string filename) { return OpenWorkspaceItem (filename, true); } - public IAsyncOperation OpenWorkspaceItem (string filename, bool closeCurrent) + public Task<bool> OpenWorkspaceItem (string filename, bool closeCurrent) { return OpenWorkspaceItem (filename, closeCurrent, true); } - public IAsyncOperation OpenWorkspaceItem (string filename, bool closeCurrent, bool loadPreferences) + public async Task<bool> OpenWorkspaceItem (string filename, bool closeCurrent, bool loadPreferences) { + if (openingItem) + return false; + if (filename.StartsWith ("file://", StringComparison.Ordinal)) filename = new Uri(filename).LocalPath; @@ -543,21 +463,21 @@ namespace MonoDevelop.Ide if (item != null) { IdeApp.ProjectOperations.CurrentSelectedWorkspaceItem = item; IdeApp.Workbench.StatusBar.ShowWarning (GettextCatalog.GetString ("{0} is already opened", item.FileName.FileName)); - return MonoDevelop.Core.ProgressMonitoring.NullAsyncOperation.Success; + return true; } if (closeCurrent) { if (!Close ()) - return MonoDevelop.Core.ProgressMonitoring.NullAsyncOperation.Failure; + return false; } using (var monitor = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { bool reloading = IsReloading; - DispatchService.BackgroundDispatch (delegate { - BackgroundLoadWorkspace (monitor, filename, loadPreferences, reloading); - }); - return monitor.AsyncOperation; + openingItem = true; + IdeApp.Workbench.LockGui (); + + return await BackgroundLoadWorkspace (monitor, filename, loadPreferences, reloading); } } @@ -577,7 +497,7 @@ namespace MonoDevelop.Ide } } - void BackgroundLoadWorkspace (IProgressMonitor monitor, string filename, bool loadPreferences, bool reloading) + async Task<bool> BackgroundLoadWorkspace (ProgressMonitor monitor, string filename, bool loadPreferences, bool reloading) { WorkspaceItem item = null; ITimeTracker timer = Counters.OpenWorkspaceItemTimer.BeginTiming (); @@ -589,67 +509,66 @@ namespace MonoDevelop.Ide if (!File.Exists (filename)) { monitor.ReportError (GettextCatalog.GetString ("File not found: {0}", filename), null); monitor.Dispose (); - return; + return false; } if (!Services.ProjectService.IsWorkspaceItemFile (filename)) { if (!Services.ProjectService.IsSolutionItemFile (filename)) { monitor.ReportError (GettextCatalog.GetString ("File is not a project or solution: {0}", filename), null); monitor.Dispose (); - return; + return false; } - + // It is a project, not a solution. Try to create a dummy solution and add the project to it timer.Trace ("Getting wrapper solution"); - item = IdeApp.Services.ProjectService.GetWrapperSolution (monitor, filename); + item = await IdeApp.Services.ProjectService.GetWrapperSolution (monitor, filename); } if (item == null) { timer.Trace ("Reading item"); - item = Services.ProjectService.ReadWorkspaceItem (monitor, filename); - if (monitor.IsCancelRequested) { + item = await Services.ProjectService.ReadWorkspaceItem (monitor, filename); + if (monitor.CancellationToken.IsCancellationRequested) { monitor.Dispose (); - return; + return false; } } timer.Trace ("Registering to recent list"); DesktopService.RecentFiles.AddProject (item.FileName, item.Name); - Gtk.Application.Invoke (delegate { - // Add the item in the GUI thread. It is not safe to do it in the background thread. - Items.Add (item); - }); + Items.Add (item); + } catch (Exception ex) { monitor.ReportError ("Load operation failed.", ex); // Don't use 'finally' to dispose the monitor, since it has to be disposed later monitor.Dispose (); timer.End (); - return; + return false; } finally { + Gtk.Application.Invoke ((s,o) => IdeApp.Workbench.UnlockGui ()); + openingItem = false; if (reloading) SetReloading (false); } - Gtk.Application.Invoke (delegate { - using (monitor) { - try { - if (IdeApp.ProjectOperations.CurrentSelectedWorkspaceItem == null) - IdeApp.ProjectOperations.CurrentSelectedWorkspaceItem = GetAllSolutions ().FirstOrDefault (); - if (Items.Count == 1 && loadPreferences) { - timer.Trace ("Restoring workspace preferences"); - RestoreWorkspacePreferences (item); - } - timer.Trace ("Reattaching documents"); - ReattachDocumentProjects (null); - monitor.ReportSuccess (GettextCatalog.GetString ("Solution loaded.")); - } finally { - timer.End (); + using (monitor) { + try { + if (IdeApp.ProjectOperations.CurrentSelectedWorkspaceItem == null) + IdeApp.ProjectOperations.CurrentSelectedWorkspaceItem = GetAllSolutions ().FirstOrDefault (); + if (Items.Count == 1 && loadPreferences) { + timer.Trace ("Restoring workspace preferences"); + RestoreWorkspacePreferences (item); } + timer.Trace ("Reattaching documents"); + ReattachDocumentProjects (null); + monitor.ReportSuccess (GettextCatalog.GetString ("Solution loaded.")); + } finally { + timer.End (); } - }); + } + return true; } void RestoreWorkspacePreferences (WorkspaceItem item) @@ -799,7 +718,7 @@ namespace MonoDevelop.Ide { if (item.NeedsReload) { IEnumerable<string> closedDocs; - if (AllowReload (item.GetAllProjects (), out closedDocs)) { + if (AllowReload (item.GetAllItems<Project> (), out closedDocs)) { if (item.ParentWorkspace == null) { string file = item.FileName; try { @@ -812,7 +731,7 @@ namespace MonoDevelop.Ide } } else { - using (IProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true)) { + using (ProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true)) { item.ParentWorkspace.ReloadItem (m, item); ReattachDocumentProjects (closedDocs); } @@ -835,7 +754,7 @@ namespace MonoDevelop.Ide } } - void OnCheckProject (SolutionItem entry) + void OnCheckProject (SolutionFolderItem entry) { if (entry.NeedsReload) { IEnumerable projects = null; @@ -848,7 +767,7 @@ namespace MonoDevelop.Ide IEnumerable<string> closedDocs; if (AllowReload (projects, out closedDocs)) { - using (IProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { + using (ProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { // Root folders never need to reload entry.ParentFolder.ReloadItem (m, entry); ReattachDocumentProjects (closedDocs); @@ -860,9 +779,9 @@ namespace MonoDevelop.Ide if (entry is SolutionFolder) { ArrayList ens = new ArrayList (); - foreach (SolutionItem ce in ((SolutionFolder)entry).Items) + foreach (SolutionFolderItem ce in ((SolutionFolder)entry).Items) ens.Add (ce); - foreach (SolutionItem ce in ens) + foreach (SolutionFolderItem ce in ens) OnCheckProject (ce); } } @@ -1155,13 +1074,13 @@ namespace MonoDevelop.Ide NotifyItemRemovedFromSolutionRec (sender, args.SolutionItem, args.Solution); } - void NotifyItemRemovedFromSolutionRec (object sender, SolutionItem e, Solution sol) + void NotifyItemRemovedFromSolutionRec (object sender, SolutionFolderItem e, Solution sol) { if (e == IdeApp.ProjectOperations.CurrentSelectedSolutionItem) IdeApp.ProjectOperations.CurrentSelectedSolutionItem = null; if (e is SolutionFolder) { - foreach (SolutionItem ce in ((SolutionFolder)e).Items) + foreach (SolutionFolderItem ce in ((SolutionFolder)e).Items) NotifyItemRemovedFromSolutionRec (sender, ce, sol); } if (ItemRemovedFromSolution != null) @@ -1174,7 +1093,7 @@ namespace MonoDevelop.Ide // the top if (s != this && Items.Contains (args.Item)) Items.Remove (args.Item); - foreach (WorkspaceItem item in args.Item.GetAllItems ()) { + foreach (WorkspaceItem item in args.Item.GetAllItems<WorkspaceItem> ()) { if (item is Solution) SubscribeSolution ((Solution)item); OnItemLoaded (item); @@ -1183,7 +1102,7 @@ namespace MonoDevelop.Ide void NotifyDescendantItemRemoved (object s, WorkspaceItemEventArgs args) { - foreach (WorkspaceItem item in args.Item.GetAllItems ()) { + foreach (WorkspaceItem item in args.Item.GetAllItems<WorkspaceItem> ()) { OnItemUnloaded (item); if (item is Solution) UnsubscribeSolution ((Solution)item); @@ -1460,17 +1379,17 @@ namespace MonoDevelop.Ide public class ItemUnloadingEventArgs: EventArgs { - IBuildTarget item; + WorkspaceObject item; public bool Cancel { get; set; } - public IBuildTarget Item { + public WorkspaceObject Item { get { return item; } } - public ItemUnloadingEventArgs (IBuildTarget item) + public ItemUnloadingEventArgs (WorkspaceObject item) { this.item = item; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs index 7dce9e26f2..428069645f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs @@ -44,7 +44,7 @@ namespace MonoDevelop.Ide internal static class Counters { - internal static TimerCounter Initialization = InstrumentationService.CreateTimerCounter ("IDE Initialization", "IDE"); + internal static TimerCounter Initialization = InstrumentationService.CreateTimerCounter ("IDE Initialization", "IDE", id:"Ide.Initialization"); internal static Counter OpenDocuments = InstrumentationService.CreateCounter ("Open documents", "IDE"); internal static Counter DocumentsInMemory = InstrumentationService.CreateCounter ("Documents in memory", "IDE"); internal static Counter PadsLoaded = InstrumentationService.CreateCounter ("Pads loaded", "IDE"); diff --git a/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.ProgressMonitoring.ProgressBarMonitor.cs b/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.ProgressMonitoring.ProgressBarMonitor.cs deleted file mode 100644 index dae4d14160..0000000000 --- a/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.ProgressMonitoring.ProgressBarMonitor.cs +++ /dev/null @@ -1,49 +0,0 @@ - -// This file has been generated by the GUI designer. Do not modify. -namespace MonoDevelop.Ide.ProgressMonitoring -{ - public partial class ProgressBarMonitor - { - private global::Gtk.HBox hbox1; - private global::Gtk.ProgressBar progressBar; - private global::Gtk.Button buttonCancel; - - protected virtual void Build () - { - global::Stetic.Gui.Initialize (this); - // Widget MonoDevelop.Ide.ProgressMonitoring.ProgressBarMonitor - global::Stetic.BinContainer.Attach (this); - this.Name = "MonoDevelop.Ide.ProgressMonitoring.ProgressBarMonitor"; - // Container child MonoDevelop.Ide.ProgressMonitoring.ProgressBarMonitor.Gtk.Container+ContainerChild - this.hbox1 = new global::Gtk.HBox (); - this.hbox1.Name = "hbox1"; - this.hbox1.Spacing = 3; - // Container child hbox1.Gtk.Box+BoxChild - this.progressBar = new global::Gtk.ProgressBar (); - this.progressBar.Name = "progressBar"; - this.hbox1.Add (this.progressBar); - global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.progressBar])); - w1.Position = 0; - // Container child hbox1.Gtk.Box+BoxChild - this.buttonCancel = new global::Gtk.Button (); - this.buttonCancel.CanFocus = true; - this.buttonCancel.Name = "buttonCancel"; - this.buttonCancel.UseUnderline = true; - this.buttonCancel.Relief = ((global::Gtk.ReliefStyle)(2)); - this.buttonCancel.Label = ""; - global::Gtk.Image w2 = new global::Gtk.Image (); - w2.Pixbuf = global::Stetic.IconLoader.LoadIcon (this, "gtk-cancel", global::Gtk.IconSize.Menu); - this.buttonCancel.Image = w2; - this.hbox1.Add (this.buttonCancel); - global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.buttonCancel])); - w3.Position = 1; - w3.Expand = false; - w3.Fill = false; - this.Add (this.hbox1); - if ((this.Child != null)) { - this.Child.ShowAll (); - } - this.Hide (); - } - } -} diff --git a/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.NewFileDialog.cs b/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.NewFileDialog.cs index 750573d55c..07a0fe3ac4 100644 --- a/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.NewFileDialog.cs +++ b/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.NewFileDialog.cs @@ -5,27 +5,49 @@ namespace MonoDevelop.Ide.Projects internal partial class NewFileDialog { private global::Gtk.VBox vbox2; + private global::Gtk.HPaned hpaned1; + private global::Gtk.ScrolledWindow scrolledwindow1; + private global::Gtk.TreeView catView; + private global::Gtk.HPaned panedTemplates; + private global::Gtk.VBox boxTemplates; + private global::Gtk.ScrolledWindow scrolledInfo; + private global::Gtk.VBox boxInfo; + private global::Gtk.Label labelTemplateTitle; + private global::Gtk.Label infoLabel; + private global::Gtk.Label label1; + private global::Gtk.HBox hbox2; + private global::Gtk.Label label2; + private global::Gtk.Entry nameEntry; + private global::Gtk.VBox boxProject; + private global::Gtk.HBox hbox3; + private global::Gtk.CheckButton projectAddCheckbox; + private global::Gtk.ComboBox projectAddCombo; + private global::Gtk.HBox hbox4; + private global::Gtk.Label projectPathLabel; + private global::MonoDevelop.Components.FolderEntry projectFolderEntry; + private global::Gtk.Button cancelButton; + private global::Gtk.Button okButton; protected virtual void Build () @@ -211,6 +233,7 @@ namespace MonoDevelop.Ide.Projects // Container child hbox4.Gtk.Box+BoxChild this.projectFolderEntry = new global::MonoDevelop.Components.FolderEntry (); this.projectFolderEntry.Name = "projectFolderEntry"; + this.projectFolderEntry.DisplayAsRelativePath = false; this.hbox4.Add (this.projectFolderEntry); global::Gtk.Box.BoxChild w21 = ((global::Gtk.Box.BoxChild)(this.hbox4 [this.projectFolderEntry])); w21.Position = 1; diff --git a/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.ProjectFileSelectorDialog.cs b/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.ProjectFileSelectorDialog.cs index 2b8d39186d..6b3eabbc0e 100644 --- a/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.ProjectFileSelectorDialog.cs +++ b/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.ProjectFileSelectorDialog.cs @@ -5,18 +5,31 @@ namespace MonoDevelop.Ide.Projects public partial class ProjectFileSelectorDialog { private global::Gtk.HPaned hpaned1; + private global::Gtk.VBox vbox3; + private global::Gtk.ScrolledWindow GtkScrolledWindow; + private global::Gtk.TreeView projectTree; + private global::Gtk.VBox vbox4; + private global::Gtk.ScrolledWindow GtkScrolledWindow1; + private global::Gtk.TreeView fileList; + private global::Gtk.HBox hbox2; + private global::Gtk.Button AddFileButton; + private global::Gtk.HBox typeBox; + private global::Gtk.Label label2; + private global::Gtk.ComboBox fileTypeCombo; + private global::Gtk.Button buttonCancel; + private global::Gtk.Button buttonOk; protected virtual void Build () @@ -82,7 +95,6 @@ namespace MonoDevelop.Ide.Projects this.AddFileButton.Name = "AddFileButton"; this.AddFileButton.UseUnderline = true; this.AddFileButton.Relief = ((global::Gtk.ReliefStyle)(2)); - this.AddFileButton.Label = ""; global::Gtk.Image w7 = new global::Gtk.Image (); w7.Pixbuf = global::Stetic.IconLoader.LoadIcon (this, "gtk-add", global::Gtk.IconSize.Menu); this.AddFileButton.Image = w7; diff --git a/main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic b/main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic index 71afa16a0c..0d4802b042 100644 --- a/main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic +++ b/main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic @@ -5388,6 +5388,7 @@ Diagnostic</property> <property name="Tooltip" translatable="yes">Switch to Find in Files</property> <property name="CanFocus">True</property> <property name="Label" translatable="yes">Find in Files</property> + <property name="Active">True</property> <property name="DrawIndicator">False</property> <property name="HasLabel">True</property> <property name="UseUnderline">True</property> @@ -11518,42 +11519,6 @@ Visual Studio generates a default ID for embedded resources, instead of simply u </widget> </child> </widget> - <widget class="Gtk.Bin" id="MonoDevelop.Ide.ProgressMonitoring.ProgressBarMonitor" design-size="300 28"> - <property name="MemberName" /> - <property name="Visible">False</property> - <child> - <widget class="Gtk.HBox" id="hbox1"> - <property name="MemberName" /> - <property name="Spacing">3</property> - <child> - <widget class="Gtk.ProgressBar" id="progressBar"> - <property name="MemberName" /> - </widget> - <packing> - <property name="Position">0</property> - <property name="AutoSize">True</property> - </packing> - </child> - <child> - <widget class="Gtk.Button" id="buttonCancel"> - <property name="MemberName" /> - <property name="CanFocus">True</property> - <property name="Type">TextAndIcon</property> - <property name="Icon">stock:gtk-cancel Menu</property> - <property name="Label" translatable="yes" /> - <property name="UseUnderline">True</property> - <property name="Relief">None</property> - </widget> - <packing> - <property name="Position">1</property> - <property name="AutoSize">True</property> - <property name="Expand">False</property> - <property name="Fill">False</property> - </packing> - </child> - </widget> - </child> - </widget> <widget class="Gtk.Dialog" id="MonoDevelop.Ide.Projects.AddExternalFileDialog" design-size="536 286"> <property name="MemberName" /> <property name="GeneratePublic">False</property> diff --git a/main/src/core/MonoDevelop.Ide/gtkrc.mac b/main/src/core/MonoDevelop.Ide/gtkrc.mac index 0f7541a91b..c9b81dabce 100644 --- a/main/src/core/MonoDevelop.Ide/gtkrc.mac +++ b/main/src/core/MonoDevelop.Ide/gtkrc.mac @@ -158,7 +158,7 @@ style "toggle-button" = "button" { style "menu" { xthickness = 0 - ythickness = 0 + # ythickness = 0 font_name = "Lucida Grande 14" bg[PRELIGHT] = @selected_fg_color @@ -266,6 +266,11 @@ style "combo-box" = "default" } } +style "wizard-dialog" +{ + GtkDialog::content-area-border = 0 +} + style "combo-box-entry" = "combo-box" { engine "xamarin" { @@ -388,6 +393,7 @@ widget_class "<GtkDialog>.<GtkVBox>.<GtkButtonBox>.<GtkButton>*" style "dialog-b widget_class "<GtkDialog>.<GtkVBox>.<GtkHBox>.<GtkButtonBox>.<GtkButton>*" style "dialog-button" widget "*.toggleFindInFiles" style "toggle-button" widget "*.toggleReplaceInFiles" style "toggle-button" +widget "wizard_dialog" style "wizard-dialog" widget_class "*<GtkMenu>*" style "menu" widget_class "*<GtkMenuItem>*" style "menu-item" diff --git a/main/src/core/MonoDevelop.Ide/icons/light/project-status-error-16.png b/main/src/core/MonoDevelop.Ide/icons/light/project-status-error-16.png Binary files differnew file mode 100644 index 0000000000..303b0b6234 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/icons/light/project-status-error-16.png diff --git a/main/src/core/MonoDevelop.Ide/icons/light/project-status-error-16@2x.png b/main/src/core/MonoDevelop.Ide/icons/light/project-status-error-16@2x.png Binary files differnew file mode 100644 index 0000000000..a64809d01d --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/icons/light/project-status-error-16@2x.png diff --git a/main/src/core/MonoDevelop.Ide/icons/light/project-status-information-16.png b/main/src/core/MonoDevelop.Ide/icons/light/project-status-information-16.png Binary files differnew file mode 100644 index 0000000000..9a1ed0325c --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/icons/light/project-status-information-16.png diff --git a/main/src/core/MonoDevelop.Ide/icons/light/project-status-information-16@2x.png b/main/src/core/MonoDevelop.Ide/icons/light/project-status-information-16@2x.png Binary files differnew file mode 100644 index 0000000000..4418693d5b --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/icons/light/project-status-information-16@2x.png diff --git a/main/src/core/MonoDevelop.Ide/icons/light/project-status-warning-16.png b/main/src/core/MonoDevelop.Ide/icons/light/project-status-warning-16.png Binary files differnew file mode 100644 index 0000000000..0844d58e39 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/icons/light/project-status-warning-16.png diff --git a/main/src/core/MonoDevelop.Ide/icons/light/project-status-warning-16@2x.png b/main/src/core/MonoDevelop.Ide/icons/light/project-status-warning-16@2x.png Binary files differnew file mode 100644 index 0000000000..54a99a5bc2 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/icons/light/project-status-warning-16@2x.png diff --git a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/BuildEngine.cs b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/BuildEngine.cs index b50b65b1e7..b8d08a7437 100644 --- a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/BuildEngine.cs +++ b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/BuildEngine.cs @@ -60,6 +60,10 @@ namespace MonoDevelop.Projects.Formats.MSBuild get { return doneEvent; } } + public void Ping () + { + } + public void SetCulture (CultureInfo uiCulture) { BuildEngine.uiCulture = uiCulture; diff --git a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/BuildEngine.v4.0.cs b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/BuildEngine.v4.0.cs index d184314662..0c021e500d 100644 --- a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/BuildEngine.v4.0.cs +++ b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/BuildEngine.v4.0.cs @@ -59,6 +59,10 @@ namespace MonoDevelop.Projects.Formats.MSBuild get { return doneEvent; }
}
+ public void Ping ()
+ {
+ }
+
public void SetCulture (CultureInfo uiCulture) {
BuildEngine.uiCulture = uiCulture;
diff --git a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ConsoleLogger.cs b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ConsoleLogger.cs index 6de6830e73..a64fcab1f3 100644 --- a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ConsoleLogger.cs +++ b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ConsoleLogger.cs @@ -835,14 +835,12 @@ namespace MonoDevelop.Projects.Formats.MSBuild { if (!StartHandlerHasExecuted) return; - if (EventArgs is ProjectStartedEventArgs) - ConsoleLogger.ProjectFinishedHandler (null, finished_args as ProjectFinishedEventArgs); - else if (EventArgs is TargetStartedEventArgs) - ConsoleLogger.TargetFinishedHandler (null, finished_args as TargetFinishedEventArgs); - else if (EventArgs is TaskStartedEventArgs) - ConsoleLogger.TaskFinishedHandler (null, finished_args as TaskFinishedEventArgs); - else if (!(EventArgs is BuildStartedEventArgs)) - throw new InvalidOperationException ("Unexpected event on the stack, type: " + EventArgs.GetType ()); + if (EventArgs is ProjectStartedEventArgs && finished_args is ProjectFinishedEventArgs) + ConsoleLogger.ProjectFinishedHandler (null, (ProjectFinishedEventArgs) finished_args); + else if (EventArgs is TargetStartedEventArgs && finished_args is TargetFinishedEventArgs) + ConsoleLogger.TargetFinishedHandler (null, (TargetFinishedEventArgs)finished_args); + else if (EventArgs is TaskStartedEventArgs && finished_args is TaskFinishedEventArgs) + ConsoleLogger.TaskFinishedHandler (null, (TaskFinishedEventArgs)finished_args); } } diff --git a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/IBuildEngine.cs b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/IBuildEngine.cs index 9b25cae19b..95e8af6d80 100644 --- a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/IBuildEngine.cs +++ b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/IBuildEngine.cs @@ -36,5 +36,6 @@ namespace MonoDevelop.Projects.Formats.MSBuild void SetGlobalProperties (IDictionary<string, string> properties); IProjectBuilder LoadProject (string projectFile); void UnloadProject (IProjectBuilder pb); + void Ping (); } } diff --git a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ProjectBuilder.cs b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ProjectBuilder.cs index f72c2205ce..945fec8d84 100644 --- a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ProjectBuilder.cs +++ b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ProjectBuilder.cs @@ -161,24 +161,35 @@ namespace MonoDevelop.Projects.Formats.MSBuild foreach (var pc in configurations) { var p = buildEngine.Engine.GetLoadedProject (pc.ProjectFile); + + if (p != null && pc.ProjectFile == file) { + // building the project may create new items and/or modify some properties, + // so we always need to use a new instance of the project when building + buildEngine.Engine.UnloadProject (p); + p = null; + } + + Environment.CurrentDirectory = Path.GetDirectoryName (file); + if (p == null) { p = new Project (buildEngine.Engine); - var content = buildEngine.GetUnsavedProjectContent (pc.ProjectFile);
- if (content == null)
- p.Load (pc.ProjectFile);
- else { + var content = buildEngine.GetUnsavedProjectContent (pc.ProjectFile); + if (content == null) { + p.Load (pc.ProjectFile); + } else { p.FullFileName = pc.ProjectFile; if (HasXbuildFileBug ()) { // Workaround for Xamarin bug #14295: Project.Load incorrectly resets the FullFileName property var t = p.GetType (); - t.InvokeMember ("PushThisFileProperty", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, p, new object[] { p.FullFileName });
+ t.InvokeMember ("PushThisFileProperty", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, p, new object[] { p.FullFileName }); t.InvokeMember ("DoLoad", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, p, new object[] { new StringReader (content) }); } else { p.Load (new StringReader (content)); } } } + p.GlobalProperties.SetProperty ("Configuration", pc.Configuration); if (!string.IsNullOrEmpty (pc.Platform)) p.GlobalProperties.SetProperty ("Platform", pc.Platform); diff --git a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ProjectBuilder.v4.0.cs b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ProjectBuilder.v4.0.cs index 604d42c45e..a2c858a787 100644 --- a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ProjectBuilder.v4.0.cs +++ b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ProjectBuilder.v4.0.cs @@ -129,8 +129,9 @@ namespace MonoDevelop.Projects.Formats.MSBuild var r = new MSBuildTargetResult ( file, false, ex.ErrorSubcategory, ex.ErrorCode, ex.ProjectFile, ex.LineNumber, ex.ColumnNumber, ex.EndLineNumber, ex.EndColumnNumber, - ex.BaseMessage, ex.HelpKeyword); - logWriter.WriteLine (r.ToString ()); + ex.BaseMessage, ex.HelpKeyword);
+ if (logWriter != null) + logWriter.WriteLine (r.ToString ()); result = new MSBuildResult (new [] { r }); } finally {
currentLogWriter = null;
@@ -178,6 +179,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild if (content == null)
p = engine.LoadProject (file);
else {
+ Environment.CurrentDirectory = Path.GetDirectoryName (file);
p = engine.LoadProject (new XmlTextReader (new StringReader (content)));
p.FullPath = file;
}
@@ -187,7 +189,6 @@ namespace MonoDevelop.Projects.Formats.MSBuild p.SetProperty ("Platform", platform);
else
p.SetProperty ("Platform", "");
-
return p;
}
diff --git a/main/src/core/MonoDevelop.Startup/app.config b/main/src/core/MonoDevelop.Startup/app.config index b653baa9ff..aa60d91311 100644 --- a/main/src/core/MonoDevelop.Startup/app.config +++ b/main/src/core/MonoDevelop.Startup/app.config @@ -6,11 +6,6 @@ <assemblyIdentity name="ICSharpCode.SharpZipLib" publicKeyToken="1b03e6acf1164f73" culture="neutral" /> <bindingRedirect oldVersion="0.84.0.0" newVersion="2.84.0.0"/> </dependentAssembly> - <dependentAssembly> - <!-- This is required on Windows, since the GTK# installer only includes Mono.Cairo 2.0 --> - <assemblyIdentity name="Mono.Cairo" publicKeyToken="0738eb9f132ed756" culture="neutral" /> - <bindingRedirect oldVersion="4.0.0.0" newVersion="2.0.0.0"/> - </dependentAssembly> </assemblyBinding> </runtime> diff --git a/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests/HtmlWriterTests.cs b/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests/HtmlWriterTests.cs index 9431a9a511..1e7b4d3fd7 100644 --- a/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests/HtmlWriterTests.cs +++ b/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests/HtmlWriterTests.cs @@ -38,9 +38,11 @@ namespace Mono.TextEditor.Tests { if (Platform.IsWindows) Assert.Inconclusive (); - var data = Create ("class Foo {}"); + var data = Create (""); data.ColorStyle = SyntaxModeService.GetColorStyle ("Tango"); data.Document.SyntaxMode = SyntaxModeService.GetSyntaxMode (data.Document, "text/x-csharp"); + data.Text = "class Foo {}"; + SyntaxModeService.WaitUpdate (data.Document); string generatedHtml = HtmlWriter.GenerateHtml (data); Assert.AreEqual ( @"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.0 Transitional//EN""> @@ -61,13 +63,15 @@ namespace Mono.TextEditor.Tests { if (Platform.IsWindows) Assert.Inconclusive (); - var data = Create ( -@"<foo - attr1 = ""1"" - attr2 = ""2"" -/>"); + var data = Create (""); data.ColorStyle = SyntaxModeService.GetColorStyle ("Tango"); data.Document.SyntaxMode = SyntaxModeService.GetSyntaxMode (data.Document, "application/xml"); + data.Text = @"<foo + attr1 = ""1"" + attr2 = ""2"" +/>"; + SyntaxModeService.WaitUpdate (data.Document); + string generatedHtml = HtmlWriter.GenerateHtml (data); Assert.AreEqual ( @"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.0 Transitional//EN""> |