aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-06-23 07:58:44 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-06-23 15:21:26 +0200
commitff94459c809e2ccd13e6d669b053667d35b3e571 (patch)
tree288d92c99176db334fa5e2f3ae449b248ac3a27c /sources
parent443d3d036b062fddec85d8258f9af3852fdfd173 (diff)
shiboken2: Add file location to more warnings
Output most warnings in the standard file:line syntax used by compilers. This is done for C++ source code and typesystem files. Introduce a class SourceLocation and add it to type entry, AbstractMetaFunction and AbstractMetaClass. Move more messages into messages.cpp and output the location. Change the errors reported by the XML typesystem parser to the same format. [ChangeLog][shiboken] A number of error and warning messages have been prefixed by file name and line for better tooling. Task-number: PYSIDE-904 Change-Id: Ie2008f4060757e9d7ca1b25c00c7c5585240a7b8 Reviewed-by: Christian Tismer <tismer@stackless.com>
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() << '\'';