diff options
37 files changed, 442 insertions, 338 deletions
diff --git a/src/qml/common/common.pri b/src/qml/common/common.pri new file mode 100644 index 0000000000..853ec4fd88 --- /dev/null +++ b/src/qml/common/common.pri @@ -0,0 +1,2 @@ +HEADERS += \ + $$PWD/qqmljsdiagnosticmessage_p.h diff --git a/src/qml/qmldirparser/qqmlsourcecoordinate_p.h b/src/qml/common/qqmljsdiagnosticmessage_p.h index 76ac741ae8..f747578c09 100644 --- a/src/qml/qmldirparser/qqmlsourcecoordinate_p.h +++ b/src/qml/common/qqmljsdiagnosticmessage_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QQMLSOURCECOORDINATE_P_H -#define QQMLSOURCECOORDINATE_P_H +#ifndef QQMLJSDIAGNOSTICMESSAGE_P_H +#define QQMLJSDIAGNOSTICMESSAGE_P_H // // W A R N I N G @@ -51,22 +51,38 @@ // We mean it. // -#include <QtCore/qglobal.h> - -#include <climits> +#include <QtCore/qlogging.h> +#include <QtCore/qstring.h> QT_BEGIN_NAMESPACE -inline quint16 qmlSourceCoordinate(int n) +namespace QQmlJS { +struct DiagnosticMessage { - return (n > 0 && n <= static_cast<int>(USHRT_MAX)) ? static_cast<quint16>(n) : 0; -} + QString message; + QtMsgType type = QtCriticalMsg; + quint32 line = 0; + quint32 column = 0; -inline int qmlSourceCoordinate(quint16 n) -{ - return (n == 0) ? -1 : static_cast<int>(n); -} + bool isError() const + { + return type == QtCriticalMsg; + } + + bool isWarning() const + { + return type == QtWarningMsg; + } + + bool isValid() const + { + return !message.isEmpty(); + } +}; +} // namespace QQmlJS + +Q_DECLARE_TYPEINFO(QQmlJS::DiagnosticMessage, Q_MOVABLE_TYPE); QT_END_NAMESPACE -#endif // QQMLSOURCECOORDINATE_P_H +#endif // QQMLJSDIAGNOSTICMESSAGE_P_H diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 3e5798ba8b..cb46a59713 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -374,13 +374,12 @@ bool IRBuilder::generateFromQml(const QString &code, const QString &url, Documen if (!parseResult || !diagnosticMessages.isEmpty()) { // Extract errors from the parser for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) { - if (m.isWarning()) { - qWarning("%s:%d : %s", qPrintable(url), m.loc.startLine, qPrintable(m.message)); + qWarning("%s:%d : %s", qPrintable(url), m.line, qPrintable(m.message)); continue; } - recordError(m.loc, m.message); + errors << m; } return false; } @@ -1502,7 +1501,8 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O void IRBuilder::recordError(const QQmlJS::AST::SourceLocation &location, const QString &description) { QQmlJS::DiagnosticMessage error; - error.loc = location; + error.line = location.startLine; + error.column = location.startColumn; error.message = description; errors << error; } diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index b49eaee420..64298466e0 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -526,16 +526,15 @@ private: } // namespace QmlIR -struct QQmlCompileError +inline QQmlJS::DiagnosticMessage qQmlCompileError(const QV4::CompiledData::Location &location, + const QString &description) { - QQmlCompileError() {} - QQmlCompileError(const QV4::CompiledData::Location &location, const QString &description) - : location(location), description(description) {} - QV4::CompiledData::Location location; - QString description; - - bool isSet() const { return !description.isEmpty(); } -}; + QQmlJS::DiagnosticMessage error; + error.line = location.line; + error.column = location.column; + error.message = description; + return error; +} QT_END_NAMESPACE diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 04e6efb1e9..99b73679c5 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -53,7 +53,8 @@ #include <private/qv4compilercontrolflow_p.h> #include <private/qv4bytecodegenerator_p.h> #include <private/qv4compilerscanfunctions_p.h> -#include <qqmlerror.h> +#include <private/qv4stringtoarrayindex_p.h> +#include <private/qqmljsdiagnosticmessage_p.h> #include <cmath> #include <iostream> @@ -3777,7 +3778,8 @@ void Codegen::throwSyntaxError(const SourceLocation &loc, const QString &detail) hasError = true; QQmlJS::DiagnosticMessage error; error.message = detail; - error.loc = loc; + error.line = loc.startLine; + error.column = loc.startColumn; _errors << error; } @@ -3789,7 +3791,8 @@ void Codegen::throwReferenceError(const SourceLocation &loc, const QString &deta hasError = true; QQmlJS::DiagnosticMessage error; error.message = detail; - error.loc = loc; + error.line = loc.startLine; + error.column = loc.startColumn; _errors << error; } @@ -3961,28 +3964,9 @@ Codegen::VolatileMemoryLocations Codegen::scanVolatileMemoryLocations(AST::Node return scanner.scan(ast); } - -QList<QQmlError> Codegen::qmlErrors() const +QUrl Codegen::url() const { - QList<QQmlError> qmlErrors; - - // Short circuit to avoid costly (de)heap allocation of QUrl if there are no errors. - if (_errors.size() == 0) - return qmlErrors; - - qmlErrors.reserve(_errors.size()); - - QUrl url(_fileNameIsUrl ? QUrl(_module->fileName) : QUrl::fromLocalFile(_module->fileName)); - for (const QQmlJS::DiagnosticMessage &msg: qAsConst(_errors)) { - QQmlError e; - e.setUrl(url); - e.setLine(msg.loc.startLine); - e.setColumn(msg.loc.startColumn); - e.setDescription(msg.message); - qmlErrors << e; - } - - return qmlErrors; + return QUrl(_fileNameIsUrl ? QUrl(_module->fileName) : QUrl::fromLocalFile(_module->fileName)); } bool Codegen::RValue::operator==(const RValue &other) const diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index 65dc4b97b5..c76957620e 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -54,14 +54,13 @@ #include <private/qqmljsastvisitor_p.h> #include <private/qqmljsengine_p.h> #include <private/qqmljsast_p.h> +#include <private/qqmljsdiagnosticmessage_p.h> #include <private/qv4compiler_p.h> #include <private/qv4compilercontext_p.h> #include <private/qv4util_p.h> #include <private/qv4bytecodegenerator_p.h> #include <private/qv4calldata_p.h> -#include <QtQml/qqmlerror.h> - QT_BEGIN_NAMESPACE using namespace QQmlJS; @@ -673,7 +672,7 @@ protected: public: QList<DiagnosticMessage> errors() const; - QList<QQmlError> qmlErrors() const; + QUrl url() const; Reference binopHelper(QSOperator::Op oper, Reference &left, Reference &right); Reference jumpBinop(QSOperator::Op oper, Reference &left, Reference &right); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 94a179f33d..5fa44ec1ef 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -42,6 +42,7 @@ #include <private/qv4compiler_p.h> #include <private/qv4compilercontext_p.h> #include <private/qv4codegen_p.h> +#include <private/qqmljsdiagnosticmessage_p.h> #include <QtCore/QTextStream> #include <QDateTime> @@ -1766,10 +1767,10 @@ QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compileModule( sourceCode, sourceTimeStamp, &diagnostics); for (const QQmlJS::DiagnosticMessage &m : diagnostics) { if (m.isError()) { - throwSyntaxError(m.message, url.toString(), m.loc.startLine, m.loc.startColumn); + throwSyntaxError(m.message, url.toString(), m.line, m.column); return nullptr; } else { - qWarning() << url << ':' << m.loc.startLine << ':' << m.loc.startColumn + qWarning() << url << ':' << m.line << ':' << m.column << ": warning: " << m.message; } } diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index ee7f4dff0b..4dc5030fb0 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -108,10 +108,10 @@ void Script::parse() const auto diagnosticMessages = parser.diagnosticMessages(); for (const DiagnosticMessage &m : diagnosticMessages) { if (m.isError()) { - valueScope.engine->throwSyntaxError(m.message, sourceFile, m.loc.startLine, m.loc.startColumn); + valueScope.engine->throwSyntaxError(m.message, sourceFile, m.line, m.column); return; } else { - qWarning() << sourceFile << ':' << m.loc.startLine << ':' << m.loc.startColumn + qWarning() << sourceFile << ':' << m.line << ':' << m.column << ": warning: " << m.message; } } @@ -203,10 +203,19 @@ QV4::CompiledData::CompilationUnit Script::precompile( Codegen cg(unitGenerator, /*strict mode*/false); cg.generateFromProgram(fileName, finalUrl, source, program, module, contextType); - errors = cg.qmlErrors(); - if (!errors.isEmpty()) { - if (reportedErrors) - *reportedErrors << errors; + const auto v4Errors = cg.errors(); + if (!v4Errors.isEmpty()) { + const QUrl url = cg.url(); + if (reportedErrors) { + for (const auto &v4Error : v4Errors) { + QQmlError error; + error.setUrl(url); + error.setLine(v4Error.line); + error.setColumn(v4Error.column); + error.setDescription(v4Error.message); + reportedErrors->append(error); + } + } return nullptr; } diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index 4ad9057ced..aada928dea 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -245,6 +245,7 @@ #include <private/qqmljsgrammar_p.h> #include <private/qqmljsast_p.h> #include <private/qqmljsengine_p.h> +#include <private/qqmljsdiagnosticmessage_p.h> #include <QtCore/qlist.h> #include <QtCore/qstring.h> @@ -365,7 +366,7 @@ public: inline DiagnosticMessage diagnosticMessage() const { for (const DiagnosticMessage &d : diagnostic_messages) { - if (d.kind != DiagnosticMessage::Warning) + if (d.type != QtWarningMsg) return d; } @@ -376,10 +377,10 @@ public: { return diagnosticMessage().message; } inline int errorLineNumber() const - { return diagnosticMessage().loc.startLine; } + { return diagnosticMessage().line; } inline int errorColumnNumber() const - { return diagnosticMessage().loc.startColumn; } + { return diagnosticMessage().column; } protected: bool parse(int startToken); @@ -403,11 +404,22 @@ protected: void pushToken(int token); int lookaheadToken(Lexer *lexer); + static DiagnosticMessage compileError(const AST::SourceLocation &location, + const QString &message, QtMsgType kind = QtCriticalMsg) + { + DiagnosticMessage error; + error.line = location.startLine; + error.column = location.startColumn; + error.message = message; + error.type = kind; + return error; + } + void syntaxError(const AST::SourceLocation &location, const char *message) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location, QLatin1String(message))); + diagnostic_messages.append(compileError(location, QLatin1String(message))); } void syntaxError(const AST::SourceLocation &location, const QString &message) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location, message)); + diagnostic_messages.append(compileError(location, message)); } protected: @@ -840,7 +852,7 @@ UiImportHead: T_IMPORT ImportId; if (node) { node->importToken = loc(1); } else { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), + diagnostic_messages.append(compileError(loc(1), QLatin1String("Expected a qualified name id or a string literal"))); return false; // ### remove me @@ -1332,8 +1344,8 @@ UiQualifiedId: MemberExpression; /. case $rule_number: { if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, - QLatin1String("Ignored annotation"))); + diagnostic_messages.append(compileError(mem->lbracketToken, + QLatin1String("Ignored annotation"), QtWarningMsg)); sym(1).Expression = mem->base; } @@ -1343,7 +1355,7 @@ UiQualifiedId: MemberExpression; } else { sym(1).UiQualifiedId = 0; - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), + diagnostic_messages.append(compileError(loc(1), QLatin1String("Expected a qualified name id"))); return false; // ### recover @@ -1590,7 +1602,7 @@ RegularExpressionLiteral: T_DIVIDE_EQ; scan_regexp: { bool rx = lexer->scanRegExp(prefix); if (!rx) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); + diagnostic_messages.append(compileError(location(lexer), lexer->errorMessage())); return false; } @@ -4420,7 +4432,7 @@ ExportSpecifier: IdentifierName T_AS IdentifierName; yylloc.length = 0; //const QString msg = QCoreApplication::translate("QQmlParser", "Missing `;'"); - //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); + //diagnostic_messages.append(compileError(yyloc, msg, QtWarningMsg)); first_token = &token_buffer[0]; last_token = &token_buffer[1]; @@ -4457,7 +4469,7 @@ ExportSpecifier: IdentifierName T_AS IdentifierName; msg = QCoreApplication::translate("QQmlParser", "Syntax error"); else msg = QCoreApplication::translate("QQmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token])); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + diagnostic_messages.append(compileError(token_buffer[0].loc, msg)); action = errorState; goto _Lcheck_token; @@ -4488,7 +4500,7 @@ ExportSpecifier: IdentifierName T_AS IdentifierName; qDebug() << "Parse error, trying to recover (2)."; #endif const QString msg = QCoreApplication::translate("QQmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk])); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + diagnostic_messages.append(compileError(token_buffer[0].loc, msg)); pushToken(*tk); goto _Lcheck_token; @@ -4503,7 +4515,7 @@ ExportSpecifier: IdentifierName T_AS IdentifierName; int a = t_action(errorState, tk); if (a > 0 && t_action(a, yytoken)) { const QString msg = QCoreApplication::translate("QQmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk])); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + diagnostic_messages.append(compileError(token_buffer[0].loc, msg)); pushToken(tk); goto _Lcheck_token; @@ -4511,7 +4523,7 @@ ExportSpecifier: IdentifierName T_AS IdentifierName; } const QString msg = QCoreApplication::translate("QQmlParser", "Syntax error"); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + diagnostic_messages.append(compileError(token_buffer[0].loc, msg)); } return false; diff --git a/src/qml/parser/qqmljsengine_p.h b/src/qml/parser/qqmljsengine_p.h index b7f7da9478..6a754fc236 100644 --- a/src/qml/parser/qqmljsengine_p.h +++ b/src/qml/parser/qqmljsengine_p.h @@ -91,28 +91,6 @@ public: } }; - -class QML_PARSER_EXPORT DiagnosticMessage -{ -public: - enum Kind { Hint, Warning, Error }; - - DiagnosticMessage() {} - - DiagnosticMessage(Kind kind, const AST::SourceLocation &loc, const QString &message) - : kind(kind), loc(loc), message(message) {} - - bool isWarning() const - { return kind == Warning; } - - bool isError() const - { return kind == Error; } - - Kind kind = Error; - AST::SourceLocation loc; - QString message; -}; - class QML_PARSER_EXPORT Engine { Lexer *_lexer; diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp index c53b13f64d..1b3b129c6a 100644 --- a/src/qml/parser/qqmljslexer.cpp +++ b/src/qml/parser/qqmljslexer.cpp @@ -42,6 +42,8 @@ #include "qqmljsmemorypool_p.h" #include "qqmljskeywords_p.h" +#include <private/qqmljsdiagnosticmessage_p.h> + #include <QtCore/qcoreapplication.h> #include <QtCore/qvarlengtharray.h> #include <QtCore/qdebug.h> @@ -1402,6 +1404,12 @@ static inline bool isUriToken(int token) bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error) { + auto setError = [error, this](QString message) { + error->message = std::move(message); + error->line = tokenStartLine(); + error->column = tokenStartColumn(); + }; + Q_ASSERT(!_qmlMode); lex(); // fetch the first token @@ -1422,9 +1430,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error) if (! (directiveName == QLatin1String("pragma") || directiveName == QLatin1String("import"))) { - error->message = QCoreApplication::translate("QQmlParser", "Syntax error"); - error->loc.startLine = tokenStartLine(); - error->loc.startColumn = tokenStartColumn(); + setError(QCoreApplication::translate("QQmlParser", "Syntax error")); return false; // not a valid directive name } @@ -1432,9 +1438,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error) if (directiveName == QLatin1String("pragma")) { // .pragma library if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("library"))) { - error->message = QCoreApplication::translate("QQmlParser", "Syntax error"); - error->loc.startLine = tokenStartLine(); - error->loc.startColumn = tokenStartColumn(); + setError(QCoreApplication::translate("QQmlParser", "Syntax error")); return false; // expected `library } @@ -1456,9 +1460,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error) pathOrUri = tokenText(); if (!pathOrUri.endsWith(QLatin1String("js"))) { - error->message = QCoreApplication::translate("QQmlParser","Imported file must be a script"); - error->loc.startLine = tokenStartLine(); - error->loc.startColumn = tokenStartColumn(); + setError(QCoreApplication::translate("QQmlParser","Imported file must be a script")); return false; } @@ -1467,9 +1469,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error) while (true) { if (!isUriToken(_tokenKind)) { - error->message = QCoreApplication::translate("QQmlParser","Invalid module URI"); - error->loc.startLine = tokenStartLine(); - error->loc.startColumn = tokenStartColumn(); + setError(QCoreApplication::translate("QQmlParser","Invalid module URI")); return false; } @@ -1477,9 +1477,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error) lex(); if (tokenStartLine() != lineNumber) { - error->message = QCoreApplication::translate("QQmlParser","Invalid module URI"); - error->loc.startLine = tokenStartLine(); - error->loc.startColumn = tokenStartColumn(); + setError(QCoreApplication::translate("QQmlParser","Invalid module URI")); return false; } if (_tokenKind != QQmlJSGrammar::T_DOT) @@ -1489,17 +1487,13 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error) lex(); if (tokenStartLine() != lineNumber) { - error->message = QCoreApplication::translate("QQmlParser","Invalid module URI"); - error->loc.startLine = tokenStartLine(); - error->loc.startColumn = tokenStartColumn(); + setError(QCoreApplication::translate("QQmlParser","Invalid module URI")); return false; } } if (_tokenKind != T_NUMERIC_LITERAL) { - error->message = QCoreApplication::translate("QQmlParser","Module import requires a version"); - error->loc.startLine = tokenStartLine(); - error->loc.startColumn = tokenStartColumn(); + setError(QCoreApplication::translate("QQmlParser","Module import requires a version")); return false; // expected the module version number } @@ -1511,34 +1505,27 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error) // if (! (lex() == T_AS && tokenStartLine() == lineNumber)) { if (fileImport) - error->message = QCoreApplication::translate("QQmlParser", "File import requires a qualifier"); + setError(QCoreApplication::translate("QQmlParser", "File import requires a qualifier")); else - error->message = QCoreApplication::translate("QQmlParser", "Module import requires a qualifier"); + setError(QCoreApplication::translate("QQmlParser", "Module import requires a qualifier")); if (tokenStartLine() != lineNumber) { - error->loc.startLine = lineNumber; - error->loc.startColumn = column; - } else { - error->loc.startLine = tokenStartLine(); - error->loc.startColumn = tokenStartColumn(); + error->line = lineNumber; + error->line = column; } return false; // expected `as' } if (lex() != T_IDENTIFIER || tokenStartLine() != lineNumber) { if (fileImport) - error->message = QCoreApplication::translate("QQmlParser", "File import requires a qualifier"); + setError(QCoreApplication::translate("QQmlParser", "File import requires a qualifier")); else - error->message = QCoreApplication::translate("QQmlParser", "Module import requires a qualifier"); - error->loc.startLine = tokenStartLine(); - error->loc.startColumn = tokenStartColumn(); + setError(QCoreApplication::translate("QQmlParser", "Module import requires a qualifier")); return false; // expected module name } const QString module = tokenText(); if (!module.at(0).isUpper()) { - error->message = QCoreApplication::translate("QQmlParser","Invalid import qualifier"); - error->loc.startLine = tokenStartLine(); - error->loc.startColumn = tokenStartColumn(); + setError(QCoreApplication::translate("QQmlParser","Invalid import qualifier")); return false; } @@ -1549,9 +1536,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error) } if (tokenStartLine() != lineNumber) { - error->message = QCoreApplication::translate("QQmlParser", "Syntax error"); - error->loc.startLine = tokenStartLine(); - error->loc.startColumn = tokenStartColumn(); + setError(QCoreApplication::translate("QQmlParser", "Syntax error")); return false; // the directives cannot span over multiple lines } diff --git a/src/qml/parser/qqmljslexer_p.h b/src/qml/parser/qqmljslexer_p.h index 51152bfd6e..4fe40948e3 100644 --- a/src/qml/parser/qqmljslexer_p.h +++ b/src/qml/parser/qqmljslexer_p.h @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE namespace QQmlJS { class Engine; -class DiagnosticMessage; +struct DiagnosticMessage; class Directives; class QML_PARSER_EXPORT Lexer: public QQmlJSGrammar diff --git a/src/qml/qml.pro b/src/qml/qml.pro index 5cb51e0d03..99ad6ace60 100644 --- a/src/qml/qml.pro +++ b/src/qml/qml.pro @@ -67,6 +67,7 @@ HEADERS += qtqmlglobal.h \ qtqmlglobal_p.h #modules +include(common/common.pri) include(util/util.pri) include(memory/memory.pri) include(parser/parser.pri) diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri index c625743f61..15ea12cbe7 100644 --- a/src/qml/qml/qml.pri +++ b/src/qml/qml/qml.pri @@ -1,5 +1,6 @@ SOURCES += \ $$PWD/qqml.cpp \ + $$PWD/qqmlerror.cpp \ $$PWD/qqmlopenmetaobject.cpp \ $$PWD/qqmlvmemetaobject.cpp \ $$PWD/qqmlengine.cpp \ @@ -142,7 +143,8 @@ HEADERS += \ $$PWD/qqmlpropertyresolver_p.h \ $$PWD/qqmltypecompiler_p.h \ $$PWD/qqmlpropertycachecreator_p.h \ - $$PWD/qqmlpropertyvalidator_p.h + $$PWD/qqmlpropertyvalidator_p.h \ + $$PWD/qqmlsourcecoordinate_p.h qtConfig(qml-xml-http-request) { HEADERS += \ diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index 5cf87f5264..c477415ef7 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -100,7 +100,12 @@ void QQmlCustomParser::clearErrors() */ void QQmlCustomParser::error(const QV4::CompiledData::Location &location, const QString &description) { - exceptions << QQmlCompileError(location, description); + QQmlJS::DiagnosticMessage error; + error.line = location.line; + error.column = location.column; + error.message = description; + + exceptions << error; } struct StaticQtMetaObject : public QObject diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h index c8e1300a1b..94671a4f35 100644 --- a/src/qml/qml/qqmlcustomparser_p.h +++ b/src/qml/qml/qqmlcustomparser_p.h @@ -83,7 +83,7 @@ public: virtual void verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) = 0; virtual void applyBindings(QObject *, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) = 0; - QVector<QQmlCompileError> errors() const { return exceptions; } + QVector<QQmlJS::DiagnosticMessage> errors() const { return exceptions; } protected: void error(const QV4::CompiledData::Binding *binding, const QString& description) @@ -97,7 +97,7 @@ protected: const QMetaObject *resolveType(const QString&) const; private: - QVector<QQmlCompileError> exceptions; + QVector<QQmlJS::DiagnosticMessage> exceptions; QQmlEnginePrivate *engine; const QQmlPropertyValidator *validator; Flags m_flags; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index f977934b3e..b94f449a39 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -2109,15 +2109,15 @@ QList<QQmlError> QQmlEnginePrivate::qmlErrorFromDiagnostics(const QString &fileN QList<QQmlError> errors; for (const DiagnosticMessage &m : diagnosticMessages) { if (m.isWarning()) { - qWarning("%s:%d : %s", qPrintable(fileName), m.loc.startLine, qPrintable(m.message)); + qWarning("%s:%d : %s", qPrintable(fileName), m.line, qPrintable(m.message)); continue; } QQmlError error; error.setUrl(QUrl(fileName)); error.setDescription(m.message); - error.setLine(m.loc.startLine); - error.setColumn(m.loc.startColumn); + error.setLine(m.line); + error.setColumn(m.column); errors << error; } return errors; diff --git a/src/qml/qmldirparser/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp index 5e181f7e27..739d5ce4cd 100644 --- a/src/qml/qmldirparser/qqmlerror.cpp +++ b/src/qml/qml/qqmlerror.cpp @@ -39,16 +39,15 @@ #include "qqmlerror.h" #include "qqmlsourcecoordinate_p.h" +#include <private/qqmljsdiagnosticmessage_p.h> #include <QtCore/qdebug.h> #include <QtCore/qfile.h> #include <QtCore/qstringlist.h> #include <QtCore/qvector.h> -#ifndef QT_NO_QOBJECT #include <QtCore/qobject.h> #include <QtCore/qpointer.h> -#endif QT_BEGIN_NAMESPACE @@ -77,26 +76,14 @@ QT_BEGIN_NAMESPACE \sa QQuickView::errors(), QQmlComponent::errors() */ -class QQmlErrorPrivate +class QQmlErrorPrivate : public QQmlJS::DiagnosticMessage { public: - QQmlErrorPrivate(); - + QQmlErrorPrivate() { type = QtWarningMsg; } QUrl url; - QString description; - quint16 line; - quint16 column; - QtMsgType messageType; -#ifndef QT_NO_QOBJECT QPointer<QObject> object; -#endif }; -QQmlErrorPrivate::QQmlErrorPrivate() -: line(0), column(0), messageType(QtMsgType::QtWarningMsg) -{ -} - /*! Creates an empty error object. */ @@ -126,13 +113,11 @@ QQmlError &QQmlError::operator=(const QQmlError &other) if (!d) d = new QQmlErrorPrivate; d->url = other.d->url; - d->description = other.d->description; + d->message = other.d->message; d->line = other.d->line; d->column = other.d->column; -#ifndef QT_NO_QOBJECT d->object = other.d->object; -#endif - d->messageType = other.d->messageType; + d->type = other.d->type; } return *this; } @@ -179,7 +164,7 @@ void QQmlError::setUrl(const QUrl &url) QString QQmlError::description() const { if (d) - return d->description; + return d->message; return QString(); } @@ -190,7 +175,7 @@ void QQmlError::setDescription(const QString &description) { if (!d) d = new QQmlErrorPrivate; - d->description = description; + d->message = description; } /*! @@ -199,7 +184,7 @@ void QQmlError::setDescription(const QString &description) int QQmlError::line() const { if (d) - return qmlSourceCoordinate(d->line); + return qmlConvertSourceCoordinate<quint32, int>(d->line); return -1; } @@ -210,7 +195,7 @@ void QQmlError::setLine(int line) { if (!d) d = new QQmlErrorPrivate; - d->line = qmlSourceCoordinate(line); + d->line = qmlConvertSourceCoordinate<int, quint32>(line); } /*! @@ -219,7 +204,7 @@ void QQmlError::setLine(int line) int QQmlError::column() const { if (d) - return qmlSourceCoordinate(d->column); + return qmlConvertSourceCoordinate<quint32, int>(d->column); return -1; } @@ -230,10 +215,9 @@ void QQmlError::setColumn(int column) { if (!d) d = new QQmlErrorPrivate; - d->column = qmlSourceCoordinate(column); + d->column = qmlConvertSourceCoordinate<int, quint32>(column); } -#ifndef QT_NO_QOBJECT /*! Returns the nearest object where this error occurred. Exceptions in bound property expressions set this to the object @@ -256,7 +240,6 @@ void QQmlError::setObject(QObject *object) d = new QQmlErrorPrivate; d->object = object; } -#endif // QT_NO_QOBJECT /*! \since 5.9 @@ -266,7 +249,7 @@ void QQmlError::setObject(QObject *object) QtMsgType QQmlError::messageType() const { if (d) - return d->messageType; + return d->type; return QtMsgType::QtWarningMsg; } @@ -280,7 +263,7 @@ void QQmlError::setMessageType(QtMsgType messageType) { if (!d) d = new QQmlErrorPrivate; - d->messageType = messageType; + d->type = messageType; } /*! diff --git a/src/qml/qmldirparser/qqmlerror.h b/src/qml/qml/qqmlerror.h index f4221358e9..8ea493c11d 100644 --- a/src/qml/qmldirparser/qqmlerror.h +++ b/src/qml/qml/qqmlerror.h @@ -69,10 +69,8 @@ public: int column() const; void setColumn(int); -#ifndef QT_NO_QOBJECT QObject *object() const; void setObject(QObject *); -#endif QtMsgType messageType() const; void setMessageType(QtMsgType messageType); diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index 6a11583f18..be0adc54a7 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -351,7 +351,7 @@ QString QQmlExpression::sourceFile() const int QQmlExpression::lineNumber() const { Q_D(const QQmlExpression); - return qmlSourceCoordinate(d->line); + return qmlConvertSourceCoordinate<quint16, int>(d->line); } /*! @@ -361,7 +361,7 @@ int QQmlExpression::lineNumber() const int QQmlExpression::columnNumber() const { Q_D(const QQmlExpression); - return qmlSourceCoordinate(d->column); + return qmlConvertSourceCoordinate<quint16, int>(d->column); } /*! @@ -372,8 +372,8 @@ void QQmlExpression::setSourceLocation(const QString &url, int line, int column) { Q_D(QQmlExpression); d->url = url; - d->line = qmlSourceCoordinate(line); - d->column = qmlSourceCoordinate(column); + d->line = qmlConvertSourceCoordinate<int, quint16>(line); + d->column = qmlConvertSourceCoordinate<int, quint16>(column); } /*! diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index d3055b552c..d986ecfe2b 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -44,6 +44,7 @@ #include <QtCore/qcoreapplication.h> #include <QtCore/qset.h> #include <QtCore/qstringlist.h> +#include <QtQml/qqmlerror.h> #include <private/qqmldirparser_p.h> #include <private/qqmltype_p.h> #include <private/qstringhash_p.h> diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h index 28eea27675..e2dbea94e7 100644 --- a/src/qml/qml/qqmlpropertycachecreator_p.h +++ b/src/qml/qml/qqmlpropertycachecreator_p.h @@ -97,12 +97,12 @@ public: QQmlEnginePrivate *enginePrivate, const ObjectContainer *objectContainer, const QQmlImports *imports); - QQmlCompileError buildMetaObjects(); + QQmlJS::DiagnosticMessage buildMetaObjects(); protected: - QQmlCompileError buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context); - QQmlRefPointer<QQmlPropertyCache> propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlCompileError *error) const; - QQmlCompileError createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlRefPointer<QQmlPropertyCache> &baseTypeCache); + QQmlJS::DiagnosticMessage buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context); + QQmlRefPointer<QQmlPropertyCache> propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlJS::DiagnosticMessage *error) const; + QQmlJS::DiagnosticMessage createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlRefPointer<QQmlPropertyCache> &baseTypeCache); QString stringAt(int index) const { return objectContainer->stringAt(index); } @@ -128,14 +128,14 @@ inline QQmlPropertyCacheCreator<ObjectContainer>::QQmlPropertyCacheCreator(QQmlP } template <typename ObjectContainer> -inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjects() +inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjects() { QQmlBindingInstantiationContext context; return buildMetaObjectRecursively(/*root object*/0, context); } template <typename ObjectContainer> -inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context) +inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context) { const CompiledObject *obj = objectContainer->objectAt(objectIndex); @@ -155,8 +155,8 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObje auto *typeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex); Q_ASSERT(typeRef); QQmlRefPointer<QQmlPropertyCache> baseTypeCache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate)); - QQmlCompileError error = createMetaObject(context.referencingObjectIndex, obj, baseTypeCache); - if (error.isSet()) + QQmlJS::DiagnosticMessage error = createMetaObject(context.referencingObjectIndex, obj, baseTypeCache); + if (error.isValid()) return error; } } else { @@ -170,16 +170,16 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObje QQmlRefPointer<QQmlPropertyCache> baseTypeCache; { - QQmlCompileError error; + QQmlJS::DiagnosticMessage error; baseTypeCache = propertyCacheForObject(obj, context, &error); - if (error.isSet()) + if (error.isValid()) return error; } if (baseTypeCache) { if (needVMEMetaObject) { - QQmlCompileError error = createMetaObject(objectIndex, obj, baseTypeCache); - if (error.isSet()) + QQmlJS::DiagnosticMessage error = createMetaObject(objectIndex, obj, baseTypeCache); + if (error.isValid()) return error; } else { propertyCaches->set(objectIndex, baseTypeCache); @@ -200,18 +200,18 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObje if (!context.resolveInstantiatingProperty()) pendingGroupPropertyBindings->append(context); - QQmlCompileError error = buildMetaObjectRecursively(binding->value.objectIndex, context); - if (error.isSet()) + QQmlJS::DiagnosticMessage error = buildMetaObjectRecursively(binding->value.objectIndex, context); + if (error.isValid()) return error; } } - QQmlCompileError noError; + QQmlJS::DiagnosticMessage noError; return noError; } template <typename ObjectContainer> -inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContainer>::propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlCompileError *error) const +inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContainer>::propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlJS::DiagnosticMessage *error) const { if (context.instantiatingProperty) { return context.instantiatingPropertyCache(enginePrivate); @@ -221,15 +221,15 @@ inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContaine if (typeRef->isFullyDynamicType) { if (obj->propertyCount() > 0 || obj->aliasCount() > 0) { - *error = QQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully dynamic types cannot declare new properties.")); + *error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully dynamic types cannot declare new properties.")); return nullptr; } if (obj->signalCount() > 0) { - *error = QQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully dynamic types cannot declare new signals.")); + *error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully dynamic types cannot declare new signals.")); return nullptr; } if (obj->functionCount() > 0) { - *error = QQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully Dynamic types cannot declare new functions.")); + *error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully Dynamic types cannot declare new functions.")); return nullptr; } } @@ -256,7 +256,7 @@ inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContaine const QMetaObject *attachedMo = qmltype.attachedPropertiesType(enginePrivate); if (!attachedMo) { - *error = QQmlCompileError(context.instantiatingBinding->location, QQmlPropertyCacheCreatorBase::tr("Non-existent attached object")); + *error = qQmlCompileError(context.instantiatingBinding->location, QQmlPropertyCacheCreatorBase::tr("Non-existent attached object")); return nullptr; } return enginePrivate->cache(attachedMo); @@ -265,7 +265,7 @@ inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContaine } template <typename ObjectContainer> -inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlRefPointer<QQmlPropertyCache> &baseTypeCache) +inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlRefPointer<QQmlPropertyCache> &baseTypeCache) { QQmlRefPointer<QQmlPropertyCache> cache; cache.adopt(baseTypeCache->copyAndReserve(obj->propertyCount() + obj->aliasCount(), @@ -335,7 +335,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj bool notInRevision = false; QQmlPropertyData *d = resolver.property(stringAt(p->nameIndex), ¬InRevision); if (d && d->isFinal()) - return QQmlCompileError(p->location, QQmlPropertyCacheCreatorBase::tr("Cannot override FINAL property")); + return qQmlCompileError(p->location, QQmlPropertyCacheCreatorBase::tr("Cannot override FINAL property")); } auto a = obj->aliasesBegin(); @@ -344,7 +344,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj bool notInRevision = false; QQmlPropertyData *d = resolver.property(stringAt(a->nameIndex), ¬InRevision); if (d && d->isFinal()) - return QQmlCompileError(a->location, QQmlPropertyCacheCreatorBase::tr("Cannot override FINAL property")); + return qQmlCompileError(a->location, QQmlPropertyCacheCreatorBase::tr("Cannot override FINAL property")); } int effectivePropertyIndex = cache->propertyIndexCacheStart; @@ -438,7 +438,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj const QString customTypeName = stringAt(param->customTypeNameIndex); QQmlType qmltype; if (!imports->resolveType(customTypeName, &qmltype, nullptr, nullptr, nullptr)) - return QQmlCompileError(s->location, QQmlPropertyCacheCreatorBase::tr("Invalid signal parameter type: %1").arg(customTypeName)); + return qQmlCompileError(s->location, QQmlPropertyCacheCreatorBase::tr("Invalid signal parameter type: %1").arg(customTypeName)); if (qmltype.isComposite()) { QQmlRefPointer<QQmlTypeData> tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl()); @@ -461,7 +461,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj QString signalName = stringAt(s->nameIndex); if (seenSignals.contains(signalName)) - return QQmlCompileError(s->location, QQmlPropertyCacheCreatorBase::tr("Duplicate signal name: invalid override of property change signal or superclass signal")); + return qQmlCompileError(s->location, QQmlPropertyCacheCreatorBase::tr("Duplicate signal name: invalid override of property change signal or superclass signal")); seenSignals.insert(signalName); cache->appendSignal(signalName, flags, effectiveMethodIndex++, @@ -477,7 +477,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj const QString slotName = stringAt(function->nameIndex); if (seenSignals.contains(slotName)) - return QQmlCompileError(function->location, QQmlPropertyCacheCreatorBase::tr("Duplicate method name: invalid override of property change signal or superclass signal")); + return qQmlCompileError(function->location, QQmlPropertyCacheCreatorBase::tr("Duplicate method name: invalid override of property change signal or superclass signal")); // Note: we don't append slotName to the seenSignals list, since we don't // protect against overriding change signals or methods with properties. @@ -517,7 +517,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj QQmlType qmltype; if (!imports->resolveType(stringAt(p->customTypeNameIndex), &qmltype, nullptr, nullptr, nullptr)) { - return QQmlCompileError(p->location, QQmlPropertyCacheCreatorBase::tr("Invalid property type")); + return qQmlCompileError(p->location, QQmlPropertyCacheCreatorBase::tr("Invalid property type")); } Q_ASSERT(qmltype.isValid()); @@ -561,7 +561,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj effectiveSignalIndex++; } - QQmlCompileError noError; + QQmlJS::DiagnosticMessage noError; return noError; } @@ -575,11 +575,11 @@ public: void appendAliasPropertiesToMetaObjects(); - QQmlCompileError appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex); + QQmlJS::DiagnosticMessage appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex); private: void appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex); - QQmlCompileError propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyData::Flags *propertyFlags); + QQmlJS::DiagnosticMessage propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyData::Flags *propertyFlags); void collectObjectsWithAliasesRecursively(int objectIndex, QVector<int> *objectsWithAliases) const; @@ -690,7 +690,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::collectObjectsWithAl } template <typename ObjectContainer> -inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias( +inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias( const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion, QQmlPropertyData::Flags *propertyFlags) { @@ -716,7 +716,7 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::property const QV4::CompiledData::Alias *targetAlias = &(*nextAlias); if (seenAliases.contains(targetAlias)) { - return QQmlCompileError(targetAlias->location, + return qQmlCompileError(targetAlias->location, QQmlPropertyCacheCreatorBase::tr("Cyclic alias")); } @@ -738,7 +738,8 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::property // Can be caused by the alias target not being a valid id or property. E.g.: // property alias dataValue: dataVal // invalidAliasComponent { id: dataVal } - return QQmlCompileError(targetObject.location, QQmlPropertyCacheCreatorBase::tr("Invalid alias target")); + return qQmlCompileError(targetObject.location, + QQmlPropertyCacheCreatorBase::tr("Invalid alias target")); } if (typeRef->type.isValid()) @@ -784,16 +785,16 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::property propertyFlags->isWritable = !(alias.flags & QV4::CompiledData::Property::IsReadOnly) && writable; propertyFlags->isResettable = resettable; - return QQmlCompileError(); + return QQmlJS::DiagnosticMessage(); } template <typename ObjectContainer> -inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesToPropertyCache( +inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesToPropertyCache( const CompiledObject &component, int objectIndex) { const CompiledObject &object = *objectContainer->objectAt(objectIndex); if (!object.aliasCount()) - return QQmlCompileError(); + return QQmlJS::DiagnosticMessage(); QQmlPropertyCache *propertyCache = propertyCaches->at(objectIndex); Q_ASSERT(propertyCache); @@ -810,8 +811,8 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAl int type = 0; int minorVersion = 0; QQmlPropertyData::Flags propertyFlags; - QQmlCompileError error = propertyDataForAlias(component, *alias, &type, &minorVersion, &propertyFlags); - if (error.isSet()) + QQmlJS::DiagnosticMessage error = propertyDataForAlias(component, *alias, &type, &minorVersion, &propertyFlags); + if (error.isValid()) return error; const QString propertyName = objectContainer->stringAt(alias->nameIndex); @@ -823,7 +824,7 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAl type, minorVersion, effectiveSignalIndex++); } - return QQmlCompileError(); + return QQmlJS::DiagnosticMessage(); } template <typename ObjectContainer> diff --git a/src/qml/qml/qqmlpropertyvalidator.cpp b/src/qml/qml/qqmlpropertyvalidator.cpp index 71d5318652..6bb00e438d 100644 --- a/src/qml/qml/qqmlpropertyvalidator.cpp +++ b/src/qml/qml/qqmlpropertyvalidator.cpp @@ -57,7 +57,7 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, c bindingPropertyDataPerObject->resize(compilationUnit->objectCount()); } -QVector<QQmlCompileError> QQmlPropertyValidator::validate() +QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validate() { return validateObject(/*root object*/0, /*instantiatingBinding*/nullptr); } @@ -80,7 +80,8 @@ struct BindingFinder } }; -QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty) const +QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validateObject( + int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty) const { const QV4::CompiledData::Object *obj = compilationUnit->objectAt(objectIndex); @@ -93,7 +94,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex, QQmlPropertyCache *propertyCache = propertyCaches.at(objectIndex); if (!propertyCache) - return QVector<QQmlCompileError>(); + return QVector<QQmlJS::DiagnosticMessage>(); QQmlCustomParser *customParser = nullptr; if (auto typeRef = resolvedType(obj->inheritedTypeNameIndex)) { @@ -203,7 +204,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex, = pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType()) && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment); - const QVector<QQmlCompileError> subObjectValidatorErrors + const QVector<QQmlJS::DiagnosticMessage> subObjectValidatorErrors = validateObject(binding->value.objectIndex, binding, populatingValueTypeGroupProperty); if (!subObjectValidatorErrors.isEmpty()) @@ -260,12 +261,12 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex, } if (binding->type < QV4::CompiledData::Binding::Type_Script) { - QQmlCompileError bindingError = validateLiteralBinding(propertyCache, pd, binding); - if (bindingError.isSet()) + QQmlJS::DiagnosticMessage bindingError = validateLiteralBinding(propertyCache, pd, binding); + if (bindingError.isValid()) return recordError(bindingError); } else if (binding->type == QV4::CompiledData::Binding::Type_Object) { - QQmlCompileError bindingError = validateObjectBinding(pd, name, binding); - if (bindingError.isSet()) + QQmlJS::DiagnosticMessage bindingError = validateObjectBinding(pd, name, binding); + if (bindingError.isValid()) return recordError(bindingError); } else if (binding->isGroupProperty()) { if (QQmlValueTypeFactory::isValueType(pd->propType())) { @@ -316,24 +317,24 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex, customParser->validator = nullptr; customParser->engine = nullptr; customParser->imports = (QQmlImports*)nullptr; - QVector<QQmlCompileError> parserErrors = customParser->errors(); + QVector<QQmlJS::DiagnosticMessage> parserErrors = customParser->errors(); if (!parserErrors.isEmpty()) return parserErrors; } (*bindingPropertyDataPerObject)[objectIndex] = collectedBindingPropertyData; - QVector<QQmlCompileError> noError; + QVector<QQmlJS::DiagnosticMessage> noError; return noError; } -QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const +QQmlJS::DiagnosticMessage QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const { if (property->isQList()) { - return QQmlCompileError(binding->valueLocation, tr("Cannot assign primitives to lists")); + return qQmlCompileError(binding->valueLocation, tr("Cannot assign primitives to lists")); } - QQmlCompileError noError; + QQmlJS::DiagnosticMessage noError; if (property->isEnum()) { if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum) @@ -348,7 +349,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache p.enumerator().keyToValue(value.toUtf8().constData(), &ok); if (!ok) { - return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: unknown enumeration")); + return qQmlCompileError(binding->valueLocation, tr("Invalid property assignment: unknown enumeration")); } return noError; } @@ -365,7 +366,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache enginePrivate->warning(warning); return noError; } - return QQmlCompileError(binding->valueLocation, error); + return qQmlCompileError(binding->valueLocation, error); }; switch (property->propType()) { @@ -629,23 +630,23 @@ bool QQmlPropertyValidator::canCoerce(int to, QQmlPropertyCache *fromMo) const return false; } -QVector<QQmlCompileError> QQmlPropertyValidator::recordError(const QV4::CompiledData::Location &location, const QString &description) const +QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::recordError(const QV4::CompiledData::Location &location, const QString &description) const { - QVector<QQmlCompileError> errors; - errors.append(QQmlCompileError(location, description)); + QVector<QQmlJS::DiagnosticMessage> errors; + errors.append(qQmlCompileError(location, description)); return errors; } -QVector<QQmlCompileError> QQmlPropertyValidator::recordError(const QQmlCompileError &error) const +QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::recordError(const QQmlJS::DiagnosticMessage &error) const { - QVector<QQmlCompileError> errors; + QVector<QQmlJS::DiagnosticMessage> errors; errors.append(error); return errors; } -QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const +QQmlJS::DiagnosticMessage QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const { - QQmlCompileError noError; + QQmlJS::DiagnosticMessage noError; if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) { Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Object); @@ -669,7 +670,7 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData * } if (!isValueSource && !isPropertyInterceptor) { - return QQmlCompileError(binding->valueLocation, tr("\"%1\" cannot operate on \"%2\"").arg(stringAt(targetObject->inheritedTypeNameIndex)).arg(propertyName)); + return qQmlCompileError(binding->valueLocation, tr("\"%1\" cannot operate on \"%2\"").arg(stringAt(targetObject->inheritedTypeNameIndex)).arg(propertyName)); } return noError; @@ -687,7 +688,7 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData * if (!QQmlMetaType::isInterface(listType)) { QQmlPropertyCache *source = propertyCaches.at(binding->value.objectIndex); if (!canCoerce(listType, source)) { - return QQmlCompileError(binding->valueLocation, tr("Cannot assign object to list property \"%1\"").arg(propertyName)); + return qQmlCompileError(binding->valueLocation, tr("Cannot assign object to list property \"%1\"").arg(propertyName)); } } return noError; @@ -695,11 +696,11 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData * return noError; } else if (QQmlValueTypeFactory::isValueType(property->propType())) { auto typeName = QMetaType::typeName(property->propType()); - return QQmlCompileError(binding->location, tr("Can not assign value of type \"%1\" to property \"%2\", expecting an object") + return qQmlCompileError(binding->location, tr("Can not assign value of type \"%1\" to property \"%2\", expecting an object") .arg(typeName ? QString::fromLatin1(typeName) : QString::fromLatin1("<unknown type>")) .arg(propertyName)); } else if (property->propType() == qMetaTypeId<QQmlScriptString>()) { - return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: script expected")); + return qQmlCompileError(binding->valueLocation, tr("Invalid property assignment: script expected")); } else { // We want to use the raw metaObject here as the raw metaobject is the // actual property type before we applied any extensions that might @@ -719,7 +720,7 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData * } if (!isAssignable) { - return QQmlCompileError(binding->valueLocation, tr("Cannot assign object of type \"%1\" to property of type \"%2\" as the former is neither the same as the latter nor a sub-class of it.") + return qQmlCompileError(binding->valueLocation, tr("Cannot assign object of type \"%1\" to property of type \"%2\" as the former is neither the same as the latter nor a sub-class of it.") .arg(stringAt(compilationUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex)).arg(QLatin1String(QMetaType::typeName(property->propType())))); } } diff --git a/src/qml/qml/qqmlpropertyvalidator_p.h b/src/qml/qml/qqmlpropertyvalidator_p.h index 8244b2df21..f2b892e978 100644 --- a/src/qml/qml/qqmlpropertyvalidator_p.h +++ b/src/qml/qml/qqmlpropertyvalidator_p.h @@ -60,17 +60,25 @@ class QQmlPropertyValidator public: QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit); - QVector<QQmlCompileError> validate(); + QVector<QQmlJS::DiagnosticMessage> validate(); private: - QVector<QQmlCompileError> validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty = false) const; - QQmlCompileError validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const; - QQmlCompileError validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const; + QVector<QQmlJS::DiagnosticMessage> validateObject( + int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, + bool populatingValueTypeGroupProperty = false) const; + QQmlJS::DiagnosticMessage validateLiteralBinding( + QQmlPropertyCache *propertyCache, QQmlPropertyData *property, + const QV4::CompiledData::Binding *binding) const; + QQmlJS::DiagnosticMessage validateObjectBinding( + QQmlPropertyData *property, const QString &propertyName, + const QV4::CompiledData::Binding *binding) const; bool canCoerce(int to, QQmlPropertyCache *fromMo) const; - Q_REQUIRED_RESULT QVector<QQmlCompileError> recordError(const QV4::CompiledData::Location &location, const QString &description) const; - Q_REQUIRED_RESULT QVector<QQmlCompileError> recordError(const QQmlCompileError &error) const; + Q_REQUIRED_RESULT QVector<QQmlJS::DiagnosticMessage> recordError( + const QV4::CompiledData::Location &location, const QString &description) const; + Q_REQUIRED_RESULT QVector<QQmlJS::DiagnosticMessage> recordError( + const QQmlJS::DiagnosticMessage &error) const; QString stringAt(int index) const { return compilationUnit->stringAt(index); } QV4::ResolvedTypeReference *resolvedType(int id) const { diff --git a/src/qml/qml/qqmlsourcecoordinate_p.h b/src/qml/qml/qqmlsourcecoordinate_p.h new file mode 100644 index 0000000000..55e11fd147 --- /dev/null +++ b/src/qml/qml/qqmlsourcecoordinate_p.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLSOURCECOORDINATE_P_H +#define QQMLSOURCECOORDINATE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> + +#include <limits> + +QT_BEGIN_NAMESPACE + +// These methods are needed because in some public methods we historically interpret -1 as the +// invalid line or column, even though all the lines and columns are 1-based. Also, the different +// integer ranges may turn certain large values into invalid ones on conversion. + +template<typename From, typename To> +To qmlConvertSourceCoordinate(From n); + +template<> +inline quint16 qmlConvertSourceCoordinate<int, quint16>(int n) +{ + return (n > 0 && n <= int(std::numeric_limits<quint16>::max())) ? quint16(n) : 0; +} + +template<> +inline quint32 qmlConvertSourceCoordinate<int, quint32>(int n) +{ + return n > 0 ? quint32(n) : 0u; +} + +// TODO: In Qt6, change behavior and make the invalid coordinate 0 for the following two methods. + +template<> +inline int qmlConvertSourceCoordinate<quint16, int>(quint16 n) +{ + return (n == 0u) ? -1 : int(n); +} + +template<> +inline int qmlConvertSourceCoordinate<quint32, int>(quint32 n) +{ + return (n == 0u || n > quint32(std::numeric_limits<int>::max())) ? -1 : int(n); +} + +QT_END_NAMESPACE + +#endif // QQMLSOURCECOORDINATE_P_H diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp index 66320b8db9..cd2b8742b6 100644 --- a/src/qml/qml/qqmltypecompiler.cpp +++ b/src/qml/qml/qqmltypecompiler.cpp @@ -83,8 +83,8 @@ QQmlRefPointer<QV4::ExecutableCompilationUnit> QQmlTypeCompiler::compile() { QQmlPropertyCacheCreator<QQmlTypeCompiler> propertyCacheBuilder(&m_propertyCaches, &pendingGroupPropertyBindings, engine, this, imports()); - QQmlCompileError error = propertyCacheBuilder.buildMetaObjects(); - if (error.isSet()) { + QQmlJS::DiagnosticMessage error = propertyCacheBuilder.buildMetaObjects(); + if (error.isValid()) { recordError(error); return nullptr; } @@ -173,12 +173,6 @@ QQmlRefPointer<QV4::ExecutableCompilationUnit> QQmlTypeCompiler::compile() return nullptr; } -void QQmlTypeCompiler::recordError(QQmlError error) -{ - error.setUrl(url()); - errors << error; -} - void QQmlTypeCompiler::recordError(const QV4::CompiledData::Location &location, const QString &description) { QQmlError error; @@ -189,9 +183,14 @@ void QQmlTypeCompiler::recordError(const QV4::CompiledData::Location &location, errors << error; } -void QQmlTypeCompiler::recordError(const QQmlCompileError &error) +void QQmlTypeCompiler::recordError(const QQmlJS::DiagnosticMessage &message) { - recordError(error.location, error.description); + QQmlError error; + error.setDescription(message.message); + error.setLine(message.line); + error.setColumn(message.column); + error.setUrl(url()); + errors << error; } QString QQmlTypeCompiler::stringAt(int idx) const @@ -1020,17 +1019,17 @@ bool QQmlComponentAndAliasResolver::resolveAliases(int componentIndex) for (int objectIndex: qAsConst(_objectsWithAliases)) { - QQmlCompileError error; + QQmlJS::DiagnosticMessage error; const auto result = resolveAliasesInObject(objectIndex, &error); - if (error.isSet()) { + if (error.isValid()) { recordError(error); return false; } if (result == AllAliasesResolved) { - QQmlCompileError error = aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex); - if (error.isSet()) { + QQmlJS::DiagnosticMessage error = aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex); + if (error.isValid()) { recordError(error); return false; } @@ -1058,7 +1057,9 @@ bool QQmlComponentAndAliasResolver::resolveAliases(int componentIndex) return true; } -QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex, QQmlCompileError *error) +QQmlComponentAndAliasResolver::AliasResolutionResult +QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex, + QQmlJS::DiagnosticMessage *error) { const QmlIR::Object * const obj = qmlObjects->at(objectIndex); if (!obj->aliasCount()) @@ -1076,7 +1077,9 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv const int idIndex = alias->idIndex; const int targetObjectIndex = _idToObjectIndex.value(idIndex, -1); if (targetObjectIndex == -1) { - *error = QQmlCompileError(alias->referenceLocation, tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex))); + *error = qQmlCompileError( + alias->referenceLocation, + tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex))); break; } @@ -1104,7 +1107,9 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv } else { QQmlPropertyCache *targetCache = propertyCaches.at(targetObjectIndex); if (!targetCache) { - *error = QQmlCompileError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(property.toString())); + *error = qQmlCompileError( + alias->referenceLocation, + tr("Invalid alias target location: %1").arg(property.toString())); break; } @@ -1139,7 +1144,9 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv } if (!targetProperty || targetProperty->coreIndex() > 0x0000FFFF) { - *error = QQmlCompileError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(property.toString())); + *error = qQmlCompileError( + alias->referenceLocation, + tr("Invalid alias target location: %1").arg(property.toString())); break; } @@ -1148,14 +1155,18 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv if (!subProperty.isEmpty()) { const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(targetProperty->propType()); if (!valueTypeMetaObject) { - *error = QQmlCompileError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(subProperty.toString())); + *error = qQmlCompileError( + alias->referenceLocation, + tr("Invalid alias target location: %1").arg(subProperty.toString())); break; } int valueTypeIndex = valueTypeMetaObject->indexOfProperty(subProperty.toString().toUtf8().constData()); if (valueTypeIndex == -1) { - *error = QQmlCompileError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(subProperty.toString())); + *error = qQmlCompileError( + alias->referenceLocation, + tr("Invalid alias target location: %1").arg(subProperty.toString())); break; } Q_ASSERT(valueTypeIndex <= 0x0000FFFF); @@ -1345,10 +1356,10 @@ bool QQmlJSCodeGenerator::compileJavaScriptCodeInObjectsRecursively(int objectIn for (QmlIR::CompiledFunctionOrExpression *foe = object->functionsAndExpressions->first; foe; foe = foe->next) functionsToCompile << *foe; const QVector<int> runtimeFunctionIndices = v4CodeGen->generateJSCodeForFunctionsAndBindings(functionsToCompile); - const QList<QQmlError> jsErrors = v4CodeGen->qmlErrors(); + const auto jsErrors = v4CodeGen->errors(); if (!jsErrors.isEmpty()) { - for (const QQmlError &e : jsErrors) - compiler->recordError(e); + for (const auto &jsError : jsErrors) + compiler->recordError(jsError); return false; } diff --git a/src/qml/qml/qqmltypecompiler_p.h b/src/qml/qml/qqmltypecompiler_p.h index f588909c42..615694d4bc 100644 --- a/src/qml/qml/qqmltypecompiler_p.h +++ b/src/qml/qml/qqmltypecompiler_p.h @@ -97,9 +97,8 @@ public: QQmlRefPointer<QV4::ExecutableCompilationUnit> compile(); QList<QQmlError> compilationErrors() const { return errors; } - void recordError(QQmlError error); void recordError(const QV4::CompiledData::Location &location, const QString &description); - void recordError(const QQmlCompileError &error); + void recordError(const QQmlJS::DiagnosticMessage &error); int registerString(const QString &str); int registerConstant(QV4::ReturnedValue v); @@ -153,7 +152,7 @@ struct QQmlCompilePass protected: void recordError(const QV4::CompiledData::Location &location, const QString &description) const { compiler->recordError(location, description); } - void recordError(const QQmlCompileError &error) + void recordError(const QQmlJS::DiagnosticMessage &error) { compiler->recordError(error); } QV4::ResolvedTypeReference *resolvedType(int id) const @@ -276,7 +275,7 @@ protected: AllAliasesResolved }; - AliasResolutionResult resolveAliasesInObject(int objectIndex, QQmlCompileError *error); + AliasResolutionResult resolveAliasesInObject(int objectIndex, QQmlJS::DiagnosticMessage *error); QQmlEnginePrivate *enginePrivate; QQmlJS::MemoryPool *pool; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 18f1269d52..15a9c30c28 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -458,25 +458,25 @@ void QQmlDataBlob::setError(const QList<QQmlError> &errors) tryDone(); } -void QQmlDataBlob::setError(const QQmlCompileError &error) +void QQmlDataBlob::setError(const QQmlJS::DiagnosticMessage &error) { QQmlError e; - e.setColumn(error.location.column); - e.setLine(error.location.line); - e.setDescription(error.description); + e.setColumn(error.column); + e.setLine(error.line); + e.setDescription(error.message); e.setUrl(url()); setError(e); } -void QQmlDataBlob::setError(const QVector<QQmlCompileError> &errors) +void QQmlDataBlob::setError(const QVector<QQmlJS::DiagnosticMessage> &errors) { QList<QQmlError> finalErrors; finalErrors.reserve(errors.count()); - for (const QQmlCompileError &error: errors) { + for (const auto &error : errors) { QQmlError e; - e.setColumn(error.location.column); - e.setLine(error.location.line); - e.setDescription(error.description); + e.setColumn(error.column); + e.setLine(error.line); + e.setDescription(error.message); e.setUrl(url()); finalErrors << e; } @@ -1576,7 +1576,17 @@ bool QQmlTypeLoaderQmldirContent::hasError() const QList<QQmlError> QQmlTypeLoaderQmldirContent::errors(const QString &uri) const { - return m_parser.errors(uri); + QList<QQmlError> errors; + const QUrl url(uri); + for (const auto parseError : m_parser.errors(uri)) { + QQmlError error; + error.setUrl(url); + error.setLine(parseError.line); + error.setColumn(parseError.column); + error.setDescription(parseError.message); + errors.append(error); + } + return errors; } QString QQmlTypeLoaderQmldirContent::typeNamespace() const @@ -1593,7 +1603,11 @@ void QQmlTypeLoaderQmldirContent::setContent(const QString &location, const QStr void QQmlTypeLoaderQmldirContent::setError(const QQmlError &error) { - m_parser.setError(error); + QQmlJS::DiagnosticMessage parseError; + parseError.line = error.line(); + parseError.column = error.column(); + parseError.message = error.description(); + m_parser.setError(parseError); } QQmlDirComponents QQmlTypeLoaderQmldirContent::components() const @@ -2240,8 +2254,8 @@ void QQmlTypeData::createTypeAndPropertyCaches( QQmlPropertyCacheCreator<QV4::ExecutableCompilationUnit> propertyCacheCreator( &m_compiledData->propertyCaches, &pendingGroupPropertyBindings, engine, m_compiledData.data(), &m_importCache); - QQmlCompileError error = propertyCacheCreator.buildMetaObjects(); - if (error.isSet()) { + QQmlJS::DiagnosticMessage error = propertyCacheCreator.buildMetaObjects(); + if (error.isValid()) { setError(error); return; } @@ -2342,8 +2356,8 @@ void QQmlTypeData::done() QQmlRefPointer<QQmlTypeNameCache> typeNameCache; QV4::ResolvedTypeReferenceMap resolvedTypeCache; { - QQmlCompileError error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache); - if (error.isSet()) { + QQmlJS::DiagnosticMessage error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache); + if (error.isValid()) { setError(error); return; } @@ -2383,7 +2397,7 @@ void QQmlTypeData::done() { // Sanity check property bindings QQmlPropertyValidator validator(enginePrivate, m_importCache, m_compiledData); - QVector<QQmlCompileError> errors = validator.validate(); + QVector<QQmlJS::DiagnosticMessage> errors = validator.validate(); if (!errors.isEmpty()) { setError(errors); return; @@ -2527,8 +2541,8 @@ bool QQmlTypeData::loadFromSource() for (const QQmlJS::DiagnosticMessage &msg : qAsConst(compiler.errors)) { QQmlError e; e.setUrl(url()); - e.setLine(msg.loc.startLine); - e.setColumn(msg.loc.startColumn); + e.setLine(msg.line); + e.setColumn(msg.column); e.setDescription(msg.message); errors << e; } @@ -2767,7 +2781,7 @@ void QQmlTypeData::resolveTypes() loadImplicitImport(); } -QQmlCompileError QQmlTypeData::buildTypeResolutionCaches( +QQmlJS::DiagnosticMessage QQmlTypeData::buildTypeResolutionCaches( QQmlRefPointer<QQmlTypeNameCache> *typeNameCache, QV4::ResolvedTypeReferenceMap *resolvedTypeCache ) const @@ -2790,7 +2804,7 @@ QQmlCompileError QQmlTypeData::buildTypeResolutionCaches( QQmlType qmlType = resolvedType->type; if (resolvedType->typeData) { if (resolvedType->needsCreation && qmlType.isCompositeSingleton()) { - return QQmlCompileError(resolvedType->location, tr("Composite Singleton Type %1 is not creatable.").arg(qmlType.qmlTypeName())); + return qQmlCompileError(resolvedType->location, tr("Composite Singleton Type %1 is not creatable.").arg(qmlType.qmlTypeName())); } ref->compilationUnit = resolvedType->typeData->compilationUnit(); } else if (qmlType.isValid()) { @@ -2801,7 +2815,7 @@ QQmlCompileError QQmlTypeData::buildTypeResolutionCaches( QString reason = ref->type.noCreationReason(); if (reason.isEmpty()) reason = tr("Element is not creatable."); - return QQmlCompileError(resolvedType->location, reason); + return qQmlCompileError(resolvedType->location, reason); } if (ref->type.containsRevisionedAttributes()) { @@ -2814,7 +2828,7 @@ QQmlCompileError QQmlTypeData::buildTypeResolutionCaches( ref->doDynamicTypeCheck(); resolvedTypeCache->insert(resolvedType.key(), ref.take()); } - QQmlCompileError noError; + QQmlJS::DiagnosticMessage noError; return noError; } diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index d87812d48e..3330d52e56 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -86,7 +86,6 @@ class QQmlTypeData; class QQmlTypeLoader; class QQmlExtensionInterface; class QQmlProfiler; -struct QQmlCompileError; namespace QmlIR { struct Document; @@ -154,8 +153,8 @@ protected: // Can be called from within callbacks void setError(const QQmlError &); void setError(const QList<QQmlError> &errors); - void setError(const QQmlCompileError &error); - void setError(const QVector<QQmlCompileError> &errors); + void setError(const QQmlJS::DiagnosticMessage &error); + void setError(const QVector<QQmlJS::DiagnosticMessage> &errors); void setError(const QString &description); void addDependency(QQmlDataBlob *); @@ -481,7 +480,7 @@ private: void restoreIR(QV4::CompiledData::CompilationUnit &&unit); void continueLoadFromIR(); void resolveTypes(); - QQmlCompileError buildTypeResolutionCaches( + QQmlJS::DiagnosticMessage buildTypeResolutionCaches( QQmlRefPointer<QQmlTypeNameCache> *typeNameCache, QV4::ResolvedTypeReferenceMap *resolvedTypeCache ) const; diff --git a/src/qml/qmldirparser/qmldirparser.pri b/src/qml/qmldirparser/qmldirparser.pri index 660e7b395a..fefe2e75be 100644 --- a/src/qml/qmldirparser/qmldirparser.pri +++ b/src/qml/qmldirparser/qmldirparser.pri @@ -2,10 +2,7 @@ INCLUDEPATH += $$PWD INCLUDEPATH += $$OUT_PWD HEADERS += \ - $$PWD/qqmldirparser_p.h \ - $$PWD/qqmlerror.h \ - $$PWD/qqmlsourcecoordinate_p.h + $$PWD/qqmldirparser_p.h SOURCES += \ - $$PWD/qqmldirparser.cpp \ - $$PWD/qqmlerror.cpp + $$PWD/qqmldirparser.cpp diff --git a/src/qml/qmldirparser/qqmldirparser.cpp b/src/qml/qmldirparser/qqmldirparser.cpp index e944b52e47..d7662b11f5 100644 --- a/src/qml/qmldirparser/qqmldirparser.cpp +++ b/src/qml/qmldirparser/qqmldirparser.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "qqmldirparser_p.h" -#include "qqmlerror.h" #include <QtCore/QtDebug> @@ -297,8 +296,8 @@ bool QQmlDirParser::parse(const QString &source) void QQmlDirParser::reportError(quint16 line, quint16 column, const QString &description) { QQmlJS::DiagnosticMessage error; - error.loc.startLine = line; - error.loc.startColumn = column; + error.line = line; + error.column = column; error.message = description; _errors.append(error); } @@ -311,27 +310,20 @@ bool QQmlDirParser::hasError() const return false; } -void QQmlDirParser::setError(const QQmlError &e) +void QQmlDirParser::setError(const QQmlJS::DiagnosticMessage &e) { _errors.clear(); - reportError(e.line(), e.column(), e.description()); + reportError(e.line, e.column, e.message); } -QList<QQmlError> QQmlDirParser::errors(const QString &uri) const +QList<QQmlJS::DiagnosticMessage> QQmlDirParser::errors(const QString &uri) const { - QUrl url(uri); - QList<QQmlError> errors; + QList<QQmlJS::DiagnosticMessage> errors; const int numErrors = _errors.size(); errors.reserve(numErrors); for (int i = 0; i < numErrors; ++i) { - const QQmlJS::DiagnosticMessage &msg = _errors.at(i); - QQmlError e; - QString description = msg.message; - description.replace(QLatin1String("$$URI$$"), uri); - e.setDescription(description); - e.setUrl(url); - e.setLine(msg.loc.startLine); - e.setColumn(msg.loc.startColumn); + QQmlJS::DiagnosticMessage e = _errors.at(i); + e.message.replace(QLatin1String("$$URI$$"), uri); errors << e; } return errors; diff --git a/src/qml/qmldirparser/qqmldirparser_p.h b/src/qml/qmldirparser/qqmldirparser_p.h index f7a91c8b81..0957c8373a 100644 --- a/src/qml/qmldirparser/qqmldirparser_p.h +++ b/src/qml/qmldirparser/qqmldirparser_p.h @@ -56,10 +56,10 @@ #include <QtCore/QDebug> #include <private/qqmljsengine_p.h> #include <private/qv4global_p.h> +#include <private/qqmljsdiagnosticmessage_p.h> QT_BEGIN_NAMESPACE -class QQmlError; class QQmlEngine; class Q_QML_PRIVATE_EXPORT QQmlDirParser { @@ -70,8 +70,8 @@ public: bool parse(const QString &source); bool hasError() const; - void setError(const QQmlError &); - QList<QQmlError> errors(const QString &uri) const; + void setError(const QQmlJS::DiagnosticMessage &); + QList<QQmlJS::DiagnosticMessage> errors(const QString &uri) const; QString typeNamespace() const; void setTypeNamespace(const QString &s); diff --git a/src/qmldevtools/qmldevtools.pro b/src/qmldevtools/qmldevtools.pro index 4227312f3f..bea3c864cd 100644 --- a/src/qmldevtools/qmldevtools.pro +++ b/src/qmldevtools/qmldevtools.pro @@ -12,6 +12,7 @@ intel_icc: WERROR += -ww2415 clang:if(greaterThan(QT_CLANG_MAJOR_VERSION, 3)|greaterThan(QT_CLANG_MINOR_VERSION, 3)): \ WERROR += -Wno-error=unused-const-variable +include(../qml/common/common.pri) include(../qml/parser/parser.pri) include(../qml/compiler/compiler.pri) include(../qml/qmldirparser/qmldirparser.pri) diff --git a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp index 3643ca65c6..1e690e38dd 100644 --- a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp +++ b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp @@ -32,6 +32,7 @@ #include <QObject> #include <QQmlEngine> #include <QQmlComponent> +#include <private/qqmljsdiagnosticmessage_p.h> #include <private/qqmldirparser_p.h> #include <QDebug> @@ -56,12 +57,21 @@ tst_qqmldirparser::tst_qqmldirparser() namespace { - QStringList toStringList(const QList<QQmlError> &errors) + QStringList toStringList(const QList<QQmlJS::DiagnosticMessage> &errors) { QStringList rv; - foreach (const QQmlError &e, errors) - rv.append(e.toString()); + for (const QQmlJS::DiagnosticMessage &e : errors) { + QString errorString = QLatin1String("qmldir"); + if (e.line > 0) { + errorString += QLatin1Char(':') + QString::number(e.line); + if (e.column > 0) + errorString += QLatin1Char(':') + QString::number(e.column); + } + + errorString += QLatin1String(": ") + e.message; + rv.append(errorString); + } return rv; } diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp index 7b4135e1f8..ff6ba17612 100644 --- a/tools/qmlcachegen/qmlcachegen.cpp +++ b/tools/qmlcachegen/qmlcachegen.cpp @@ -82,9 +82,9 @@ Error Error::augment(const QString &contextErrorMessage) const QString diagnosticErrorMessage(const QString &fileName, const QQmlJS::DiagnosticMessage &m) { QString message; - message = fileName + QLatin1Char(':') + QString::number(m.loc.startLine) + QLatin1Char(':'); - if (m.loc.startColumn > 0) - message += QString::number(m.loc.startColumn) + QLatin1Char(':'); + message = fileName + QLatin1Char(':') + QString::number(m.line) + QLatin1Char(':'); + if (m.column > 0) + message += QString::number(m.column) + QLatin1Char(':'); if (m.isError()) message += QLatin1String(" error: "); diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp index 57aeeee0a9..ee69a0ed42 100644 --- a/tools/qmlimportscanner/main.cpp +++ b/tools/qmlimportscanner/main.cpp @@ -32,6 +32,7 @@ #include <private/qv4codegen_p.h> #include <private/qv4staticvalue_p.h> #include <private/qqmlirbuilder_p.h> +#include <private/qqmljsdiagnosticmessage_p.h> #include <QtCore/QCoreApplication> #include <QtCore/QDir> @@ -272,7 +273,7 @@ QVariantList findQmlImportsInQmlCode(const QString &filePath, const QString &cod const auto diagnosticMessages = parser.diagnosticMessages(); for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) { std::cerr << QDir::toNativeSeparators(filePath).toStdString() << ':' - << m.loc.startLine << ':' << m.message.toStdString() << std::endl; + << m.line << ':' << m.message.toStdString() << std::endl; } return QVariantList(); } diff --git a/tools/qmllint/main.cpp b/tools/qmllint/main.cpp index 0fdc3e0130..bf0ceb54b7 100644 --- a/tools/qmllint/main.cpp +++ b/tools/qmllint/main.cpp @@ -63,7 +63,7 @@ static bool lint_file(const QString &filename, bool silent) if (!success && !silent) { const auto diagnosticMessages = parser.diagnosticMessages(); for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) { - qWarning("%s:%d : %s", qPrintable(filename), m.loc.startLine, qPrintable(m.message)); + qWarning("%s:%d : %s", qPrintable(filename), m.line, qPrintable(m.message)); } } |