source: trunk/tools/qdoc3/javadocgenerator.cpp@ 348

Last change on this file since 348 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 14.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "javadocgenerator.h"
43
44QT_BEGIN_NAMESPACE
45
46enum JavaSignatureSyntax {
47 GeneratedJdocFile,
48 JavadocRef,
49 SlotSignature
50};
51
52static QString javaSignature(const FunctionNode *func, JavaSignatureSyntax syntax,
53 int maxParams = 65535)
54{
55 maxParams = qMin(maxParams, func->parameters().count());
56
57 QString result;
58
59 if (syntax == GeneratedJdocFile) {
60 if (func->access() == Node::Public) {
61 result += "public ";
62 } else if (func->access() == Node::Protected) {
63 result += "protected ";
64 } else {
65 result += "private ";
66 }
67
68 if (func->metaness() == FunctionNode::Native)
69 result += "native ";
70
71 if (func->isConst())
72 result += "final ";
73
74 // ### func->metaness() == FunctionNode::Abstract
75
76 if (func->isStatic())
77 result += "static ";
78
79 if (!func->returnType().isEmpty()) {
80 result += func->returnType();
81 result += ' ';
82 }
83 }
84
85 if (syntax == SlotSignature) {
86 result += "void mySlot";
87 } else {
88 result += func->name();
89 }
90 result += '(';
91 for (int i = 0; i < maxParams; ++i) {
92 if (i != 0)
93 result += ", ";
94 result += func->parameters().at(i).leftType();
95 if (syntax != JavadocRef) {
96 result += ' ';
97 result += func->parameters().at(i).name();
98 }
99 }
100 result += ')';
101
102 return result;
103}
104
105static QString packageName(const Node *node)
106{
107 while (node && node->type() != Node::Class && node->type() != Node::Fake)
108 node = node->parent();
109 if (!node)
110 return QString();
111 return node->moduleName();
112}
113
114JavadocGenerator::JavadocGenerator()
115 : oldDevice(0), currentDepth(0)
116{
117}
118
119JavadocGenerator::~JavadocGenerator()
120{
121}
122
123void JavadocGenerator::initializeGenerator(const Config &config)
124{
125 HtmlGenerator::initializeGenerator(config);
126
127 formattingLeftMap().insert(ATOM_FORMATTING_PARAMETER,
128 formattingLeftMap().value(ATOM_FORMATTING_TELETYPE));
129 formattingRightMap().insert(ATOM_FORMATTING_PARAMETER,
130 formattingRightMap().value(ATOM_FORMATTING_TELETYPE));
131}
132
133void JavadocGenerator::terminateGenerator()
134{
135 HtmlGenerator::terminateGenerator();
136}
137
138QString JavadocGenerator::format()
139{
140 return "javadoc";
141}
142
143void JavadocGenerator::generateTree(const Tree *tree, CodeMarker *marker)
144{
145 HtmlGenerator::generateTree(tree, marker);
146}
147
148QString JavadocGenerator::fileExtension(const Node *node)
149{
150 if (node->type() == Node::Fake) {
151 return "html";
152 } else {
153 return "jdoc";
154 }
155}
156
157QString JavadocGenerator::typeString(const Node *node)
158{
159 if (node->type() == Node::Function) {
160 const FunctionNode *func = static_cast<const FunctionNode *>(node);
161 return func->metaness() == FunctionNode::Signal ? "signal" : "method";
162 } else {
163 return HtmlGenerator::typeString(node);
164 }
165}
166
167QString JavadocGenerator::imageFileName(const Node *relative, const QString& fileBase)
168{
169 QString result = HtmlGenerator::imageFileName(relative, fileBase);
170 if (!result.isEmpty()) {
171 QString package = packageName(relative);
172 int numSubPackages = package.count('.') - 2;
173 while (numSubPackages > 0) {
174 result.prepend("%2E%2E/"); // javadoc 1.5.0_06 chokes on '../'
175 --numSubPackages;
176 }
177 }
178 return result;
179}
180
181static int textDepth = 0;
182
183void JavadocGenerator::startText(const Node *relative, CodeMarker *marker)
184{
185 if (textDepth++ == 0 && relative->type() != Node::Fake) {
186 Q_ASSERT(!oldDevice);
187 oldDevice = out().device();
188 Q_ASSERT(oldDevice);
189 out().setString(&buffer);
190 }
191 HtmlGenerator::startText(relative, marker);
192}
193
194void JavadocGenerator::endText(const Node *relative, CodeMarker *marker)
195{
196 HtmlGenerator::endText(relative, marker);
197 if (--textDepth == 0 && relative->type() != Node::Fake) {
198 Q_ASSERT(oldDevice);
199 out().setDevice(oldDevice);
200 oldDevice = 0;
201
202 /*
203 Need to escape XML metacharacters in .jdoc files.
204 */
205 buffer.replace("*/", "*&lt;!-- noop --&gt;/");
206 buffer.replace("&", "&amp;");
207 buffer.replace("\"", "&quot;");
208 buffer.replace("<", "&lt;");
209 buffer.replace(">", "&gt;");
210 out() << buffer;
211 buffer.clear();
212 }
213}
214
215int JavadocGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker)
216{
217 return HtmlGenerator::generateAtom(atom, relative, marker);
218}
219
220void JavadocGenerator::generateClassLikeNode(const InnerNode *inner, CodeMarker *marker)
221{
222 generateIndent();
223 out() << "<class name=\"" << protect(inner->name()) << "\"";
224 generateDoc(inner, marker);
225 out() << ">\n";
226
227 ++currentDepth;
228 foreach (Node *node, inner->childNodes()) {
229 if (node->isInnerNode()) {
230 generateClassLikeNode(static_cast<InnerNode *>(node), marker);
231 } else {
232 if (node->type() == Node::Enum) {
233 EnumNode *enume = static_cast<EnumNode *>(node);
234
235 generateIndent();
236 out() << "<enum name=\"" << protect(node->name()) << "\"";
237 generateDoc(node, marker);
238 out() << ">\n";
239
240 ++currentDepth;
241 const QList<EnumItem> &items = enume->items();
242 for (int i = 0; i < items.count(); ++i) {
243 const EnumItem &item = items.at(i);
244 generateIndent();
245 out() << "<enum-value name=\"" << protect(item.name()) << "\"";
246 generateEnumItemDoc(item.text(), enume, marker);
247 out() << "/>\n";
248 }
249 --currentDepth;
250
251 out() << "</enum>\n";
252 } else if (node->type() == Node::Function) {
253 FunctionNode *func = static_cast<FunctionNode *>(node);
254 generateIndent();
255 out() << (func->metaness() == FunctionNode::Signal ? "<signal" : "<method")
256 << " name=\""
257 << protect(javaSignature(func, GeneratedJdocFile))
258 << "\"";
259 generateDoc(node, marker);
260 out() << "/>\n";
261 }
262 }
263 }
264 --currentDepth;
265
266 generateIndent();
267 out() << "</class>\n";
268}
269
270void JavadocGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
271{
272 HtmlGenerator::generateFakeNode(fake, marker);
273}
274
275void JavadocGenerator::generateText(const Text& text, const Node *relative, CodeMarker *marker)
276{
277 HtmlGenerator::generateText(text, relative, marker);
278}
279
280void JavadocGenerator::generateBody(const Node *node, CodeMarker *marker)
281{
282 generateText(node->doc().body(), node, marker);
283}
284
285void JavadocGenerator::generateAlsoList( const Node *node, CodeMarker *marker )
286{
287 QList<Text> alsoList = node->doc().alsoList();
288 supplementAlsoList(node, alsoList);
289
290 if (node->type() == Node::Fake
291 || (node->type() == Node::Function
292 && static_cast<const FunctionNode *>(node)->metaness() == FunctionNode::Signal)) {
293 Text text;
294
295 if (!alsoList.isEmpty()) {
296 text << Atom(Atom::ListLeft, ATOM_LIST_TAG)
297 << Atom(Atom::ListTagLeft, ATOM_LIST_TAG)
298 << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
299 << "See Also:"
300 << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
301 << Atom(Atom::ListTagRight, ATOM_LIST_TAG)
302 << Atom(Atom::ListItemLeft, ATOM_LIST_TAG);
303
304 for (int i = 0; i < alsoList.count(); ++i) {
305 if (i != 0)
306 text << ", ";
307 text << alsoList.at(i);
308 }
309 text << Atom(Atom::ListItemRight, ATOM_LIST_TAG)
310 << Atom(Atom::ListRight, ATOM_LIST_TAG);
311 }
312
313 generateText(text, node, marker);
314 } else {
315 foreach (const Text &text, alsoList) {
316 out() << "\n@see ";
317 generateText(text, node, marker);
318 }
319 }
320}
321
322QString JavadocGenerator::refForNode( const Node *node )
323{
324 if (node->type() == Node::Function)
325 return javaSignature(static_cast<const FunctionNode *>(node), JavadocRef);
326
327 return HtmlGenerator::refForNode(node);
328}
329
330QString JavadocGenerator::linkForNode( const Node *node, const Node *relative )
331{
332 // ### EVIL, relative should never be null
333 if (!relative)
334 relative = node;
335
336 if (packageName(node).isEmpty()) {
337 // ### jasmin: Fixme
338 return QString();
339 }
340
341 QString result;
342 if (node->type() == Node::Fake) {
343 result = node->name();
344 } else {
345 if (!node->isInnerNode()) {
346 result = linkForNode(node->parent(), relative) + "#" + refForNode(node);
347 } else {
348 result = node->name() + ".html";
349 }
350 }
351
352 QStringList nodePackage = packageName(node).split(".");
353 QStringList relativePackage = packageName(relative).split(".");
354 if (nodePackage == QStringList(QString()) || relativePackage == QStringList(QString())) {
355 qWarning("I'm in trouble [%s][%s]", qPrintable(node->name()), qPrintable(relative->name()));
356 return QString();
357 }
358
359 int i = nodePackage.count() - 1;
360 while (nodePackage.value(i) != relativePackage.value(i)) {
361 result.prepend(nodePackage.at(i) + "/");
362 --i;
363 }
364
365 ++i;
366 while (i < relativePackage.count()) {
367 result.prepend("%2E%2E/"); // javadoc 1.5.0_06 chokes on '../'
368 ++i;
369 }
370
371 return result;
372}
373
374QString JavadocGenerator::refForAtom(Atom *atom, const Node *node)
375{
376 return HtmlGenerator::refForAtom(atom, node);
377}
378
379/*
380 Neutralize dumb functions called from HtmlGenerator.
381*/
382void JavadocGenerator::generateDcf(const QString & /* fileBase */, const QString & /* startPage */,
383 const QString & /* title */, DcfSection & /* dcfRoot */)
384{
385}
386
387void JavadocGenerator::generateIndex(const QString & /* fileBase */, const QString & /* url */,
388 const QString & /* title */)
389{
390}
391
392void JavadocGenerator::generateIndent()
393{
394 for (int i = 0; i < currentDepth; ++i)
395 out() << " ";
396}
397
398void JavadocGenerator::generateDoc(const Node *node, CodeMarker *marker)
399{
400 const Text &text = node->doc().body();
401 if (!text.isEmpty()) {
402 out() << " doc=\"/**\n";
403 Generator::generateStatus(node, marker);
404 generateText(text, node, marker);
405 if (node && node->type() == Node::Function) {
406 const FunctionNode *func = static_cast<const FunctionNode *>(node);
407 if (func->metaness() == FunctionNode::Signal) {
408 QStringList slotSignatures;
409 for (int i = func->parameters().count(); i >= 0; --i)
410 slotSignatures += javaSignature(func, SlotSignature, i);
411
412 Text text;
413
414 text << Atom(Atom::ListLeft, ATOM_LIST_TAG)
415 << Atom(Atom::ListTagLeft, ATOM_LIST_TAG)
416 << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD);
417
418 if (slotSignatures.count() == 1) {
419 text << "Compatible Slot Signature:";
420 } else {
421 text << "Compatible Slot Signatures:";
422 }
423
424 text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
425 << Atom(Atom::ListTagRight, ATOM_LIST_TAG);
426
427 for (int i = 0; i < slotSignatures.count(); ++i) {
428 text << Atom(Atom::ListItemLeft, ATOM_LIST_TAG)
429 << Atom(Atom::C, marker->markedUpCode(slotSignatures.at(i), 0, ""))
430 << Atom(Atom::ListItemRight, ATOM_LIST_TAG);
431 }
432 text << Atom(Atom::ListRight, ATOM_LIST_TAG);
433 generateText(text, node, marker);
434 }
435 }
436 if (node)
437 generateAlsoList(node, marker);
438 out() << " */\"";
439 }
440}
441
442void JavadocGenerator::generateEnumItemDoc(const Text &text, const Node *node, CodeMarker *marker)
443{
444 out() << " doc=\"/**\n";
445 if (text.isEmpty()) {
446 out() << "Internal.";
447 } else {
448 generateText(text, node, marker);
449 }
450 out() << " */\"";
451}
452
453QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.