~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric

« back to all changes in this revision

Viewing changes to src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/mcs/doc.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-06-27 17:03:13 UTC
  • mto: (1.8.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: james.westby@ubuntu.com-20110627170313-6cvz3s19x6e9hqe9
ImportĀ upstreamĀ versionĀ 2.5.92+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// doc.cs: Support for XML documentation comment.
 
3
//
 
4
// Authors:
 
5
//      Atsushi Enomoto <atsushi@ximian.com>
 
6
//  Marek Safar (marek.safar@gmail.com>
 
7
//
 
8
// Dual licensed under the terms of the MIT X11 or GNU GPL
 
9
//
 
10
// Copyright 2004 Novell, Inc.
 
11
//
 
12
//
 
13
 
 
14
using System;
 
15
using System.Collections.Generic;
 
16
using System.IO;
 
17
using System.Text;
 
18
using System.Xml;
 
19
using System.Linq;
 
20
 
 
21
namespace Mono.CSharp
 
22
{
 
23
        //
 
24
        // Implements XML documentation generation.
 
25
        //
 
26
        class DocumentationBuilder
 
27
        {
 
28
                //
 
29
                // Used to create element which helps well-formedness checking.
 
30
                //
 
31
                readonly XmlDocument XmlDocumentation;
 
32
 
 
33
                readonly ModuleContainer module;
 
34
 
 
35
                //
 
36
                // The output for XML documentation.
 
37
                //
 
38
                XmlWriter XmlCommentOutput;
 
39
 
 
40
                static readonly string line_head = Environment.NewLine + "            ";
 
41
 
 
42
                //
 
43
                // Stores XmlDocuments that are included in XML documentation.
 
44
                // Keys are included filenames, values are XmlDocuments.
 
45
                //
 
46
                Dictionary<string, XmlDocument> StoredDocuments = new Dictionary<string, XmlDocument> ();
 
47
 
 
48
                public DocumentationBuilder (ModuleContainer module)
 
49
                {
 
50
                        this.module = module;
 
51
                        XmlDocumentation = new XmlDocument ();
 
52
                        XmlDocumentation.PreserveWhitespace = false;
 
53
                }
 
54
 
 
55
                Report Report {
 
56
                        get {
 
57
                                return module.Compiler.Report;
 
58
                        }
 
59
                }
 
60
 
 
61
                public MemberName ParsedName {
 
62
                        get; set;
 
63
                }
 
64
 
 
65
                public List<DocumentationParameter> ParsedParameters {
 
66
                        get; set;
 
67
                }
 
68
 
 
69
                public TypeExpression ParsedBuiltinType {
 
70
                        get; set;
 
71
                }
 
72
 
 
73
                public Operator.OpType? ParsedOperator {
 
74
                        get; set;
 
75
                }
 
76
 
 
77
                XmlNode GetDocCommentNode (MemberCore mc, string name)
 
78
                {
 
79
                        // FIXME: It could be even optimizable as not
 
80
                        // to use XmlDocument. But anyways the nodes
 
81
                        // are not kept in memory.
 
82
                        XmlDocument doc = XmlDocumentation;
 
83
                        try {
 
84
                                XmlElement el = doc.CreateElement ("member");
 
85
                                el.SetAttribute ("name", name);
 
86
                                string normalized = mc.DocComment;
 
87
                                el.InnerXml = normalized;
 
88
                                // csc keeps lines as written in the sources
 
89
                                // and inserts formatting indentation (which 
 
90
                                // is different from XmlTextWriter.Formatting
 
91
                                // one), but when a start tag contains an 
 
92
                                // endline, it joins the next line. We don't
 
93
                                // have to follow such a hacky behavior.
 
94
                                string [] split =
 
95
                                        normalized.Split ('\n');
 
96
                                int j = 0;
 
97
                                for (int i = 0; i < split.Length; i++) {
 
98
                                        string s = split [i].TrimEnd ();
 
99
                                        if (s.Length > 0)
 
100
                                                split [j++] = s;
 
101
                                }
 
102
                                el.InnerXml = line_head + String.Join (
 
103
                                        line_head, split, 0, j);
 
104
                                return el;
 
105
                        } catch (Exception ex) {
 
106
                                Report.Warning (1570, 1, mc.Location, "XML documentation comment on `{0}' is not well-formed XML markup ({1})",
 
107
                                        mc.GetSignatureForError (), ex.Message);
 
108
 
 
109
                                return doc.CreateComment (String.Format ("FIXME: Invalid documentation markup was found for member {0}", name));
 
110
                        }
 
111
                }
 
112
 
 
113
                //
 
114
                // Generates xml doc comments (if any), and if required,
 
115
                // handle warning report.
 
116
                //
 
117
                internal void GenerateDocumentationForMember (MemberCore mc)
 
118
                {
 
119
                        string name = mc.DocCommentHeader + mc.GetSignatureForDocumentation ();
 
120
 
 
121
                        XmlNode n = GetDocCommentNode (mc, name);
 
122
 
 
123
                        XmlElement el = n as XmlElement;
 
124
                        if (el != null) {
 
125
                                var pm = mc as IParametersMember;
 
126
                                if (pm != null) {
 
127
                                        CheckParametersComments (mc, pm, el);
 
128
                                }
 
129
 
 
130
                                // FIXME: it could be done with XmlReader
 
131
                                XmlNodeList nl = n.SelectNodes (".//include");
 
132
                                if (nl.Count > 0) {
 
133
                                        // It could result in current node removal, so prepare another list to iterate.
 
134
                                        var al = new List<XmlNode> (nl.Count);
 
135
                                        foreach (XmlNode inc in nl)
 
136
                                                al.Add (inc);
 
137
                                        foreach (XmlElement inc in al)
 
138
                                                if (!HandleInclude (mc, inc))
 
139
                                                        inc.ParentNode.RemoveChild (inc);
 
140
                                }
 
141
 
 
142
                                // FIXME: it could be done with XmlReader
 
143
                                DeclSpace ds_target = mc as DeclSpace;
 
144
                                if (ds_target == null)
 
145
                                        ds_target = mc.Parent;
 
146
 
 
147
                                foreach (XmlElement see in n.SelectNodes (".//see"))
 
148
                                        HandleSee (mc, ds_target, see);
 
149
                                foreach (XmlElement seealso in n.SelectNodes (".//seealso"))
 
150
                                        HandleSeeAlso (mc, ds_target, seealso);
 
151
                                foreach (XmlElement see in n.SelectNodes (".//exception"))
 
152
                                        HandleException (mc, ds_target, see);
 
153
                        }
 
154
 
 
155
                        n.WriteTo (XmlCommentOutput);
 
156
                }
 
157
 
 
158
                //
 
159
                // Processes "include" element. Check included file and
 
160
                // embed the document content inside this documentation node.
 
161
                //
 
162
                bool HandleInclude (MemberCore mc, XmlElement el)
 
163
                {
 
164
                        bool keep_include_node = false;
 
165
                        string file = el.GetAttribute ("file");
 
166
                        string path = el.GetAttribute ("path");
 
167
                        if (file == "") {
 
168
                                Report.Warning (1590, 1, mc.Location, "Invalid XML `include' element. Missing `file' attribute");
 
169
                                el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el);
 
170
                                keep_include_node = true;
 
171
                        }
 
172
                        else if (path.Length == 0) {
 
173
                                Report.Warning (1590, 1, mc.Location, "Invalid XML `include' element. Missing `path' attribute");
 
174
                                el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el);
 
175
                                keep_include_node = true;
 
176
                        }
 
177
                        else {
 
178
                                XmlDocument doc;
 
179
                                if (!StoredDocuments.TryGetValue (file, out doc)) {
 
180
                                        try {
 
181
                                                doc = new XmlDocument ();
 
182
                                                doc.Load (file);
 
183
                                                StoredDocuments.Add (file, doc);
 
184
                                        } catch (Exception) {
 
185
                                                el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (String.Format (" Badly formed XML in at comment file `{0}': cannot be included ", file)), el);
 
186
                                                Report.Warning (1592, 1, mc.Location, "Badly formed XML in included comments file -- `{0}'", file);
 
187
                                        }
 
188
                                }
 
189
                                if (doc != null) {
 
190
                                        try {
 
191
                                                XmlNodeList nl = doc.SelectNodes (path);
 
192
                                                if (nl.Count == 0) {
 
193
                                                        el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" No matching elements were found for the include tag embedded here. "), el);
 
194
                                        
 
195
                                                        keep_include_node = true;
 
196
                                                }
 
197
                                                foreach (XmlNode n in nl)
 
198
                                                        el.ParentNode.InsertBefore (el.OwnerDocument.ImportNode (n, true), el);
 
199
                                        } catch (Exception ex) {
 
200
                                                el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Failed to insert some or all of included XML "), el);
 
201
                                                Report.Warning (1589, 1, mc.Location, "Unable to include XML fragment `{0}' of file `{1}' ({2})", path, file, ex.Message);
 
202
                                        }
 
203
                                }
 
204
                        }
 
205
                        return keep_include_node;
 
206
                }
 
207
 
 
208
                //
 
209
                // Handles <see> elements.
 
210
                //
 
211
                void HandleSee (MemberCore mc, DeclSpace ds, XmlElement see)
 
212
                {
 
213
                        HandleXrefCommon (mc, ds, see);
 
214
                }
 
215
 
 
216
                //
 
217
                // Handles <seealso> elements.
 
218
                //
 
219
                void HandleSeeAlso (MemberCore mc, DeclSpace ds, XmlElement seealso)
 
220
                {
 
221
                        HandleXrefCommon (mc, ds, seealso);
 
222
                }
 
223
 
 
224
                //
 
225
                // Handles <exception> elements.
 
226
                //
 
227
                void HandleException (MemberCore mc, DeclSpace ds, XmlElement seealso)
 
228
                {
 
229
                        HandleXrefCommon (mc, ds, seealso);
 
230
                }
 
231
 
 
232
                FullNamedExpression ResolveMemberName (IMemberContext context, MemberName mn)
 
233
                {
 
234
                        if (mn.Left == null)
 
235
                                return context.LookupNamespaceOrType (mn.Name, mn.Arity, LookupMode.Probing, Location.Null);
 
236
 
 
237
                        var left = ResolveMemberName (context, mn.Left);
 
238
                        var ns = left as Namespace;
 
239
                        if (ns != null)
 
240
                                return ns.LookupTypeOrNamespace (context, mn.Name, mn.Arity, LookupMode.Probing, Location.Null);
 
241
 
 
242
                        TypeExpr texpr = left as TypeExpr;
 
243
                        if (texpr != null) {
 
244
                                var found = MemberCache.FindNestedType (texpr.Type, ParsedName.Name, ParsedName.Arity);
 
245
                                if (found != null)
 
246
                                        return new TypeExpression (found, Location.Null);
 
247
 
 
248
                                return null;
 
249
                        }
 
250
 
 
251
                        return left;
 
252
                }
 
253
 
 
254
                //
 
255
                // Processes "see" or "seealso" elements from cref attribute.
 
256
                //
 
257
                void HandleXrefCommon (MemberCore mc, DeclSpace ds, XmlElement xref)
 
258
                {
 
259
                        string cref = xref.GetAttribute ("cref");
 
260
                        // when, XmlReader, "if (cref == null)"
 
261
                        if (!xref.HasAttribute ("cref"))
 
262
                                return;
 
263
 
 
264
                        // Nothing to be resolved the reference is marked explicitly
 
265
                        if (cref.Length > 2 && cref [1] == ':')
 
266
                                return;
 
267
 
 
268
                        // Additional symbols for < and > are allowed for easier XML typing
 
269
                        cref = cref.Replace ('{', '<').Replace ('}', '>');
 
270
 
 
271
                        var encoding = module.Compiler.Settings.Encoding;
 
272
                        var s = new MemoryStream (encoding.GetBytes (cref));
 
273
                        SeekableStreamReader seekable = new SeekableStreamReader (s, encoding);
 
274
 
 
275
                        var source_file = new CompilationSourceFile ("{documentation}", "", 1);
 
276
                        var doc_module = new ModuleContainer (module.Compiler);
 
277
                        doc_module.DocumentationBuilder = this;
 
278
                        source_file.NamespaceContainer = new NamespaceContainer (null, doc_module, null, source_file);
 
279
 
 
280
                        Report parse_report = new Report (new NullReportPrinter ());
 
281
                        var parser = new CSharpParser (seekable, source_file, parse_report);
 
282
                        ParsedParameters = null;
 
283
                        ParsedName = null;
 
284
                        ParsedBuiltinType = null;
 
285
                        ParsedOperator = null;
 
286
                        parser.Lexer.putback_char = Tokenizer.DocumentationXref;
 
287
                        parser.Lexer.parsing_generic_declaration_doc = true;
 
288
                        parser.parse ();
 
289
                        if (parse_report.Errors > 0) {
 
290
                                Report.Warning (1584, 1, mc.Location, "XML comment on `{0}' has syntactically incorrect cref attribute `{1}'",
 
291
                                        mc.GetSignatureForError (), cref);
 
292
 
 
293
                                xref.SetAttribute ("cref", "!:" + cref);
 
294
                                return;
 
295
                        }
 
296
 
 
297
                        MemberSpec member;
 
298
                        string prefix = null;
 
299
                        FullNamedExpression fne = null;
 
300
 
 
301
                        //
 
302
                        // Try built-in type first because we are using ParsedName as identifier of
 
303
                        // member names on built-in types
 
304
                        //
 
305
                        if (ParsedBuiltinType != null && (ParsedParameters == null || ParsedName != null)) {
 
306
                                member = ParsedBuiltinType.Type;
 
307
                        } else {
 
308
                                member = null;
 
309
                        }
 
310
 
 
311
                        if (ParsedName != null || ParsedOperator.HasValue) {
 
312
                                TypeSpec type = null;
 
313
                                string member_name = null;
 
314
 
 
315
                                if (member == null) {
 
316
                                        if (ParsedOperator.HasValue) {
 
317
                                                type = mc.CurrentType;
 
318
                                        } else if (ParsedName.Left != null) {
 
319
                                                fne = ResolveMemberName (mc, ParsedName.Left);
 
320
                                                if (fne != null) {
 
321
                                                        var ns = fne as Namespace;
 
322
                                                        if (ns != null) {
 
323
                                                                fne = ns.LookupTypeOrNamespace (mc, ParsedName.Name, ParsedName.Arity, LookupMode.Probing, Location.Null);
 
324
                                                                if (fne != null) {
 
325
                                                                        member = fne.Type;
 
326
                                                                }
 
327
                                                        } else {
 
328
                                                                type = fne.Type;
 
329
                                                        }
 
330
                                                }
 
331
                                        } else {
 
332
                                                fne = ResolveMemberName (mc, ParsedName);
 
333
                                                if (fne == null) {
 
334
                                                        type = mc.CurrentType;
 
335
                                                } else if (ParsedParameters == null) {
 
336
                                                        member = fne.Type;
 
337
                                                } else if (fne.Type.MemberDefinition == mc.CurrentType.MemberDefinition) {
 
338
                                                        member_name = Constructor.ConstructorName;
 
339
                                                        type = fne.Type;
 
340
                                                }
 
341
                                        }
 
342
                                } else {
 
343
                                        type = (TypeSpec) member;
 
344
                                        member = null;
 
345
                                }
 
346
 
 
347
                                if (ParsedParameters != null) {
 
348
                                        var old_printer = mc.Module.Compiler.Report.SetPrinter (new NullReportPrinter ());
 
349
                                        foreach (var pp in ParsedParameters) {
 
350
                                                pp.Resolve (mc);
 
351
                                        }
 
352
                                        mc.Module.Compiler.Report.SetPrinter (old_printer);
 
353
                                }
 
354
 
 
355
                                if (type != null) {
 
356
                                        if (member_name == null)
 
357
                                                member_name = ParsedOperator.HasValue ?
 
358
                                                        Operator.GetMetadataName (ParsedOperator.Value) : ParsedName.Name;
 
359
 
 
360
                                        int parsed_param_count;
 
361
                                        if (ParsedOperator == Operator.OpType.Explicit || ParsedOperator == Operator.OpType.Implicit) {
 
362
                                                parsed_param_count = ParsedParameters.Count - 1;
 
363
                                        } else if (ParsedParameters != null) {
 
364
                                                parsed_param_count = ParsedParameters.Count;
 
365
                                        } else {
 
366
                                                parsed_param_count = 0;
 
367
                                        }
 
368
 
 
369
                                        int parameters_match = -1;
 
370
                                        do {
 
371
                                                var members = MemberCache.FindMembers (type, member_name, true);
 
372
                                                if (members != null) {
 
373
                                                        foreach (var m in members) {
 
374
                                                                if (ParsedName != null && m.Arity != ParsedName.Arity)
 
375
                                                                        continue;
 
376
 
 
377
                                                                if (ParsedParameters != null) {
 
378
                                                                        IParametersMember pm = m as IParametersMember;
 
379
                                                                        if (pm == null)
 
380
                                                                                continue;
 
381
 
 
382
                                                                        if (m.Kind == MemberKind.Operator && !ParsedOperator.HasValue)
 
383
                                                                                continue;
 
384
 
 
385
                                                                        int i;
 
386
                                                                        for (i = 0; i < parsed_param_count; ++i) {
 
387
                                                                                var pparam = ParsedParameters[i];
 
388
 
 
389
                                                                                if (i >= pm.Parameters.Count || pparam == null ||
 
390
                                                                                        pparam.TypeSpec != pm.Parameters.Types[i] ||
 
391
                                                                                        (pparam.Modifier & Parameter.Modifier.SignatureMask) != (pm.Parameters.FixedParameters[i].ModFlags & Parameter.Modifier.SignatureMask)) {
 
392
 
 
393
                                                                                        if (i > parameters_match) {
 
394
                                                                                                parameters_match = i;
 
395
                                                                                        }
 
396
 
 
397
                                                                                        i = -1;
 
398
                                                                                        break;
 
399
                                                                                }
 
400
                                                                        }
 
401
 
 
402
                                                                        if (i < 0)
 
403
                                                                                continue;
 
404
 
 
405
                                                                        if (ParsedOperator == Operator.OpType.Explicit || ParsedOperator == Operator.OpType.Implicit) {
 
406
                                                                                if (pm.MemberType != ParsedParameters[parsed_param_count].TypeSpec) {
 
407
                                                                                        parameters_match = parsed_param_count + 1;
 
408
                                                                                        continue;
 
409
                                                                                }
 
410
                                                                        } else {
 
411
                                                                                if (parsed_param_count != pm.Parameters.Count)
 
412
                                                                                        continue;
 
413
                                                                        }
 
414
                                                                }
 
415
 
 
416
                                                                if (member != null) {
 
417
                                                                        Report.Warning (419, 3, mc.Location,
 
418
                                                                                "Ambiguous reference in cref attribute `{0}'. Assuming `{1}' but other overloads including `{2}' have also matched",
 
419
                                                                                cref, member.GetSignatureForError (), m.GetSignatureForError ());
 
420
 
 
421
                                                                        break;
 
422
                                                                }
 
423
 
 
424
                                                                member = m;
 
425
                                                        }
 
426
                                                }
 
427
 
 
428
                                                // Continue with parent type for nested types
 
429
                                                if (member == null) {
 
430
                                                        type = type.DeclaringType;
 
431
                                                } else {
 
432
                                                        type = null;
 
433
                                                }
 
434
                                        } while (type != null);
 
435
 
 
436
                                        if (member == null && parameters_match >= 0) {
 
437
                                                for (int i = parameters_match; i < parsed_param_count; ++i) {
 
438
                                                        Report.Warning (1580, 1, mc.Location, "Invalid type for parameter `{0}' in XML comment cref attribute `{1}'",
 
439
                                                                        (i + 1).ToString (), cref);
 
440
                                                }
 
441
 
 
442
                                                if (parameters_match == parsed_param_count + 1) {
 
443
                                                        Report.Warning (1581, 1, mc.Location, "Invalid return type in XML comment cref attribute `{0}'", cref);
 
444
                                                }
 
445
                                        }
 
446
                                }
 
447
                        }
 
448
 
 
449
                        if (member == null) {
 
450
                                Report.Warning (1574, 1, mc.Location, "XML comment on `{0}' has cref attribute `{1}' that could not be resolved",
 
451
                                        mc.GetSignatureForError (), cref);
 
452
                                cref = "!:" + cref;
 
453
                        } else if (member == InternalType.Namespace) {
 
454
                                cref = "N:" + fne.GetSignatureForError ();
 
455
                        } else {
 
456
                                prefix = GetMemberDocHead (member);
 
457
                                cref = prefix + member.GetSignatureForDocumentation ();
 
458
                        }
 
459
 
 
460
                        xref.SetAttribute ("cref", cref);
 
461
                }
 
462
 
 
463
                //
 
464
                // Get a prefix from member type for XML documentation (used
 
465
                // to formalize cref target name).
 
466
                //
 
467
                static string GetMemberDocHead (MemberSpec type)
 
468
                {
 
469
                        if (type is FieldSpec)
 
470
                                return "F:";
 
471
                        if (type is MethodSpec)
 
472
                                return "M:";
 
473
                        if (type is EventSpec)
 
474
                                return "E:";
 
475
                        if (type is PropertySpec)
 
476
                                return "P:";
 
477
                        if (type is TypeSpec)
 
478
                                return "T:";
 
479
 
 
480
                        throw new NotImplementedException (type.GetType ().ToString ());
 
481
                }
 
482
 
 
483
                //
 
484
                // Raised (and passed an XmlElement that contains the comment)
 
485
                // when GenerateDocComment is writing documentation expectedly.
 
486
                //
 
487
                // FIXME: with a few effort, it could be done with XmlReader,
 
488
                // that means removal of DOM use.
 
489
                //
 
490
                void CheckParametersComments (MemberCore member, IParametersMember paramMember, XmlElement el)
 
491
                {
 
492
                        HashSet<string> found_tags = null;
 
493
                        foreach (XmlElement pelem in el.SelectNodes ("param")) {
 
494
                                string xname = pelem.GetAttribute ("name");
 
495
                                if (xname.Length == 0)
 
496
                                        continue; // really? but MS looks doing so
 
497
 
 
498
                                if (found_tags == null) {
 
499
                                        found_tags = new HashSet<string> ();
 
500
                                }
 
501
 
 
502
                                if (xname != "" && paramMember.Parameters.GetParameterIndexByName (xname) < 0) {
 
503
                                        Report.Warning (1572, 2, member.Location,
 
504
                                                "XML comment on `{0}' has a param tag for `{1}', but there is no parameter by that name",
 
505
                                                member.GetSignatureForError (), xname);
 
506
                                        continue;
 
507
                                }
 
508
 
 
509
                                if (found_tags.Contains (xname)) {
 
510
                                        Report.Warning (1571, 2, member.Location,
 
511
                                                "XML comment on `{0}' has a duplicate param tag for `{1}'",
 
512
                                                member.GetSignatureForError (), xname);
 
513
                                        continue;
 
514
                                }
 
515
 
 
516
                                found_tags.Add (xname);
 
517
                        }
 
518
 
 
519
                        if (found_tags != null) {
 
520
                                foreach (Parameter p in paramMember.Parameters.FixedParameters) {
 
521
                                        if (!found_tags.Contains (p.Name) && !(p is ArglistParameter))
 
522
                                                Report.Warning (1573, 4, member.Location,
 
523
                                                        "Parameter `{0}' has no matching param tag in the XML comment for `{1}'",
 
524
                                                        p.Name, member.GetSignatureForError ());
 
525
                                }
 
526
                        }
 
527
                }
 
528
 
 
529
                //
 
530
                // Outputs XML documentation comment from tokenized comments.
 
531
                //
 
532
                public bool OutputDocComment (string asmfilename, string xmlFileName)
 
533
                {
 
534
                        XmlTextWriter w = null;
 
535
                        try {
 
536
                                w = new XmlTextWriter (xmlFileName, null);
 
537
                                w.Indentation = 4;
 
538
                                w.Formatting = Formatting.Indented;
 
539
                                w.WriteStartDocument ();
 
540
                                w.WriteStartElement ("doc");
 
541
                                w.WriteStartElement ("assembly");
 
542
                                w.WriteStartElement ("name");
 
543
                                w.WriteString (Path.GetFileNameWithoutExtension (asmfilename));
 
544
                                w.WriteEndElement (); // name
 
545
                                w.WriteEndElement (); // assembly
 
546
                                w.WriteStartElement ("members");
 
547
                                XmlCommentOutput = w;
 
548
                                module.GenerateDocComment (this);
 
549
                                w.WriteFullEndElement (); // members
 
550
                                w.WriteEndElement ();
 
551
                                w.WriteWhitespace (Environment.NewLine);
 
552
                                w.WriteEndDocument ();
 
553
                                return true;
 
554
                        } catch (Exception ex) {
 
555
                                Report.Error (1569, "Error generating XML documentation file `{0}' (`{1}')", xmlFileName, ex.Message);
 
556
                                return false;
 
557
                        } finally {
 
558
                                if (w != null)
 
559
                                        w.Close ();
 
560
                        }
 
561
                }
 
562
        }
 
563
 
 
564
        class DocumentationParameter
 
565
        {
 
566
                public readonly Parameter.Modifier Modifier;
 
567
                public FullNamedExpression Type;
 
568
                TypeSpec type;
 
569
 
 
570
                public DocumentationParameter (Parameter.Modifier modifier, FullNamedExpression type)
 
571
                        : this (type)
 
572
                {
 
573
                        this.Modifier = modifier;
 
574
                }
 
575
 
 
576
                public DocumentationParameter (FullNamedExpression type)
 
577
                {
 
578
                        this.Type = type;
 
579
                }
 
580
 
 
581
                public TypeSpec TypeSpec {
 
582
                        get {
 
583
                                return type;
 
584
                        }
 
585
                }
 
586
 
 
587
                public void Resolve (IMemberContext context)
 
588
                {
 
589
                        type = Type.ResolveAsType (context);
 
590
                }
 
591
        }
 
592
}