Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
5#include "logging.h"
8#include "scanner.h"
9
10#include <QtCore/qcommandlineparser.h>
11#include <QtCore/qcoreapplication.h>
12#include <QtCore/qdir.h>
13#include <QtCore/qfile.h>
14
15#include <iostream>
16
17using namespace Qt::Literals::StringLiterals;
18
19int main(int argc, char *argv[])
20{
21 QCoreApplication a(argc, argv);
22 a.setApplicationName(u"Qt Attributions Scanner"_s);
23 a.setApplicationVersion(u"1.3"_s);
24
25 QCommandLineParser parser;
26 parser.setApplicationDescription(tr("Processes attribution files in Qt sources."));
27 parser.addPositionalArgument(u"paths"_s,
28 tr("Paths to qt_attribution.json/README.chromium files, "
29 "or directories to be scannned recursively."));
30 parser.addHelpOption();
31 parser.addVersionOption();
32
33 QCommandLineOption generatorOption(u"output-format"_s,
34 tr("Output format (\"qdoc\", \"json\")."),
35 u"generator"_s, u"qdoc"_s);
36 QCommandLineOption inputFormatOption(u"input-files"_s,
37 tr("Input files (\"qt_attributions\" scans for "
38 "qt_attribution.json, \"chromium_attributions\" for "
39 "README.Chromium, \"all\" for both)."),
40 u"input_format"_s,
41 u"qt_attributions"_s);
42 QCommandLineOption filterOption(u"filter"_s,
43 tr("Filter packages according to <filter> "
44 "(e.g. QDocModule=qtcore)"),
45 u"expression"_s);
46 QCommandLineOption baseDirOption(u"basedir"_s,
47 tr("Paths in documentation are made relative to this "
48 "directory."),
49 u"directory"_s);
50 QCommandLineOption noCheckPathsOption(
51 u"no-check-paths"_s,
52 tr("Do not check whether referenced file paths exist in basedir."));
53 QCommandLineOption outputOption({ u"o"_s, u"output"_s },
54 tr("Write generated data to <file>."),
55 u"file"_s);
56 QCommandLineOption verboseOption(u"verbose"_s, tr("Verbose output."));
57 QCommandLineOption silentOption({ u"s"_s, u"silent"_s }, tr("Minimal output."));
58
59 parser.addOption(generatorOption);
60 parser.addOption(inputFormatOption);
61 parser.addOption(filterOption);
62 parser.addOption(baseDirOption);
63 parser.addOption(noCheckPathsOption);
64 parser.addOption(outputOption);
65 parser.addOption(verboseOption);
66 parser.addOption(silentOption);
67
68 parser.process(a.arguments());
69
70 using Scanner::Checks, Scanner::Check;
71 Checks checks = Check::All;
72 checks.setFlag(Check::Paths, !parser.isSet(noCheckPathsOption));
73
74 LogLevel logLevel = NormalLog;
75 if (parser.isSet(verboseOption) && parser.isSet(silentOption)) {
76 std::cerr << qPrintable(tr("--verbose and --silent cannot be set simultaneously.")) << std::endl;
77 parser.showHelp(1);
78 }
79
80 if (parser.isSet(verboseOption))
81 logLevel = VerboseLog;
82 else if (parser.isSet(silentOption))
83 logLevel = SilentLog;
84
85 if (parser.positionalArguments().size() == 0)
86 parser.showHelp(2);
87
88 const QStringList paths = parser.positionalArguments();
89
90 QString inputFormat = parser.value(inputFormatOption);
91 Scanner::InputFormats formats;
92 if (inputFormat == "qt_attributions"_L1)
94 else if (inputFormat == "chromium_attributions"_L1)
96 else if (inputFormat == "all"_L1)
98 else {
99 std::cerr << qPrintable(tr("%1 is not a valid input-files argument").arg(inputFormat)) << std::endl << std::endl;
100 parser.showHelp(8);
101 }
102
103 // Parse the attribution files
104 QList<Package> packages;
105 for (const QString &path: paths) {
106 const QFileInfo pathInfo(path);
107 if (pathInfo.isDir()) {
108 if (logLevel == VerboseLog)
109 std::cerr << qPrintable(tr("Recursively scanning %1 for attribution files...").arg(
110 QDir::toNativeSeparators(path))) << std::endl;
111 std::optional<QList<Package>> p
112 = Scanner::scanDirectory(path, formats, checks, logLevel);
113 if (!p)
114 return 1;
115 packages.append(*p);
116 } else if (pathInfo.isFile()) {
117 std::optional<QList<Package>> p = Scanner::readFile(path, checks, logLevel);
118 if (!p)
119 return 1;
120 packages.append(*p);
121
122 } else {
123 std::cerr << qPrintable(tr("%1 is not a valid file or directory.").arg(
124 QDir::toNativeSeparators(path))) << std::endl << std::endl;
125 parser.showHelp(7);
126 }
127 }
128
129 // Apply the filter
130 if (parser.isSet(filterOption)) {
131 PackageFilter filter(parser.value(filterOption));
132 if (filter.type == PackageFilter::InvalidFilter)
133 return 4;
134 packages.erase(std::remove_if(packages.begin(), packages.end(),
135 [&filter](const Package &p) { return !filter(p); }),
136 packages.end());
137 }
138
139 if (logLevel == VerboseLog)
140 std::cerr << qPrintable(tr("%1 packages found.").arg(packages.size())) << std::endl;
141
142 // Prepare the output text stream
143 QFile outFile(parser.value(outputOption));
144 QTextStream out(stdout);
145 if (!outFile.fileName().isEmpty()) {
146 if (!outFile.open(QFile::WriteOnly)) {
147 std::cerr << qPrintable(tr("Cannot open %1 for writing.").arg(
148 QDir::toNativeSeparators(outFile.fileName())))
149 << std::endl;
150 return 5;
151 }
152 out.setDevice(&outFile);
153 }
154
155 // Generate the output and write it
156 QString generator = parser.value(generatorOption);
157 if (generator == "qdoc"_L1) {
158 QString baseDirectory = parser.value(baseDirOption);
159 if (baseDirectory.isEmpty()) {
160 if (paths.size() != 1) {
161 std::cerr << qPrintable(tr("baseDir option is not optional."));
162 return 1;
163 }
164
165 const QFileInfo pathInfo(paths.last());
166 if (pathInfo.isDir()) {
167 // include top level module name in printed paths
168 baseDirectory = pathInfo.dir().absoluteFilePath(u".."_s);
169 } else {
170 baseDirectory = pathInfo.absoluteDir().absoluteFilePath(u".."_s);
171 }
172 }
173
174 QDocGenerator::generate(out, packages, baseDirectory, logLevel);
175 } else if (generator == "json"_L1) {
176 JsonGenerator::generate(out, packages, logLevel);
177 } else {
178 std::cerr << qPrintable(tr("Unknown output-format %1.").arg(generator)) << std::endl;
179 return 6;
180 }
181
182 if (logLevel == VerboseLog)
183 std::cerr << qPrintable(tr("Processing is done.")) << std::endl;
184
185 return 0;
186}
int main(int argc, char *argv[])
[2]
Definition buffer.cpp:77
InputFormat
Definition scanner.h:17
LogLevel
Definition logging.h:9
@ NormalLog
Definition logging.h:11
@ SilentLog
Definition logging.h:12
@ VerboseLog
Definition logging.h:10
void generate(QTextStream &out, const QList< Package > &packages, LogLevel logLevel)
void generate(QTextStream &out, const QList< Package > &packages, const QString &baseDirectory, LogLevel logLevel)