File: ecmaspec-provider.cs

package info (click to toggle)
mono 6.12.0.199%2Bds-4
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,273,192 kB
  • sloc: cs: 11,181,844; xml: 2,850,076; ansic: 689,413; cpp: 123,344; perl: 59,361; javascript: 30,841; asm: 21,845; makefile: 19,951; sh: 15,030; python: 4,771; pascal: 925; sql: 859; sed: 16; php: 1
file content (193 lines) | stat: -rw-r--r-- 5,274 bytes parent folder | download | duplicates (12)
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
//
// The ecmaspec provider is for ECMA specifications
//
// Authors:
//	John Luke (jluke@cfl.rr.com)
//	Ben Maurer (bmaurer@users.sourceforge.net)
//
// Use like this:
//   mono assembler.exe --ecmaspec DIRECTORY --out name
//

using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.Xml;
using System.Collections.Generic;
using Lucene.Net.Index;
using Lucene.Net.Documents;

namespace Monodoc.Providers
{
	public class EcmaSpecProvider : Provider
	{
		string basedir;
	
		public EcmaSpecProvider (string base_directory)
		{
			basedir = base_directory;
			if (!Directory.Exists (basedir))
				throw new DirectoryNotFoundException (String.Format ("The directory `{0}' does not exist", basedir));
		}
	
		public override void PopulateTree (Tree tree)
		{
			XPathNavigator n = new XPathDocument (Path.Combine (basedir, "toc.xml")).CreateNavigator ();
			n.MoveToRoot ();
			n.MoveToFirstChild ();
			PopulateNode (n.SelectChildren ("node", ""), tree.RootNode);
		}
	
		void PopulateNode (XPathNodeIterator nodes, Node treeNode)
		{
			foreach (XPathNavigator n in nodes) {
				string secNumber = n.GetAttribute ("number", "");
				string secName = n.GetAttribute ("name", "");

				var storage = treeNode.Tree.HelpSource.Storage;
				using (var file = File.OpenRead (Path.Combine (basedir, secNumber + ".xml")))
					storage.Store (secNumber, file);

				Node thisNode = treeNode.GetOrCreateNode (secNumber + ": " + secName, "ecmaspec:" + secNumber);
			
				if (n.HasChildren)
					PopulateNode (n.SelectChildren ("node", ""), thisNode);
			}
		}

		public override void CloseTree (HelpSource hs, Tree tree)
		{
		}
	}

	public class EcmaSpecHelpSource : HelpSource
	{
		const string EcmaspecPrefix = "ecmaspec:";
		const string TocPart = "%toc"; // What is returned as TocXml
		const string SpecPart = "%spec"; // What is returned as Ecmaspec

		public EcmaSpecHelpSource (string base_file, bool create) : base (base_file, create)
		{
		}

		public override DocumentType GetDocumentTypeForId (string id)
		{
			return id.EndsWith (TocPart) ? DocumentType.TocXml : DocumentType.EcmaSpecXml;
		}

		public override bool IsGeneratedContent (string id)
		{
			return id == "root:" || id.EndsWith (TocPart);
		}

		public override bool IsMultiPart (string id, out IEnumerable<string> parts)
		{
			if (id == "root:" || id.EndsWith (TocPart) || id.EndsWith (SpecPart)) {
				parts = null;
				return false;
			}
			parts = MakeMultiPart (id);
			return true;
		}

		IEnumerable<string> MakeMultiPart (string baseId)
		{
			yield return baseId + SpecPart;
			yield return baseId + TocPart;
		}

		public override string GetText (string id)
		{
			Node n = id == "root:" ? Tree.RootNode : MatchNode (EcmaspecPrefix + id.Substring (0, id.Length - TocPart.Length));
			if (n == null)
				throw new ArgumentException ("id", string.Format ("{0} -> {1}", id, EcmaspecPrefix + id.Substring (0, id.Length - TocPart.Length)));
			return TreeDumper.ExportToTocXml (n, "C# Language Specification", "In this section:");
		}

		public override Stream GetHelpStream (string id)
		{
			return id.EndsWith (SpecPart) ? base.GetHelpStream (id.Substring (0, id.IndexOf (SpecPart))) : base.GetHelpStream (id);
		}
	
		public override void PopulateSearchableIndex (IndexWriter writer) 
		{
			foreach (Node n in Tree.RootNode.ChildNodes)
				AddDocuments (writer, n);
		}

		protected override string UriPrefix {
			get {
				return EcmaspecPrefix;
			}
		}

		void AddDocuments (IndexWriter writer, Node node) 
		{
			string url = node.PublicUrl;
			Stream file_stream = GetHelpStream (url.Substring (9));
			if (file_stream == null) //Error
				return;
			XmlDocument xdoc = new XmlDocument ();
			xdoc.Load (new XmlTextReader (file_stream));

			//Obtain the title
			XmlNode nelem = xdoc.DocumentElement;
			string title = nelem.Attributes["number"].Value + ": " + nelem.Attributes["title"].Value;

			//Obtain the text
			StringBuilder s = new StringBuilder ();
			GetTextNode (nelem, s);
			string text = s.ToString ();

			//Obtain the examples
			StringBuilder s2 = new StringBuilder ();
			GetExamples (nelem, s2);
			string examples = s2.ToString ();

			//Write to the Lucene Index all the parts
			SearchableDocument doc = new SearchableDocument ();
			doc.Title = title;
			doc.HotText = title.Substring (title.IndexOf (':')); 
			doc.Url = url;
			doc.Text = text;
			doc.Examples = examples;
			writer.AddDocument (doc.LuceneDoc);
		
			if (node.IsLeaf)
				return;

			foreach (Node n in node.ChildNodes)
				AddDocuments (writer, n);
		}

		void GetTextNode (XmlNode n, StringBuilder s) 
		{
			//dont include c# code
			if (n.Name == "code_example")
				return;
			//include all text from nodes
			if (n.NodeType == XmlNodeType.Text)
				s.Append (n.Value);
		
			//recursively explore all nodes
			if (n.HasChildNodes)
				foreach (XmlNode n_child in n.ChildNodes)
					GetTextNode (n_child, s);
		}

		void GetExamples (XmlNode n, StringBuilder s)
		{
			if (n.Name == "code_example") {
				if (n.FirstChild.Name == "#cdata-section")
					s.Append (n.FirstChild.Value);
			} else {
				if (n.HasChildNodes)
					foreach (XmlNode n_child in n.ChildNodes)
						GetExamples (n_child, s);
			}
		}
	}
}