Mercurial > projects > dil
comparison trunk/src/cmd/DDocXML.d @ 799:fd719161e743
New ddoc emitter for XML type output.
author | Jari-Matti M?kel? <jmjm@iki.fi> |
---|---|
date | Sat, 01 Mar 2008 18:04:29 +0200 |
parents | |
children | dcd30b0ba711 |
comparison
equal
deleted
inserted
replaced
798:c24be8d4f6ab | 799:fd719161e743 |
---|---|
1 /++ | |
2 Author: Aziz Köksal & Jari-Matti Mäkelä | |
3 License: GPL3 | |
4 +/ | |
5 module cmd.DDocXML; | |
6 | |
7 import cmd.DDoc; | |
8 import cmd.Generate; | |
9 import dil.doc.Parser; | |
10 import dil.doc.Macro; | |
11 import dil.doc.Doc; | |
12 import dil.ast.Node; | |
13 import dil.ast.Declarations, | |
14 dil.ast.Statements, | |
15 dil.ast.Expression, | |
16 dil.ast.Parameters, | |
17 dil.ast.Types; | |
18 import dil.ast.DefaultVisitor; | |
19 import dil.lexer.Token; | |
20 import dil.lexer.Funcs; | |
21 import dil.semantic.Module; | |
22 import dil.semantic.Pass1; | |
23 import dil.semantic.Symbol; | |
24 import dil.semantic.Symbols; | |
25 import dil.Compilation; | |
26 import dil.Information; | |
27 import dil.Converter; | |
28 import dil.SourceText; | |
29 import dil.Enums; | |
30 import dil.Time; | |
31 import common; | |
32 | |
33 import tango.text.Ascii : toUpper; | |
34 import tango.io.File; | |
35 import tango.io.FilePath; | |
36 | |
37 /// Traverses the syntax tree and writes DDoc macros to a string buffer. | |
38 class DDocXMLEmitter : DDocEmitter | |
39 { | |
40 this(Module modul, MacroTable mtable, bool includeUndocumented, | |
41 TokenHighlighter tokenHL) | |
42 { | |
43 super(modul, mtable, includeUndocumented, tokenHL); | |
44 } | |
45 | |
46 /// Writes params to the text buffer. | |
47 void writeParams(Parameters params) | |
48 { | |
49 if (!params.items.length) | |
50 return; | |
51 | |
52 write("$(PARAMS "); | |
53 auto lastParam = params.items[$-1]; | |
54 foreach (param; params.items) | |
55 { | |
56 if (param.isCVariadic) | |
57 write("..."); | |
58 else | |
59 { | |
60 assert(param.type); | |
61 // Write storage classes. | |
62 auto typeBegin = param.type.baseType.begin; | |
63 if (typeBegin !is param.begin) // Write storage classes. | |
64 write(textSpan(param.begin, typeBegin.prevNWS), " "); | |
65 write(escape(textSpan(typeBegin, param.type.end))); // Write type. | |
66 if (param.name) | |
67 write(" $(DDOC_PARAM ", param.name.str, ")"); | |
68 if (param.isDVariadic) | |
69 write("..."); | |
70 if (param.defValue) | |
71 write(" = ", escape(textSpan(param.defValue.begin, param.defValue.end))); | |
72 } | |
73 if (param !is lastParam) | |
74 write(", "); | |
75 } | |
76 write(")"); | |
77 } | |
78 | |
79 /// Writes the current template parameters to the text buffer. | |
80 void writeTemplateParams() | |
81 { | |
82 if (!tparams) | |
83 return; | |
84 write("$(TEMPLATE_PARAMS ", escape(textSpan(tparams.begin, tparams.end))[1..$-1], ")"); | |
85 tparams = null; | |
86 } | |
87 | |
88 /// Writes bases to the text buffer. | |
89 void writeInheritanceList(BaseClassType[] bases) | |
90 { | |
91 if (bases.length == 0) | |
92 return; | |
93 auto basesBegin = bases[0].begin.prevNWS; | |
94 if (basesBegin.kind == TOK.Colon) | |
95 basesBegin = bases[0].begin; | |
96 write("$(PARENTS ", escape(textSpan(basesBegin, bases[$-1].end)), ")"); | |
97 } | |
98 | |
99 /// Writes a symbol to the text buffer. E.g: $(SYMBOL Buffer, 123) | |
100 void SYMBOL(char[] name, Declaration d) | |
101 { | |
102 auto loc = d.begin.getRealLocation(); | |
103 auto str = Format("$(SYMBOL {}, {})", name, loc.lineNum); | |
104 write(str); | |
105 // write("$(DDOC_PSYMBOL ", name, ")"); | |
106 } | |
107 | |
108 /// Writes a declaration to the text buffer. | |
109 void DECL(void delegate() dg, Declaration d, bool writeSemicolon = true) | |
110 { | |
111 if (cmntIsDitto) | |
112 { alias prevDeclOffset offs; | |
113 assert(offs != 0); | |
114 auto savedText = text; | |
115 text = ""; | |
116 write("\n$(DDOC_DECL "); | |
117 dg(); | |
118 writeAttributes(d); | |
119 write(")"); | |
120 // Insert text at offset. | |
121 auto len = text.length; | |
122 text = savedText[0..offs] ~ text ~ savedText[offs..$]; | |
123 offs += len; // Add length of the inserted text to the offset. | |
124 return; | |
125 } | |
126 write("\n$(DDOC_DECL "); | |
127 dg(); | |
128 writeAttributes(d); | |
129 write(")"); | |
130 prevDeclOffset = text.length; | |
131 } | |
132 | |
133 | |
134 /// Writes a class or interface declaration. | |
135 void writeClassOrInterface(T)(T d) | |
136 { | |
137 if (!ddoc(d)) | |
138 return d; | |
139 DECL({ | |
140 write(d.begin.srcText, ", "); | |
141 SYMBOL(d.name.str, d); | |
142 writeTemplateParams(); | |
143 writeInheritanceList(d.bases); | |
144 }, d); | |
145 DESC({ | |
146 writeComment(); | |
147 MEMBERS(is(T == ClassDeclaration) ? "CLASS" : "INTERFACE", { | |
148 scope s = new Scope(); | |
149 /*FIXME*/ d.decls && DefaultVisitor.visit(d.decls); | |
150 }); | |
151 }); | |
152 } | |
153 | |
154 /// Writes a struct or union declaration. | |
155 void writeStructOrUnion(T)(T d) | |
156 { | |
157 if (!ddoc(d)) | |
158 return d; | |
159 DECL({ | |
160 write(d.begin.srcText, d.name ? ", " : ""); | |
161 if (d.name) | |
162 SYMBOL(d.name.str, d); | |
163 writeTemplateParams(); | |
164 }, d); | |
165 DESC({ | |
166 writeComment(); | |
167 MEMBERS(is(T == StructDeclaration) ? "STRUCT" : "UNION", { | |
168 scope s = new Scope(); | |
169 /*FIXME*/ d.decls && DefaultVisitor.visit(d.decls); | |
170 }); | |
171 }); | |
172 } | |
173 | |
174 /// Writes an alias or typedef declaration. | |
175 void writeAliasOrTypedef(T)(T d) | |
176 { | |
177 auto prefix = is(T == AliasDeclaration) ? "alias " : "typedef "; | |
178 if (auto vd = d.decl.Is!(VariablesDeclaration)) | |
179 { | |
180 auto type = textSpan(vd.typeNode.baseType.begin, vd.typeNode.end); | |
181 foreach (name; vd.names) | |
182 DECL({ write(prefix, ", "); write(escape(type), " "); SYMBOL(name.str, d); }, d); | |
183 } | |
184 else if (auto fd = d.decl.Is!(FunctionDeclaration)) | |
185 {} | |
186 // DECL({ write(textSpan(d.begin, d.end)); }, false); | |
187 DESC({ writeComment(); }); | |
188 } | |
189 | |
190 /// Writes the attributes of a declaration in brackets. | |
191 void writeAttributes(Declaration d) | |
192 { | |
193 char[][] attributes; | |
194 | |
195 if (d.prot != Protection.None) | |
196 attributes ~= "$(PROT " ~ .toString(d.prot) ~ ")"; | |
197 | |
198 auto stc = d.stc; | |
199 stc &= ~StorageClass.Auto; // Ignore auto. | |
200 foreach (stcStr; .toStrings(stc)) | |
201 attributes ~= "$(STC " ~ stcStr ~ ")"; | |
202 | |
203 LinkageType ltype; | |
204 if (auto vd = d.Is!(VariablesDeclaration)) | |
205 ltype = vd.linkageType; | |
206 else if (auto fd = d.Is!(FunctionDeclaration)) | |
207 ltype = fd.linkageType; | |
208 | |
209 if (ltype != LinkageType.None) | |
210 attributes ~= "$(LINKAGE extern(" ~ .toString(ltype) ~ "))"; | |
211 | |
212 if (!attributes.length) | |
213 return; | |
214 | |
215 write("$(ATTRIBUTES "); | |
216 foreach (attribute; attributes) | |
217 write(attribute); | |
218 write(")"); | |
219 } | |
220 | |
221 alias Declaration D; | |
222 | |
223 // alias DDocEmitter.visit visit; | |
224 | |
225 D visit(EnumDeclaration d) | |
226 { | |
227 if (!ddoc(d)) | |
228 return d; | |
229 DECL({ | |
230 write("enum, ", d.name ? " " : ""); | |
231 d.name && SYMBOL(d.name.str, d); | |
232 }, d); | |
233 DESC({ | |
234 writeComment(); | |
235 /*FIXME*/ MEMBERS("ENUM", { scope s = new Scope(); DefaultVisitor.visit(d); }); | |
236 }); | |
237 return d; | |
238 } | |
239 | |
240 D visit(EnumMemberDeclaration d) | |
241 { | |
242 if (!ddoc(d)) | |
243 return d; | |
244 DECL({ write("member, "); SYMBOL(d.name.str, d); }, d, false); | |
245 DESC({ writeComment(); }); | |
246 return d; | |
247 } | |
248 | |
249 D visit(TemplateDeclaration d) | |
250 { | |
251 this.tparams = d.tparams; | |
252 if (d.begin.kind != TOK.Template) | |
253 { // This is a templatized class/interface/struct/union/function. | |
254 /*FIXME*/ DefaultVisitor.visit(d.decls); | |
255 this.tparams = null; | |
256 return d; | |
257 } | |
258 if (!ddoc(d)) | |
259 return d; | |
260 DECL({ | |
261 write("template, "); | |
262 SYMBOL(d.name.str, d); | |
263 writeTemplateParams(); | |
264 }, d); | |
265 DESC({ | |
266 writeComment(); | |
267 MEMBERS("TEMPLATE", { | |
268 scope s = new Scope(); | |
269 /*FIXME*/ DefaultVisitor.visit(d.decls); | |
270 }); | |
271 }); | |
272 return d; | |
273 } | |
274 | |
275 | |
276 D visit(ConstructorDeclaration d) | |
277 { | |
278 if (!ddoc(d)) | |
279 return d; | |
280 DECL({ write("constructor, "); SYMBOL("this", d); writeParams(d.params); }, d); | |
281 DESC({ writeComment(); }); | |
282 return d; | |
283 } | |
284 | |
285 D visit(StaticConstructorDeclaration d) | |
286 { | |
287 if (!ddoc(d)) | |
288 return d; | |
289 DECL({ write("static constructor, "); SYMBOL("this", d); write("()"); }, d); | |
290 DESC({ writeComment(); }); | |
291 return d; | |
292 } | |
293 | |
294 D visit(DestructorDeclaration d) | |
295 { | |
296 if (!ddoc(d)) | |
297 return d; | |
298 DECL({ write("destructor, ~"); SYMBOL("this", d); }, d); | |
299 DESC({ writeComment(); }); | |
300 return d; | |
301 } | |
302 | |
303 D visit(StaticDestructorDeclaration d) | |
304 { | |
305 if (!ddoc(d)) | |
306 return d; | |
307 DECL({ write("static destructor, ~"); SYMBOL("this", d); }, d); | |
308 DESC({ writeComment(); }); | |
309 return d; | |
310 } | |
311 | |
312 D visit(FunctionDeclaration d) | |
313 { | |
314 if (!ddoc(d)) | |
315 return d; | |
316 auto type = textSpan(d.returnType.baseType.begin, d.returnType.end); | |
317 DECL({ | |
318 write("function, "); | |
319 write("$(TYPE "); | |
320 write("$(RETURNS ", escape(type), ")"); | |
321 writeTemplateParams(); | |
322 writeParams(d.params); | |
323 write(")"); | |
324 SYMBOL(d.name.str, d); | |
325 }, d); | |
326 DESC({ writeComment(); }); | |
327 return d; | |
328 } | |
329 | |
330 D visit(NewDeclaration d) | |
331 { | |
332 if (!ddoc(d)) | |
333 return d; | |
334 DECL({ write("new, "); SYMBOL("new", d); writeParams(d.params); }, d); | |
335 DESC({ writeComment(); }); | |
336 return d; | |
337 } | |
338 | |
339 D visit(DeleteDeclaration d) | |
340 { | |
341 if (!ddoc(d)) | |
342 return d; | |
343 DECL({ write("delete, "); SYMBOL("delete", d); writeParams(d.params); }, d); | |
344 DESC({ writeComment(); }); | |
345 return d; | |
346 } | |
347 | |
348 D visit(VariablesDeclaration d) | |
349 { | |
350 if (!ddoc(d)) | |
351 return d; | |
352 char[] type = "auto"; | |
353 if (d.typeNode) | |
354 type = textSpan(d.typeNode.baseType.begin, d.typeNode.end); | |
355 foreach (name; d.names) | |
356 DECL({ write("variable, "); write("$(TYPE ", escape(type), ")"); SYMBOL(name.str, d); }, d); | |
357 DESC({ writeComment(); }); | |
358 return d; | |
359 } | |
360 | |
361 D visit(InvariantDeclaration d) | |
362 { | |
363 if (!ddoc(d)) | |
364 return d; | |
365 DECL({ write("invariant, "); SYMBOL("invariant", d); }, d); | |
366 DESC({ writeComment(); }); | |
367 return d; | |
368 } | |
369 | |
370 D visit(UnittestDeclaration d) | |
371 { | |
372 if (!ddoc(d)) | |
373 return d; | |
374 DECL({ write("unittest, "); SYMBOL("unittest", d); }, d); | |
375 DESC({ writeComment(); }); | |
376 return d; | |
377 } | |
378 } |