1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the tools applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include "qdoccommandlineparser.h"
30 
31 #include "loggingcategory.h"
32 #include "utilities.h"
33 
34 #include <QtCore/qdebug.h>
35 #include <QtCore/qdir.h>
36 #include <QtCore/qfile.h>
37 
QDocCommandLineParser()38 QDocCommandLineParser::QDocCommandLineParser()
39     : QCommandLineParser(),
40       defineOption(QStringList() << QStringLiteral("D")),
41       dependsOption(QStringList() << QStringLiteral("depends")),
42       highlightingOption(QStringList() << QStringLiteral("highlighting")),
43       showInternalOption(QStringList() << QStringLiteral("showinternal")),
44       redirectDocumentationToDevNullOption(QStringList()
45                                            << QStringLiteral("redirect-documentation-to-dev-null")),
46       noExamplesOption(QStringList() << QStringLiteral("no-examples")),
47       indexDirOption(QStringList() << QStringLiteral("indexdir")),
48       installDirOption(QStringList() << QStringLiteral("installdir")),
49       obsoleteLinksOption(QStringList() << QStringLiteral("obsoletelinks")),
50       outputDirOption(QStringList() << QStringLiteral("outputdir")),
51       outputFormatOption(QStringList() << QStringLiteral("outputformat")),
52       noLinkErrorsOption(QStringList() << QStringLiteral("no-link-errors")),
53       autoLinkErrorsOption(QStringList() << QStringLiteral("autolink-errors")),
54       debugOption(QStringList() << QStringLiteral("debug")),
55       prepareOption(QStringList() << QStringLiteral("prepare")),
56       generateOption(QStringList() << QStringLiteral("generate")),
57       logProgressOption(QStringList() << QStringLiteral("log-progress")),
58       singleExecOption(QStringList() << QStringLiteral("single-exec")),
59       writeQaPagesOption(QStringList() << QStringLiteral("write-qa-pages")),
60       includePathOption("I", "Add dir to the include path for header files.", "path"),
61       includePathSystemOption("isystem", "Add dir to the system include path for header files.",
62                               "path"),
63       frameworkOption("F", "Add macOS framework to the include path for header files.",
64                       "framework"),
65       timestampsOption(QStringList() << QStringLiteral("timestamps")),
66       useDocBookExtensions(QStringList() << QStringLiteral("docbook-extensions"))
67 {
68     setApplicationDescription(QCoreApplication::translate("qdoc", "Qt documentation generator"));
69     addHelpOption();
70     addVersionOption();
71 
72     setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
73 
74     addPositionalArgument("file1.qdocconf ...", QCoreApplication::translate("qdoc", "Input files"));
75 
76     defineOption.setDescription(QCoreApplication::translate(
77             "qdoc", "Define the argument as a macro while parsing sources"));
78     defineOption.setValueName(QStringLiteral("macro[=def]"));
79     addOption(defineOption);
80 
81     dependsOption.setDescription(QCoreApplication::translate("qdoc", "Specify dependent modules"));
82     dependsOption.setValueName(QStringLiteral("module"));
83     addOption(dependsOption);
84 
85     highlightingOption.setDescription(QCoreApplication::translate(
86             "qdoc", "Turn on syntax highlighting (makes qdoc run slower)"));
87     addOption(highlightingOption);
88 
89     showInternalOption.setDescription(
90             QCoreApplication::translate("qdoc", "Include content marked internal"));
91     addOption(showInternalOption);
92 
93     redirectDocumentationToDevNullOption.setDescription(
94             QCoreApplication::translate("qdoc",
95                                         "Save all documentation content to /dev/null. Useful if "
96                                         "someone is interested in qdoc errors only."));
97     addOption(redirectDocumentationToDevNullOption);
98 
99     noExamplesOption.setDescription(
100             QCoreApplication::translate("qdoc", "Do not generate documentation for examples"));
101     addOption(noExamplesOption);
102 
103     indexDirOption.setDescription(QCoreApplication::translate(
104             "qdoc", "Specify a directory where QDoc should search for index files to load"));
105     indexDirOption.setValueName(QStringLiteral("dir"));
106     addOption(indexDirOption);
107 
108     installDirOption.setDescription(QCoreApplication::translate(
109             "qdoc",
110             "Specify the directory where the output will be after running \"make install\""));
111     installDirOption.setValueName(QStringLiteral("dir"));
112     addOption(installDirOption);
113 
114     obsoleteLinksOption.setDescription(QCoreApplication::translate(
115             "qdoc", "Report links from obsolete items to non-obsolete items"));
116     addOption(obsoleteLinksOption);
117 
118     outputDirOption.setDescription(QCoreApplication::translate(
119             "qdoc", "Specify output directory, overrides setting in qdocconf file"));
120     outputDirOption.setValueName(QStringLiteral("dir"));
121     addOption(outputDirOption);
122 
123     outputFormatOption.setDescription(QCoreApplication::translate(
124             "qdoc", "Specify output format, overrides setting in qdocconf file"));
125     outputFormatOption.setValueName(QStringLiteral("format"));
126     addOption(outputFormatOption);
127 
128     noLinkErrorsOption.setDescription(
129             QCoreApplication::translate("qdoc", "Do not print link errors (i.e. missing targets)"));
130     addOption(noLinkErrorsOption);
131 
132     autoLinkErrorsOption.setDescription(
133             QCoreApplication::translate("qdoc", "Show errors when automatic linking fails"));
134     addOption(autoLinkErrorsOption);
135 
136     debugOption.setDescription(QCoreApplication::translate("qdoc", "Enable debug output"));
137     addOption(debugOption);
138 
139     prepareOption.setDescription(QCoreApplication::translate(
140             "qdoc", "Run qdoc only to generate an index file, not the docs"));
141     addOption(prepareOption);
142 
143     generateOption.setDescription(QCoreApplication::translate(
144             "qdoc", "Run qdoc to read the index files and generate the docs"));
145     addOption(generateOption);
146 
147     logProgressOption.setDescription(
148             QCoreApplication::translate("qdoc", "Log progress on stderr."));
149     addOption(logProgressOption);
150 
151     singleExecOption.setDescription(
152             QCoreApplication::translate("qdoc", "Run qdoc once over all the qdoc conf files."));
153     addOption(singleExecOption);
154 
155     writeQaPagesOption.setDescription(QCoreApplication::translate("qdoc", "Write QA pages."));
156     addOption(writeQaPagesOption);
157 
158     includePathOption.setFlags(QCommandLineOption::ShortOptionStyle);
159     addOption(includePathOption);
160 
161     addOption(includePathSystemOption);
162 
163     frameworkOption.setFlags(QCommandLineOption::ShortOptionStyle);
164     addOption(frameworkOption);
165 
166     timestampsOption.setDescription(
167             QCoreApplication::translate("qdoc", "Timestamp each qdoc log line."));
168     addOption(timestampsOption);
169 
170     useDocBookExtensions.setDescription(QCoreApplication::translate(
171             "qdoc", "Use the DocBook Library extensions for metadata."));
172     addOption(useDocBookExtensions);
173 }
174 
175 /*!
176  * \internal
177  *
178  * Create a list of arguments from the command line and/or file(s).
179  * This lets QDoc accept arguments contained in a file provided as a
180  * command-line argument prepended by '@'.
181  */
argumentsFromCommandLineAndFile(const QStringList & arguments)182 static QStringList argumentsFromCommandLineAndFile(const QStringList &arguments)
183 {
184     QStringList allArguments;
185     allArguments.reserve(arguments.size());
186     for (const QString &argument : arguments) {
187         // "@file" doesn't start with a '-' so we can't use QCommandLineParser for it
188         if (argument.startsWith(QLatin1Char('@'))) {
189             QString optionsFile = argument;
190             optionsFile.remove(0, 1);
191             if (optionsFile.isEmpty())
192                 qFatal("The @ option requires an input file");
193             QFile f(optionsFile);
194             if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
195                 qFatal("Cannot open options file specified with @: %ls",
196                        qUtf16Printable(optionsFile));
197             while (!f.atEnd()) {
198                 QString line = QString::fromLocal8Bit(f.readLine().trimmed());
199                 if (!line.isEmpty())
200                     allArguments << line;
201             }
202         } else {
203             allArguments << argument;
204         }
205     }
206     return allArguments;
207 }
208 
process(const QStringList & arguments)209 void QDocCommandLineParser::process(const QStringList &arguments)
210 {
211     auto allArguments = argumentsFromCommandLineAndFile(arguments);
212     QCommandLineParser::process(allArguments);
213 
214     if (isSet(singleExecOption) && isSet(indexDirOption))
215         qDebug("WARNING: -indexdir option ignored: Index files are not used in single-exec mode.");
216 }
217