From 009c7413952c01c7ba4722aa73c968e07dc17e04 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 4 Apr 2019 11:29:58 +0200 Subject: shiboken: Allow for include paths with relative directories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve the absolute file paths of the code model items against the include paths of shiboken to reconstruct the relative paths. Change-Id: Id0f793315b01c0fc65a4cfb26b3372f9c6688872 Fixes: PYSIDE-975 Reviewed-by: Volker Aßmann Reviewed-by: Cristian Maureira-Fredes --- .../shiboken2/ApiExtractor/abstractmetabuilder.cpp | 50 ++++++++++++++++++++-- .../shiboken2/ApiExtractor/abstractmetabuilder.h | 2 + .../shiboken2/ApiExtractor/abstractmetabuilder_p.h | 2 + sources/shiboken2/ApiExtractor/apiextractor.cpp | 1 + sources/shiboken2/ApiExtractor/typesystem.cpp | 14 ++++++ sources/shiboken2/ApiExtractor/typesystem.h | 11 +---- sources/shiboken2/generator/main.cpp | 6 ++- 7 files changed, 71 insertions(+), 15 deletions(-) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 655d44833..685cbb78d 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -3197,16 +3197,60 @@ void AbstractMetaBuilder::setGlobalHeader(const QString& globalHeader) d->m_globalHeader = QFileInfo(globalHeader); } +void AbstractMetaBuilder::setHeaderPaths(const HeaderPaths &hp) +{ + for (const auto & h: hp) { + if (h.type != HeaderType::Framework && h.type != HeaderType::FrameworkSystem) + d->m_headerPaths.append(QFile::decodeName(h.path)); + } +} + void AbstractMetaBuilder::setSkipDeprecated(bool value) { d->m_skipDeprecated = value; } +// PYSIDE-975: When receiving an absolute path name from the code model, try +// to resolve it against the include paths set on shiboken in order to recreate +// relative paths like #include . + +static inline bool isFileSystemSlash(QChar c) +{ + return c == QLatin1Char('/') || c == QLatin1Char('\\'); +} + +static bool matchHeader(const QString &headerPath, const QString &fileName) +{ +#if defined(Q_OS_WIN) || defined(Q_OS_DARWIN) + static const Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive; +#else + static const Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive; +#endif + const int pathSize = headerPath.size(); + return fileName.size() > pathSize + && isFileSystemSlash(fileName.at(pathSize)) + && fileName.startsWith(headerPath, caseSensitivity); +} + void AbstractMetaBuilderPrivate::setInclude(TypeEntry *te, const QString &fileName) const { - QFileInfo info(fileName); - if (m_globalHeader.fileName() != info.fileName()) - te->setInclude(Include(Include::IncludePath, info.fileName())); + auto it = m_resolveIncludeHash.find(fileName); + if (it == m_resolveIncludeHash.end()) { + QFileInfo info(fileName); + if (m_globalHeader.fileName() == info.fileName()) + return; + + int bestMatchLength = 0; + for (const auto &headerPath : m_headerPaths) { + if (headerPath.size() > bestMatchLength && matchHeader(headerPath, fileName)) + bestMatchLength = headerPath.size(); + } + const QString include = bestMatchLength > 0 + ? fileName.right(fileName.size() - bestMatchLength - 1) + : info.fileName(); + it = m_resolveIncludeHash.insert(fileName, {Include::IncludePath, include}); + } + te->setInclude(it.value()); } #ifndef QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h index ed89060ac..1789ca2aa 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h @@ -30,6 +30,7 @@ #define ABSTRACTMETABUILDER_H #include "abstractmetalang_typedefs.h" +#include "header_paths.h" #include "dependency.h" #include "clangparser/compilersupport.h" @@ -85,6 +86,7 @@ public: * filled. */ void setGlobalHeader(const QString& globalHeader); + void setHeaderPaths(const HeaderPaths &h); void setSkipDeprecated(bool value); diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index 8466fd50a..8d5b924dd 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -183,6 +183,8 @@ public: QString m_logDirectory; QFileInfo m_globalHeader; + QStringList m_headerPaths; + mutable QHash m_resolveIncludeHash; bool m_skipDeprecated; }; diff --git a/sources/shiboken2/ApiExtractor/apiextractor.cpp b/sources/shiboken2/ApiExtractor/apiextractor.cpp index e301d891f..fbe7664e9 100644 --- a/sources/shiboken2/ApiExtractor/apiextractor.cpp +++ b/sources/shiboken2/ApiExtractor/apiextractor.cpp @@ -224,6 +224,7 @@ bool ApiExtractor::run() m_builder->setLogDirectory(m_logDirectory); m_builder->setGlobalHeader(m_cppFileName); m_builder->setSkipDeprecated(m_skipDeprecated); + m_builder->setHeaderPaths(m_includePaths); QByteArrayList arguments; arguments.reserve(m_includePaths.size() + 1); for (const HeaderPath &headerPath : qAsConst(m_includePaths)) diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index ad97e40ee..3bb2f0efa 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -3483,6 +3483,20 @@ static const QSet &primitiveCppTypes() return result; } +void TypeEntry::setInclude(const Include &inc) +{ + // This is a workaround for preventing double inclusion of the QSharedPointer implementation + // header, which does not use header guards. In the previous parser this was not a problem + // because the Q_QDOC define was set, and the implementation header was never included. + if (inc.name().endsWith(QLatin1String("qsharedpointer_impl.h"))) { + QString path = inc.name(); + path.remove(QLatin1String("_impl")); + m_include = Include(inc.type(), path); + } else { + m_include = inc; + } +} + bool TypeEntry::isCppPrimitive() const { if (!isPrimitive()) diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 96d0bb5fd..1e1b04136 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -835,16 +835,7 @@ public: { return m_include; } - void setInclude(const Include &inc) - { - // This is a workaround for preventing double inclusion of the QSharedPointer implementation - // header, which does not use header guards. In the previous parser this was not a problem - // because the Q_QDOC define was set, and the implementation header was never included. - if (inc.name() == QLatin1String("qsharedpointer_impl.h")) - m_include = Include(inc.type(), QLatin1String("qsharedpointer.h")); - else - m_include = inc; - } + void setInclude(const Include &inc); // Replace conversionRule arg to CodeSnip in future version /// Set the type convertion rule diff --git a/sources/shiboken2/generator/main.cpp b/sources/shiboken2/generator/main.cpp index 094990b64..1817f6b03 100644 --- a/sources/shiboken2/generator/main.cpp +++ b/sources/shiboken2/generator/main.cpp @@ -373,8 +373,10 @@ static void parseIncludePathOption(const QString &option, HeaderType headerType, const QStringList includePathListList = it.value().split(pathSplitter, QString::SkipEmptyParts); args.erase(it); - for (const QString &s : includePathListList) - extractor.addIncludePath(HeaderPath{QFile::encodeName(s), headerType}); + for (const QString &s : includePathListList) { + auto path = QFile::encodeName(QDir::cleanPath(s)); + extractor.addIncludePath(HeaderPath{path, headerType}); + } } } -- cgit v1.2.3