aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2023-09-14 10:44:35 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2023-09-20 14:55:46 +0200
commit95314e809969bf38714a7b63651ce877621618d8 (patch)
tree77e960cf40ff6db1c5a98f58ff8c01bdef6e5763 /sources/shiboken6
parented069c99be37364bf28ff3834d9e635389ea7af6 (diff)
shiboken6: Move options parsing into API extractor
Similar to the previous change for the TypeDatabase, add an OptionsParser for ApiExtractor and let it handle the its options directly instead of passing them from main. via ApiExtractor. Many ApiExtractor setters can then be removed. Pick-to: 6.6 Change-Id: I3fe37e2903edcc4f6e4a91181917d008df1e5ca8 Reviewed-by: Shyamnath Premnadh <Shyamnath.Premnadh@qt.io>
Diffstat (limited to 'sources/shiboken6')
-rw-r--r--sources/shiboken6/ApiExtractor/apiextractor.cpp221
-rw-r--r--sources/shiboken6/ApiExtractor/apiextractor.h12
-rw-r--r--sources/shiboken6/ApiExtractor/messages.cpp5
-rw-r--r--sources/shiboken6/ApiExtractor/messages.h2
-rw-r--r--sources/shiboken6/generator/main.cpp140
5 files changed, 199 insertions, 181 deletions
diff --git a/sources/shiboken6/ApiExtractor/apiextractor.cpp b/sources/shiboken6/ApiExtractor/apiextractor.cpp
index c754d01e0..7b8ddf340 100644
--- a/sources/shiboken6/ApiExtractor/apiextractor.cpp
+++ b/sources/shiboken6/ApiExtractor/apiextractor.cpp
@@ -13,6 +13,7 @@
#include "exception.h"
#include "messages.h"
#include "modifications.h"
+#include "optionsparser.h"
#include "reporthandler.h"
#include "typedatabase.h"
#include "customconversion.h"
@@ -42,7 +43,181 @@ struct InstantiationCollectContext
QStringList instantiatedContainersNames;
};
-struct ApiExtractorPrivate
+struct ApiExtractorOptions
+{
+ QString m_typeSystemFileName;
+ QFileInfoList m_cppFileNames;
+ HeaderPaths m_includePaths;
+ QStringList m_clangOptions;
+ QString m_logDirectory;
+ LanguageLevel m_languageLevel = LanguageLevel::Default;
+ bool m_skipDeprecated = false;
+};
+
+static inline QString languageLevelDescription()
+{
+ return u"C++ Language level (c++11..c++17, default="_s
+ + QLatin1StringView(clang::languageLevelOption(clang::emulatedCompilerLanguageLevel()))
+ + u')';
+}
+
+QList<OptionDescription> ApiExtractor::options()
+{
+ return {
+ {u"use-global-header"_s,
+ u"Use the global headers in generated code."_s},
+ {u"clang-option"_s,
+ u"Option to be passed to clang"_s},
+ {u"clang-options"_s,
+ u"A comma-separated list of options to be passed to clang"_s},
+ {u"skip-deprecated"_s,
+ u"Skip deprecated functions"_s},
+ {u"-F<path>"_s, {} },
+ {u"framework-include-paths="_s + OptionsParser::pathSyntax(),
+ u"Framework include paths used by the C++ parser"_s},
+ {u"-isystem<path>"_s, {} },
+ {u"system-include-paths="_s + OptionsParser::pathSyntax(),
+ u"System include paths used by the C++ parser"_s},
+ {u"language-level=, -std=<level>"_s,
+ languageLevelDescription()},
+ };
+}
+
+class ApiExtractorOptionsParser : public OptionsParser
+{
+public:
+ explicit ApiExtractorOptionsParser(ApiExtractorOptions *o) : m_options(o) {}
+
+ bool handleBoolOption(const QString &key, OptionSource source) override;
+ bool handleOption(const QString &key, const QString &value,
+ OptionSource source) override;
+
+private:
+ void parseIncludePathOption(const QString &value, HeaderType headerType);
+ void parseIncludePathOption(const QStringList &values, HeaderType headerType);
+ void setLanguageLevel(const QString &value);
+
+ ApiExtractorOptions *m_options;
+};
+
+void ApiExtractorOptionsParser::parseIncludePathOption(const QString &value,
+ HeaderType headerType)
+{
+ const auto path = QFile::encodeName(QDir::cleanPath(value));
+ m_options->m_includePaths.append(HeaderPath{path, headerType});
+}
+
+void ApiExtractorOptionsParser::parseIncludePathOption(const QStringList &values,
+ HeaderType headerType)
+{
+ for (const auto &value : values)
+ parseIncludePathOption(value, headerType);
+}
+
+void ApiExtractorOptionsParser::setLanguageLevel(const QString &value)
+{
+ const QByteArray languageLevelBA = value.toLatin1();
+ const LanguageLevel level = clang::languageLevelFromOption(languageLevelBA.constData());
+ if (level == LanguageLevel::Default)
+ throw Exception(msgInvalidLanguageLevel(value));
+ m_options->m_languageLevel = level;
+}
+
+bool ApiExtractorOptionsParser::handleBoolOption(const QString &key, OptionSource source)
+{
+ static const auto isystemOption = "isystem"_L1;
+
+ switch (source) {
+ case OptionSource::CommandLine:
+ case OptionSource::ProjectFile:
+ if (key == u"use-global-header") {
+ AbstractMetaBuilder::setUseGlobalHeader(true);
+ return true;
+ }
+ if (key == u"skip-deprecated") {
+ m_options->m_skipDeprecated = true;
+ return true;
+ }
+ break;
+
+ case OptionSource::CommandLineSingleDash:
+ if (key.startsWith(u'I')) { // Shorthand path arguments -I/usr/include...
+ parseIncludePathOption(key.sliced(1), HeaderType::Standard);
+ return true;
+ }
+ if (key.startsWith(u'F')) {
+ parseIncludePathOption(key.sliced(1), HeaderType::Framework);
+ return true;
+ }
+ if (key.startsWith(isystemOption)) {
+ parseIncludePathOption(key.sliced(isystemOption.size()), HeaderType::System);
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+bool ApiExtractorOptionsParser::handleOption(const QString &key, const QString &value,
+ OptionSource source)
+{
+ if (source == OptionSource::CommandLineSingleDash) {
+ if (key == u"std") {
+ setLanguageLevel(value);
+ return true;
+ }
+ return false;
+ }
+
+ if (key == u"clang-option") {
+ m_options->m_clangOptions.append(value);
+ return true;
+ }
+ if (key == u"clang-options") {
+ m_options->m_clangOptions.append(value.split(u','));
+ return true;
+ }
+ if (key == u"include-paths") {
+ parseIncludePathOption(value.split(QDir::listSeparator()), HeaderType::Standard);
+ return true;
+ }
+ if (key == u"framework-include-paths") {
+ parseIncludePathOption(value.split(QDir::listSeparator()), HeaderType::Framework);
+ return true;
+ }
+ if (key == u"system-include-paths") {
+ parseIncludePathOption(value.split(QDir::listSeparator()), HeaderType::System);
+ return true;
+ }
+ if (key == u"language-level") {
+ setLanguageLevel(value);
+ return true;
+ }
+
+ if (source == OptionSource::ProjectFile) {
+ if (key == u"include-path") {
+ parseIncludePathOption(value, HeaderType::Standard);
+ return true;
+ }
+ if (key == u"framework-include-path") {
+ parseIncludePathOption(value, HeaderType::Framework);
+ return true;
+ }
+ if (key == u"system-include-path") {
+ parseIncludePathOption(value, HeaderType::System);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+std::shared_ptr<OptionsParser> ApiExtractor::createOptionsParser()
+{
+ return std::make_shared<ApiExtractorOptionsParser>(d);
+}
+
+struct ApiExtractorPrivate : public ApiExtractorOptions
{
bool runHelper(ApiExtractorFlags flags);
@@ -63,14 +238,7 @@ struct ApiExtractorPrivate
void addInstantiatedSmartPointer(InstantiationCollectContext &context,
const AbstractMetaType &type);
- QString m_typeSystemFileName;
- QFileInfoList m_cppFileNames;
- HeaderPaths m_includePaths;
- QStringList m_clangOptions;
AbstractMetaBuilder *m_builder = nullptr;
- QString m_logDirectory;
- LanguageLevel m_languageLevel = LanguageLevel::Default;
- bool m_skipDeprecated = false;
};
ApiExtractor::ApiExtractor() :
@@ -84,16 +252,6 @@ ApiExtractor::~ApiExtractor()
delete d;
}
-void ApiExtractor::addIncludePath(const HeaderPath& path)
-{
- d->m_includePaths << path;
-}
-
-void ApiExtractor::addIncludePath(const HeaderPaths& paths)
-{
- d->m_includePaths << paths;
-}
-
HeaderPaths ApiExtractor::includePaths() const
{
return d->m_includePaths;
@@ -124,18 +282,6 @@ QString ApiExtractor::typeSystem() const
return d->m_typeSystemFileName;
}
-void ApiExtractor::setSkipDeprecated(bool value)
-{
- d->m_skipDeprecated = value;
- if (d->m_builder)
- d->m_builder->setSkipDeprecated(d->m_skipDeprecated);
-}
-
-void ApiExtractor::setSilent ( bool value )
-{
- ReportHandler::setSilent(value);
-}
-
const AbstractMetaEnumList &ApiExtractor::globalEnums() const
{
Q_ASSERT(d->m_builder);
@@ -281,26 +427,11 @@ LanguageLevel ApiExtractor::languageLevel() const
return d->m_languageLevel;
}
-void ApiExtractor::setLanguageLevel(LanguageLevel languageLevel)
-{
- d->m_languageLevel = languageLevel;
-}
-
QStringList ApiExtractor::clangOptions() const
{
return d->m_clangOptions;
}
-void ApiExtractor::setClangOptions(const QStringList &co)
-{
- d->m_clangOptions = co;
-}
-
-void ApiExtractor::setUseGlobalHeader(bool h)
-{
- AbstractMetaBuilder::setUseGlobalHeader(h);
-}
-
AbstractMetaFunctionPtr
ApiExtractor::inheritTemplateFunction(const AbstractMetaFunctionCPtr &function,
const AbstractMetaTypeList &templateTypes)
diff --git a/sources/shiboken6/ApiExtractor/apiextractor.h b/sources/shiboken6/ApiExtractor/apiextractor.h
index ef8e1b958..feae9454c 100644
--- a/sources/shiboken6/ApiExtractor/apiextractor.h
+++ b/sources/shiboken6/ApiExtractor/apiextractor.h
@@ -20,6 +20,8 @@ class AbstractMetaClass;
class AbstractMetaEnum;
class AbstractMetaFunction;
class ComplexTypeEntry;
+struct OptionDescription;
+class OptionsParser;
QT_BEGIN_NAMESPACE
class QDebug;
@@ -36,21 +38,17 @@ public:
ApiExtractor();
~ApiExtractor();
+ static QList<OptionDescription> options();
+ std::shared_ptr<OptionsParser> createOptionsParser();
+
void setTypeSystem(const QString& typeSystemFileName);
QString typeSystem() const;
void setCppFileNames(const QFileInfoList &cppFileNames);
QFileInfoList cppFileNames() const;
- void setSkipDeprecated(bool value);
- static void setSilent(bool value);
- void addIncludePath(const HeaderPath& path);
- void addIncludePath(const HeaderPaths& paths);
HeaderPaths includePaths() const;
void setLogDirectory(const QString& logDir);
LanguageLevel languageLevel() const;
- void setLanguageLevel(LanguageLevel languageLevel);
QStringList clangOptions() const;
- void setClangOptions(const QStringList &co);
- static void setUseGlobalHeader(bool h);
const AbstractMetaEnumList &globalEnums() const;
const AbstractMetaFunctionCList &globalFunctions() const;
diff --git a/sources/shiboken6/ApiExtractor/messages.cpp b/sources/shiboken6/ApiExtractor/messages.cpp
index 0393fa3b3..c3ad3d5c1 100644
--- a/sources/shiboken6/ApiExtractor/messages.cpp
+++ b/sources/shiboken6/ApiExtractor/messages.cpp
@@ -953,3 +953,8 @@ QString msgMissingProjectFileMarker(const QString &name, const QByteArray &start
return u"First line of project file \""_s + QDir::toNativeSeparators(name)
+ u"\" must be the string \""_s + QString::fromLatin1(startMarker) + u"\"."_s;
}
+
+QString msgInvalidLanguageLevel(const QString &l)
+{
+ return u"Invalid argument for language level: \""_s + l + u"\"."_s;
+}
diff --git a/sources/shiboken6/ApiExtractor/messages.h b/sources/shiboken6/ApiExtractor/messages.h
index 93b9d10f1..833899b68 100644
--- a/sources/shiboken6/ApiExtractor/messages.h
+++ b/sources/shiboken6/ApiExtractor/messages.h
@@ -253,4 +253,6 @@ QString msgUnknownArrayPointerConversion(const QString &s);
QString msgMissingProjectFileMarker(const QString &name, const QByteArray &startMarker);
+QString msgInvalidLanguageLevel(const QString &l);
+
#endif // MESSAGES_H
diff --git a/sources/shiboken6/generator/main.cpp b/sources/shiboken6/generator/main.cpp
index 37d9272d3..a30b05603 100644
--- a/sources/shiboken6/generator/main.cpp
+++ b/sources/shiboken6/generator/main.cpp
@@ -27,22 +27,13 @@
using namespace Qt::StringLiterals;
-static const QChar clangOptionsSplitter = u',';
-static inline QString clangOptionOption() { return QStringLiteral("clang-option"); }
-static inline QString clangOptionsOption() { return QStringLiteral("clang-options"); }
static inline QString compilerOption() { return QStringLiteral("compiler"); }
static inline QString compilerPathOption() { return QStringLiteral("compiler-path"); }
static inline QString platformOption() { return QStringLiteral("platform"); }
-static inline QString languageLevelOption() { return QStringLiteral("language-level"); }
-static inline QString includePathOption() { return QStringLiteral("include-paths"); }
-static inline QString frameworkIncludePathOption() { return QStringLiteral("framework-include-paths"); }
-static inline QString systemIncludePathOption() { return QStringLiteral("system-include-paths"); }
static inline QString logUnmatchedOption() { return QStringLiteral("log-unmatched"); }
static inline QString helpOption() { return QStringLiteral("help"); }
static inline QString diffOption() { return QStringLiteral("diff"); }
-static inline QString useGlobalHeaderOption() { return QStringLiteral("use-global-header"); }
static inline QString dryrunOption() { return QStringLiteral("dry-run"); }
-static inline QString skipDeprecatedOption() { return QStringLiteral("skip-deprecated"); }
static inline QString printBuiltinTypesOption() { return QStringLiteral("print-builtin-types"); }
static const char helpHint[] = "Note: use --help or -h for more information.\n";
@@ -111,28 +102,12 @@ bool CommandLineArguments::addCommonOption(const QString &option,
if (option == compilerOption() || option == compilerPathOption()
|| option == platformOption()) {
options.insert(option, value);
- } else if (option == clangOptionOption()) {
- options.insert(option, QStringList(value));
- } else if (option == clangOptionsOption()) {
- addToOptionsList(option, value, clangOptionsSplitter);
} else {
result = false;
}
return result;
}
-// Return the file command line option matching a project file keyword
-static QString projectFileKeywordToCommandLineOption(const QString &p)
-{
- if (p == u"include-path")
- return includePathOption(); // "include-paths", ...
- if (p == u"framework-include-path")
- return frameworkIncludePathOption();
- if (p == u"system-include-paths")
- return systemIncludePathOption();
- return {};
-}
-
static void processProjectFileLine(const QByteArray &line, CommandLineArguments &args)
{
if (line.isEmpty())
@@ -146,18 +121,12 @@ static void processProjectFileLine(const QByteArray &line, CommandLineArguments
const QString key = lineS.left(split).trimmed();
const QString value = lineS.mid(split + 1).trimmed();
- const QString fileOption = projectFileKeywordToCommandLineOption(key);
- if (fileOption.isEmpty()) {
- if (key == u"header-file") {
- args.positionalArguments.prepend(value);
- } else if (key == u"typesystem-file") {
- args.positionalArguments.append(value);
- } else {
- args.options.insert(key, value);
- }
+ if (key == u"header-file") {
+ args.positionalArguments.prepend(value);
+ } else if (key == u"typesystem-file") {
+ args.positionalArguments.append(value);
} else {
- // Add single line value to the path list
- args.addToOptionsList(fileOption, QDir::toNativeSeparators(value));
+ args.options.insert(key, value);
}
}
@@ -220,28 +189,14 @@ static void getCommandLineArg(QString arg, int &argNum, CommandLineArguments &ar
}
const QString option = arg.left(split);
const QString value = arg.mid(split + 1).trimmed();
- if (args.addCommonOption(option, value)) {
- } else if (option == includePathOption() || option == frameworkIncludePathOption()
- || option == systemIncludePathOption()) {
- // Add platform path-separator separated list value to path list
- args.addToOptionsPathList(option, value);
- } else {
+ if (!args.addCommonOption(option, value))
args.options.insert(option, value);
- }
return;
}
if (arg.startsWith(u'-')) {
arg.remove(0, 1);
- if (arg.startsWith(u'I')) // Shorthand path arguments -I/usr/include...
- args.addToOptionsPathList(includePathOption(), arg.mid(1));
- else if (arg.startsWith(u'F'))
- args.addToOptionsPathList(frameworkIncludePathOption(), arg.mid(1));
- else if (arg.startsWith(u"isystem"))
- args.addToOptionsPathList(systemIncludePathOption(), arg.mid(7));
- else if (arg == u"h")
+ if (arg == u"h")
args.options.insert(helpOption(), QString());
- else if (arg.startsWith(u"std="))
- args.options.insert(languageLevelOption(), arg.mid(4));
else
args.options.insert(arg, QString());
return;
@@ -276,13 +231,6 @@ static inline Generators shibokenGenerators()
return result;
}
-static inline QString languageLevelDescription()
-{
- return u"C++ Language level (c++11..c++17, default="_s
- + QLatin1StringView(clang::languageLevelOption(clang::emulatedCompilerLanguageLevel()))
- + u')';
-}
-
void printUsage()
{
const auto generatorOptions = Generator::options();
@@ -296,28 +244,14 @@ void printUsage()
u"Set the debug level"_s},
{u"documentation-only"_s,
u"Do not generates any code, just the documentation"_s},
- {clangOptionOption(),
- u"Option to be passed to clang"_s},
- {clangOptionsOption(),
- u"A comma-separated list of options to be passed to clang"_s},
{compilerOption() + u"=<type>"_s,
u"Emulated compiler type (g++, msvc, clang)"_s},
{platformOption() + u"=<name>"_s,
u"Emulated platform (windows, darwin, unix)"_s},
{compilerPathOption() + u"=<file>"_s,
u"Path to the compiler for determining builtin include paths"_s},
- {u"-F<path>"_s, {} },
- {u"framework-include-paths="_s + OptionsParser::pathSyntax(),
- u"Framework include paths used by the C++ parser"_s},
- {u"-isystem<path>"_s, {} },
- {u"system-include-paths="_s + OptionsParser::pathSyntax(),
- u"System include paths used by the C++ parser"_s},
- {useGlobalHeaderOption(),
- u"Use the global headers in generated code."_s},
{u"generator-set=<\"generator module\">"_s,
u"generator-set to be used. e.g. qtdoc"_s},
- {skipDeprecatedOption(),
- u"Skip deprecated functions"_s},
{diffOption(), u"Print a diff of wrapper files"_s},
{dryrunOption(), u"Dry run, do not generate wrapper files"_s},
{u"-h"_s, {} },
@@ -325,8 +259,6 @@ void printUsage()
{u"-I<path>"_s, {} },
{u"include-paths="_s + OptionsParser::pathSyntax(),
u"Include paths used by the C++ parser"_s},
- {languageLevelOption() + u"=, -std=<level>"_s,
- languageLevelDescription()},
{u"license-file=<license-file>"_s,
u"File used for copyright headers of generated files"_s},
{u"no-suppress-warnings"_s,
@@ -344,6 +276,7 @@ void printUsage()
};
s << generalOptions
+ << ApiExtractor::options()
<< TypeDatabase::options()
<< "\nSource generator options:\n\n" << generatorOptions
<< ShibokenGenerator::options();
@@ -367,21 +300,6 @@ static inline void errorPrint(const QString &s, const QStringList &arguments)
std::cerr << " \"" << qPrintable(argument) << "\"\n";
}
-static void parseIncludePathOption(const QString &option, HeaderType headerType,
- CommandLineArguments &args,
- ApiExtractor &extractor)
-{
- const auto it = args.options.find(option);
- if (it != args.options.end()) {
- const auto includePathListList = it.value().toStringList();
- args.options.erase(it);
- for (const QString &s : includePathListList) {
- auto path = QFile::encodeName(QDir::cleanPath(s));
- extractor.addIncludePath(HeaderPath{path, headerType});
- }
- }
-}
-
int shibokenMain(const QStringList &argV)
{
// PYSIDE-757: Request a deterministic ordering of QHash in the code model
@@ -424,6 +342,8 @@ int shibokenMain(const QStringList &argV)
OptionsParserList optionParser;
optionParser.append(Generator::createOptionsParser());
optionParser.append(TypeDatabase::instance()->createOptionsParser());
+ ApiExtractor extractor;
+ optionParser.append(extractor.createOptionsParser());
// Pre-defined generator sets.
if (generatorSet == u"qtdoc") {
@@ -456,12 +376,6 @@ int shibokenMain(const QStringList &argV)
FileOut::setDiff(true);
}
- ait = args.options.find(useGlobalHeaderOption());
- if (ait != args.options.end()) {
- args.options.erase(ait);
- ApiExtractor::setUseGlobalHeader(true);
- }
-
ait = args.options.find(dryrunOption());
if (ait != args.options.end()) {
args.options.erase(ait);
@@ -503,17 +417,11 @@ int shibokenMain(const QStringList &argV)
}
// Create and set-up API Extractor
- ApiExtractor extractor;
extractor.setLogDirectory(outputDirectory);
- ait = args.options.find(skipDeprecatedOption());
- if (ait != args.options.end()) {
- extractor.setSkipDeprecated(true);
- args.options.erase(ait);
- }
ait = args.options.find(u"silent"_s);
if (ait != args.options.end()) {
- extractor.setSilent(true);
+ ReportHandler::setSilent(true);
args.options.erase(ait);
} else {
ait = args.options.find(u"debug-level"_s);
@@ -527,12 +435,6 @@ int shibokenMain(const QStringList &argV)
}
}
- ait = args.options.find(clangOptionsOption());
- if (ait != args.options.end()) {
- extractor.setClangOptions(ait.value().toStringList());
- args.options.erase(ait);
- }
-
ait = args.options.find(compilerOption());
if (ait != args.options.end()) {
const QString name = ait.value().toString();
@@ -564,13 +466,6 @@ int shibokenMain(const QStringList &argV)
args.options.erase(ait);
}
- parseIncludePathOption(includePathOption(), HeaderType::Standard,
- args, extractor);
- parseIncludePathOption(frameworkIncludePathOption(), HeaderType::Framework,
- args, extractor);
- parseIncludePathOption(systemIncludePathOption(), HeaderType::System,
- args, extractor);
-
if (args.positionalArguments.size() < 2) {
errorPrint(u"Insufficient positional arguments, specify header-file and typesystem-file."_s,
argV);
@@ -598,19 +493,6 @@ int shibokenMain(const QStringList &argV)
optionParser.process(&options);
optionParser.clear();
- ait = args.options.find(languageLevelOption());
- if (ait != args.options.end()) {
- const QByteArray languageLevelBA = ait.value().toString().toLatin1();
- args.options.erase(ait);
- const LanguageLevel level = clang::languageLevelFromOption(languageLevelBA.constData());
- if (level == LanguageLevel::Default) {
- std::cout << "Invalid argument for language level: \""
- << languageLevelBA.constData() << "\"\n" << helpHint;
- return EXIT_FAILURE;
- }
- extractor.setLanguageLevel(level);
- }
-
/* Make sure to remove the project file's arguments (if any) and
* --project-file, also the arguments of each generator before
* checking if there isn't any existing arguments in argsHandler.