aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
Diffstat (limited to 'sources')
-rw-r--r--sources/shiboken2/ApiExtractor/CMakeLists.txt1
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp48
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp20
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h9
-rw-r--r--sources/shiboken2/ApiExtractor/messages.cpp98
-rw-r--r--sources/shiboken2/ApiExtractor/messages.h30
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.cpp6
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.h4
-rw-r--r--sources/shiboken2/ApiExtractor/reporthandler.cpp18
-rw-r--r--sources/shiboken2/ApiExtractor/sourcelocation.cpp100
-rw-r--r--sources/shiboken2/ApiExtractor/sourcelocation.h67
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase.cpp20
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase.h3
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.cpp10
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.h5
-rw-r--r--sources/shiboken2/ApiExtractor/typesystemparser.cpp54
-rw-r--r--sources/shiboken2/ApiExtractor/typesystemparser.h4
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp3
18 files changed, 430 insertions, 70 deletions
diff --git a/sources/shiboken2/ApiExtractor/CMakeLists.txt b/sources/shiboken2/ApiExtractor/CMakeLists.txt
index f8e504583..28644fe49 100644
--- a/sources/shiboken2/ApiExtractor/CMakeLists.txt
+++ b/sources/shiboken2/ApiExtractor/CMakeLists.txt
@@ -13,6 +13,7 @@ fileout.cpp
graph.cpp
messages.cpp
reporthandler.cpp
+sourcelocation.cpp
typeparser.cpp
typesystem.cpp
typesystemparser.cpp
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
index d4268941f..093b2fb68 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
@@ -212,9 +212,8 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications()
if (!found) {
qCWarning(lcShiboken).noquote().nospace()
- << msgNoFunctionForModification(signature,
+ << msgNoFunctionForModification(clazz, signature,
modification.originalSignature(),
- clazz->qualifiedCppName(),
possibleSignatures, functions);
}
}
@@ -553,9 +552,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
&& !entry->isCustom()
&& (entry->generateCode() & TypeEntry::GenerateTargetLang)
&& !AbstractMetaClass::findClass(m_metaClasses, entry)) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
- .arg(entry->qualifiedCppName());
+ qCWarning(lcShiboken, "%s", qPrintable(msgTypeNotDefined(entry)));
} else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) {
auto fte = static_cast<const FunctionTypeEntry *>(entry);
const QStringList &signatures = fte->signatures();
@@ -568,13 +565,13 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
}
}
if (!ok) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("Global function '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
- .arg(signature);
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgGlobalFunctionNotDefined(fte, signature)));
}
}
} else if (entry->isEnum() && (entry->generateCode() & TypeEntry::GenerateTargetLang)) {
- const QString name = static_cast<const EnumTypeEntry *>(entry)->targetLangQualifier();
+ auto enumEntry = static_cast<const EnumTypeEntry *>(entry);
+ const QString name = enumEntry->targetLangQualifier();
AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses, name);
const bool enumFound = cls
@@ -583,9 +580,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
if (!enumFound) {
entry->setCodeGeneration(TypeEntry::GenerateNothing);
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("enum '%1' is specified in typesystem, but not declared")
- .arg(entry->qualifiedCppName());
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgEnumNotDefined(enumEntry)));
}
}
@@ -744,8 +740,8 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
auto type = TypeDatabase::instance()->findNamespaceType(namespaceName, namespaceItem->fileName());
if (!type) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("namespace '%1' does not have a type entry").arg(namespaceName);
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgNamespaceNoTypeEntry(namespaceItem, namespaceName)));
return nullptr;
}
@@ -1035,6 +1031,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
}
auto *metaClass = new AbstractMetaClass;
+ metaClass->setSourceLocation(classItem->sourceLocation());
metaClass->setTypeEntry(type);
if (classItem->isFinal())
@@ -1188,9 +1185,8 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(const VariableModel
if (!metaType) {
const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(colonColon());
if (cls->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("skipping field '%1::%2' with unmatched type '%3'")
- .arg(cls->name(), fieldName, type);
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgSkippingField(field, cls->name(), type)));
}
delete metaField;
return nullptr;
@@ -1454,9 +1450,8 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
for (const auto &baseClassName : baseClasses) {
if (!types->isClassRejected(baseClassName)) {
if (!types->findType(baseClassName)) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("class '%1' inherits from unknown base class '%2'")
- .arg(metaClass->name(), baseClassName);
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgUnknownBase(metaClass, baseClassName)));
return false;
}
auto baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClassName);
@@ -1769,6 +1764,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
}
auto *metaFunction = new AbstractMetaFunction;
+ metaFunction->setSourceLocation(functionItem->sourceLocation());
if (deprecated)
*metaFunction += AbstractMetaAttributes::Deprecated;
@@ -1871,12 +1867,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
if (!currentClass
|| (currentClass->typeEntry()->codeGeneration()
& TypeEntry::GenerateTargetLang)) {
- qCWarning(lcShiboken).noquote().nospace()
- << "Stripping argument #" << (i + 1) << " of "
- << originalQualifiedSignatureWithReturn
- << " due to unmatched type \"" << arg->type().toString()
- << "\" with default expression \""
- << arg->defaultValueExpression() << "\".";
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgStrippingArgument(functionItem, i, originalQualifiedSignatureWithReturn, arg)));
}
break;
}
@@ -1940,8 +1932,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
fixArgumentNames(metaFunction, functionMods);
QString errorMessage;
if (!applyArrayArgumentModifications(functionMods, metaFunction, &errorMessage)) {
- qCWarning(lcShiboken, "While traversing %s: %s",
- qPrintable(className), qPrintable(errorMessage));
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgArrayModificationFailed(functionItem, className, errorMessage)));
}
}
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
index 390143cda..e9a2c2b57 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
@@ -783,6 +783,16 @@ bool AbstractMetaFunction::autoDetectAllowThread() const
return !maybeGetter;
}
+SourceLocation AbstractMetaFunction::sourceLocation() const
+{
+ return m_sourceLocation;
+}
+
+void AbstractMetaFunction::setSourceLocation(const SourceLocation &sourceLocation)
+{
+ m_sourceLocation = sourceLocation;
+}
+
static inline TypeSystem::AllowThread allowThreadMod(const AbstractMetaClass *klass)
{
return klass->typeEntry()->allowThread();
@@ -2636,6 +2646,16 @@ void AbstractMetaClass::formatMembers(QDebug &d) const
}
}
+SourceLocation AbstractMetaClass::sourceLocation() const
+{
+ return m_sourceLocation;
+}
+
+void AbstractMetaClass::setSourceLocation(const SourceLocation &sourceLocation)
+{
+ m_sourceLocation = sourceLocation;
+}
+
QDebug operator<<(QDebug d, const AbstractMetaClass *ac)
{
QDebugStateSaver saver(d);
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h
index 00f137100..830631e68 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang.h
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h
@@ -30,6 +30,7 @@
#define ABSTRACTMETALANG_H
#include "abstractmetalang_typedefs.h"
+#include "sourcelocation.h"
#include "typesystem_enums.h"
#include "typesystem_typedefs.h"
@@ -1093,6 +1094,9 @@ public:
void formatDebugVerbose(QDebug &d) const;
#endif
+ SourceLocation sourceLocation() const;
+ void setSourceLocation(const SourceLocation &sourceLocation);
+
private:
bool autoDetectAllowThread() const;
@@ -1111,6 +1115,7 @@ private:
QPropertySpec *m_propertySpec = nullptr;
AbstractMetaArgumentList m_arguments;
AddedFunctionPtr m_addedFunction;
+ SourceLocation m_sourceLocation;
uint m_constant : 1;
uint m_reverse : 1;
uint m_explicit : 1;
@@ -1682,6 +1687,9 @@ public:
static AbstractMetaEnum *findEnum(const AbstractMetaClassList &classes,
const EnumTypeEntry *entry);
+ SourceLocation sourceLocation() const;
+ void setSourceLocation(const SourceLocation &sourceLocation);
+
private:
#ifndef QT_NO_DEBUG_STREAM
void format(QDebug &d) const;
@@ -1719,6 +1727,7 @@ private:
QStringList m_baseClassNames; // Base class names from C++, including rejected
QVector<TypeEntry *> m_templateArgs;
ComplexTypeEntry *m_typeEntry = nullptr;
+ SourceLocation m_sourceLocation;
// FunctionModelItem m_qDebugStreamFunction;
bool m_stream = false;
diff --git a/sources/shiboken2/ApiExtractor/messages.cpp b/sources/shiboken2/ApiExtractor/messages.cpp
index 0e905c9a0..930cd2c70 100644
--- a/sources/shiboken2/ApiExtractor/messages.cpp
+++ b/sources/shiboken2/ApiExtractor/messages.cpp
@@ -28,6 +28,7 @@
#include "messages.h"
#include "abstractmetalang.h"
+#include "sourcelocation.h"
#include "typedatabase.h"
#include "typesystem.h"
#include <codemodel.h>
@@ -43,19 +44,20 @@ static inline QString colonColon() { return QStringLiteral("::"); }
// abstractmetabuilder.cpp
-QString msgNoFunctionForModification(const QString &signature,
+QString msgNoFunctionForModification(const AbstractMetaClass *klass,
+ const QString &signature,
const QString &originalSignature,
- const QString &className,
const QStringList &possibleSignatures,
const AbstractMetaFunctionList &allFunctions)
{
QString result;
QTextStream str(&result);
- str << "signature '" << signature << '\'';
+ str << klass->typeEntry()->sourceLocation() << "signature '"
+ << signature << '\'';
if (!originalSignature.isEmpty() && originalSignature != signature)
str << " (specified as '" << originalSignature << "')";
str << " for function modification in '"
- << className << "' not found.";
+ << klass->qualifiedCppName() << "' not found.";
if (!possibleSignatures.isEmpty()) {
str << "\n Possible candidates:\n";
for (const auto &s : possibleSignatures)
@@ -135,6 +137,7 @@ QString msgNoEnumTypeEntry(const EnumModelItem &enumItem,
{
QString result;
QTextStream str(&result);
+ str << enumItem->sourceLocation();
msgFormatEnumType(str, enumItem, className);
str << " does not have a type entry";
return result;
@@ -148,11 +151,22 @@ QString msgNoEnumTypeConflict(const EnumModelItem &enumItem,
QDebug debug(&result); // Use the debug operator for TypeEntry::Type
debug.noquote();
debug.nospace();
+ debug << enumItem->sourceLocation().toString();
msgFormatEnumType(debug, enumItem, className);
debug << " is not an enum (type: " << t->type() << ')';
return result;
}
+QString msgNamespaceNoTypeEntry(const NamespaceModelItem &item,
+ const QString &fullName)
+{
+ QString result;
+ QTextStream str(&result);
+ str << item->sourceLocation() << "namespace '" << fullName
+ << "' does not have a type entry";
+ return result;
+}
+
QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te)
{
QString result = QLatin1String("Ambiguous types of varying types found for \"") + qualifiedName
@@ -195,7 +209,7 @@ QString msgSkippingFunction(const FunctionModelItem &functionItem,
{
QString result;
QTextStream str(&result);
- str << "skipping ";
+ str << functionItem->sourceLocation() << "skipping ";
if (functionItem->isAbstract())
str << "abstract ";
str << "function '" << signature << "', " << why;
@@ -206,6 +220,80 @@ QString msgSkippingFunction(const FunctionModelItem &functionItem,
return result;
}
+QString msgSkippingField(const VariableModelItem &field, const QString &className,
+ const QString &type)
+{
+ QString result;
+ QTextStream str(&result);
+ str << field->sourceLocation() << "skipping field '" << className
+ << "::" << field->name() << "' with unmatched type '" << type << '\'';
+ return result;
+}
+
+static const char msgCompilationError[] =
+ "This could potentially lead to compilation errors.";
+
+QString msgTypeNotDefined(const TypeEntry *entry)
+{
+ QString result;
+ QTextStream str(&result);
+ str << entry->sourceLocation() << "type '" <<entry->qualifiedCppName()
+ << "' is specified in typesystem, but not defined. " << msgCompilationError;
+ return result;
+}
+
+QString msgGlobalFunctionNotDefined(const FunctionTypeEntry *fte,
+ const QString &signature)
+{
+ QString result;
+ QTextStream str(&result);
+ str << fte->sourceLocation() << "Global function '" << signature
+ << "' is specified in typesystem, but not defined. " << msgCompilationError;
+ return result;
+}
+
+QString msgStrippingArgument(const FunctionModelItem &f, int i,
+ const QString &originalSignature,
+ const ArgumentModelItem &arg)
+{
+ QString result;
+ QTextStream str(&result);
+ str << f->sourceLocation() << "Stripping argument #" << (i + 1) << " of "
+ << originalSignature << " due to unmatched type \""
+ << arg->type().toString() << "\" with default expression \""
+ << arg->defaultValueExpression() << "\".";
+ return result;
+}
+
+QString msgEnumNotDefined(const EnumTypeEntry *t)
+{
+ QString result;
+ QTextStream str(&result);
+ str << t->sourceLocation() << "enum '" << t->qualifiedCppName()
+ << "' is specified in typesystem, but not declared.";
+ return result;
+}
+
+QString msgUnknownBase(const AbstractMetaClass *metaClass, const QString &baseClassName)
+{
+ QString result;
+ QTextStream str(&result);
+ str << metaClass->sourceLocation() << "class '" << metaClass->name()
+ << "' inherits from unknown base class '" << baseClassName << "'";
+ return result;
+}
+
+QString msgArrayModificationFailed(const FunctionModelItem &functionItem,
+ const QString &className,
+ const QString &errorMessage)
+{
+ QString result;
+ QTextStream str(&result);
+ str << functionItem->sourceLocation() << "While traversing " << className
+ << ": " << errorMessage;
+ return result;
+}
+
QString msgCannotResolveEntity(const QString &name, const QString &reason)
{
return QLatin1String("Cannot resolve entity \"") + name
diff --git a/sources/shiboken2/ApiExtractor/messages.h b/sources/shiboken2/ApiExtractor/messages.h
index 3934c35b3..72484050a 100644
--- a/sources/shiboken2/ApiExtractor/messages.h
+++ b/sources/shiboken2/ApiExtractor/messages.h
@@ -37,6 +37,8 @@
#include <QtCore/QString>
#include <QtCore/QVector>
+class EnumTypeEntry;
+class FunctionTypeEntry;
class TypeEntry;
class TypeInfo;
struct TypeRejection;
@@ -52,9 +54,9 @@ QString msgAddedFunctionInvalidArgType(const QString &addedFuncName,
QString msgAddedFunctionInvalidReturnType(const QString &addedFuncName,
const QString &typeName, const QString &why);
-QString msgNoFunctionForModification(const QString &signature,
+QString msgNoFunctionForModification(const AbstractMetaClass *klass,
+ const QString &signature,
const QString &originalSignature,
- const QString &className,
const QStringList &possibleSignatures,
const AbstractMetaFunctionList &allFunctions);
@@ -66,6 +68,9 @@ QString msgNoEnumTypeConflict(const EnumModelItem &enumItem,
const QString &className,
const TypeEntry *t);
+QString msgNamespaceNoTypeEntry(const NamespaceModelItem &item,
+ const QString &fullName);
+
QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te);
QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te);
@@ -78,6 +83,27 @@ QString msgUnmatchedReturnType(const FunctionModelItem &functionItem,
QString msgSkippingFunction(const FunctionModelItem &functionItem,
const QString &signature, const QString &why);
+QString msgSkippingField(const VariableModelItem &field, const QString &className,
+ const QString &type);
+
+QString msgTypeNotDefined(const TypeEntry *entry);
+
+QString msgGlobalFunctionNotDefined(const FunctionTypeEntry *fte,
+ const QString &signature);
+
+QString msgStrippingArgument(const FunctionModelItem &f, int i,
+ const QString &originalSignature,
+ const ArgumentModelItem &arg);
+
+QString msgEnumNotDefined(const EnumTypeEntry *t);
+
+QString msgUnknownBase(const AbstractMetaClass *metaClass,
+ const QString &baseClassName);
+
+QString msgArrayModificationFailed(const FunctionModelItem &functionItem,
+ const QString &className,
+ const QString &errorMessage);
+
QString msgCannotResolveEntity(const QString &name, const QString &reason);
QString msgCannotSetArrayUsage(const QString &function, int i, const QString &reason);
diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
index e381ba083..e5a6e074c 100644
--- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
+++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
@@ -30,6 +30,7 @@
#include "codemodel.h"
+#include <sourcelocation.h>
#include <clangparser/clangutils.h>
#include <algorithm>
@@ -608,6 +609,11 @@ void _CodeModelItem::setEndPosition(int line, int column)
m_endColumn = column;
}
+SourceLocation _CodeModelItem::sourceLocation() const
+{
+ return SourceLocation(m_fileName, m_startLine);
+}
+
#ifndef QT_NO_DEBUG_STREAM
template <class It>
static void formatPtrSequence(QDebug &d, It i1, It i2, const char *separator=", ")
diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h
index 5bbd9ed3e..ea9cdc30d 100644
--- a/sources/shiboken2/ApiExtractor/parser/codemodel.h
+++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h
@@ -47,6 +47,8 @@ QT_FORWARD_DECLARE_CLASS(QDebug)
#define DECLARE_MODEL_NODE(k) \
enum { __node_kind = Kind_##k };
+class SourceLocation;
+
class CodeModel
{
public:
@@ -296,6 +298,8 @@ public:
void getEndPosition(int *line, int *column);
void setEndPosition(int line, int column);
+ SourceLocation sourceLocation() const;
+
inline CodeModel *model() const { return m_model; }
#ifndef QT_NO_DEBUG_STREAM
diff --git a/sources/shiboken2/ApiExtractor/reporthandler.cpp b/sources/shiboken2/ApiExtractor/reporthandler.cpp
index a489f7548..2c6ab444b 100644
--- a/sources/shiboken2/ApiExtractor/reporthandler.cpp
+++ b/sources/shiboken2/ApiExtractor/reporthandler.cpp
@@ -122,13 +122,19 @@ void ReportHandler::setPrefix(const QString &p)
void ReportHandler::messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &text)
{
+ // Check for file location separator added by SourceLocation
+ int fileLocationPos = text.indexOf(QLatin1String(":\t"));
if (type == QtWarningMsg) {
if (m_silent || m_reportedWarnings.contains(text))
return;
- const TypeDatabase *db = TypeDatabase::instance();
- if (db && db->isSuppressedWarning(text)) {
- ++m_suppressedCount;
- return;
+ if (auto db = TypeDatabase::instance()) {
+ const bool suppressed = fileLocationPos >= 0
+ ? db->isSuppressedWarning(text.midRef(fileLocationPos + 2))
+ : db->isSuppressedWarning(text);
+ if (suppressed) {
+ ++m_suppressedCount;
+ return;
+ }
}
++m_warningCount;
++m_step_warning;
@@ -137,7 +143,11 @@ void ReportHandler::messageOutput(QtMsgType type, const QMessageLogContext &cont
QString message = m_prefix;
if (!message.isEmpty())
message.append(QLatin1Char(' '));
+ const int prefixLength = message.size();
message.append(text);
+ // Replace file location tab by space
+ if (fileLocationPos >= 0)
+ message[prefixLength + fileLocationPos + 1] = QLatin1Char(' ');
fprintf(stderr, "%s\n", qPrintable(qFormatLogMessage(type, context, message)));
}
diff --git a/sources/shiboken2/ApiExtractor/sourcelocation.cpp b/sources/shiboken2/ApiExtractor/sourcelocation.cpp
new file mode 100644
index 000000000..1ba66e05b
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/sourcelocation.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "sourcelocation.h"
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+
+SourceLocation::SourceLocation() = default;
+
+SourceLocation::SourceLocation(const QString &file, int l)
+ : m_fileName(file), m_lineNumber(l)
+{
+}
+
+bool SourceLocation::isValid() const
+{
+ return m_lineNumber >= 0 && !m_fileName.isEmpty();
+}
+
+QString SourceLocation::fileName() const
+{
+ return m_fileName;
+}
+
+void SourceLocation::setFileName(const QString &fileName)
+{
+ m_fileName = fileName;
+}
+
+int SourceLocation::lineNumber() const
+{
+ return m_lineNumber;
+}
+
+void SourceLocation::setLineNumber(int lineNumber)
+{
+ m_lineNumber = lineNumber;
+}
+
+QString SourceLocation::toString() const
+{
+ QString result;
+ QTextStream s(&result);
+ format(s);
+ return result;
+}
+
+template<class Stream>
+void SourceLocation::format(Stream &s) const
+{
+ if (isValid())
+ s << QDir::toNativeSeparators(m_fileName) << ':' << m_lineNumber << ':';
+ else
+ s << "<unknown>";
+}
+
+QTextStream &operator<<(QTextStream &s, const SourceLocation &l)
+{
+ if (l.isValid()) {
+ l.format(s);
+ s << '\t'; // ":\t" is used by ReportHandler for filtering suppressions
+ }
+ return s;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const SourceLocation &l)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ l.format(d);
+ return d;
+}
+#endif
diff --git a/sources/shiboken2/ApiExtractor/sourcelocation.h b/sources/shiboken2/ApiExtractor/sourcelocation.h
new file mode 100644
index 000000000..630a841d8
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/sourcelocation.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SOURCE_LOCATION_H
+#define SOURCE_LOCATION_H
+
+#include <QString>
+
+QT_FORWARD_DECLARE_CLASS(QDebug)
+QT_FORWARD_DECLARE_CLASS(QTextStream)
+
+class SourceLocation
+{
+public:
+ explicit SourceLocation(const QString &file, int l);
+ SourceLocation();
+
+ bool isValid() const;
+
+ QString fileName() const;
+ void setFileName(const QString &fileName);
+
+ int lineNumber() const;
+ void setLineNumber(int lineNumber);
+
+ QString toString() const;
+
+ template<class Stream>
+ void format(Stream &s) const;
+
+private:
+ QString m_fileName;
+ int m_lineNumber = 0;
+};
+
+QTextStream &operator<<(QTextStream &s, const SourceLocation &l);
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const SourceLocation &l);
+#endif
+
+#endif // SOURCE_LOCATION_H
diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp
index 4a29a25c9..0cfde1c66 100644
--- a/sources/shiboken2/ApiExtractor/typedatabase.cpp
+++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp
@@ -568,17 +568,25 @@ bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMe
return true;
}
-bool TypeDatabase::isSuppressedWarning(const QString& s) const
+template <class String> // QString, QStringRef
+bool TypeDatabase::isSuppressedWarningHelper(const String &s) const
{
if (!m_suppressWarnings)
return false;
+ return std::any_of(m_suppressedWarnings.cbegin(), m_suppressedWarnings.end(),
+ [&s] (const QRegularExpression &e) {
+ return e.match(s).hasMatch();
+ });
+}
- for (const QRegularExpression &warning : m_suppressedWarnings) {
- if (warning.match(s).hasMatch())
- return true;
- }
+bool TypeDatabase::isSuppressedWarning(const QString &s) const
+{
+ return isSuppressedWarningHelper(s);
+}
- return false;
+bool TypeDatabase::isSuppressedWarning(const QStringRef &s) const
+{
+ return isSuppressedWarningHelper(s);
}
QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile, const QString &currentPath) const
diff --git a/sources/shiboken2/ApiExtractor/typedatabase.h b/sources/shiboken2/ApiExtractor/typedatabase.h
index 7651d6b7b..7981febf3 100644
--- a/sources/shiboken2/ApiExtractor/typedatabase.h
+++ b/sources/shiboken2/ApiExtractor/typedatabase.h
@@ -163,6 +163,7 @@ public:
bool addSuppressedWarning(const QString &warning, QString *errorMessage);
bool isSuppressedWarning(const QString &s) const;
+ bool isSuppressedWarning(const QStringRef &s) const;
static QString globalNamespaceClassName(const TypeEntry *te);
@@ -192,6 +193,8 @@ private:
template <class Predicate>
TypeEntries findTypesHelper(const QString &name, Predicate pred) const;
TypeEntry *resolveTypeDefEntry(TypedefEntry *typedefEntry, QString *errorMessage);
+ template <class String>
+ bool isSuppressedWarningHelper(const String &s) const;
bool m_suppressWarnings = true;
TypeEntryMultiMap m_entries; // Contains duplicate entries (cf addInlineNamespaceLookups).
diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp
index 729e6b32b..5634aa515 100644
--- a/sources/shiboken2/ApiExtractor/typesystem.cpp
+++ b/sources/shiboken2/ApiExtractor/typesystem.cpp
@@ -811,6 +811,16 @@ QString TypeEntry::buildTargetLangName() const
return result;
}
+SourceLocation TypeEntry::sourceLocation() const
+{
+ return m_sourceLocation;
+}
+
+void TypeEntry::setSourceLocation(const SourceLocation &sourceLocation)
+{
+ m_sourceLocation = sourceLocation;
+}
+
QString TypeEntry::targetLangEntryName() const
{
if (m_cachedTargetLangEntryName.isEmpty()) {
diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h
index c6995b64d..9d97f5c93 100644
--- a/sources/shiboken2/ApiExtractor/typesystem.h
+++ b/sources/shiboken2/ApiExtractor/typesystem.h
@@ -32,6 +32,7 @@
#include "typesystem_enums.h"
#include "typesystem_typedefs.h"
#include "include.h"
+#include "sourcelocation.h"
#include <QtCore/QHash>
#include <QtCore/qobjectdefs.h>
@@ -848,6 +849,9 @@ public:
void useAsTypedef(const TypeEntry *source);
+ SourceLocation sourceLocation() const;
+ void setSourceLocation(const SourceLocation &sourceLocation);
+
#ifndef QT_NO_DEBUG_STREAM
virtual void formatDebug(QDebug &d) const;
#endif
@@ -874,6 +878,7 @@ private:
QString m_conversionRule;
QVersionNumber m_version;
CustomConversion *m_customConversion = nullptr;
+ SourceLocation m_sourceLocation; // XML file
uint m_codeGeneration = GenerateAll;
int m_revision = 0;
int m_sbkIndex = 0;
diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.cpp b/sources/shiboken2/ApiExtractor/typesystemparser.cpp
index 0c4d43e76..ff8f1d59d 100644
--- a/sources/shiboken2/ApiExtractor/typesystemparser.cpp
+++ b/sources/shiboken2/ApiExtractor/typesystemparser.cpp
@@ -519,14 +519,14 @@ static QString msgReaderMessage(const QXmlStreamReader &reader,
{
QString message;
QTextStream str(&message);
- str << type << ": ";
const QString fileName = readerFileName(reader);
if (fileName.isEmpty())
str << "<stdin>:";
else
str << QDir::toNativeSeparators(fileName) << ':';
+ // Use a tab separator like SourceLocation for suppression detection
str << reader.lineNumber() << ':' << reader.columnNumber()
- << ": " << what;
+ << ":\t" << type << ": " << what;
return message;
}
@@ -631,6 +631,7 @@ bool TypeSystemParser::parse(QXmlStreamReader &reader)
{
m_error.clear();
m_currentPath.clear();
+ m_currentFile.clear();
m_smartPointerInstantiations.clear();
const bool result = parseXml(reader) && setupSmartPointerInstantiations();
m_smartPointerInstantiations.clear();
@@ -640,8 +641,11 @@ bool TypeSystemParser::parse(QXmlStreamReader &reader)
bool TypeSystemParser::parseXml(QXmlStreamReader &reader)
{
const QString fileName = readerFileName(reader);
- if (!fileName.isEmpty())
- m_currentPath = QFileInfo(fileName).absolutePath();
+ if (!fileName.isEmpty()) {
+ QFileInfo fi(fileName);
+ m_currentPath = fi.absolutePath();
+ m_currentFile = fi.absoluteFilePath();
+ }
m_entityResolver.reset(new TypeSystemEntityResolver(m_currentPath));
reader.setEntityResolver(m_entityResolver.data());
@@ -1109,8 +1113,11 @@ bool TypeSystemParser::checkRootElement()
return ok;
}
-void TypeSystemParser::applyCommonAttributes(TypeEntry *type, QXmlStreamAttributes *attributes) const
+void TypeSystemParser::applyCommonAttributes(const QXmlStreamReader &reader, TypeEntry *type,
+ QXmlStreamAttributes *attributes) const
{
+ type->setSourceLocation(SourceLocation(m_currentFile,
+ reader.lineNumber()));
type->setCodeGeneration(m_generate);
const int revisionIndex =
indexOfAttribute(*attributes, u"revision");
@@ -1119,7 +1126,7 @@ void TypeSystemParser::applyCommonAttributes(TypeEntry *type, QXmlStreamAttribut
}
FlagsTypeEntry *
- TypeSystemParser::parseFlagsEntry(const QXmlStreamReader &,
+ TypeSystemParser::parseFlagsEntry(const QXmlStreamReader &reader,
EnumTypeEntry *enumEntry, QString flagName,
const QVersionNumber &since,
QXmlStreamAttributes *attributes)
@@ -1140,7 +1147,7 @@ FlagsTypeEntry *
}
ftype->setOriginalName(flagName);
- applyCommonAttributes(ftype, attributes);
+ applyCommonAttributes(reader, ftype, attributes);
QStringList lst = flagName.split(colonColon());
const QString targetLangFlagName = QStringList(lst.mid(0, lst.size() - 1)).join(QLatin1Char('.'));
@@ -1166,7 +1173,7 @@ FlagsTypeEntry *
}
SmartPointerTypeEntry *
- TypeSystemParser::parseSmartPointerEntry(const QXmlStreamReader &,
+ TypeSystemParser::parseSmartPointerEntry(const QXmlStreamReader &reader,
const QString &name, const QVersionNumber &since,
QXmlStreamAttributes *attributes)
{
@@ -1219,7 +1226,7 @@ SmartPointerTypeEntry *
auto *type = new SmartPointerTypeEntry(name, getter, smartPointerType,
refCountMethodName, since, currentParentTypeEntry());
- applyCommonAttributes(type, attributes);
+ applyCommonAttributes(reader, type, attributes);
m_smartPointerInstantiations.insert(type, instantiations);
return type;
}
@@ -1232,7 +1239,7 @@ PrimitiveTypeEntry *
if (!checkRootElement())
return nullptr;
auto *type = new PrimitiveTypeEntry(name, since, currentParentTypeEntry());
- applyCommonAttributes(type, attributes);
+ applyCommonAttributes(reader, type, attributes);
for (int i = attributes->size() - 1; i >= 0; --i) {
const QStringRef name = attributes->at(i).qualifiedName();
if (name == targetLangNameAttribute()) {
@@ -1258,7 +1265,7 @@ PrimitiveTypeEntry *
}
ContainerTypeEntry *
- TypeSystemParser::parseContainerTypeEntry(const QXmlStreamReader &,
+ TypeSystemParser::parseContainerTypeEntry(const QXmlStreamReader &reader,
const QString &name, const QVersionNumber &since,
QXmlStreamAttributes *attributes)
{
@@ -1276,7 +1283,7 @@ ContainerTypeEntry *
return nullptr;
}
auto *type = new ContainerTypeEntry(name, containerType, since, currentParentTypeEntry());
- applyCommonAttributes(type, attributes);
+ applyCommonAttributes(reader, type, attributes);
return type;
}
@@ -1288,7 +1295,7 @@ EnumTypeEntry *
if (!checkRootElement())
return nullptr;
auto *entry = new EnumTypeEntry(name, since, currentParentTypeEntry());
- applyCommonAttributes(entry, attributes);
+ applyCommonAttributes(reader, entry, attributes);
entry->setTargetLangPackage(m_defaultPackage);
QString flagNames;
@@ -1330,7 +1337,7 @@ NamespaceTypeEntry *
return nullptr;
QScopedPointer<NamespaceTypeEntry> result(new NamespaceTypeEntry(name, since, currentParentTypeEntry()));
auto visibility = TypeSystem::Visibility::Unspecified;
- applyCommonAttributes(result.data(), attributes);
+ applyCommonAttributes(reader, result.data(), attributes);
for (int i = attributes->size() - 1; i >= 0; --i) {
const QStringRef attributeName = attributes->at(i).qualifiedName();
if (attributeName == QLatin1String("files")) {
@@ -1380,14 +1387,14 @@ NamespaceTypeEntry *
}
ValueTypeEntry *
- TypeSystemParser::parseValueTypeEntry(const QXmlStreamReader &,
+ TypeSystemParser::parseValueTypeEntry(const QXmlStreamReader &reader,
const QString &name, const QVersionNumber &since,
QXmlStreamAttributes *attributes)
{
if (!checkRootElement())
return nullptr;
auto *typeEntry = new ValueTypeEntry(name, since, currentParentTypeEntry());
- applyCommonAttributes(typeEntry, attributes);
+ applyCommonAttributes(reader, typeEntry, attributes);
const int defaultCtIndex =
indexOfAttribute(*attributes, u"default-constructor");
if (defaultCtIndex != -1)
@@ -1396,7 +1403,7 @@ ValueTypeEntry *
}
FunctionTypeEntry *
- TypeSystemParser::parseFunctionTypeEntry(const QXmlStreamReader &,
+ TypeSystemParser::parseFunctionTypeEntry(const QXmlStreamReader &reader,
const QString &name, const QVersionNumber &since,
QXmlStreamAttributes *attributes)
{
@@ -1414,7 +1421,7 @@ FunctionTypeEntry *
if (!existingType) {
auto *result = new FunctionTypeEntry(name, signature, since, currentParentTypeEntry());
- applyCommonAttributes(result, attributes);
+ applyCommonAttributes(reader, result, attributes);
return result;
}
@@ -1430,9 +1437,10 @@ FunctionTypeEntry *
}
TypedefEntry *
- TypeSystemParser::parseTypedefEntry(const QXmlStreamReader &, const QString &name,
- const QVersionNumber &since,
- QXmlStreamAttributes *attributes)
+ TypeSystemParser::parseTypedefEntry(const QXmlStreamReader &reader,
+ const QString &name,
+ const QVersionNumber &since,
+ QXmlStreamAttributes *attributes)
{
if (!checkRootElement())
return nullptr;
@@ -1448,7 +1456,7 @@ TypedefEntry *
}
const QString sourceType = attributes->takeAt(sourceIndex).value().toString();
auto result = new TypedefEntry(name, sourceType, since, currentParentTypeEntry());
- applyCommonAttributes(result, attributes);
+ applyCommonAttributes(reader, result, attributes);
return result;
}
@@ -2824,7 +2832,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader)
if (!checkRootElement())
return false;
element->entry = new ObjectTypeEntry(name, versionRange.since, currentParentTypeEntry());
- applyCommonAttributes(element->entry, &attributes);
+ applyCommonAttributes(reader, element->entry, &attributes);
applyComplexTypeAttributes(reader, static_cast<ComplexTypeEntry *>(element->entry), &attributes);
break;
case StackElement::FunctionTypeEntry:
diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.h b/sources/shiboken2/ApiExtractor/typesystemparser.h
index b4be2765c..66d61f4a1 100644
--- a/sources/shiboken2/ApiExtractor/typesystemparser.h
+++ b/sources/shiboken2/ApiExtractor/typesystemparser.h
@@ -168,7 +168,8 @@ private:
const TypeEntry *currentParentTypeEntry() const;
bool checkRootElement();
- void applyCommonAttributes(TypeEntry *type, QXmlStreamAttributes *attributes) const;
+ void applyCommonAttributes(const QXmlStreamReader &reader, TypeEntry *type,
+ QXmlStreamAttributes *attributes) const;
PrimitiveTypeEntry *
parsePrimitiveTypeEntry(const QXmlStreamReader &, const QString &name,
const QVersionNumber &since, QXmlStreamAttributes *);
@@ -272,6 +273,7 @@ private:
QString m_currentSignature;
QString m_currentPath;
+ QString m_currentFile;
QScopedPointer<TypeSystemEntityResolver> m_entityResolver;
QHash<SmartPointerTypeEntry *, QString> m_smartPointerInstantiations;
};
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index edd24aa23..d0c144358 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -2265,7 +2265,8 @@ static void checkTypeViability(const AbstractMetaFunction *func, const AbstractM
return;
QString message;
QTextStream str(&message);
- str << "There's no user provided way (conversion rule, argument"
+ str << func->sourceLocation()
+ << "There's no user provided way (conversion rule, argument"
" removal, custom code, etc) to handle the primitive ";
if (argIdx == 0)
str << "return type '" << type->cppSignature() << '\'';