Skip to content
This repository was archived by the owner on Oct 4, 2021. It is now read-only.

Commit ca54e57

Browse files
author
Rodrigo Moya
authored
Merge pull request #9105 from mono/pr-improve-feature-switch-service
Improve feature switch service
2 parents 1bf2403 + 169d349 commit ca54e57

File tree

16 files changed

+249
-13
lines changed

16 files changed

+249
-13
lines changed

main/src/addins/MonoDevelop.DotNetCore/Properties/MonoDevelop.DotNetCore.addin.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,4 +1617,8 @@
16171617
<CommandItem id="MonoDevelop.DotNetCore.Commands.Pack" insertbefore="Publish" />
16181618
</Condition>
16191619
</Extension>
1620+
1621+
<Extension path="/MonoDevelop/Core/FeatureSwitches">
1622+
<FeatureSwitch id="VBNetDotnetCoreTemplates" _description="Enable VB.NET support for .NET Core" defaultValue="false" />
1623+
</Extension>
16201624
</ExtensionModel>

main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/Properties/MonoDevelop.TextEditor.addin.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,4 +340,8 @@
340340
<Description>TextMate folder with syntax highlighting definitions, code snippets and syntax color themes</Description>
341341
<ExtensionNode name="Repository" type="MonoDevelop.TextEditor.TextMateRepositoryExtensionNode"/>
342342
</ExtensionPoint>
343+
344+
<Extension path="/MonoDevelop/Core/FeatureSwitches">
345+
<FeatureSwitch id="AlwaysUseLegacyEditor" _description="Enable old editor" defaultValue="false" />
346+
</Extension>
343347
</ExtensionModel>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// FeatureSwitchExtensionNode.cs
3+
//
4+
// Author:
5+
// Rodrigo Moya <[email protected]>
6+
//
7+
// Copyright (c) 2019 Microsoft Corp (http://microsoft.com)
8+
//
9+
// Permission is hereby granted, free of charge, to any person obtaining a copy
10+
// of this software and associated documentation files (the "Software"), to deal
11+
// in the Software without restriction, including without limitation the rights
12+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
// copies of the Software, and to permit persons to whom the Software is
14+
// furnished to do so, subject to the following conditions:
15+
//
16+
// The above copyright notice and this permission notice shall be included in
17+
// all copies or substantial portions of the Software.
18+
//
19+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
// THE SOFTWARE.
26+
27+
using System;
28+
using Mono.Addins;
29+
30+
namespace MonoDevelop.Core.Addins
31+
{
32+
[ExtensionNode (Description = "Feature switch information.")]
33+
sealed class FeatureSwitchExtensionNode : ExtensionNode
34+
{
35+
//these fields are assigned by reflection, suppress "never assigned" warning
36+
#pragma warning disable 649
37+
38+
[NodeAttribute ("_description", "Id of the feature switch.")]
39+
public string Description { get; private set; }
40+
41+
[NodeAttribute ("defaultValue", "Default value.")]
42+
public bool DefaultValue { get; private set; }
43+
44+
#pragma warning restore 649
45+
}
46+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// FeatureSwitch.cs
3+
//
4+
// Author:
5+
// Rodrigo Moya <[email protected]>
6+
//
7+
// Copyright (c) 2019 Microsoft, Corp. (http://microsoft.com)
8+
//
9+
// Permission is hereby granted, free of charge, to any person obtaining a copy
10+
// of this software and associated documentation files (the "Software"), to deal
11+
// in the Software without restriction, including without limitation the rights
12+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
// copies of the Software, and to permit persons to whom the Software is
14+
// furnished to do so, subject to the following conditions:
15+
//
16+
// The above copyright notice and this permission notice shall be included in
17+
// all copies or substantial portions of the Software.
18+
//
19+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
// THE SOFTWARE.
26+
27+
namespace MonoDevelop.Core.FeatureConfiguration
28+
{
29+
internal sealed class FeatureSwitch
30+
{
31+
public FeatureSwitch (string name, string description, bool defaultValue)
32+
{
33+
Name = name;
34+
Description = description;
35+
DefaultValue = defaultValue;
36+
}
37+
38+
public string Name { get; }
39+
40+
public string Description { get; }
41+
42+
public bool DefaultValue { get; }
43+
44+
public bool? CurrentValue { get; set; }
45+
}
46+
}

main/src/core/MonoDevelop.Core/MonoDevelop.Core.FeatureConfiguration/FeatureSwitchService.cs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,35 @@
2525
// THE SOFTWARE.
2626

2727
using System;
28+
using System.Collections.Generic;
29+
using System.Collections.Immutable;
2830
using System.Linq;
2931
using Mono.Addins;
32+
using MonoDevelop.Core.Addins;
3033

3134
namespace MonoDevelop.Core.FeatureConfiguration
3235
{
3336
public static class FeatureSwitchService
3437
{
38+
static Dictionary<string, FeatureSwitch> featureSwitches = new Dictionary<string, FeatureSwitch> ();
39+
40+
internal static void Initialize ()
41+
{
42+
AddinManager.AddExtensionNodeHandler ("/MonoDevelop/Core/FeatureSwitches", HandleFeatureSwitchExtension);
43+
}
44+
45+
static void HandleFeatureSwitchExtension (object sender, ExtensionNodeEventArgs args)
46+
{
47+
var fs = args.ExtensionNode as FeatureSwitchExtensionNode;
48+
if (fs != null) {
49+
if (args.Change == ExtensionChange.Add) {
50+
RegisterFeatureSwitch (fs.Id, fs.Description, fs.DefaultValue);
51+
} else {
52+
UnregisterFeatureSwitch (fs.Id);
53+
}
54+
}
55+
}
56+
3557
public static bool? IsFeatureEnabled (string featureName)
3658
{
3759
if (string.IsNullOrEmpty (featureName)) {
@@ -49,7 +71,12 @@ public static class FeatureSwitchService
4971
}
5072

5173
// Fallback to ask extensions, enabling by default
52-
var extensions = AddinManager.GetExtensionObjects<IFeatureSwitchController> ("/MonoDevelop/Core/FeatureConfiguration/FeatureSwitchChecks");
74+
if (featureSwitches.TryGetValue (featureName, out var feature)) {
75+
return feature.CurrentValue ?? feature.DefaultValue;
76+
}
77+
78+
// Backwards support for obsolete IFeatureSwitchController API
79+
var extensions = AddinManager.GetExtensionObjects<IFeatureSwitchController> ();
5380
if (extensions != null) {
5481
bool explicitlyEnabled = false, explicitlyDisabled = false;
5582
foreach (var ext in extensions) {
@@ -69,5 +96,41 @@ public static class FeatureSwitchService
6996

7097
return null;
7198
}
99+
100+
#region Internal API for unit tests
101+
102+
internal static void SetFeatureSwitchValue (string id, bool? value)
103+
{
104+
if (!featureSwitches.TryGetValue (id, out var featureSwitch)) {
105+
// This feature switch is not registered, so register it now
106+
featureSwitch = new FeatureSwitch (id, null, false);
107+
featureSwitches.Add (id, featureSwitch);
108+
}
109+
110+
featureSwitch.CurrentValue = value;
111+
}
112+
113+
internal static IEnumerable<FeatureSwitch> DescribeFeatures ()
114+
{
115+
return featureSwitches.Values;
116+
}
117+
118+
internal static void RegisterFeatureSwitch (string id, string description, bool defaultValue)
119+
{
120+
LoggingService.LogInfo ($"Registering feature {id} ({description} = {defaultValue})");
121+
if (featureSwitches.TryGetValue (id, out _)) {
122+
LoggingService.LogWarning ($"Feature switch {id} already registered, ignoring new registration");
123+
} else {
124+
featureSwitches.Add (id, new FeatureSwitch (id, description, defaultValue));
125+
}
126+
}
127+
128+
internal static void UnregisterFeatureSwitch (string id)
129+
{
130+
LoggingService.LogInfo ($"Unregistering feature {id}");
131+
featureSwitches.Remove (id);
132+
}
133+
134+
#endregion
72135
}
73136
}

main/src/core/MonoDevelop.Core/MonoDevelop.Core.FeatureConfiguration/IFeatureSwitchController.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
//
2-
// IFeatureSwitchEnabler.cs
2+
// IFeatureSwitchController.cs
33
//
44
// Author:
55
// Rodrigo Moya <[email protected]>
66
//
7-
// Copyright (c) 2018 Microsoft Corp. (http://www.microsoft.com)
7+
// Copyright (c) 2019 Microsoft Corp. (http://microsoft.com)
88
//
99
// Permission is hereby granted, free of charge, to any person obtaining a copy
1010
// of this software and associated documentation files (the "Software"), to deal
@@ -24,8 +24,11 @@
2424
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2525
// THE SOFTWARE.
2626

27+
using System;
28+
2729
namespace MonoDevelop.Core.FeatureConfiguration
2830
{
31+
[Obsolete ("Implement feature switches via '/MonoDevelop/Core/FeatureSwitches' extension point")]
2932
public interface IFeatureSwitchController
3033
{
3134
bool? IsFeatureEnabled (string featureName);

main/src/core/MonoDevelop.Core/MonoDevelop.Core.addin.xml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919

2020
<!-- Extension points -->
2121

22-
<ExtensionPoint path="/MonoDevelop/Core/FeatureConfiguration/FeatureSwitchChecks" name="Feature switch checks">
23-
<Description>Pluggable checks for feature dynamic enabling/disabling</Description>
24-
<ExtensionNode objectType="MonoDevelop.Core.FeatureConfiguration.IFeatureSwitchController" />
25-
</ExtensionPoint>
22+
<ExtensionPoint path="/MonoDevelop/Core/FeatureConfiguration/FeatureSwitchChecks" name="Feature switch checks">
23+
<Description>Pluggable checks for feature dynamic enabling/disabling</Description>
24+
<ExtensionNode objectType="MonoDevelop.Core.FeatureConfiguration.IFeatureSwitchController" />
25+
</ExtensionPoint>
2626

2727
<ExtensionPoint path = "/MonoDevelop/Core/ExecutionModes" name = "Execution modes">
2828
<Description>Execution modes such as default, debug, profiler, etc.</Description>
@@ -171,6 +171,11 @@
171171
<Description>Allows defining fallback search paths for MSBuild project imports</Description>
172172
<ExtensionNode name="SearchPath" type="MonoDevelop.Projects.Extensions.ImportSearchPathExtensionNode" />
173173
</ExtensionPoint>
174+
175+
<ExtensionPoint path="/MonoDevelop/Core/FeatureSwitches">
176+
<Description>Feature flags to allow disabling/enabling development features.</Description>
177+
<ExtensionNode name="FeatureSwitch" type="MonoDevelop.Core.Addins.FeatureSwitchExtensionNode"/>
178+
</ExtensionPoint>
174179

175180
<!-- Extensions -->
176181

main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,6 @@
719719
<Compile Include="MonoDevelop.Core.Web\IHttpCredentialsHandler.cs" />
720720
<Compile Include="MonoDevelop.Core.Web\DefaultHttpClientHandler.cs" />
721721
<Compile Include="MonoDevelop.Projects.MSBuild\MSBuildProcessService.cs" />
722-
<Compile Include="MonoDevelop.Core.FeatureConfiguration\IFeatureSwitchController.cs" />
723722
<Compile Include="MonoDevelop.Core\Service.cs" />
724723
<Compile Include="MonoDevelop.Core\ServiceProvider.cs" />
725724
<Compile Include="MonoDevelop.Core\IService.cs" />
@@ -745,6 +744,9 @@
745744
<Compile Include="MonoDevelop.Projects\FrameworkReference.cs" />
746745
<Compile Include="MonoDevelop.Core\DedicatedThreadScheduler.cs" />
747746
<Compile Include="MonoDevelop.Projects.MSBuild\IntrinsicFunctions.Extensions.cs" />
747+
<Compile Include="MonoDevelop.Core.FeatureConfiguration\FeatureSwitch.cs" />
748+
<Compile Include="MonoDevelop.Core.AddIns\FeatureSwitchExtensionNode.cs" />
749+
<Compile Include="MonoDevelop.Core.FeatureConfiguration\IFeatureSwitchController.cs" />
748750
</ItemGroup>
749751
<ItemGroup>
750752
<None Include="BuildVariables.cs.in" />

main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
using Mono.Addins.Setup;
4343
using MonoDevelop.Core.Assemblies;
4444
using MonoDevelop.Core.Execution;
45+
using MonoDevelop.Core.FeatureConfiguration;
4546
using MonoDevelop.Core.Instrumentation;
4647
using MonoDevelop.Core.Setup;
4748
using MonoDevelop.Core.Web;
@@ -144,6 +145,9 @@ public static void Initialize (bool updateAddinRegistry)
144145
systemAssemblyService = new SystemAssemblyService ();
145146
systemAssemblyService.Initialize ();
146147
LoadMSBuildLibraries ();
148+
149+
// Initialize extra services
150+
FeatureSwitchService.Initialize ();
147151

148152
initialized = true;
149153

main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,5 +437,10 @@
437437
<Assembly file="Microsoft.VisualStudio.Text.UI.dll"/>
438438
<Assembly file="MonoDevelop.Ide.dll"/>
439439
</Extension>
440+
441+
<Extension path="/MonoDevelop/Core/FeatureSwitches">
442+
<FeatureSwitch id="IdeBuildOutputView" _description="Enable structured build output UI" defaultValue="false" />
443+
<FeatureSwitch id="RUNTIME_SELECTOR" _description="Enable runtime selection on UI" defaultValue="false" />
444+
</Extension>
440445

441446
</ExtensionModel>

0 commit comments

Comments
 (0)