diff options
author | Lluis Sanchez <llsan@microsoft.com> | 2017-05-03 22:17:06 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-03 22:17:06 +0300 |
commit | 1163df7bf2bfdbb57d276ce0e5746a8f8bb1b1d9 (patch) | |
tree | 7acd6433d9ecd96f7aee0eb7f5271f08b07f28b5 /main | |
parent | bed0adb1a21b3e31174f703647e10eb68be50775 (diff) | |
parent | f4fadc0b1b180e3e41b17e910d270d8869ace491 (diff) |
Merge pull request #2292 from mhutch/capability-condition
[Project] Add VS-like AppliesTo extension condition
Diffstat (limited to 'main')
10 files changed, 163 insertions, 39 deletions
diff --git a/main/external/mono-addins b/main/external/mono-addins -Subproject a9a84ae335611f0ef7cc1945b40a6b7b84de0c6 +Subproject 925f835acdcec8e830a722367b563506370bc49 diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.addin.xml b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.addin.xml index 937fc9f0f4..9264fe63d2 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.addin.xml +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.addin.xml @@ -108,6 +108,9 @@ <ConditionType id="ItemType" type="MonoDevelop.Core.Gui.Dialogs.OptionPanels.ItemTypeCondition"> <Description>Type of the item. If no namespace is provided, MonoDevelop.Projects is assumed.</Description> </ConditionType> + <ConditionType id="AppliesTo" type="MonoDevelop.Projects.Extensions.AppliesToCondition"> + <Description>Project capability expression.</Description> + </ConditionType> </ExtensionPoint> <ExtensionPoint path = "/MonoDevelop/ProjectModel/LanguageBindings" name = "Language bindings"> diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj index aaec6949af..350f2ebef7 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj @@ -358,6 +358,7 @@ <Compile Include="Mono.Options.cs" /> <Compile Include="MonoDevelop.Core.Logging\InstrumentationLogger.cs" /> <Compile Include="MonoDevelop.Core.Instrumentation\TimerCounter.cs" /> + <Compile Include="MonoDevelop.Projects\AppliesToAttribute.cs" /> <Compile Include="MonoDevelop.Projects\ProjectService.cs" /> <Compile Include="MonoDevelop.Projects\ProjectPathItemPropertyAttribute.cs" /> <Compile Include="MonoDevelop.Projects\SolutionConfiguration.cs" /> @@ -703,6 +704,7 @@ <Compile Include="MonoDevelop.Projects.MSBuild\MSBuildEvent.cs" /> <Compile Include="MonoDevelop.Projects\MSBuildLogger.cs" /> <Compile Include="MonoDevelop.Projects.Extensions\ImportSearchPathExtensionNode.cs" /> + <Compile Include="MonoDevelop.Projects.Extensions\AppliesToCondition.cs" /> </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/AppliesToCondition.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/AppliesToCondition.cs new file mode 100644 index 0000000000..fa87716ff5 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/AppliesToCondition.cs @@ -0,0 +1,50 @@ +// +// AppliesToCondition.cs +// +// Author: +// Mikayla Hutchinson <m.j.hutchinson@gmail.com> +// +// Copyright (c) 2017 Microsoft Corp. +// +// 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 Mono.Addins; + +namespace MonoDevelop.Projects.Extensions +{ + public class AppliesToCondition : ConditionType + { + readonly WorkspaceObject workspaceObject; + + public AppliesToCondition (WorkspaceObject workspaceObject) + { + this.workspaceObject = workspaceObject; + } + + public override bool Evaluate (NodeElement conditionNode) + { + var project = workspaceObject as Project; + if (project == null) { + return false; + } + var expr = conditionNode.GetAttribute ("capability"); + return project.IsCapabilityMatch (expr); + } + } +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/AppliesToAttribute.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/AppliesToAttribute.cs new file mode 100644 index 0000000000..d2ed38401b --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/AppliesToAttribute.cs @@ -0,0 +1,48 @@ +//
+// AppliesToAttribute.cs
+//
+// Copyright (c) Microsoft Corp.
+//
+// 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 Mono.Addins;
+
+namespace MonoDevelop.Projects
+{
+ /// <summary>
+ /// Restricts an extension to projects matching a capability expression.
+ /// </summary>
+ public class AppliesToAttribute : CustomConditionAttribute
+ {
+ /// <summary>
+ /// Initializes the attribute with a project capability expression.
+ /// </summary>
+ /// <param name="capability">Project capability expression.</param>
+ public AppliesToAttribute ([NodeAttribute("capability")] string capability)
+ {
+ this.Capability = capability;
+ }
+
+ /// <summary>
+ /// Project capability expression.
+ /// </summary>
+ [NodeAttribute ("capability")]
+ public string Capability { get; set; }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObject.cs index 1aa256a6f0..afccbde274 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObject.cs @@ -69,6 +69,7 @@ namespace MonoDevelop.Projects extensionContext = AddinManager.CreateExtensionContext (); extensionContext.RegisterCondition ("ItemType", new ItemTypeCondition (GetType ())); + ExtensionContext.RegisterCondition ("AppliesTo", new AppliesToCondition (this)); OnInitialize (); InitializeExtensionChain (); diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/ItemOptionPanels.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/ItemOptionPanels.addin.xml index 4a059c141a..f0286b7e9d 100644 --- a/main/src/core/MonoDevelop.Ide/ExtensionModel/ItemOptionPanels.addin.xml +++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/ItemOptionPanels.addin.xml @@ -12,6 +12,9 @@ <ConditionType id="ProjectTypeId" type="MonoDevelop.Projects.Extensions.ProjectTypeIdCondition"> <Description>The id can be a project type guid or a flavor guid, or the corresponding type alias</Description> </ConditionType> + <ConditionType id="AppliesTo" type="MonoDevelop.Projects.Extensions.AppliesToCondition"> + <Description>Project capability expression.</Description> + </ConditionType> <ConditionType id="SupportsTarget" type="MonoDevelop.Projects.Extensions.SupportsTargetCondition"> <Description>MSBuild Target that a project must have.</Description> </ConditionType> diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/Templates.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/Templates.addin.xml index afad35e2f6..fd0a532ca5 100644 --- a/main/src/core/MonoDevelop.Ide/ExtensionModel/Templates.addin.xml +++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/Templates.addin.xml @@ -4,6 +4,15 @@ <ExtensionPoint path = "/MonoDevelop/Ide/FileTemplates" name = "File templates"> <Description>File templates to be shown in the New File dialog.</Description> <ExtensionNode name="FileTemplate" type="MonoDevelop.Ide.Codons.ProjectTemplateCodon"/> + <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="ProjectTypeId" type="MonoDevelop.Projects.Extensions.ProjectTypeIdCondition"> + <Description>The id can be a project type guid or a flavor guid, or the corresponding type alias</Description> + </ConditionType> + <ConditionType id="AppliesTo" type="MonoDevelop.Projects.Extensions.AppliesToCondition"> + <Description>Project capability expression.</Description> + </ConditionType> </ExtensionPoint> <ExtensionPoint path = "/MonoDevelop/Ide/FileTemplateTypes" name = "File template types"> 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 f7b322d16f..937fe4b9cc 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 @@ -51,10 +51,12 @@ namespace MonoDevelop.Ide.Gui.Dialogs extensionContext.RegisterCondition ("ItemType", new ItemTypeCondition (DataObject.GetType ())); extensionContext.RegisterCondition ("ActiveLanguage", new ProjectLanguageCondition (DataObject)); if (DataObject is Project) { + extensionContext.RegisterCondition ("AppliesTo", new AppliesToCondition ((Project)DataObject)); extensionContext.RegisterCondition ("FlavorType", new FlavorTypeCondition ((Project)DataObject)); extensionContext.RegisterCondition ("ProjectTypeId", new ProjectTypeIdCondition ((Project)DataObject)); extensionContext.RegisterCondition ("SupportsTarget", new SupportsTargetCondition ((Project)DataObject)); } else { + extensionContext.RegisterCondition ("AppliesTo", new FalseCondition ()); extensionContext.RegisterCondition ("FlavorType", new FalseCondition ()); extensionContext.RegisterCondition ("ProjectTypeId", new FalseCondition ()); } 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 c7981a49b7..9c4fd4c535 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplate.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplate.cs @@ -41,6 +41,7 @@ using MonoDevelop.Core; using MonoDevelop.Ide.Codons; using MonoDevelop.Ide.Gui; using MonoDevelop.Projects; +using MonoDevelop.Projects.Extensions; namespace MonoDevelop.Ide.Templates { @@ -60,8 +61,6 @@ namespace MonoDevelop.Ide.Templates public List<FileDescriptionTemplate> Files { get; private set; } = new List<FileDescriptionTemplate> (); - public static List<FileTemplate> fileTemplates = new List<FileTemplate> (); - public IconId Icon { get; private set; } = String.Empty; public string Id { get; private set; } = String.Empty; @@ -191,58 +190,65 @@ namespace MonoDevelop.Ide.Templates return fileTemplate; } - static FileTemplate () + static FileTemplate LoadTemplate (ProjectTemplateCodon codon) { - AddinManager.AddExtensionNodeHandler ("/MonoDevelop/Ide/FileTemplates", OnExtensionChanged); + try { + FileTemplate t = LoadFileTemplate (codon.Addin, codon); + t.Id = codon.Id; + return t; + } catch (Exception e) { + string extId = null, addinId = null; + if (codon != null) { + if (codon.HasId) + extId = codon.Id; + if (codon.Addin != null) + addinId = codon.Addin.Id; + } + LoggingService.LogError ("Error loading template id {0} in addin {1}:\n{2}", + extId ?? "(null)", addinId ?? "(null)", e.ToString ()); + } + return null; } - static void OnExtensionChanged (object s, ExtensionNodeEventArgs args) + static string EXTENSION_PATH = "/MonoDevelop/Ide/FileTemplates"; + + internal static List<FileTemplate> GetFileTemplates (Project project, string projectPath) { - if (args.Change == ExtensionChange.Add) { - var codon = (ProjectTemplateCodon)args.ExtensionNode; - try { - FileTemplate t = LoadFileTemplate (codon.Addin, codon); - t.Id = codon.Id; - fileTemplates.Add (t); - } catch (Exception e) { - string extId = null, addinId = null; - if (codon != null) { - if (codon.HasId) - extId = codon.Id; - if (codon.Addin != null) - addinId = codon.Addin.Id; - } - LoggingService.LogError ("Error loading template id {0} in addin {1}:\n{2}", - extId ?? "(null)", addinId ?? "(null)", e.ToString ()); - } + var extensionContext = AddinManager.CreateExtensionContext (); + if (project != null) { + extensionContext.RegisterCondition ("AppliesTo", new AppliesToCondition (project)); + extensionContext.RegisterCondition ("FlavorType", new FlavorTypeCondition (project)); + extensionContext.RegisterCondition ("ProjectTypeId", new ProjectTypeIdCondition (project)); } else { - var codon = (ProjectTemplateCodon)args.ExtensionNode; - foreach (FileTemplate t in fileTemplates) { - if (t.Id == codon.Id) { - fileTemplates.Remove (t); - break; - } + extensionContext.RegisterCondition ("AppliesTo", new TrueCondition ()); + extensionContext.RegisterCondition ("FlavorType", new TrueCondition ()); + extensionContext.RegisterCondition ("ProjectTypeId", new TrueCondition ()); + } + + var list = new List<FileTemplate> (); + foreach (var node in extensionContext.GetExtensionNodes<ProjectTemplateCodon> (EXTENSION_PATH)) { + var template = LoadTemplate (node); + if (template.IsValidForProject (project, projectPath)) { + list.Add (template); } } + + return list; } - internal static List<FileTemplate> GetFileTemplates (Project project, string projectPath) + class TrueCondition : ConditionType { - var list = new List<FileTemplate> (); - foreach (var t in fileTemplates) { - if (t.IsValidForProject (project, projectPath)) - list.Add (t); + public override bool Evaluate (NodeElement conditionNode) + { + return true; } - return list; } internal static FileTemplate GetFileTemplateByID (string templateID) { - foreach (FileTemplate t in fileTemplates) - if (t.Id == templateID) - return t; - - return null; + var node = AddinManager.GetExtensionNodes<ProjectTemplateCodon> (EXTENSION_PATH) + .FirstOrDefault (n => n.Id == templateID); + return node == null ? null : LoadTemplate (node); } public virtual bool Create (SolutionFolderItem policyParent, Project project, string directory, string language, string name) |