This repository has been archived by the owner on Jan 14, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 111
/
populate.cs
376 lines (296 loc) · 15.1 KB
/
populate.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
using System;
using System.Reflection;
using System.IO;
using MonoMac.Foundation;
using System.Xml.Linq;
using System.Linq;
using System.Xml.XPath;
using System.Xml;
using System.Text;
using System.Collections.Generic;
class CtorUpdater {
static Dictionary<string,Dictionary<string,List<string>>> eventArgsUsage = new Dictionary<string,Dictionary<string,List<string>>>();
static int Record (Type t, string evtsig, string last)
{
string evt = evtsig.Substring (evtsig.IndexOf ('<')+1);
evt = evt.Substring (0, evt.IndexOf ('>'));
if (last.EndsWith (";"))
last = last.Substring (0, last.Length-1);
//Console.WriteLine ("Recording: {0} {1} {2}", t, evt, last);
if (!eventArgsUsage.ContainsKey (evt)){
eventArgsUsage [evt] = new Dictionary<string,List<string>>();
}
var v = eventArgsUsage [evt];
if (!v.ContainsKey (t.FullName)){
v [t.FullName] = new List<string> ();
}
v [t.FullName].Add (last);
return 1;
}
public static void Save (XDocument xmldoc, Type t)
{
string xmldocpath = String.Format ("{0}/{1}/{2}.xml", monotouch_dir, t.Namespace, t.Name);
var s = new XmlWriterSettings ();
s.Indent = true;
s.Encoding = new UTF8Encoding (false);
s.OmitXmlDeclaration = true;
using (var stream = File.Create (xmldocpath)){
using (var xmlw = XmlWriter.Create (stream, s)){
xmldoc.Save (xmlw);
}
stream.Write (new byte [] { 10 }, 0, 1);
}
}
public static void ProcessEventArgs (Type t)
{
var xmldoc = LoadDoc (t);
var summary = xmldoc.XPathSelectElement ("Type/Docs/summary");
var sb = new StringBuilder ();
int count = 0;
if (eventArgsUsage.ContainsKey (t.FullName)){
foreach (var e in eventArgsUsage [t.FullName]){
int n = e.Value.Count;
int i = 0;
foreach (var s in e.Value){
i++;
if (sb.Length != 0){
if (i == n)
sb.Append (" and ");
else
sb.Append (", ");
}
sb.Append (String.Format ("<see cref=\"E:{0}.{1}\"/>", t.FullName, s));
count++;
}
}
} // else Console.WriteLine ("NO users for {0}", t);
summary.ReplaceAll (XElement.Parse ("<Root>Provides data for the " + sb.ToString () + (count > 1 ? " events." : " event.") + "</Root>").DescendantNodes ());
var remarks = xmldoc.XPathSelectElement ("Type/Docs/remarks");
if (remarks.Value == "To be added.")
remarks.Value = "";
var ctorSummary = xmldoc.XPathSelectElement ("Type/Members/Member[@MemberName='.ctor']/Docs/summary");
if (ctorSummary != null)
ctorSummary.Value = "Initializes a new instance of the " + t.Name + " class.";
// else Console.WriteLine ("NO ctor for {0}", t.Name);
var ctorRemarks = xmldoc.XPathSelectElement ("Type/Members/Member[@MemberName='.ctor']/Docs/remarks");
if (ctorRemarks != null){
if (ctorRemarks.Value == "To be added.")
ctorRemarks.Value = "";
}
Save (xmldoc, t);
}
public static void ProcessNSO (Type t)
{
var xmldoc = LoadDoc (t);
var flagctor = from el in xmldoc.XPathSelectElements ("Type/Members/Member")
let y = el.XPathSelectElements ("MemberSignature").FirstOrDefault ()
where y != null
where y.Attribute ("Value").Value.IndexOf ("MonoMac.Foundation.NSObjectFlag") != -1
select el;
var coderctor = from el in xmldoc.XPathSelectElements ("Type/Members/Member")
let y = el.XPathSelectElements ("MemberSignature").FirstOrDefault ()
where y != null
where y.Attribute ("Value").Value.IndexOf ("NSCoder") != -1
select el;
var intptrctor = from el in xmldoc.XPathSelectElements ("Type/Members/Member")
let y = el.XPathSelectElements ("MemberSignature").FirstOrDefault ()
where y != null
where y.Attribute ("Value").Value.IndexOf ("IntPtr handle") != -1
select el;
var classhandles = from el in xmldoc.XPathSelectElements ("Type/Members/Member[@MemberName='ClassHandle']")
let y = el.XPathSelectElements ("MemberSignature").FirstOrDefault ()
where y != null
let value = y.Attribute ("Value").Value
where value == "public virtual IntPtr ClassHandle { get; }" || value == "public override IntPtr ClassHandle { get; }"
select el;
var delegates = from el in xmldoc.XPathSelectElements ("Type/Members/Member[@MemberName='Delegate']")
select el;
var weakdelegates = from el in xmldoc.XPathSelectElements ("Type/Members/Member[@MemberName='WeakDelegate']")
select el;
foreach (var x in classhandles){
var e = x.XPathSelectElement ("Docs/summary");
e.Value = "The handle for this class.";
e = x.XPathSelectElement ("Docs/value");
e.Value = "The pointer to the Objective-C class.";
e = x.XPathSelectElement ("Docs/remarks");
e.Value = "Each MonoMac class mirrors an unmanaged Objective-C class. This value contains the pointer to the Objective-C class, it is similar to calling objc_getClass with the object name.";
}
foreach (var x in flagctor){
var e = x.XPathSelectElement ("Docs/param");
e.Value = "Unused sentinel value, pass NSObjectFlag.Empty.";
e = x.XPathSelectElement ("Docs/summary");
e.Value = "Constructor to call on derived classes when the derived class has an [Export] constructor.";
e = x.XPathSelectElement ("Docs/remarks");
e.RemoveAll ();
e.Add (XElement.Parse ("<para>This constructor should be called by derived classes when they are initialized using an [Export] attribute. " +
"The argument value is ignore, typically the chaining would look like this:</para>"));
e.Add (XElement.Parse ("<example><code lang=\"C#\">\n" +
"public class MyClass : BaseClass {\n"+
" [Export (\"initWithFoo:\")]\n" +
" public MyClass (string foo) : base (NSObjectFlag.Empty)\n"+
" {\n" +
" ...\n" +
" }\n" +
"</code></example>"));
}
foreach (var x in coderctor){
var e = x.XPathSelectElement ("Docs/param");
if (e != null)
e.Value = "The unarchiver object.";
e = x.XPathSelectElement ("Docs/summary");
e.Value = "A constructor that initializes the object from the data stored in the unarchiver object.";
e = x.XPathSelectElement ("Docs/remarks");
e.RemoveAll ();
e.Value = "This constructor is provided to allow the class to be initialized from an unarchiver (for example, during NIB deserialization).";
}
foreach (var x in intptrctor){
var e = x.XPathSelectElement ("Docs/param");
e.Value = "Pointer (handle) to the unmanaged object.";
e = x.XPathSelectElement ("Docs/summary");
e.Value = "A constructor used when creating managed representations of unmanaged objects; Called by the runtime.";
e = x.XPathSelectElement ("Docs/remarks");
e.RemoveAll ();
e.Add (XElement.Parse ("<para>This constructor is invoked by the runtime infrastructure (<see cref=\"M:MonoMac.ObjCRuntime.GetNSObject (System.IntPtr)\"/>) to create a new managed representation for a pointer to an unmanaged Objective-C object. You should not invoke this method directly, instead you should call the GetNSObject method as it will prevent two instances of a managed object to point to the same native object.</para>"));
}
foreach (var x in delegates){
var dtype = x.XPathSelectElement ("ReturnValue/ReturnType").Value;
var e = x.XPathSelectElement ("Docs/summary");
e.Value = String.Format ("An instance of the {0} model class which acts as the class delegate.", dtype);
e = x.XPathSelectElement ("Docs/value");
e.Value = String.Format ("The instance of the {0} model class", dtype);
e = x.XPathSelectElement ("Docs/remarks");
e.RemoveAll ();
e.Add (XElement.Parse ("<para>The delegate instance assigned to this object will be used to handle events or provide data on demand to this class.</para>"));
e.Add (XElement.Parse ("<para>When setting the Delegate or WeakDelegate values events will be delivered to the specified instance instead of being delivered to the C#-style events</para>"));
e.Add (XElement.Parse ("<para>This is the strongly typed version of the object, use the WeakDelegate property instead if you want to merely assign a class derived from NSObject that has been decorated with [Export] attributes.</para>"));
}
foreach (var x in weakdelegates){
var e = x.XPathSelectElement ("Docs/summary");
e.Value = "An object that can respond to the delegate protocol for this type";
e = x.XPathSelectElement ("Docs/value");
e.Value = "The instance that will respond to events and data requests.";
e = x.XPathSelectElement ("Docs/remarks");
e.RemoveAll ();
e.Add (XElement.Parse ("<para>The delegate instance assigned to this object will be used to handle events or provide data on demand to this class.</para>"));
e.Add (XElement.Parse ("<para>When setting the Delegate or WeakDelegate values events will be delivered to the specified instance instead of being delivered to the C#-style events</para>"));
e.Add (XElement.Parse ("<para> Methods must be decorated with the [Export (\"selectorName\")] attribute to respond to each method from the protocol. Alternatively use the Delegate method which is strongly typed and does not require the [Export] attributes on methods.</para>"));
}
Save (xmldoc, t);
}
static string monotouch_dir;
static public XDocument LoadDoc (Type t)
{
string xmldocpath = String.Format ("{0}/{1}/{2}.xml", monotouch_dir, t.Namespace, t.Name);
return XDocument.Load (xmldocpath);
}
public static void ScanEvents (Type t)
{
var xmldoc = LoadDoc (t);
var events = from el in xmldoc.XPathSelectElements ("Type/Members/Member")
let p = el.XPathSelectElements ("MemberType").FirstOrDefault ()
where p != null && p.Value == "Event" || p.Value == "Field"
let y = el.XPathSelectElements ("MemberSignature").FirstOrDefault ().Attribute ("Value")
where y.Value.IndexOf ("EventArgs>") != -1 && y.Value.IndexOf ("<EventArgs>") == -1
select Record (t, y.Value, y.Value.Substring (y.Value.LastIndexOf ('>')+1).Trim ());
// Run query
events.ToList ();
}
public static void DocumentHandle (Type t)
{
var xmldoc = LoadDoc (t);
var h = xmldoc.XPathSelectElement ("Type/Members/Member[@MemberName='Handle']");
if (h == null)
return;
var e = h.XPathSelectElement ("Docs/summary");
e.Value = "Handle (pointer) to the unmanaged object representation.";
e = h.XPathSelectElement ("Docs/value");
e.Value = "A pointer";
e = h.XPathSelectElement ("Docs/remarks");
e.Value = "This IntPtr is a handle to the underlying unmanaged representation for this object.";
Save (xmldoc, t);
}
public static void DocumentDisposable (Type t)
{
var xmldoc = LoadDoc (t);
var dispose = from el in xmldoc.XPathSelectElements ("Type/Members/Member[@MemberName='Dispose' or @MemberName='System.IDisposable.Dispose']")
let c = el.XPathSelectElements ("MemberSignature").FirstOrDefault ().Attribute ("Value")
where c.Value.IndexOf ("Dispose ()") != -1
select el;
var disposevirt = from el in xmldoc.XPathSelectElements ("Type/Members/Member[@MemberName='Dispose']")
let c = el.XPathSelectElements ("MemberSignature").FirstOrDefault ().Attribute ("Value")
where c.Value.IndexOf ("Dispose (bool") != -1
select el;
var finalize = from el in xmldoc.XPathSelectElements ("Type/Members/Member[@MemberName='Finalize']")
select el;
foreach (var f in finalize){
var e = f.XPathSelectElement ("Docs/summary");
e.Value = "Finalizer for the " + t.Name + " object";
e = f.XPathSelectElement ("Docs/remarks");
e.Value = "";
}
foreach (var d in dispose){
var e = d.XPathSelectElement ("Docs/summary");
e.Value = "Releases the resourced used by the " + t.Name + " object.";
e = d.XPathSelectElement ("Docs/remarks");
e.RemoveAll ();
e.Add (XElement.Parse ("<para>The Dispose method releases the resources used by the " + t.Name + " class.</para>"));
e.Add (XElement.Parse ("<para>Calling the Dispose method when you are finished using the " +t.Name + " ensures that all external resources used by this managed object are released as soon as possible. Once you have invoked the Dispose method, the object is no longer useful and you should no longer make any calls to it. For more information on releasing resources see ``Cleaning up Unmananaged Resources'' at http://msdn.microsoft.com/en-us/library/498928w2.aspx</para>"));
}
foreach (var d in disposevirt){
var e = d.XPathSelectElement ("Docs/summary");
e.Value = "Releases the resourced used by the " + t.Name + " object.";
e = d.XPathSelectElement ("Docs/param[@name='disposing']");
//e = d.XPathSelectElement ("Docs/param");
if (e != null){
e.RemoveAll ();
// Add it back after removeall
e.Add (new XAttribute ("name", "disposing"));
e.Add (XElement.Parse ("<para>If set to <see langword=\"true\"/>, the method is invoked directly and will dispose manage and unmanaged resources; If set to <see langword=\"false\"/> the method is being called by the garbage collector finalizer and should only release unmanaged resources.</para>"));
}
e = d.XPathSelectElement ("Docs/remarks");
e.RemoveAll ();
e.Add (XElement.Parse ("<para>This Dispose method releases the resources used by the " + t.Name + " class.</para>"));
e.Add (XElement.Parse ("<para>This method is called by both the Dispose() method and the object finalizer (Finalize). When invoked by the Dispose method, the parameter disposting <paramref name=\"disposing\"/> is set to <see langword=\"true\"/> and any managed object references that this object holds are also disposed or released; when invoked by the object finalizer, on the finalizer thread the value is set to <see langword=\"false\"/>. </para>"));
e.Add (XElement.Parse ("<para>Calling the Dispose method when you are finished using the " +t.Name + " ensures that all external resources used by this managed object are released as soon as possible. Once you have invoked the Dispose method, the object is no longer useful and you should no longer make any calls to it.</para>"));
e.Add (XElement.Parse ("<para> For more information on how to override this method and on the Dispose/IDisposable pattern, read the ``Implementing a Dispose Method'' document at http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx</para>"));
}
Save (xmldoc, t);
}
public static int Main (string [] args)
{
Assembly monotouch = typeof (MonoMac.Foundation.NSObject).Assembly;
bool update_events = false;
var dir = args [0];
if (File.Exists (Path.Combine (dir, "en"))){
Console.WriteLine ("The directory does not seem to be the root for documentation (missing en directory)");
return 1;
}
monotouch_dir = Path.Combine (dir, "en");
Type nso = monotouch.GetType ("MonoMac.Foundation.NSObject");
foreach (Type t in monotouch.GetTypes ()){
if (t.IsNotPublic || t.IsNested)
continue;
if (typeof (IDisposable).IsAssignableFrom (t)){
DocumentDisposable (t);
}
DocumentHandle (t);
if (typeof (MonoMac.ObjCRuntime.INativeObject).IsAssignableFrom (t)){
}
if (update_events)
ScanEvents (t);
if (t == nso || t.IsSubclassOf (nso))
ProcessNSO (t);
}
// Now go and populate EventArgs
if (update_events){
foreach (Type t in monotouch.GetTypes ()){
if (t.IsNotPublic || t.IsNested)
continue;
if (t.IsSubclassOf (typeof (EventArgs))){
ProcessEventArgs (t);
}
}
}
return 0;
}
}