2008-12-08 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / tools / mdoc / Mono.Documentation / validate.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.IO;
5 using System.Reflection;
6 using System.Xml;
7 using System.Xml.Schema;
8
9 using Mono.Options;
10
11 namespace Mono.Documentation
12 {
13         public class MDocValidator : MDocCommand
14         {
15                 XmlReaderSettings settings;
16                 long errors = 0;
17
18                 public override void Run (IEnumerable<string> args)
19                 {
20                         string[] validFormats = {
21                                 "ecma",
22                         };
23                         string format = "ecma";
24                         var p = new OptionSet () {
25                                 { "f|format=",
26                                         "The documentation {0:FORMAT} used within PATHS.  " + 
27                                                 "Valid formats include:\n  " +
28                                                 string.Join ("\n  ", validFormats) + "\n" +
29                                                 "If no format provided, `ecma' is used.",
30                                         v => format = v },
31                         };
32                         List<string> files = Parse (p, args, "validate", 
33                                         "[OPTIONS]+ PATHS",
34                                         "Validate PATHS against the specified format schema.");
35                         if (files == null)
36                                 return;
37                         if (Array.IndexOf (validFormats, format) < 0)
38                                 Error ("Invalid documentation format: {0}.", format);
39                         Run (format, files);
40                 }
41         
42                 public void Run (string format, IEnumerable<string> files)
43                 {
44                         Stream s = null;
45
46                         switch (format) {
47                                 case "ecma":
48                                         s = Assembly.GetExecutingAssembly ().GetManifestResourceStream ("monodoc-ecma.xsd");
49                                         break;
50
51                                 default:
52                                         throw new NotSupportedException (string.Format ("The format `{0}' is not suppoted.", format));
53                         }
54
55                         if (s == null)
56                                 throw new NotSupportedException (string.Format ("The schema for `{0}' was not found.", format));
57
58                         settings = new XmlReaderSettings ();
59                         settings.Schemas.Add (XmlSchema.Read (s, null));
60                         settings.Schemas.Compile ();
61                         settings.ValidationType = ValidationType.Schema;
62                         settings.ValidationEventHandler += OnValidationEvent;
63
64                         // skip args[0] because it is the provider name
65                         foreach (string arg in files) {
66                                 if (IsMonodocFile (arg))
67                                         ValidateFile (arg);
68
69                                 if (Directory.Exists (arg))
70                                 {
71                                         RecurseDirectory (arg);
72                                 }
73                         }
74
75                         Message (errors == 0 ? TraceLevel.Info : TraceLevel.Error, 
76                                         "Total validation errors: {0}", errors);
77                 }
78
79                 void ValidateFile (string file)
80                 {
81                         try {
82                                 using (var reader = XmlReader.Create (new XmlTextReader (file), settings)) {
83                                         while (reader.Read ()) {
84                                                 // do nothing
85                                         }
86                                 }
87                         }
88                         catch (Exception e) {
89                                 Message (TraceLevel.Error, "mdoc: {0}", e.ToString ());
90                         }
91                 }
92
93                 void RecurseDirectory (string dir)
94                 {
95                         string[] files = Directory.GetFiles (dir, "*.xml");
96                         foreach (string f in files)
97                         {
98                                 if (IsMonodocFile (f))
99                                         ValidateFile (f);
100                         }
101
102                         string[] dirs = Directory.GetDirectories (dir);
103                         foreach (string d in dirs)
104                                 RecurseDirectory (d);
105                 }
106
107                 void OnValidationEvent (object sender, ValidationEventArgs a)
108                 {
109                         errors ++;
110                         Message (TraceLevel.Error, "mdoc: {0}", a.Message);
111                 }
112
113                 static bool IsMonodocFile (string file)
114                 {
115                                 if (File.Exists (file) && Path.GetExtension (file).ToLower () == ".xml")
116                                         return true;
117                                 else
118                                         return false;
119                         
120                 }
121         }
122 }
123