~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/maccore/tools/docfixer/document-generated-code.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
// erased in the compilation process (like the link between events
9
9
// and their ObjC delegate classes).
10
10
//
11
 
 
 
11
// Copyright 2012 Xamarin Inc
 
12
//
12
13
using System;
13
14
using System.Collections.Generic;
14
15
using System.Reflection;
53
54
        {
54
55
                var ns = t.Namespace;
55
56
                var typeName = t.FullName.Substring (ns.Length+1);
 
57
                if (ns == "MonoTouch.Foundation"){
 
58
                        if (typeName == "NSString2")
 
59
                                typeName = "NSString";
 
60
                        if (typeName == "NSObject2")
 
61
                                typeName = "NSObject";
 
62
                }
 
63
                
56
64
                return String.Format ("{0}/{1}/{2}{3}.xml", assembly_dir, ns, typeName, notification ? "+Notifications" : "");
57
65
        }
58
66
        
87
95
                var xmlSettings = new XmlWriterSettings (){
88
96
                        Indent = true,
89
97
                        Encoding = new UTF8Encoding (false),
90
 
                        OmitXmlDeclaration = true
 
98
                        OmitXmlDeclaration = true,
 
99
                        NewLineChars = Environment.NewLine
91
100
                };
92
101
                using (var output = File.CreateText (xmldocpath)){
93
 
                        var xmlw = XmlWriter.Create (output, xmlSettings);
94
 
                        xmldoc.Save (xmlw);
95
 
                        output.WriteLine ();
 
102
                        using (var xmlw = XmlWriter.Create (output, xmlSettings)){
 
103
                                xmldoc.Save (xmlw);
 
104
                                output.WriteLine ();
 
105
                        }
96
106
                }
97
107
        }
98
108
        
106
116
                }
107
117
        }
108
118
 
 
119
        static XElement GetXmlNodeForMemberName (Type t, XDocument xdoc, string name)
 
120
        {
 
121
                var field = xdoc.XPathSelectElement ("Type/Members/Member[@MemberName='" + name + "']");
 
122
                if (field == null){
 
123
                        if (!warnings_up_to_date.ContainsKey (t)){
 
124
                                Console.WriteLine ("Warning: {0} document is not up-to-date with the latest assembly (could not find Field <Member MemberName='{1}')", t, name);
 
125
                                warnings_up_to_date [t] = true;
 
126
                        }
 
127
                }
 
128
                return field;
 
129
        }
 
130
 
 
131
        static XElement GetXmlNodeFromExport (Type t, XDocument xdoc, string selector)
 
132
        {
 
133
                return (from m in xdoc.XPathSelectElements ("Type/Members/Member")
 
134
                        let a = m.XPathSelectElement ("Attributes/Attribute/AttributeName")
 
135
                        where a != null && a.Value.IndexOf ("MonoTouch.Foundation.Export(\"" + selector + "\"") != -1
 
136
                        select m).FirstOrDefault ();
 
137
        }
 
138
 
109
139
        //
110
140
        // Handles fields, but perhaps this is better done in DocFixer to pull the definitions
111
141
        // from the docs?
112
142
        //
113
 
        public static void ProcessField (Type t, XDocument xdoc, PropertyInfo pi)
 
143
        public static void ProcessField (Type t, XDocument xdoc, PropertyInfo pi, bool isNotification)
114
144
        {
115
145
                var fieldAttr = pi.GetCustomAttributes (typeof (FieldAttribute), true);
116
146
                if (fieldAttr.Length == 0)
117
147
                        return;
118
148
                
119
149
                var export = ((FieldAttribute) fieldAttr [0]).SymbolName;
 
150
 
 
151
                var field = GetXmlNodeForMemberName (t, xdoc, pi.Name);
 
152
                if (field == null)
 
153
                        return;
120
154
                
121
 
                var field = xdoc.XPathSelectElement ("Type/Members/Member[@MemberName='" + pi.Name + "']");
122
 
                if (field == null){
123
 
                        if (!warnings_up_to_date.ContainsKey (t)){
124
 
                                Console.WriteLine ("Warning: {0} document is not up-to-date with the latest assembly (could not find Field <Member MemberName='{1}')", t, pi.Name);
125
 
                                warnings_up_to_date [t] = true;
126
 
                        }
127
 
                        return;
128
 
                }
129
155
                var returnType = field.XPathSelectElement ("ReturnValue/ReturnType");
130
156
                var summary = field.XPathSelectElement ("Docs/summary");
131
157
                var remarks = field.XPathSelectElement ("Docs/remarks");
132
158
                var example = field.XPathSelectElement ("Docs/remarks/example");
133
 
                if (mergeAppledocs){
134
 
                        if (returnType.Value == "MonoMac.Foundation.NSString" && export.EndsWith ("Notification")){
 
159
                if (isNotification || (returnType.Value.EndsWith (".Foundation.NSString") && export.EndsWith ("Notification"))){
 
160
                        if (mergeAppledocs){
135
161
                                var mdoc = docGenerator.GetAppleMemberDocs (ToCecilType (t), export);
136
162
                                if (mdoc == null){
137
163
                                        Console.WriteLine ("Failed to load docs for {0} - {1}", t.Name, export);
144
170
                                // Make this pretty, the first paragraph we turn into the summary,
145
171
                                // the rest we put in the remarks section
146
172
                                //
147
 
                                summary.Value = "";
 
173
                                summary.RemoveAll ();
148
174
                                summary.Add (section);
149
175
 
150
176
                                var skipOne = summary.Nodes ().Skip (2).ToArray ();
151
 
                                remarks.Value = "";
 
177
                                remarks.RemoveAll ();
152
178
                                remarks.Add (skipOne);
153
179
                                foreach (var n in skipOne)
154
180
                                        n.Remove ();
155
181
                                if (example != null)
156
182
                                        remarks.Add (example);
157
183
                        }
 
184
                } else {
 
185
                        var value = field.XPathSelectElement ("Docs/value");
 
186
                        if (value != null && value.Value == "To be added.")
 
187
                                value.RemoveAll ();
 
188
 
 
189
                        //var since = pi.GetCustomAttributes (typeof (SinceAttribute), true);
 
190
                        //if (since.Length != 0 && pi.PropertyType.IsClass) {
 
191
                                // TODO: Could format the since value into the text
 
192
                        //      value.Value = "Value will be null when the constant is not available";
 
193
                        //}
 
194
 
 
195
                        summary.RemoveAll ();
 
196
                        summary.Value = "Represents the value associated with the constant " + export;
158
197
                }
159
198
        }
160
199
 
182
221
                        return;
183
222
                }
184
223
                var name = pi.Name;
185
 
                var mname = name.Substring (0, name.Length-("Notification".Length));
 
224
                var mname = name.EndsWith ("Notification") ? name.Substring (0, name.Length-("Notification".Length)) : name;
186
225
                
187
226
                var returnType = field.XPathSelectElement ("ReturnValue/ReturnType");
188
227
                var summary = field.XPathSelectElement ("Docs/summary");
198
237
                        }
199
238
                }
200
239
 
201
 
                if (remarks.Value == "To be added.")
202
 
                        remarks.Value = "";
203
 
                
204
 
                remarks.AddFirst (XElement.Parse (String.Format ("<para id='tool-remark'>If you want to subscribe to this notification, you can use the convenience <see cref='T:{0}+Notifications'/>.<see cref='M:{0}+Notifications.Observe{1}'/> method which offers strongly typed access to the parameters of the notification.</para>", t.Name, mname)));
 
240
                var evengArgsType = DocumentNotificationNestedType (t, pi, body.ToString ());
 
241
 
 
242
                remarks.RemoveAll ();
 
243
                remarks.Add (XElement.Parse ("<para id='tool-remark'>This constant can be used with the <see cref=\"T:MonoTouch.Foundation.NSNotificationCenter\"/> to register a listener for this notification.   This is an NSString instead of a string, because these values can be used as tokens in some native libraries instead of being used purely for their actual string content.    The 'notification' parameter to the callback contains extra information that is specific to the notification type.</para>"));
 
244
                remarks.Add (XElement.Parse (String.Format ("<para id='tool-remark'>If you want to subscribe to this notification, you can use the convenience <see cref='T:{0}+Notifications'/>.<see cref='M:{0}+Notifications.Observe{1}'/> method which offers strongly typed access to the parameters of the notification.</para>", t.Name, name)));
205
245
                remarks.Add (XElement.Parse ("<para>The following example shows how to use the strongly typed Notifications class, to take the guesswork out of the available properties in the notification:</para>"));
206
246
                remarks.Add (XElement.Parse (String.Format ("<example><code lang=\"c#\">\n" +
207
247
                                                            "//\n// Lambda style\n//\n\n// listening\n" +
209
249
                                                            "// To stop listening:\n" +
210
250
                                                            "notification.Dispose ();\n\n" +
211
251
                                                            "//\n// Method style\n//\nNSObject notification;\n" +
212
 
                                                            "void Callback (object sender, {1} args)\n"+
 
252
                                                            "void Callback (object sender, {3} args)\n"+
213
253
                                                            "{{\n    // Access strongly typed args\n{2}\n}}\n\n" +
214
254
                                                            "void Setup ()\n{{\n" +
215
255
                                                            "    notification = {0}.Notifications.Observe{1} (Callback);\n}}\n\n" +
216
256
                                                            "void Teardown ()\n{{\n" +
217
 
                                                            "    notification.Dispose ();\n}}</code></example>", t.Name, mname, body)));
 
257
                                                            "    notification.Dispose ();\n}}</code></example>", t.Name, mname, body, evengArgsType)));
 
258
                remarks.Add (XElement.Parse ("<para>The following example shows how to use the notification with the DefaultCenter API:</para>"));
 
259
                remarks.Add (XElement.Parse (String.Format ("<example><code lang=\"c#\">\n" +
 
260
                                                      "// Lambda style\n" +
 
261
                                                      "NSNotificationCenter.DefaultCenter.AddObserver (\n        {0}.{1}, (notification) => {{Console.WriteLine (\"Received the notification {0}\", notification); }}\n\n\n" +
 
262
                                                      "// Method style\n" +
 
263
                                                      "void Callback (NSNotification notification)\n{{\n" +
 
264
                                                      "    Console.WriteLine (\"Received a notification {0}\", notification);\n}}\n\n" +
 
265
                                                      "void Setup ()\n{{\n" +
 
266
                                                      "    NSNotificationCenter.DefaultCenter.AddObserver ({0}.{1}, Callback);\n}}\n</code></example>", t.Name, name)));
 
267
                
218
268
 
219
269
                // Keep track of the uses, so we can list all of the observers.
220
270
                if (notification_event_args != null){
226
276
                        list.Add (notification_event_args);
227
277
                        event_args_to_notification_uses [notification_event_args] = list;
228
278
                }
229
 
                DocumentNotificationNestedType (t, pi, body.ToString ());
230
279
        }
231
280
 
232
 
        public static void DocumentNotificationNestedType (Type t, PropertyInfo pi, string body)
 
281
        public static string DocumentNotificationNestedType (Type t, PropertyInfo pi, string body)
233
282
        {
234
 
                var class_doc = GetDoc (t, true);
 
283
                string handlerType = null;
 
284
                var class_doc = GetDoc (t, notification: true);
235
285
 
236
286
                if (class_doc == null){
237
287
                        Console.WriteLine ("Error, can not find Notification class for type {0}", t);
238
 
                        return;
 
288
                        Environment.Exit (1);
239
289
                }
240
 
 
241
290
                var class_summary = class_doc.XPathSelectElement ("Type/Docs/summary");
242
291
                var class_remarks = class_doc.XPathSelectElement ("Type/Docs/remarks");
243
292
 
244
 
                class_summary.Value = "Notification posted by the <see cref =\"T:" + t.FullName + "\"/> class.";
245
 
                class_remarks.Value = "";
 
293
                class_summary.RemoveAll ();
 
294
                class_summary.Add (XElement.Parse ("<para>Notification posted by the <see cref =\"T:" + t.FullName + "\"/> class.</para>"));
 
295
                class_remarks.RemoveAll ();
246
296
                class_remarks.Add (XElement.Parse ("<para>This is a static class which contains various helper methods that allow developers to observe events posted " +
247
297
                                                   "in the iOS notification hub (<see cref=\"T:MonoTouch.Foundation.NSNotificationCenter\"/>).</para>"));
248
298
                class_remarks.Add (XElement.Parse ("<para>The methods defined in this class post events invoke the provided method or lambda with a " +
257
307
                        let convertedName = propName.EndsWith ("Notification") ? propName.Substring (0, propLen-("Notification".Length)) : propName
258
308
                        select new Tuple<string,string> (convertedName, ((FieldAttribute) fieldAttrs [0]).SymbolName) ;
259
309
 
 
310
                // So the code below actually only executes once.
 
311
                if (notifications.Count() > 1){
 
312
                        Console.WriteLine ("WHOA!   DocumentNotificationNestedType got more than 1 notification");
 
313
                }
 
314
                
260
315
                foreach (var notification in notifications){
261
316
                        var mname = "Observe" + notification.Item1;
262
317
                        var method = class_doc.XPathSelectElement ("Type/Members/Member[@MemberName='" + mname + "']");
263
318
 
264
319
                        var handler = method.XPathSelectElement ("Docs/param");
 
320
 
 
321
                        handlerType = (string) method.XPathSelectElement ("Parameters/Parameter").Attribute ("Type");
 
322
                        if (handlerType.StartsWith ("System.EventHandler<"))
 
323
                                handlerType = handlerType.Substring (20, handlerType.Length-21);
 
324
 
 
325
                        // Turn System.EventHandler<Foo> into EventHandler<Foo>, looks prettier
 
326
                        if (handlerType.StartsWith ("System."))
 
327
                                handlerType = handlerType.Substring (7);
265
328
                        var summary = method.XPathSelectElement ("Docs/summary");
266
329
                        var remarks = method.XPathSelectElement ("Docs/remarks");
267
330
                        var returns = method.XPathSelectElement ("Docs/returns");
269
332
                                Console.WriteLine ("Looking for {0}, and this is the class\n{1}", notification.Item1, class_doc);
270
333
                        handler.Value = "Method to invoke when the notification is posted.";
271
334
                        summary.Value = "Registers a method to be notified when the " + notification.Item2 + " notification is posted.";
272
 
                        returns.Value = "The returned NSObject represents the registered notification.   Either call Dispose on the object to stop receiving notifications, or pass it to <see cref=\"M:MonoTouch.Foundation.NSNotification.RemoveObserver\"/>";
273
 
                        remarks.Value = "";
 
335
                        returns.RemoveAll ();
 
336
                        returns.Add (XElement.Parse ("<para>The returned NSObject represents the registered notification.   Either call Dispose on the object to stop receiving notifications, or pass it to <see cref=\"M:MonoTouch.Foundation.NSNotificationCenter.RemoveObserver\"/></para>"));
 
337
                        remarks.RemoveAll ();
274
338
                        remarks.Add (XElement.Parse ("<para>The following example shows how you can use this method in your code</para>"));
275
339
 
276
340
                        remarks.Add (XElement.Parse (String.Format ("<example><code lang=\"c#\">\n" +
277
341
                                                                    "//\n// Lambda style\n//\n\n// listening\n" +
278
 
                                                                    "notification = {0}.Notifications.Observe{1} ((sender, args) => {{\n    /* Access strongly typed args */\n{2}\n}});\n\n" +
 
342
                                                                    "notification = {0}.Notifications.{1} ((sender, args) => {{\n    /* Access strongly typed args */\n{2}\n}});\n\n" +
279
343
                                                                    "// To stop listening:\n" +
280
344
                                                                    "notification.Dispose ();\n\n" +
281
345
                                                                    "//\n//Method style\n//\nNSObject notification;\n" +
282
 
                                                                    "void Callback (object sender, {1} args)\n"+
 
346
                                                                    "void Callback (object sender, {3} args)\n"+
283
347
                                                                    "{{\n    // Access strongly typed args\n{2}\n}}\n\n" +
284
348
                                                                    "void Setup ()\n{{\n" +
285
 
                                                                    "    notification = {0}.Notifications.Observe{1} (Callback);\n}}\n\n" +
 
349
                                                                    "    notification = {0}.Notifications.{1} (Callback);\n}}\n\n" +
286
350
                                                                    "void Teardown ()\n{{\n" +
287
 
                                                                    "    notification.Dispose ();\n}}</code></example>", t.Name, mname, body)));
 
351
                                                                    "    notification.Dispose ();\n}}</code></example>", t.Name, mname, body, handlerType)));
288
352
                
289
353
                }
290
354
                Save (GetMdocPath (t, true), class_doc);
291
 
                
 
355
                return handlerType;
292
356
        }
293
357
 
294
358
        public static void PopulateEvents (XDocument xmldoc, BaseTypeAttribute bta, Type t)
316
380
                        }
317
381
                }
318
382
        }
 
383
 
 
384
        //
 
385
        // This prepares a node that contains text, like this:
 
386
        // <foo>To be added.</foo>
 
387
        //
 
388
        // to wrap the text in a para.
 
389
        // <foo><para>To be added.</para></foo>
 
390
        //
 
391
        static void PrepareNakedNode (XElement element, bool addStub = true)
 
392
        {
 
393
                if (element.HasElements)
 
394
                        return;
 
395
                var val = element.Value;
 
396
                if (addStub && val == "To be added.")
 
397
                        val = "(More documentation for this node is coming)";
 
398
                
 
399
                element.Value = "";
 
400
                element.Add (XElement.Parse ("<para>" + val + "</para>"));
 
401
        }
 
402
        
 
403
        
 
404
        public static void AnnotateNullAllowedPropertyValue (Type t, XDocument xdoc, PropertyInfo pi)
 
405
        {
 
406
                var field = GetXmlNodeForMemberName (t, xdoc, pi.Name);
 
407
                if (field == null)
 
408
                        return;
 
409
                var value = field.XPathSelectElement ("Docs/value");
 
410
                var toolgen_null_annotations = value.XPathSelectElement ("para[@tool='nullallowed']");
 
411
                if (toolgen_null_annotations == null)
 
412
                        PrepareNakedNode (value);
 
413
                else
 
414
                        toolgen_null_annotations.Remove ();
 
415
 
 
416
                value.Add (XElement.Parse ("<para tool='nullallowed'>This value can be <see langword=\"null\"/>.</para>"));
 
417
        }
319
418
        
320
419
        public static void ProcessNSO (Type t, BaseTypeAttribute bta)
321
420
        {
322
421
                var xmldoc = GetDoc (t);
323
 
                if (xmldoc == null)
 
422
                if (xmldoc == null){
 
423
                        Console.WriteLine ("Can not find docs for {0}", t);
324
424
                        return;
325
 
                
 
425
                }
 
426
 
326
427
                foreach (var pi in t.GatherProperties ()){
327
428
                        object [] attrs;
328
429
                        var kbd = false;
 
430
                        if (pi.GetCustomAttributes (typeof (InternalAttribute), true).Length > 0)
 
431
                                continue;
 
432
 
329
433
                        if (pi.GetCustomAttributes (typeof (FieldAttribute), true).Length > 0){
330
 
                                ProcessField (t, xmldoc, pi);
 
434
                                bool is_notification = pi.GetCustomAttributes (typeof (NotificationAttribute), true).Length != 0;
 
435
                                ProcessField (t, xmldoc, pi, is_notification);
331
436
 
332
 
                                if ((attrs = pi.GetCustomAttributes (typeof (NotificationAttribute), true)).Length > 0)
 
437
                                if (is_notification)
333
438
                                        ProcessNotification (t, xmldoc, pi);
334
439
                                continue;
335
440
                        }
336
 
                        
337
 
                }
338
 
 
 
441
                        if (pi.GetCustomAttributes (typeof (NullAllowedAttribute), true).Length > 0){
 
442
                                AnnotateNullAllowedPropertyValue (t, xmldoc, pi);
 
443
 
 
444
                                //
 
445
                                // Propagate the [NullAllowed] from the WeakXXX to XXX
 
446
                                //
 
447
                                if (pi.Name.StartsWith ("Weak")){
 
448
                                        var npi = t.GetProperty (pi.Name.Substring (4));
 
449
 
 
450
                                        // Validate that the other property is actually a wrapper around this one.
 
451
                                        if (npi != null && npi.GetCustomAttributes (typeof (WrapAttribute), true).Length > 0){
 
452
                                                if (npi != null)
 
453
                                                        AnnotateNullAllowedPropertyValue (t, xmldoc, npi);
 
454
                                        } else
 
455
                                                Console.WriteLine ("Did not find matching {0}", pi.Name);
 
456
                                        
 
457
                                }
 
458
                        }
 
459
                        if (pi.GetCustomAttributes (typeof (ThreadSafeAttribute), true).Length > 0){
 
460
                                var field = GetXmlNodeForMemberName (t, xmldoc, pi.Name);
 
461
                                if (field == null)
 
462
                                        return;
 
463
                                var remarks = field.XPathSelectElement ("Docs/remarks");
 
464
                                if (remarks != null)
 
465
                                        AddThreadRemark (remarks, "This");
 
466
                        }
 
467
                }
 
468
                foreach (var mi in t.GatherMethods ()){
 
469
                        //
 
470
                        // Since it is a pain to go from a MethodInfo into an ECMA XML signature name
 
471
                        // we will lookup the method by the [Export] attribute
 
472
                        //
 
473
 
 
474
                        if (mi.GetCustomAttributes (typeof (InternalAttribute), true).Length > 0)
 
475
                                continue;
 
476
                        
 
477
                        var attrs = mi.GetCustomAttributes (typeof (ExportAttribute), true);
 
478
                        if (attrs.Length == 0)
 
479
                                continue;
 
480
                        var ea = attrs [0] as ExportAttribute;
 
481
                        var node = GetXmlNodeFromExport (t, xmldoc, ea.Selector);
 
482
                        if (node == null){
 
483
                                Console.WriteLine ("Did not find the selector {0} on type {1}", ea.Selector, t);
 
484
                                continue;
 
485
                        }
 
486
                        
 
487
                        if (mi.GetCustomAttributes (typeof (ThreadSafeAttribute), true).Length > 0){
 
488
                                var remarks = node.XPathSelectElement ("Docs/remarks");
 
489
                                AddThreadRemark (remarks, "This");
 
490
                        }
 
491
                        foreach (var parameter in mi.GetParameters ()){
 
492
                                if (parameter.GetCustomAttributes (typeof (NullAllowedAttribute), true).Length > 0){
 
493
                                        var par = node.XPathSelectElement ("Docs/param[@name='" + parameter.Name + "']");
 
494
                                        if (par == null){
 
495
                                                Console.WriteLine ("Did not find parameter {0} in {1}.{2}\n{3}", parameter.Name, t, mi, node);
 
496
                                                continue;
 
497
                                        }
 
498
                                        var toolgen_null_annotations = par.XPathSelectElement ("para[@tool='nullallowed']");
 
499
                                        if (toolgen_null_annotations == null)
 
500
                                                PrepareNakedNode (par, addStub: false);
 
501
                                        else
 
502
                                                toolgen_null_annotations.Remove ();
 
503
                                        par.Add (XElement.Parse ("<para tool='nullallowed'>This parameter can be <see langword=\"null\"/>.</para>"));
 
504
                                }
 
505
                        }
 
506
                }
 
507
                
339
508
                if (bta != null && bta.Events != null){
340
509
                        PopulateEvents (xmldoc, bta, t);
341
510
                }
342
511
        }
343
 
                        
 
512
 
 
513
        static void AddThreadRemark (XElement node, string msg)
 
514
        {
 
515
                var threadNode =  node.XPathSelectElement ("para[@tool='threads']");
 
516
                if (threadNode == null)
 
517
                        PrepareNakedNode (node);
 
518
                else
 
519
                        threadNode.Remove ();
 
520
                node.Add (XElement.Parse ("<para tool='threads'>" + msg + " can be used from a background thread.</para>"));
 
521
        }
 
522
        
 
523
        public static void AnnotateThreadSafeType (Type t)
 
524
        {
 
525
                var xmldoc = GetDoc (t);
 
526
                if (xmldoc == null){
 
527
                        Console.WriteLine ("Can not find docs for {0}", t);
 
528
                        return;
 
529
                }
 
530
                var typeRemarks = xmldoc.XPathSelectElement ("Type/Docs/remarks");
 
531
                AddThreadRemark (typeRemarks, "The members of this class");
 
532
 
 
533
                var memberRemarks = xmldoc.XPathSelectElements ("Type/Members/Member/Docs/remarks");
 
534
                foreach (var mr in memberRemarks)
 
535
                        AddThreadRemark (mr, "This");
 
536
        }
 
537
        
344
538
        public static int Main (string [] args)
345
539
        {
346
540
                string dir = null;
381
575
                assembly_dir = Path.Combine (dir, "en");
382
576
                assembly = Assembly.LoadFrom (lib);
383
577
 
384
 
                docGenerator = new AppleDocMerger (new AppleDocMerger.Options {
385
 
                        DocBase = Path.Combine (docBase, "Contents/Resources/Documents/documentation"),
386
 
                        DebugDocs = debugDoc,
387
 
                        MonodocArchive = new MDocDirectoryArchive (assembly_dir),
388
 
                        Assembly = Mono.Cecil.AssemblyDefinition.ReadAssembly (lib),
389
 
                        BaseAssemblyNamespace = ns,
390
 
                        ImportSamples = false
391
 
                });
 
578
                if (mergeAppledocs){
 
579
                        docGenerator = new AppleDocMerger (new AppleDocMerger.Options {
 
580
                                DocBase = Path.Combine (docBase, "Contents/Resources/Documents/documentation"),
 
581
                                DebugDocs = debugDoc,
 
582
                                MonodocArchive = new MDocDirectoryArchive (assembly_dir),
 
583
                                        Assembly = Mono.Cecil.AssemblyDefinition.ReadAssembly (lib),
 
584
                                        BaseAssemblyNamespace = ns,
 
585
                                        ImportSamples = false
 
586
                                        });
 
587
                }
392
588
 
393
589
                foreach (Type t in assembly.GetTypes ()){
394
 
                        if (debugDoc){
 
590
                        if (t.GetCustomAttributes (typeof (ThreadSafeAttribute), true).Length > 0)
 
591
                                AnnotateThreadSafeType (t);
 
592
                        
 
593
                        if (debugDoc && mergeAppledocs){
395
594
                                string str = docGenerator.GetAppleDocFor (ToCecilType (t));
396
595
                                if (str == null){
397
596
                                        Console.WriteLine ("Could not find docs for {0}", t);
399
598
                                
400
599
                                continue;
401
600
                        }
402
 
                        
 
601
 
403
602
                        if (debug != null && t.FullName != debug)
404
603
                                continue;
405
604