Skip to content

Commit 7067f0e

Browse files
committed
Extended plugin interface to query data from the plugin.
1 parent 6079c2a commit 7067f0e

6 files changed

Lines changed: 167 additions & 22 deletions

File tree

‎ReClass.NET/CodeGenerator/CustomCodeGenerator.cs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,18 @@ public MemberDefinition GetMemberDefinition(BaseNode node, Language language, IL
3434
}
3535
}
3636

37-
public class CustomCodeGenerator
37+
internal class CustomCodeGenerator
3838
{
39-
private static readonly List<ICustomCodeGenerator> generators = new List<ICustomCodeGenerator>();
39+
private static readonly ISet<ICustomCodeGenerator> generators = new HashSet<ICustomCodeGenerator>();
4040

41-
public static void RegisterCustomType(ICustomCodeGenerator generator)
41+
public static void Add(ICustomCodeGenerator generator)
4242
{
4343
Contract.Requires(generator != null);
4444

4545
generators.Add(generator);
4646
}
4747

48-
public static void DeregisterCustomType(ICustomCodeGenerator generator)
48+
public static void Remove(ICustomCodeGenerator generator)
4949
{
5050
Contract.Requires(generator != null);
5151

‎ReClass.NET/DataExchange/ReClass/CustomNodeSerializer.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,14 @@ internal class CustomNodeSerializer
8888
{
8989
private static readonly List<ICustomNodeSerializer> converters = new List<ICustomNodeSerializer>();
9090

91-
public static void RegisterCustomType(ICustomNodeSerializer serializer)
91+
public static void Add(ICustomNodeSerializer serializer)
9292
{
9393
Contract.Requires(serializer != null);
9494

9595
converters.Add(serializer);
9696
}
9797

98-
public static void DeregisterCustomType(ICustomNodeSerializer serializer)
98+
public static void Remove(ICustomNodeSerializer serializer)
9999
{
100100
Contract.Requires(serializer != null);
101101

‎ReClass.NET/Plugins/Plugin.cs‎

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,36 @@
1+
using System;
2+
using System.Collections.Generic;
13
using System.Diagnostics.Contracts;
24
using System.Drawing;
5+
using ReClassNET.CodeGenerator;
6+
using ReClassNET.DataExchange.ReClass;
7+
using ReClassNET.Nodes;
38

49
namespace ReClassNET.Plugins
510
{
6-
public abstract class Plugin
11+
public class Plugin
712
{
13+
public class CustomNodeTypes
14+
{
15+
/// <summary>
16+
/// A list with custom node types.
17+
/// </summary>
18+
public IReadOnlyList<Type> NodeTypes { get; set; }
19+
20+
/// <summary>
21+
/// An instance of a serializer which can process the custom node types.
22+
/// </summary>
23+
public ICustomNodeSerializer Serializer { get; set; }
24+
25+
/// <summary>
26+
/// An instance of a code generator which can process the custom node types.
27+
/// </summary>
28+
public ICustomCodeGenerator CodeGenerator { get; set; }
29+
}
30+
31+
/// <summary>
32+
/// The icon of the plugin.
33+
/// </summary>
834
public virtual Image Icon => null;
935

1036
public virtual bool Initialize(IPluginHost host)
@@ -18,5 +44,23 @@ public virtual void Terminate()
1844
{
1945

2046
}
47+
48+
/// <summary>
49+
/// Gets called once to receive all node info readers the plugin provides.
50+
/// </summary>
51+
/// <returns>A list with node info readers or <c>null</c> if the plugin provides none.</returns>
52+
public virtual IReadOnlyList<INodeInfoReader> GetNodeInfoReaders()
53+
{
54+
return null;
55+
}
56+
57+
/// <summary>
58+
/// Gets called once to receive all custom node types the plugin provides.
59+
/// </summary>
60+
/// <returns>Informations about the custom nodes or <c>null</c> if the plugin provides none.</returns>
61+
public virtual CustomNodeTypes GetCustomNodeTypes()
62+
{
63+
return null;
64+
}
2165
}
2266
}

‎ReClass.NET/Plugins/PluginInfo.cs‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Diagnostics;
34
using System.Diagnostics.Contracts;
45
using System.IO;
56
using ReClassNET.Extensions;
67
using ReClassNET.Native;
7-
using ReClassNET.Util;
8+
using ReClassNET.Nodes;
89

910
namespace ReClassNET.Plugins
1011
{
@@ -29,6 +30,10 @@ internal class PluginInfo : IDisposable
2930

3031
public IntPtr NativeHandle { get; set; }
3132

33+
public IReadOnlyList<INodeInfoReader> NodeInfoReaders { get; set; }
34+
35+
public Plugin.CustomNodeTypes CustomNodeTypes { get; set; }
36+
3237
public PluginInfo(string filePath, FileVersionInfo versionInfo)
3338
{
3439
Contract.Requires(filePath != null);
@@ -49,8 +54,6 @@ public PluginInfo(string filePath, FileVersionInfo versionInfo)
4954
}
5055
}
5156

52-
#region IDisposable Support
53-
5457
~PluginInfo()
5558
{
5659
ReleaseUnmanagedResources();
@@ -84,7 +87,5 @@ public void Dispose()
8487

8588
GC.SuppressFinalize(this);
8689
}
87-
88-
#endregion
8990
}
9091
}

‎ReClass.NET/Plugins/PluginManager.cs‎

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
using System.Diagnostics;
44
using System.Diagnostics.Contracts;
55
using System.IO;
6+
using ReClassNET.CodeGenerator;
67
using ReClassNET.Core;
8+
using ReClassNET.DataExchange.ReClass;
79
using ReClassNET.Extensions;
810
using ReClassNET.Logger;
911
using ReClassNET.Native;
10-
using ReClassNET.Util;
12+
using ReClassNET.Nodes;
13+
using ReClassNET.UI;
1114

1215
namespace ReClassNET.Plugins
1316
{
@@ -87,6 +90,9 @@ private void LoadPlugins(IEnumerable<FileInfo> files, ILogger logger, bool check
8790
{
8891
continue;
8992
}
93+
94+
RegisterNodeInfoReaders(pi);
95+
RegisterCustomNodeTypes(pi);
9096
}
9197
else
9298
{
@@ -109,7 +115,17 @@ private void LoadPlugins(IEnumerable<FileInfo> files, ILogger logger, bool check
109115

110116
public void UnloadAllPlugins()
111117
{
112-
plugins.ForEach(p => p.Dispose());
118+
foreach (var pi in plugins)
119+
{
120+
if (pi.Interface != null) // Exclude native plugins
121+
{
122+
DeregisterNodeInfoReaders(pi);
123+
DeregisterCustomNodeTypes(pi);
124+
}
125+
126+
pi.Dispose();
127+
}
128+
113129
plugins.Clear();
114130
}
115131

@@ -140,5 +156,83 @@ private static IntPtr CreateNativePluginInstance(string filePath)
140156
}
141157
return handle;
142158
}
159+
160+
private static void RegisterNodeInfoReaders(PluginInfo pluginInfo)
161+
{
162+
Contract.Requires(pluginInfo != null);
163+
164+
var nodeInfoReaders = pluginInfo.Interface.GetNodeInfoReaders();
165+
166+
if (nodeInfoReaders == null || nodeInfoReaders.Count == 0)
167+
{
168+
return;
169+
}
170+
171+
pluginInfo.NodeInfoReaders = nodeInfoReaders;
172+
173+
BaseNode.NodeInfoReader.AddRange(nodeInfoReaders);
174+
}
175+
176+
private static void DeregisterNodeInfoReaders(PluginInfo pluginInfo)
177+
{
178+
Contract.Requires(pluginInfo != null);
179+
180+
if (pluginInfo.NodeInfoReaders == null)
181+
{
182+
return;
183+
}
184+
185+
foreach (var reader in pluginInfo.NodeInfoReaders)
186+
{
187+
BaseNode.NodeInfoReader.Remove(reader);
188+
}
189+
}
190+
191+
private static void RegisterCustomNodeTypes(PluginInfo pluginInfo)
192+
{
193+
Contract.Requires(pluginInfo != null);
194+
195+
var customNodeTypes = pluginInfo.Interface.GetCustomNodeTypes();
196+
197+
if (customNodeTypes == null)
198+
{
199+
return;
200+
}
201+
202+
if (customNodeTypes.NodeTypes == null || customNodeTypes.Serializer == null || customNodeTypes.CodeGenerator == null)
203+
{
204+
throw new ArgumentException(); // TODO
205+
}
206+
207+
foreach (var nodeType in customNodeTypes.NodeTypes)
208+
{
209+
if (!nodeType.IsSubclassOf(typeof(BaseNode)))
210+
{
211+
throw new ArgumentException($"Type '{nodeType}' is not a valid node.");
212+
}
213+
}
214+
215+
pluginInfo.CustomNodeTypes = customNodeTypes;
216+
217+
NodeTypesBuilder.AddPluginNodeGroup(pluginInfo.Interface, customNodeTypes.NodeTypes);
218+
219+
CustomNodeSerializer.Add(customNodeTypes.Serializer);
220+
CustomCodeGenerator.Add(customNodeTypes.CodeGenerator);
221+
}
222+
223+
private static void DeregisterCustomNodeTypes(PluginInfo pluginInfo)
224+
{
225+
Contract.Requires(pluginInfo != null);
226+
227+
if (pluginInfo.CustomNodeTypes == null)
228+
{
229+
return;
230+
}
231+
232+
NodeTypesBuilder.RemovePluginNodeGroup(pluginInfo.Interface);
233+
234+
CustomNodeSerializer.Remove(pluginInfo.CustomNodeTypes.Serializer);
235+
CustomCodeGenerator.Remove(pluginInfo.CustomNodeTypes.CodeGenerator);
236+
}
143237
}
144238
}

‎ReClass.NET/UI/NodeTypesBuilder.cs‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010

1111
namespace ReClassNET.UI
1212
{
13-
public static class NodeTypesBuilder
13+
internal static class NodeTypesBuilder
1414
{
1515
private static readonly List<Type[]> defaultNodeTypeGroupList = new List<Type[]>();
16-
private static readonly Dictionary<Plugin, List<Type>> pluginNodeTypes = new Dictionary<Plugin, List<Type>>();
16+
private static readonly Dictionary<Plugin, IReadOnlyList<Type>> pluginNodeTypes = new Dictionary<Plugin, IReadOnlyList<Type>>();
1717

1818
static NodeTypesBuilder()
1919
{
@@ -29,18 +29,24 @@ static NodeTypesBuilder()
2929
defaultNodeTypeGroupList.Add(new[] { typeof(VirtualMethodTableNode), typeof(FunctionNode), typeof(FunctionPtrNode) });
3030
}
3131

32-
public static List<Type> RegisterPluginNodeGroup(Plugin plugin)
32+
public static void AddPluginNodeGroup(Plugin plugin, IReadOnlyList<Type> nodeTypes)
3333
{
3434
Contract.Requires(plugin != null);
35+
Contract.Requires(nodeTypes != null);
3536

36-
if (!pluginNodeTypes.TryGetValue(plugin, out var types))
37+
if (pluginNodeTypes.ContainsKey(plugin))
3738
{
38-
types = new List<Type>();
39-
40-
pluginNodeTypes.Add(plugin, types);
39+
throw new InvalidOperationException(); // TODO
4140
}
4241

43-
return types;
42+
pluginNodeTypes.Add(plugin, nodeTypes);
43+
}
44+
45+
public static void RemovePluginNodeGroup(Plugin plugin)
46+
{
47+
Contract.Requires(plugin != null);
48+
49+
pluginNodeTypes.Remove(plugin);
4450
}
4551

4652
public static IEnumerable<ToolStripItem> CreateToolStripButtons(Action<Type> handler)

0 commit comments

Comments
 (0)