Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /**************************************************************************** |
---|---|
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the tools applications of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and Digia. For licensing terms and |
14 | ** conditions see http://qt.digia.com/licensing. For further information |
15 | ** use the contact form at http://qt.digia.com/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
24 | ** |
25 | ** In addition, as a special exception, Digia gives you certain additional |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
28 | ** |
29 | ** GNU General Public License Usage |
30 | ** Alternatively, this file may be used under the terms of the GNU |
31 | ** General Public License version 3.0 as published by the Free Software |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the |
33 | ** packaging of this file. Please review the following information to |
34 | ** ensure the GNU General Public License version 3.0 requirements will be |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. |
36 | ** |
37 | ** |
38 | ** $QT_END_LICENSE$ |
39 | ** |
40 | ****************************************************************************/ |
41 | |
42 | /* |
43 | main.cpp |
44 | */ |
45 | |
46 | #include <qglobal.h> |
47 | #include <stdlib.h> |
48 | #include "codemarker.h" |
49 | #include "codeparser.h" |
50 | #include "config.h" |
51 | #include "cppcodemarker.h" |
52 | #include "cppcodeparser.h" |
53 | #include "ditaxmlgenerator.h" |
54 | #include "doc.h" |
55 | #include "htmlgenerator.h" |
56 | #include "jscodemarker.h" |
57 | #include "plaincodemarker.h" |
58 | #include "puredocparser.h" |
59 | #include "qmlcodemarker.h" |
60 | #include "qmlcodeparser.h" |
61 | #include "tokenizer.h" |
62 | #include "tree.h" |
63 | #include <qdebug.h> |
64 | |
65 | #include "qtranslator.h" |
66 | #ifndef QT_BOOTSTRAPPED |
67 | # include "qcoreapplication.h" |
68 | #endif |
69 | |
70 | QT_BEGIN_NAMESPACE |
71 | |
72 | /* |
73 | The default indent for code is 4. |
74 | The default value for false is 0. |
75 | The default language is c++. |
76 | The default output format is html. |
77 | The default tab size is 8. |
78 | And those are all the default values for configuration variables. |
79 | */ |
80 | static const struct { |
81 | const char *key; |
82 | const char *value; |
83 | } defaults[] = { |
84 | { CONFIG_CODEINDENT, "4"}, |
85 | { CONFIG_FALSEHOODS, "0"}, |
86 | { CONFIG_LANGUAGE, "Cpp"}, |
87 | { CONFIG_OUTPUTFORMATS, "HTML"}, |
88 | { CONFIG_TABSIZE, "8"}, |
89 | { 0, 0 } |
90 | }; |
91 | |
92 | static bool slow = false; |
93 | static bool showInternal = false; |
94 | static bool obsoleteLinks = false; |
95 | static QStringList defines; |
96 | static QHash<QString, Tree *> trees; |
97 | |
98 | /*! |
99 | Print the help message to \c stdout. |
100 | */ |
101 | static void printHelp() |
102 | { |
103 | Location::information(tr("Usage: qdoc [options] file1.qdocconf ...\n" |
104 | "Options:\n" |
105 | " -help " |
106 | "Display this information and exit\n" |
107 | " -version " |
108 | "Display version of qdoc and exit\n" |
109 | " -D<name> " |
110 | "Define <name> as a macro while parsing sources\n" |
111 | " -slow " |
112 | "Turn on features that slow down qdoc\n" |
113 | " -showinternal " |
114 | "Include stuff marked internal\n" |
115 | " -obsoletelinks " |
116 | "Report links from obsolete items to non-obsolete items") ); |
117 | } |
118 | |
119 | /*! |
120 | Prints the qdoc version number to stdout. |
121 | */ |
122 | static void printVersion() |
123 | { |
124 | QString s = tr("qdoc version %1").arg(QT_VERSION_STR); |
125 | Location::information(s); |
126 | } |
127 | |
128 | /*! |
129 | Processes the qdoc config file \a fileName. This is the |
130 | controller for all of qdoc. |
131 | */ |
132 | static void processQdocconfFile(const QString &fileName) |
133 | { |
134 | #ifndef QT_NO_TRANSLATION |
135 | QList<QTranslator *> translators; |
136 | #endif |
137 | |
138 | /* |
139 | The Config instance represents the configuration data for qdoc. |
140 | All the other classes are initialized with the config. Here we |
141 | initialize the configuration with some default values. |
142 | */ |
143 | Config config(tr("qdoc")); |
144 | int i = 0; |
145 | while (defaults[i].key) { |
146 | config.setStringList(defaults[i].key, |
147 | QStringList() << defaults[i].value); |
148 | ++i; |
149 | } |
150 | config.setStringList(CONFIG_SYNTAXHIGHLIGHTING, QStringList(slow ? "true": "false")); |
151 | config.setStringList(CONFIG_SHOWINTERNAL, |
152 | QStringList(showInternal ? "true": "false")); |
153 | config.setStringList(CONFIG_OBSOLETELINKS, |
154 | QStringList(obsoleteLinks ? "true": "false")); |
155 | |
156 | /* |
157 | With the default configuration values in place, load |
158 | the qdoc configuration file. Note that the configuration |
159 | file may include other configuration files. |
160 | |
161 | The Location class keeps track of the current location |
162 | in the file being processed, mainly for error reporting |
163 | purposes. |
164 | */ |
165 | Location::initialize(config); |
166 | config.load(fileName); |
167 | |
168 | /* |
169 | Add the defines to the configuration variables. |
170 | */ |
171 | QStringList defs = defines + config.getStringList(CONFIG_DEFINES); |
172 | config.setStringList(CONFIG_DEFINES,defs); |
173 | Location::terminate(); |
174 | |
175 | QString prevCurrentDir = QDir::currentPath(); |
176 | QString dir = QFileInfo(fileName).path(); |
177 | if (!dir.isEmpty()) |
178 | QDir::setCurrent(dir); |
179 | |
180 | /* |
181 | Initialize all the classes and data structures with the |
182 | qdoc configuration. |
183 | */ |
184 | Location::initialize(config); |
185 | Tokenizer::initialize(config); |
186 | Doc::initialize(config); |
187 | CodeMarker::initialize(config); |
188 | CodeParser::initialize(config); |
189 | Generator::initialize(config); |
190 | |
191 | #ifndef QT_NO_TRANSLATION |
192 | /* |
193 | Load the language translators, if the configuration specifies any. |
194 | */ |
195 | QStringList fileNames = config.getStringList(CONFIG_TRANSLATORS); |
196 | QStringList::Iterator fn = fileNames.begin(); |
197 | while (fn != fileNames.end()) { |
198 | QTranslator *translator = new QTranslator(0); |
199 | if (!translator->load(*fn)) |
200 | config.lastLocation().error(tr("Cannot load translator '%1'") |
201 | .arg(*fn)); |
202 | QCoreApplication::instance()->installTranslator(translator); |
203 | translators.append(translator); |
204 | ++fn; |
205 | } |
206 | #endif |
207 | |
208 | //QSet<QString> outputLanguages = config.getStringSet(CONFIG_OUTPUTLANGUAGES); |
209 | |
210 | /* |
211 | Get the source language (Cpp) from the configuration |
212 | and the location in the configuration file where the |
213 | source language was set. |
214 | */ |
215 | QString lang = config.getString(CONFIG_LANGUAGE); |
216 | Location langLocation = config.lastLocation(); |
217 | |
218 | /* |
219 | Initialize the tree where all the parsed sources will be stored. |
220 | The tree gets built as the source files are parsed, and then the |
221 | documentation output is generated by traversing the tree. |
222 | */ |
223 | Tree *tree = new Tree; |
224 | tree->setVersion(config.getString(CONFIG_VERSION)); |
225 | |
226 | /* |
227 | By default, the only output format is HTML. |
228 | */ |
229 | QSet<QString> outputFormats = config.getStringSet(CONFIG_OUTPUTFORMATS); |
230 | Location outputFormatsLocation = config.lastLocation(); |
231 | |
232 | /* |
233 | Read some XML indexes containing definitions from other documentation sets. |
234 | */ |
235 | QStringList indexFiles = config.getStringList(CONFIG_INDEXES); |
236 | tree->readIndexes(indexFiles); |
237 | |
238 | #if 0 |
239 | /* |
240 | I think we won't beusing this... |
241 | |
242 | Read the list of DITA excluded directories. |
243 | */ |
244 | QSet<QString> ditaExcludedDirs; |
245 | QStringList ditaExcludedDirsList = config.getStringList("dita.metadata.excludedirs"); |
246 | foreach (const QString &t, ditaExcludedDirsList) |
247 | ditaExcludedDirs.insert(QDir::fromNativeSeparators(t)); |
248 | |
249 | if (!ditaExcludedDirs.isEmpty()) { |
250 | QSet<QString>::iterator i = ditaExcludedDirs.begin(); |
251 | while (i != ditaExcludedDirs.end()) { |
252 | qDebug() << "DITA EXCLUDED DIR:"<< (*i); |
253 | ++i; |
254 | } |
255 | } |
256 | #endif |
257 | |
258 | /* |
259 | Read the list of excluded directories. |
260 | */ |
261 | QSet<QString> excludedDirs; |
262 | QStringList excludedDirsList = config.getStringList(CONFIG_EXCLUDEDIRS); |
263 | foreach (const QString &excludeDir, excludedDirsList) |
264 | excludedDirs.insert(QDir::fromNativeSeparators(excludeDir)); |
265 | |
266 | /* |
267 | Get all the header files: "*.ch *.h *.h++ *.hh *.hpp *.hxx" |
268 | Put them in a set. |
269 | */ |
270 | QSet<QString> headers = QSet<QString>::fromList( |
271 | config.getAllFiles(CONFIG_HEADERS, CONFIG_HEADERDIRS, excludedDirs)); |
272 | |
273 | /* |
274 | Get all the source text files: "*.cpp *.qdoc *.mm" |
275 | Put them in a set. |
276 | */ |
277 | QSet<QString> sources = QSet<QString>::fromList( |
278 | config.getAllFiles(CONFIG_SOURCES, CONFIG_SOURCEDIRS, excludedDirs)); |
279 | |
280 | /* |
281 | Parse each header file in the set using the appropriate parser and add it |
282 | to the big tree. |
283 | */ |
284 | QSet<CodeParser *> usedParsers; |
285 | |
286 | QSet<QString>::ConstIterator h = headers.begin(); |
287 | while (h != headers.end()) { |
288 | CodeParser *codeParser = CodeParser::parserForHeaderFile(*h); |
289 | if (codeParser) { |
290 | codeParser->parseHeaderFile(config.location(), *h, tree); |
291 | usedParsers.insert(codeParser); |
292 | } |
293 | ++h; |
294 | } |
295 | |
296 | foreach (CodeParser *codeParser, usedParsers) |
297 | codeParser->doneParsingHeaderFiles(tree); |
298 | |
299 | usedParsers.clear(); |
300 | /* |
301 | Parse each source text file in the set using the appropriate parser and |
302 | add it to the big tree. |
303 | */ |
304 | QSet<QString>::ConstIterator s = sources.begin(); |
305 | while (s != sources.end()) { |
306 | CodeParser *codeParser = CodeParser::parserForSourceFile(*s); |
307 | if (codeParser) { |
308 | codeParser->parseSourceFile(config.location(), *s, tree); |
309 | usedParsers.insert(codeParser); |
310 | } |
311 | ++s; |
312 | } |
313 | |
314 | foreach (CodeParser *codeParser, usedParsers) |
315 | codeParser->doneParsingSourceFiles(tree); |
316 | |
317 | /* |
318 | Now the big tree has been built from all the header and |
319 | source files. Resolve all the class names, function names, |
320 | targets, URLs, links, and other stuff that needs resolving. |
321 | */ |
322 | tree->resolveGroups(); |
323 | tree->resolveTargets(); |
324 | |
325 | /* |
326 | Now the tree has been built, and all the stuff that needed |
327 | resolving has been resolved. Now it is time to traverse |
328 | the big tree and generate the documentation output. |
329 | */ |
330 | QSet<QString>::ConstIterator of = outputFormats.begin(); |
331 | while (of != outputFormats.end()) { |
332 | Generator *generator = Generator::generatorForFormat(*of); |
333 | if (generator == 0) |
334 | outputFormatsLocation.fatal(tr("Unknown output format '%1'") |
335 | .arg(*of)); |
336 | generator->generateTree(tree); |
337 | ++of; |
338 | } |
339 | |
340 | /* |
341 | Generate the XML tag file, if it was requested. |
342 | */ |
343 | QString tagFile = config.getString(CONFIG_TAGFILE); |
344 | if (!tagFile.isEmpty()) { |
345 | tree->generateTagFile(tagFile); |
346 | } |
347 | |
348 | tree->setVersion(""); |
349 | Generator::terminate(); |
350 | CodeParser::terminate(); |
351 | CodeMarker::terminate(); |
352 | Doc::terminate(); |
353 | Tokenizer::terminate(); |
354 | Location::terminate(); |
355 | QDir::setCurrent(prevCurrentDir); |
356 | |
357 | #ifndef QT_NO_TRANSLATION |
358 | qDeleteAll(translators); |
359 | #endif |
360 | #ifdef DEBUG_SHUTDOWN_CRASH |
361 | qDebug() << "main(): Delete tree"; |
362 | #endif |
363 | delete tree; |
364 | #ifdef DEBUG_SHUTDOWN_CRASH |
365 | qDebug() << "main(): Tree deleted"; |
366 | #endif |
367 | } |
368 | |
369 | QT_END_NAMESPACE |
370 | |
371 | int main(int argc, char **argv) |
372 | { |
373 | QT_USE_NAMESPACE |
374 | |
375 | #ifndef QT_BOOTSTRAPPED |
376 | QCoreApplication app(argc, argv); |
377 | #endif |
378 | |
379 | /* |
380 | Create code parsers for the languages to be parsed, |
381 | and create a tree for C++. |
382 | */ |
383 | CppCodeParser cppParser; |
384 | QmlCodeParser qmlParser; |
385 | PureDocParser docParser; |
386 | |
387 | /* |
388 | Create code markers for plain text and C++. |
389 | */ |
390 | PlainCodeMarker plainMarker; |
391 | CppCodeMarker cppMarker; |
392 | JsCodeMarker jsMarker; |
393 | QmlCodeMarker qmlMarker; |
394 | |
395 | HtmlGenerator htmlGenerator; |
396 | DitaXmlGenerator ditaxmlGenerator; |
397 | |
398 | QStringList qdocFiles; |
399 | QString opt; |
400 | int i = 1; |
401 | |
402 | while (i < argc) { |
403 | opt = argv[i++]; |
404 | |
405 | if (opt == "-help") { |
406 | printHelp(); |
407 | return EXIT_SUCCESS; |
408 | } |
409 | else if (opt == "-version") { |
410 | printVersion(); |
411 | return EXIT_SUCCESS; |
412 | } |
413 | else if (opt == "--") { |
414 | while (i < argc) |
415 | qdocFiles.append(argv[i++]); |
416 | } |
417 | else if (opt.startsWith("-D")) { |
418 | QString define = opt.mid(2); |
419 | defines += define; |
420 | } |
421 | else if (opt == "-slow") { |
422 | slow = true; |
423 | } |
424 | else if (opt == "-showinternal") { |
425 | showInternal = true; |
426 | } |
427 | else if (opt == "-obsoletelinks") { |
428 | obsoleteLinks = true; |
429 | } |
430 | else { |
431 | qdocFiles.append(opt); |
432 | } |
433 | } |
434 | |
435 | if (qdocFiles.isEmpty()) { |
436 | printHelp(); |
437 | return EXIT_FAILURE; |
438 | } |
439 | |
440 | /* |
441 | Main loop. |
442 | */ |
443 | foreach (QString qf, qdocFiles) { |
444 | //qDebug() << "PROCESSING:" << qf; |
445 | processQdocconfFile(qf); |
446 | } |
447 | |
448 | qDeleteAll(trees); |
449 | return EXIT_SUCCESS; |
450 | } |
451 | |
452 |
Warning: That file was not part of the compilation database. It may have many parsing errors.