1 | // Copyright (C) 2021 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
3 | |
4 | #ifndef CONFIG_H |
5 | #define CONFIG_H |
6 | |
7 | #include "location.h" |
8 | #include "qdoccommandlineparser.h" |
9 | #include "singleton.h" |
10 | |
11 | #include <QtCore/qmap.h> |
12 | #include <QtCore/qset.h> |
13 | #include <QtCore/qstack.h> |
14 | #include <QtCore/qstringlist.h> |
15 | |
16 | #include <utility> |
17 | |
18 | QT_BEGIN_NAMESPACE |
19 | |
20 | class Config; |
21 | |
22 | /* |
23 | Contains information about a location |
24 | where a ConfigVar string needs to be expanded |
25 | from another config variable. |
26 | */ |
27 | struct ExpandVar |
28 | { |
29 | int m_valueIndex {}; |
30 | int m_index {}; |
31 | QString m_var {}; |
32 | QChar m_delim {}; |
33 | |
34 | ExpandVar(int valueIndex, int index, QString var, const QChar &delim) |
35 | : m_valueIndex(valueIndex), m_index(index), m_var(std::move(var)), m_delim(delim) |
36 | { |
37 | } |
38 | }; |
39 | |
40 | class ConfigVar |
41 | { |
42 | public: |
43 | struct ConfigValue { |
44 | QString m_value; |
45 | QString m_path; |
46 | }; |
47 | |
48 | [[nodiscard]] QString asString(const QString defaultString = QString()) const; |
49 | [[nodiscard]] QStringList asStringList() const; |
50 | [[nodiscard]] QSet<QString> asStringSet() const; |
51 | [[nodiscard]] bool asBool() const; |
52 | [[nodiscard]] int asInt() const; |
53 | [[nodiscard]] const Location &location() const { return m_location; } |
54 | |
55 | ConfigVar() = default; |
56 | ConfigVar(QString name, const QStringList &values, const QString &dir, |
57 | const Location &loc = Location(), |
58 | const QList<ExpandVar> &expandVars = QList<ExpandVar>()) |
59 | : m_name(std::move(name)), m_location(loc), m_expandVars(expandVars) |
60 | { |
61 | for (const auto &v : values) |
62 | m_values << ConfigValue {.m_value: v, .m_path: dir}; |
63 | } |
64 | |
65 | private: |
66 | void append(const ConfigVar &other); |
67 | |
68 | private: |
69 | QString m_name {}; |
70 | QList<ConfigValue> m_values {}; |
71 | Location m_location {}; |
72 | QList<ExpandVar> m_expandVars {}; |
73 | |
74 | friend class Config; |
75 | }; |
76 | |
77 | /* |
78 | In this multimap, the key is a config variable name. |
79 | */ |
80 | typedef QMap<QString, ConfigVar> ConfigVarMap; |
81 | |
82 | class Config : public Singleton<Config> |
83 | { |
84 | public: |
85 | ~Config(); |
86 | |
87 | enum QDocPass { Neither, Prepare, Generate }; |
88 | |
89 | enum PathFlags : unsigned char { |
90 | None = 0x0, |
91 | // TODO: [unenforced-unclear-validation] |
92 | // The Validate flag is used, for example, during the retrival |
93 | // of paths in getCanonicalPathList. |
94 | // It is unclear what kind of validation it performs, if any, |
95 | // and when this validation is required. |
96 | // Instead, remove this kind of flag and ensure that any |
97 | // amount of required validation is performed during the |
98 | // parsing step, if possilbe, and only once. |
99 | // Furthemore, ensure any such validation removes some |
100 | // uncertainty on dependent subsystems, moving constraints to |
101 | // preconditions and expressing them at the API boundaries. |
102 | Validate = 0x1, |
103 | IncludePaths = 0x2 |
104 | }; |
105 | |
106 | void init(const QString &programName, const QStringList &args); |
107 | [[nodiscard]] bool getDebug() const { return m_debug; } |
108 | [[nodiscard]] bool getAtomsDump() const { return m_atomsDump; } |
109 | [[nodiscard]] bool showInternal() const { return m_showInternal; } |
110 | |
111 | void clear(); |
112 | void reset(); |
113 | void load(const QString &fileName); |
114 | void setStringList(const QString &var, const QStringList &values); |
115 | void insertStringList(const QString &var, const QStringList &values); |
116 | |
117 | void showHelp(int exitCode = 0) { m_parser.showHelp(exitCode); } |
118 | [[nodiscard]] QStringList qdocFiles() const { return m_parser.positionalArguments(); } |
119 | [[nodiscard]] const QString &programName() const { return m_prog; } |
120 | [[nodiscard]] const Location &location() const { return m_location; } |
121 | [[nodiscard]] const ConfigVar &get(const QString &var) const |
122 | { |
123 | // Avoid injecting default-constructed values to map if var doesn't exist |
124 | static ConfigVar empty; |
125 | auto it = m_configVars.constFind(key: var); |
126 | return (it != m_configVars.constEnd()) ? *it : empty; |
127 | } |
128 | [[nodiscard]] QString getOutputDir(const QString &format = QString("HTML" )) const; |
129 | [[nodiscard]] QSet<QString> getOutputFormats() const; |
130 | [[nodiscard]] QStringList getCanonicalPathList(const QString &var, |
131 | PathFlags flags = None) const; |
132 | [[nodiscard]] QRegularExpression getRegExp(const QString &var) const; |
133 | [[nodiscard]] QList<QRegularExpression> getRegExpList(const QString &var) const; |
134 | [[nodiscard]] QSet<QString> subVars(const QString &var) const; |
135 | QStringList getAllFiles(const QString &filesVar, const QString &dirsVar, |
136 | const QSet<QString> &excludedDirs = QSet<QString>(), |
137 | const QSet<QString> &excludedFiles = QSet<QString>()); |
138 | [[nodiscard]] QString getIncludeFilePath(const QString &fileName) const; |
139 | QStringList getExampleQdocFiles(const QSet<QString> &excludedDirs, |
140 | const QSet<QString> &excludedFiles); |
141 | QStringList getExampleImageFiles(const QSet<QString> &excludedDirs, |
142 | const QSet<QString> &excludedFiles); |
143 | QString getExampleProjectFile(const QString &examplePath); |
144 | |
145 | static QStringList loadMaster(const QString &fileName); |
146 | static bool isFileExcluded(const QString &fileName, const QSet<QString> &excludedFiles); |
147 | static QStringList getFilesHere(const QString &dir, const QString &nameFilter, |
148 | const Location &location = Location(), |
149 | const QSet<QString> &excludedDirs = QSet<QString>(), |
150 | const QSet<QString> &excludedFiles = QSet<QString>()); |
151 | static QString findFile(const Location &location, const QStringList &files, |
152 | const QStringList &dirs, const QString &fileName, |
153 | QString *userFriendlyFilePath = nullptr); |
154 | static QString copyFile(const Location &location, const QString &sourceFilePath, |
155 | const QString &userFriendlySourceFilePath, |
156 | const QString &targetDirPath); |
157 | static int numParams(const QString &value); |
158 | static void pushWorkingDir(const QString &dir); |
159 | static void popWorkingDir(); |
160 | |
161 | static const QString dot; |
162 | |
163 | static bool generateExamples; |
164 | static QString installDir; |
165 | static QString overrideOutputDir; |
166 | static QSet<QString> overrideOutputFormats; |
167 | |
168 | [[nodiscard]] inline bool singleExec() const; |
169 | [[nodiscard]] inline bool dualExec() const; |
170 | QStringList &defines() { return m_defines; } |
171 | QStringList &dependModules() { return m_dependModules; } |
172 | QStringList &includePaths() { return m_includePaths; } |
173 | QStringList &indexDirs() { return m_indexDirs; } |
174 | [[nodiscard]] QString currentDir() const { return m_currentDir; } |
175 | void setCurrentDir(const QString &path) { m_currentDir = path; } |
176 | [[nodiscard]] QString previousCurrentDir() const { return m_previousCurrentDir; } |
177 | void setPreviousCurrentDir(const QString &path) { m_previousCurrentDir = path; } |
178 | |
179 | void setQDocPass(const QDocPass &pass) { m_qdocPass = pass; }; |
180 | [[nodiscard]] bool preparing() const { return (m_qdocPass == Prepare); } |
181 | [[nodiscard]] bool generating() const { return (m_qdocPass == Generate); } |
182 | |
183 | private: |
184 | void processCommandLineOptions(const QStringList &args); |
185 | void setIncludePaths(); |
186 | void setIndexDirs(); |
187 | void expandVariables(); |
188 | |
189 | QStringList m_dependModules {}; |
190 | QStringList m_defines {}; |
191 | QStringList m_includePaths {}; |
192 | QStringList m_indexDirs {}; |
193 | QStringList m_exampleFiles {}; |
194 | QStringList m_exampleDirs {}; |
195 | QString m_currentDir {}; |
196 | QString m_previousCurrentDir {}; |
197 | |
198 | bool m_showInternal { false }; |
199 | static bool m_debug; |
200 | |
201 | // An option that can be set trough a similarly named command-line option. |
202 | // When this is set, every time QDoc parses a block-comment, a |
203 | // human-readable presentation of the `Atom`s structure for that |
204 | // block will shown to the user. |
205 | static bool m_atomsDump; |
206 | |
207 | static bool isMetaKeyChar(QChar ch); |
208 | void load(Location location, const QString &fileName); |
209 | |
210 | QString m_prog {}; |
211 | Location m_location {}; |
212 | ConfigVarMap m_configVars {}; |
213 | |
214 | static QMap<QString, QString> ; |
215 | static QStack<QString> m_workingDirs; |
216 | static QMap<QString, QStringList> m_includeFilesMap; |
217 | QDocCommandLineParser m_parser {}; |
218 | |
219 | QDocPass m_qdocPass { Neither }; |
220 | }; |
221 | |
222 | struct ConfigStrings |
223 | { |
224 | static QString ALIAS; |
225 | static QString AUTOLINKERRORS; |
226 | static QString BUILDVERSION; |
227 | static QString CLANGDEFINES; |
228 | static QString CODEINDENT; |
229 | static QString CODEPREFIX; |
230 | static QString CODESUFFIX; |
231 | static QString CPPCLASSESPAGE; |
232 | static QString CPPCLASSESTITLE; |
233 | static QString DEFINES; |
234 | static QString DEPENDS; |
235 | static QString DESCRIPTION; |
236 | static QString DOCBOOKEXTENSIONS; |
237 | static QString ; |
238 | static QString EXAMPLEDIRS; |
239 | static QString EXAMPLES; |
240 | static QString EXAMPLESINSTALLPATH; |
241 | static QString EXCLUDEDIRS; |
242 | static QString EXCLUDEFILES; |
243 | static QString ; |
244 | static QString FALSEHOODS; |
245 | static QString FORMATTING; |
246 | static QString ; |
247 | static QString ; |
248 | static QString ; |
249 | static QString ; |
250 | static QString HOMEPAGE; |
251 | static QString HOMETITLE; |
252 | static QString IGNOREDIRECTIVES; |
253 | static QString IGNORETOKENS; |
254 | static QString IGNORESINCE; |
255 | static QString IGNOREWORDS; |
256 | static QString IMAGEDIRS; |
257 | static QString IMAGES; |
258 | static QString INCLUDEPATHS; |
259 | static QString INCLUSIVE; |
260 | static QString INDEXES; |
261 | static QString LANDINGPAGE; |
262 | static QString LANDINGTITLE; |
263 | static QString LANGUAGE; |
264 | static QString LOCATIONINFO; |
265 | static QString LOGPROGRESS; |
266 | static QString MACRO; |
267 | static QString MANIFESTMETA; |
268 | static QString ; |
269 | static QString NATURALLANGUAGE; |
270 | static QString NAVIGATION; |
271 | static QString NOLINKERRORS; |
272 | static QString OUTPUTDIR; |
273 | static QString OUTPUTFORMATS; |
274 | static QString OUTPUTPREFIXES; |
275 | static QString OUTPUTSUFFIXES; |
276 | static QString PROJECT; |
277 | static QString REDIRECTDOCUMENTATIONTODEVNULL; |
278 | static QString QHP; |
279 | static QString QUOTINGINFORMATION; |
280 | static QString SCRIPTS; |
281 | static QString SHOWINTERNAL; |
282 | static QString SINGLEEXEC; |
283 | static QString SOURCEDIRS; |
284 | static QString SOURCEENCODING; |
285 | static QString SOURCES; |
286 | static QString SPURIOUS; |
287 | static QString STYLESHEETS; |
288 | static QString SYNTAXHIGHLIGHTING; |
289 | static QString TABSIZE; |
290 | static QString TAGFILE; |
291 | static QString TIMESTAMPS; |
292 | static QString TOCTITLES; |
293 | static QString URL; |
294 | static QString VERSION; |
295 | static QString VERSIONSYM; |
296 | static QString FILEEXTENSIONS; |
297 | static QString IMAGEEXTENSIONS; |
298 | static QString QMLTYPESPAGE; |
299 | static QString QMLTYPESTITLE; |
300 | static QString WARNINGLIMIT; |
301 | }; |
302 | |
303 | #define CONFIG_AUTOLINKERRORS ConfigStrings::AUTOLINKERRORS |
304 | #define CONFIG_BUILDVERSION ConfigStrings::BUILDVERSION |
305 | #define CONFIG_CLANGDEFINES ConfigStrings::CLANGDEFINES |
306 | #define CONFIG_CODEINDENT ConfigStrings::CODEINDENT |
307 | #define CONFIG_CODEPREFIX ConfigStrings::CODEPREFIX |
308 | #define CONFIG_CODESUFFIX ConfigStrings::CODESUFFIX |
309 | #define CONFIG_CPPCLASSESPAGE ConfigStrings::CPPCLASSESPAGE |
310 | #define CONFIG_CPPCLASSESTITLE ConfigStrings::CPPCLASSESTITLE |
311 | #define CONFIG_DEFINES ConfigStrings::DEFINES |
312 | #define CONFIG_DEPENDS ConfigStrings::DEPENDS |
313 | #define CONFIG_DESCRIPTION ConfigStrings::DESCRIPTION |
314 | #define CONFIG_DOCBOOKEXTENSIONS ConfigStrings::DOCBOOKEXTENSIONS |
315 | #define ConfigStrings::ENDHEADER |
316 | #define CONFIG_EXAMPLEDIRS ConfigStrings::EXAMPLEDIRS |
317 | #define CONFIG_EXAMPLES ConfigStrings::EXAMPLES |
318 | #define CONFIG_EXAMPLESINSTALLPATH ConfigStrings::EXAMPLESINSTALLPATH |
319 | #define CONFIG_EXCLUDEDIRS ConfigStrings::EXCLUDEDIRS |
320 | #define CONFIG_EXCLUDEFILES ConfigStrings::EXCLUDEFILES |
321 | #define ConfigStrings::EXTRAIMAGES |
322 | #define CONFIG_FALSEHOODS ConfigStrings::FALSEHOODS |
323 | #define CONFIG_FORMATTING ConfigStrings::FORMATTING |
324 | #define ConfigStrings::HEADERDIRS |
325 | #define ConfigStrings::HEADERS |
326 | #define ConfigStrings::HEADERSCRIPTS |
327 | #define ConfigStrings::HEADERSTYLES |
328 | #define CONFIG_HOMEPAGE ConfigStrings::HOMEPAGE |
329 | #define CONFIG_HOMETITLE ConfigStrings::HOMETITLE |
330 | #define CONFIG_IGNOREDIRECTIVES ConfigStrings::IGNOREDIRECTIVES |
331 | #define CONFIG_IGNORESINCE ConfigStrings::IGNORESINCE |
332 | #define CONFIG_IGNORETOKENS ConfigStrings::IGNORETOKENS |
333 | #define CONFIG_IGNOREWORDS ConfigStrings::IGNOREWORDS |
334 | #define CONFIG_IMAGEDIRS ConfigStrings::IMAGEDIRS |
335 | #define CONFIG_IMAGES ConfigStrings::IMAGES |
336 | #define CONFIG_INCLUDEPATHS ConfigStrings::INCLUDEPATHS |
337 | #define CONFIG_INCLUSIVE ConfigStrings::INCLUSIVE |
338 | #define CONFIG_INDEXES ConfigStrings::INDEXES |
339 | #define CONFIG_LANDINGPAGE ConfigStrings::LANDINGPAGE |
340 | #define CONFIG_LANDINGTITLE ConfigStrings::LANDINGTITLE |
341 | #define CONFIG_LANGUAGE ConfigStrings::LANGUAGE |
342 | #define CONFIG_LOCATIONINFO ConfigStrings::LOCATIONINFO |
343 | #define CONFIG_LOGPROGRESS ConfigStrings::LOGPROGRESS |
344 | #define CONFIG_MACRO ConfigStrings::MACRO |
345 | #define CONFIG_MANIFESTMETA ConfigStrings::MANIFESTMETA |
346 | #define ConfigStrings::MODULEHEADER |
347 | #define CONFIG_NATURALLANGUAGE ConfigStrings::NATURALLANGUAGE |
348 | #define CONFIG_NAVIGATION ConfigStrings::NAVIGATION |
349 | #define CONFIG_NOLINKERRORS ConfigStrings::NOLINKERRORS |
350 | #define CONFIG_OUTPUTDIR ConfigStrings::OUTPUTDIR |
351 | #define CONFIG_OUTPUTFORMATS ConfigStrings::OUTPUTFORMATS |
352 | #define CONFIG_OUTPUTPREFIXES ConfigStrings::OUTPUTPREFIXES |
353 | #define CONFIG_OUTPUTSUFFIXES ConfigStrings::OUTPUTSUFFIXES |
354 | #define CONFIG_PROJECT ConfigStrings::PROJECT |
355 | #define CONFIG_REDIRECTDOCUMENTATIONTODEVNULL ConfigStrings::REDIRECTDOCUMENTATIONTODEVNULL |
356 | #define CONFIG_QHP ConfigStrings::QHP |
357 | #define CONFIG_QUOTINGINFORMATION ConfigStrings::QUOTINGINFORMATION |
358 | #define CONFIG_SCRIPTS ConfigStrings::SCRIPTS |
359 | #define CONFIG_SHOWINTERNAL ConfigStrings::SHOWINTERNAL |
360 | #define CONFIG_SINGLEEXEC ConfigStrings::SINGLEEXEC |
361 | #define CONFIG_SOURCEDIRS ConfigStrings::SOURCEDIRS |
362 | #define CONFIG_SOURCEENCODING ConfigStrings::SOURCEENCODING |
363 | #define CONFIG_SOURCES ConfigStrings::SOURCES |
364 | #define CONFIG_SPURIOUS ConfigStrings::SPURIOUS |
365 | #define CONFIG_STYLESHEETS ConfigStrings::STYLESHEETS |
366 | #define CONFIG_SYNTAXHIGHLIGHTING ConfigStrings::SYNTAXHIGHLIGHTING |
367 | #define CONFIG_TABSIZE ConfigStrings::TABSIZE |
368 | #define CONFIG_TAGFILE ConfigStrings::TAGFILE |
369 | #define CONFIG_TIMESTAMPS ConfigStrings::TIMESTAMPS |
370 | #define CONFIG_TOCTITLES ConfigStrings::TOCTITLES |
371 | #define CONFIG_URL ConfigStrings::URL |
372 | #define CONFIG_VERSION ConfigStrings::VERSION |
373 | #define CONFIG_VERSIONSYM ConfigStrings::VERSIONSYM |
374 | #define CONFIG_FILEEXTENSIONS ConfigStrings::FILEEXTENSIONS |
375 | #define CONFIG_IMAGEEXTENSIONS ConfigStrings::IMAGEEXTENSIONS |
376 | #define CONFIG_QMLTYPESPAGE ConfigStrings::QMLTYPESPAGE |
377 | #define CONFIG_QMLTYPESTITLE ConfigStrings::QMLTYPESTITLE |
378 | #define CONFIG_WARNINGLIMIT ConfigStrings::WARNINGLIMIT |
379 | |
380 | inline bool Config::singleExec() const |
381 | { |
382 | return m_configVars.value(CONFIG_SINGLEEXEC).asBool(); |
383 | } |
384 | |
385 | inline bool Config::dualExec() const |
386 | { |
387 | return !m_configVars.value(CONFIG_SINGLEEXEC).asBool(); |
388 | } |
389 | |
390 | QT_END_NAMESPACE |
391 | |
392 | #endif |
393 | |