diff --git a/doc/qtcreator/src/editors/creator-code-syntax.qdoc b/doc/qtcreator/src/editors/creator-code-syntax.qdoc index 3f542df9d1f..4d05f3f288e 100644 --- a/doc/qtcreator/src/editors/creator-code-syntax.qdoc +++ b/doc/qtcreator/src/editors/creator-code-syntax.qdoc @@ -669,10 +669,18 @@ \l{http://linterrors.com/js/the-array-literal-notation-is-preferrable} {The array literal notation [] is preferable}. + \row + \li M324 + \li Error + \li Hit maximum recursion limit visiting AST, the code model will be unreliable + and most likely invalid + \li + \row \li M400 \li Warning \li Duplicate import + \li \endtable diff --git a/src/libs/qmljs/CMakeLists.txt b/src/libs/qmljs/CMakeLists.txt index 5ccb629cb23..3357b0da66e 100644 --- a/src/libs/qmljs/CMakeLists.txt +++ b/src/libs/qmljs/CMakeLists.txt @@ -4,7 +4,6 @@ add_qtc_library(QmlJS SOURCES jsoncheck.cpp jsoncheck.h parser/qmldirparser.cpp parser/qmldirparser_p.h - parser/qmlerror.cpp parser/qmlerror.h parser/qmljsast.cpp parser/qmljsast_p.h parser/qmljsastfwd_p.h parser/qmljsastvisitor.cpp parser/qmljsastvisitor_p.h @@ -15,6 +14,7 @@ add_qtc_library(QmlJS parser/qmljslexer.cpp parser/qmljslexer_p.h parser/qmljsmemorypool_p.h parser/qmljsparser.cpp parser/qmljsparser_p.h + parser/qmljssourcelocation.cpp parser/qmljssourcelocation_p.h persistenttrie.cpp persistenttrie.h qmljs_global.h qmljsbind.cpp qmljsbind.h diff --git a/src/libs/qmljs/jsoncheck.cpp b/src/libs/qmljs/jsoncheck.cpp index 15d0edb1a78..d2beb507cc9 100644 --- a/src/libs/qmljs/jsoncheck.cpp +++ b/src/libs/qmljs/jsoncheck.cpp @@ -310,6 +310,14 @@ bool JsonCheck::visit(StringLiteral *ast) return false; } +void JsonCheck::throwRecursionDepthError() +{ + analysis()->m_messages.append(Message(ErrHitMaximumRecursion, + SourceLocation(), + QString(), QString(), false)); + +} + static QString formatExpectedTypes(QStringList all) { all.removeDuplicates(); diff --git a/src/libs/qmljs/jsoncheck.h b/src/libs/qmljs/jsoncheck.h index e8efc8db190..9885ad2353d 100644 --- a/src/libs/qmljs/jsoncheck.h +++ b/src/libs/qmljs/jsoncheck.h @@ -59,6 +59,8 @@ private: bool visit(AST::NumericLiteral *ast) override; bool visit(AST::StringLiteral *ast) override; + void throwRecursionDepthError() override; + struct AnalysisData { AnalysisData() : m_ranking(0), m_hasMatch(false) {} @@ -71,12 +73,12 @@ private: }; void processSchema(AST::Node *ast); - bool proceedCheck(Utils::JsonValue::Kind kind, const AST::SourceLocation &location); + bool proceedCheck(Utils::JsonValue::Kind kind, const SourceLocation &location); AnalysisData *analysis(); Document::Ptr m_doc; - AST::SourceLocation m_firstLoc; + SourceLocation m_firstLoc; Utils::JsonSchema *m_schema; QStack m_analysis; }; diff --git a/src/libs/qmljs/parser/cmd.sed b/src/libs/qmljs/parser/cmd.sed index a9b8ac0a6e5..0e6fc698281 100644 --- a/src/libs/qmljs/parser/cmd.sed +++ b/src/libs/qmljs/parser/cmd.sed @@ -1,16 +1,25 @@ -s/private\/qdeclarative/qml/g +s/include */include "qmljs\/parser\/\1"/g +s/qtqmlcompilerglobal_p.h/qmljsglobal_p.h/g +s//"qmljsglobal_p.h"/g +s/Q_QMLCOMPILER_PRIVATE_EXPORT/QML_PARSER_EXPORT/g s/qqml/qml/g s/QDECLARATIVE/QML/g s/QQml/Qml/g s/QQMLJS/QMLJS/g s/Q_QML_EXPORT //g -s/Q_QML_PRIVATE_EXPORT/QML_PARSER_EXPORT/ +s/Q_QML_PRIVATE_EXPORT/QML_PARSER_EXPORT/g +s/QT_BEGIN_NAMESPACE/QT_QML_BEGIN_NAMESPACE/g +s/QT_END_NAMESPACE/QT_QML_END_NAMESPACE/g # adjust pri file s/ \$\$PWD\/qmljsglobal_p.h/ $$PWD\/qmljsglobal_p.h \\\ + $$PWD\/qmljssourcelocation_p.h \\\ + $$PWD\/qmljsmemorypool_p.h \\\ $$PWD\/qmldirparser_p.h \\\ - $$PWD\/qmlerror.h/ -s/ \$\$PWD\/qmljsparser.cpp/ $$PWD\/qmljsparser.cpp \\\ + $$PWD\/qmljsgrammar_p.h \\\ + $$PWD\/qmljsparser_p.h/ + +s/ \$\$PWD\/qmljslexer.cpp/ $$PWD\/qmljslexer.cpp \\\ $$PWD\/qmldirparser.cpp \\\ - $$PWD\/qmlerror.cpp/ -s/OTHER_FILES/DISTFILES/ + $$PWD\/qmljsgrammar.cpp \\\ + $$PWD\/qmljsparser.cpp/ diff --git a/src/libs/qmljs/parser/gen-parser.sh b/src/libs/qmljs/parser/gen-parser.sh index acd30d0906a..c78c307adcf 100755 --- a/src/libs/qmljs/parser/gen-parser.sh +++ b/src/libs/qmljs/parser/gen-parser.sh @@ -10,11 +10,12 @@ # cd src/libs/qmljs/parser # QTDIR=~/path/to/qtdeclarative-checkout ./gen-parser.sh -if [ -z "$QTDIR" ]; then - echo "Usage: QTDIR=~/path/to/qtdeclarative-checkout $0" 1>&2 +if [ -z "$QTDIR" -o -z "$QLALR" ]; then + echo "Usage: QTDIR=~/path/to/qtdeclarative-checkout QLALR=~/path/to/qlalr $0" 1>&2 exit 1 fi + me=$(dirname $0) for i in $QTDIR/src/qml/parser/*.{g,h,cpp,pri}; do @@ -23,22 +24,23 @@ for i in $QTDIR/src/qml/parser/*.{g,h,cpp,pri}; do fi done -for i in $QTDIR/src/qml/qml/qqml{error.{h,cpp},dirparser{_p.h,.cpp}}; do - sed -f $me/cmd.sed $i > $me/$(echo $(basename $i) | sed s/qqml/qml/) +for i in $QTDIR/src/qml/qmldirparser/*.{h,cpp}; do + if ! echo $i | grep -q qmljsglobal; then + sed -f $me/cmd.sed $i > $me/$(echo $(basename $i) | sed s/qqml/qml/) + fi done -# export QmlDirParser -perl -p -0777 -i -e 's/QT_BEGIN_NAMESPACE\n\nclass QmlError;\nclass QmlEngine;\nclass Q_AUTOTEST_EXPORT QmlDirParser/#include "qmljsglobal_p.h"\n\nQT_BEGIN_NAMESPACE\n\nclass QmlError;\nclass QmlEngine;\nclass QML_PARSER_EXPORT QmlDirParser/' qmldirparser_p.h -# export QmlJSGrammar -perl -p -0777 -i -e 's/#include \n\nQT_BEGIN_NAMESPACE\n\nclass QmlJSGrammar\n/#include "qmljsglobal_p.h"\n#include \n\nQT_BEGIN_NAMESPACE\n\nclass QML_PARSER_EXPORT QmlJSGrammar\n/' qmljsgrammar_p.h +for i in $QTDIR/src/qml/common/qqmljs{sourcelocation,memorypool}_p.h; do + sed -f $me/cmd.sed $i > $me/$(echo $(basename $i) | sed s/qqmljs/qmljs/) +done + +# remove qmlapiversion_p.h include +#include "qmlapiversion_p.h" +perl -p -0777 -i -e 's/#include \"qmlapiversion_p.h\"//' qmljsdiagnosticmessage_p.h # remove qmlglobal_p.h include perl -p -0777 -i -e 's/#include \"qmlglobal_p.h\"//' qmldirparser.cpp # remove qmlglobal_p.h include -perl -p -0777 -i -e 's/#include \"qmlglobal_p.h\"//' qmlerror.cpp -# remove qmlglobal_p.h include perl -p -0777 -i -e 's/#include \//' qmldirparser.cpp -# remove QtQml/qtqmlglobal.h include -perl -p -0777 -i -e 's/#include \//' qmlerror.h # replace private/qhashedstring_p.h include and QHashedStringRef perl -p -0777 -i -e 's/#include \//' qmldirparser_p.h perl -p -0777 -i -e 's/QHashedStringRef/QString/g' qmldirparser_p.h qmldirparser.cpp @@ -51,11 +53,15 @@ sed -i -e 's/chars.length()/chars.size()/' $me/qmljslexer.cpp sed -i -e 's/DiagnosticMessage::Error/Severity::Error/g' $me/qmljsparser.cpp sed -i -e 's/DiagnosticMessage::Warning/Severity::Warning/g' $me/qmljsparser.cpp sed -i -e 's/DiagnosticMessage::Warning/Severity::Warning/g' $me/qmljsparser_p.h -sed -i -e 's|#include ||g' $me/qmlerror.cpp sed -i -e 's|#include |#include |g' $me/qmljsengine_p.h sed -i -e 's|#include |#include |g' $me/qmljsengine_p.h sed -i -e 's/qt_qnan/qQNaN/' $me/qmljsengine_p.cpp sed -i -e 's|#include |#include |' $me/qmljsengine_p.cpp perl -p -0777 -i -e 's/QT_QML_BEGIN_NAMESPACE/#include \nQT_QML_BEGIN_NAMESPACE/' qmljsengine_p.h +patch -p1 < grammar.patch +$QLALR qmljs.g + ./changeLicense.py $me/../qmljs_global.h qml*.{cpp,h} + +patch -p1 < parser.patch diff --git a/src/libs/qmljs/parser/grammar.patch b/src/libs/qmljs/parser/grammar.patch new file mode 100644 index 00000000000..6189b89a905 --- /dev/null +++ b/src/libs/qmljs/parser/grammar.patch @@ -0,0 +1,21 @@ +diff -u parser-genOut/qmljs.g parser/qmljs.g +--- parser-genOut/qmljs.g 2020-03-02 13:53:50.000000000 +0100 ++++ parser/qmljs.g 2020-03-02 13:55:50.000000000 +0100 +@@ -379,7 +379,7 @@ + inline DiagnosticMessage diagnosticMessage() const + { + for (const DiagnosticMessage &d : diagnostic_messages) { +- if (d.type != QtWarningMsg) ++ if (d.kind != Severity::Warning) + return d; + } + +@@ -423,7 +423,7 @@ + DiagnosticMessage error; + error.loc = location; + error.message = message; +- error.type = kind; ++ error.kind = DiagnosticMessage::qtMsgTypeToKind(kind); + return error; + } + diff --git a/src/libs/qmljs/parser/parser.patch b/src/libs/qmljs/parser/parser.patch index c1bef1860c3..d8e530133e0 100644 --- a/src/libs/qmljs/parser/parser.patch +++ b/src/libs/qmljs/parser/parser.patch @@ -1,157 +1,83 @@ -diff --git a/src/libs/qmljs/parser/qmlerror.cpp b/src/libs/qmljs/parser/qmlerror.cpp -index d090a19..5ec311d 100644 ---- a/src/libs/qmljs/parser/qmlerror.cpp -+++ b/src/libs/qmljs/parser/qmlerror.cpp -@@ -65,6 +65,12 @@ QT_BEGIN_NAMESPACE +diff -u parser-genOut/qmljsgrammar.cpp parser/qmljsgrammar.cpp +--- parser-genOut/qmljsgrammar.cpp 2020-03-02 13:53:50.000000000 +0100 ++++ parser/qmljsgrammar.cpp 2020-03-02 14:16:26.000000000 +0100 +@@ -21,7 +21,8 @@ + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** +-***************************************************************************// This file was generated by qlalr - DO NOT EDIT! ++***************************************************************************/ ++// This file was generated by qlalr - DO NOT EDIT! + #include "qmljsgrammar_p.h" - \sa QQuickView::errors(), QmlComponent::errors() - */ -+ -+static quint16 qmlSourceCoordinate(int n) -+{ -+ return (n > 0 && n <= static_cast(USHRT_MAX)) ? static_cast(n) : 0; -+} -+ - class QmlErrorPrivate + const char *const QmlJSGrammar::spell [] = { +diff -u parser-genOut/qmljsgrammar_p.h parser/qmljsgrammar_p.h +--- parser/qmljsgrammar_p.h 2020-03-03 13:51:43.000000000 +0100 ++++ parser-fixed2/qmljsgrammar_p.h 2020-03-02 17:20:56.000000000 +0100 +@@ -21,11 +21,13 @@ + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** +-***************************************************************************// This file was generated by qlalr - DO NOT EDIT! ++***************************************************************************/ ++// This file was generated by qlalr - DO NOT EDIT! + #ifndef QMLJSGRAMMAR_P_H + #define QMLJSGRAMMAR_P_H ++#include "qmljsglobal_p.h" + +-class QmlJSGrammar ++class QML_PARSER_EXPORT QmlJSGrammar { public: -diff --git a/src/libs/qmljs/parser/qmljsengine_p.cpp b/src/libs/qmljs/parser/qmljsengine_p.cpp -index 1e22fa5..10fc3d1 100644 ---- a/src/libs/qmljs/parser/qmljsengine_p.cpp -+++ b/src/libs/qmljs/parser/qmljsengine_p.cpp -@@ -110,7 +110,7 @@ double integerFromString(const QString &str, int radix) - - - Engine::Engine() -- : _lexer(0) -+ : _lexer(0), _directives(0) - { } - - Engine::~Engine() -@@ -131,6 +131,12 @@ Lexer *Engine::lexer() const - void Engine::setLexer(Lexer *lexer) - { _lexer = lexer; } - -+void Engine::setDirectives(Directives *directives) -+{ _directives = directives; } -+ -+Directives *Engine::directives() const -+{ return _directives; } -+ - MemoryPool *Engine::pool() - { return &_pool; } - -diff --git a/src/libs/qmljs/parser/qmljsengine_p.h b/src/libs/qmljs/parser/qmljsengine_p.h -index b1f7e1a..29b69d1 100644 ---- a/src/libs/qmljs/parser/qmljsengine_p.h -+++ b/src/libs/qmljs/parser/qmljsengine_p.h -@@ -44,36 +44,35 @@ - #include "qmljsglobal_p.h" - #include "qmljsastfwd_p.h" - #include "qmljsmemorypool_p.h" -+#include - - #include - #include - --#include - QT_QML_BEGIN_NAMESPACE - + enum VariousConstants { +diff -u parser-genOut/qmljslexer_p.h parser/qmljslexer_p.h +--- parser-genOut/qmljslexer_p.h 2020-03-02 13:53:50.000000000 +0100 ++++ parser/qmljslexer_p.h 2020-03-02 13:55:13.000000000 +0100 +@@ -47,7 +47,7 @@ namespace QmlJS { - class Lexer; -+class Directives; - class MemoryPool; + class Engine; +-struct DiagnosticMessage; ++class DiagnosticMessage; + class Directives; - class QML_PARSER_EXPORT DiagnosticMessage - { - public: -- enum Kind { Warning, Error }; -- - DiagnosticMessage() -- : kind(Error) {} -+ : kind(Severity::Error) {} + class QML_PARSER_EXPORT Lexer: public QmlJSGrammar +diff -u parser-genOut/qmljsparser.cpp parser/qmljsparser.cpp +--- parser-genOut/qmljsparser.cpp 2020-03-02 13:53:50.000000000 +0100 ++++ parser/qmljsparser.cpp 2020-03-02 14:16:01.000000000 +0100 +@@ -22,5 +22,6 @@ + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ****************************************************************************/ ++#line 172 "qmljs.g" -- DiagnosticMessage(Kind kind, const AST::SourceLocation &loc, const QString &message) -+ DiagnosticMessage(Severity::Enum kind, const AST::SourceLocation &loc, const QString &message) - : kind(kind), loc(loc), message(message) {} + #include "qmljs/parser/qmljsengine_p.h" +diff -u parser-genOut/qmljsparser_p.h parser/qmljsparser_p.h +--- parser-genOut/qmljsparser_p.h 2020-03-02 13:53:50.000000000 +0100 ++++ parser/qmljsparser_p.h 2020-03-02 14:13:25.000000000 +0100 +@@ -22,6 +22,7 @@ + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ****************************************************************************/ ++#line 223 "qmljs.g" - bool isWarning() const -- { return kind == Warning; } -+ { return kind == Severity::Warning; } - bool isError() const -- { return kind == Error; } -+ { return kind == Severity::Error; } + // + +diff -u parser-genOut/parser.pri parser/parser.pri +--- parser-genOut/parser.pri 2020-03-02 15:40:09.000000000 +0100 ++++ parser/parser.pri 2020-03-02 15:41:11.000000000 +0100 +@@ -22,10 +22,10 @@ + $$PWD/qmljsparser.cpp \ -- Kind kind; -+ Severity::Enum kind; - AST::SourceLocation loc; - QString message; - }; -@@ -81,6 +80,7 @@ public: - class QML_PARSER_EXPORT Engine - { - Lexer *_lexer; -+ Directives *_directives; - MemoryPool _pool; - QList _comments; - QString _extraCode; -@@ -99,6 +99,9 @@ public: - Lexer *lexer() const; - void setLexer(Lexer *lexer); +-CONFIG += qlalr ++#CONFIG += qlalr + QLALRSOURCES = $$PWD/qmljs.g +-QMAKE_QLALRFLAGS = --no-debug --qt ++#QMAKE_QLALRFLAGS = --no-debug --qt -+ void setDirectives(Directives *directives); -+ Directives *directives() const; -+ - MemoryPool *pool(); + OTHER_FILES += $$QLALRSOURCES - inline QStringRef midRef(int position, int size) { return _code.midRef(position, size); } -diff --git a/src/libs/qmljs/parser/qmljslexer.cpp b/src/libs/qmljs/parser/qmljslexer.cpp -index 9698e9d..036be75 100644 ---- a/src/libs/qmljs/parser/qmljslexer.cpp -+++ b/src/libs/qmljs/parser/qmljslexer.cpp -@@ -345,7 +345,7 @@ static inline bool isIdentifierStart(QChar ch) - // fast path for ascii - if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || - (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || -- ch == '$' || ch == '_') -+ ch == QLatin1Char('$') || ch == QLatin1Char('_')) - return true; - - switch (ch.category()) { -@@ -368,7 +368,7 @@ static bool isIdentifierPart(QChar ch) - if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || - (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || - (ch.unicode() >= '0' && ch.unicode() <= '9') || -- ch == '$' || ch == '_' || -+ ch == QLatin1Char('$') || ch == QLatin1Char('_') || - ch.unicode() == 0x200c /* ZWNJ */ || ch.unicode() == 0x200d /* ZWJ */) - return true; - -diff --git a/src/libs/qmljs/parser/qmljsparser.cpp b/src/libs/qmljs/parser/qmljsparser.cpp -index 6e61637..e016b91 100644 ---- a/src/libs/qmljs/parser/qmljsparser.cpp -+++ b/src/libs/qmljs/parser/qmljsparser.cpp -@@ -157,7 +157,20 @@ bool Parser::parse(int startToken) - - token_buffer[0].token = startToken; - first_token = &token_buffer[0]; -- last_token = &token_buffer[1]; -+ if (startToken == T_FEED_JS_PROGRAM) { -+ Directives ignoreDirectives; -+ Directives *directives = driver->directives(); -+ if (!directives) -+ directives = &ignoreDirectives; -+ lexer->scanDirectives(directives); -+ token_buffer[1].token = lexer->tokenKind(); -+ token_buffer[1].dval = lexer->tokenValue(); -+ token_buffer[1].loc = location(lexer); -+ token_buffer[1].spell = lexer->tokenSpell(); -+ last_token = &token_buffer[2]; -+ } else { -+ last_token = &token_buffer[1]; -+ } - - tos = -1; - program = 0; + # make sure we install the headers generated by qlalr +-private_headers.CONFIG += no_check_exist ++#private_headers.CONFIG += no_check_exist diff --git a/src/libs/qmljs/parser/parser.pri b/src/libs/qmljs/parser/parser.pri index 7418ea56be2..0694a5188bd 100644 --- a/src/libs/qmljs/parser/parser.pri +++ b/src/libs/qmljs/parser/parser.pri @@ -3,30 +3,29 @@ HEADERS += \ $$PWD/qmljsastfwd_p.h \ $$PWD/qmljsastvisitor_p.h \ $$PWD/qmljsengine_p.h \ - $$PWD/qmljsgrammar_p.h \ $$PWD/qmljslexer_p.h \ - $$PWD/qmljsmemorypool_p.h \ - $$PWD/qmljsparser_p.h \ $$PWD/qmljsglobal_p.h \ + $$PWD/qmljssourcelocation_p.h \ + $$PWD/qmljsmemorypool_p.h \ $$PWD/qmldirparser_p.h \ - $$PWD/qmlerror.h \ + $$PWD/qmljsgrammar_p.h \ + $$PWD/qmljsparser_p.h \ $$PWD/qmljskeywords_p.h SOURCES += \ $$PWD/qmljsast.cpp \ $$PWD/qmljsastvisitor.cpp \ $$PWD/qmljsengine_p.cpp \ - $$PWD/qmljsgrammar.cpp \ $$PWD/qmljslexer.cpp \ - $$PWD/qmljsparser.cpp \ $$PWD/qmldirparser.cpp \ - $$PWD/qmlerror.cpp + $$PWD/qmljsgrammar.cpp \ + $$PWD/qmljsparser.cpp \ #CONFIG += qlalr QLALRSOURCES = $$PWD/qmljs.g #QMAKE_QLALRFLAGS = --no-debug --qt -DISTFILES += $$QLALRSOURCES +OTHER_FILES += $$QLALRSOURCES # make sure we install the headers generated by qlalr #private_headers.CONFIG += no_check_exist diff --git a/src/libs/qmljs/parser/qmldirparser.cpp b/src/libs/qmljs/parser/qmldirparser.cpp index d56affdbe12..003f4aa97bb 100644 --- a/src/libs/qmljs/parser/qmldirparser.cpp +++ b/src/libs/qmljs/parser/qmldirparser.cpp @@ -24,11 +24,10 @@ ****************************************************************************/ #include "qmldirparser_p.h" -#include "qmlerror.h" #include -QT_BEGIN_NAMESPACE +QT_QML_BEGIN_NAMESPACE static int parseInt(const QStringRef &str, bool *ok) { @@ -60,12 +59,18 @@ static bool parseVersion(const QString &str, int *major, int *minor) return false; } -QmlDirParser::QmlDirParser() : _designerSupported(false) -{ -} - -QmlDirParser::~QmlDirParser() +void QmlDirParser::clear() { + _errors.clear(); + _typeNamespace.clear(); + _components.clear(); + _dependencies.clear(); + _imports.clear(); + _scripts.clear(); + _plugins.clear(); + _designerSupported = false; + _typeInfos.clear(); + _className.clear(); } inline static void scanSpace(const QChar *&ch) { @@ -88,13 +93,6 @@ inline static void scanWord(const QChar *&ch) { */ bool QmlDirParser::parse(const QString &source) { - _errors.clear(); - _plugins.clear(); - _components.clear(); - _scripts.clear(); - _designerSupported = false; - _className.clear(); - quint16 lineNumber = 0; bool firstLine = true; @@ -193,7 +191,7 @@ bool QmlDirParser::parse(const QString &source) } Component entry(sections[1], sections[2], -1, -1); entry.internal = true; - _components.insertMulti(entry.typeName, entry); + _components.insert(entry.typeName, entry); } else if (sections[0] == QLatin1String("singleton")) { if (sectionCount < 3 || sectionCount > 4) { reportError(lineNumber, 0, @@ -204,7 +202,7 @@ bool QmlDirParser::parse(const QString &source) // singleton TestSingletonType TestSingletonType.qml Component entry(sections[1], sections[2], -1, -1); entry.singleton = true; - _components.insertMulti(entry.typeName, entry); + _components.insert(entry.typeName, entry); } else { // handle qmldir module listing case where singleton is defined in the following pattern: // singleton TestSingletonType 2.0 TestSingletonType20.qml @@ -213,7 +211,7 @@ bool QmlDirParser::parse(const QString &source) const QString &fileName = sections[3]; Component entry(sections[1], fileName, major, minor); entry.singleton = true; - _components.insertMulti(entry.typeName, entry); + _components.insert(entry.typeName, entry); } else { reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected .").arg(sections[2])); } @@ -249,10 +247,17 @@ bool QmlDirParser::parse(const QString &source) } else { reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected .").arg(sections[2])); } + } else if (sections[0] == QLatin1String("import")) { + if (sectionCount != 2) { + reportError(lineNumber, 0, + QStringLiteral("import requires 2 arguments, but %1 were provided").arg(sectionCount - 1)); + continue; + } + _imports << sections[1]; } else if (sectionCount == 2) { // No version specified (should only be used for relative qmldir files) const Component entry(sections[0], sections[1], -1, -1); - _components.insertMulti(entry.typeName, entry); + _components.insert(entry.typeName, entry); } else if (sectionCount == 3) { int major, minor; if (parseVersion(sections[1], &major, &minor)) { @@ -264,7 +269,7 @@ bool QmlDirParser::parse(const QString &source) _scripts.append(entry); } else { const Component entry(sections[0], fileName, major, minor); - _components.insertMulti(entry.typeName, entry); + _components.insert(entry.typeName, entry); } } else { reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected .").arg(sections[1])); @@ -297,27 +302,20 @@ bool QmlDirParser::hasError() const return false; } -void QmlDirParser::setError(const QmlError &e) +void QmlDirParser::setError(const QmlJS::DiagnosticMessage &e) { _errors.clear(); - reportError(e.line(), e.column(), e.description()); + reportError(e.loc.startLine, e.loc.startColumn, e.message); } -QList QmlDirParser::errors(const QString &uri) const +QList QmlDirParser::errors(const QString &uri) const { - QUrl url(uri); - QList errors; + QList errors; const int numErrors = _errors.size(); errors.reserve(numErrors); for (int i = 0; i < numErrors; ++i) { - const QmlJS::DiagnosticMessage &msg = _errors.at(i); - QmlError 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); + QmlJS::DiagnosticMessage e = _errors.at(i); + e.message.replace(QLatin1String("$$URI$$"), uri); errors << e; } return errors; @@ -338,7 +336,7 @@ QList QmlDirParser::plugins() const return _plugins; } -QHash QmlDirParser::components() const +QMultiHash QmlDirParser::components() const { return _components; } @@ -348,17 +346,20 @@ QHash QmlDirParser::dependencies() const return _dependencies; } +QStringList QmlDirParser::imports() const +{ + return _imports; +} + QList QmlDirParser::scripts() const { return _scripts; } -#ifdef QT_CREATOR QList QmlDirParser::typeInfos() const { return _typeInfos; } -#endif bool QmlDirParser::designerSupported() const { @@ -384,4 +385,4 @@ QDebug &operator<< (QDebug &debug, const QmlDirParser::Script &script) return debug << qPrintable(output); } -QT_END_NAMESPACE +QT_QML_END_NAMESPACE diff --git a/src/libs/qmljs/parser/qmldirparser_p.h b/src/libs/qmljs/parser/qmldirparser_p.h index a39bfff0d27..9b26d023510 100644 --- a/src/libs/qmljs/parser/qmldirparser_p.h +++ b/src/libs/qmljs/parser/qmldirparser_p.h @@ -39,34 +39,44 @@ #include #include #include -#include "qmljsengine_p.h" -#include "qmljsglobal_p.h" +#include "qmljs/parser/qmljsglobal_p.h" +#include "qmljs/parser/qmljsengine_p.h" +#include "qmljs/parser/qmljsdiagnosticmessage_p.h" -QT_BEGIN_NAMESPACE +QT_QML_BEGIN_NAMESPACE -class QmlError; class QmlEngine; class QML_PARSER_EXPORT QmlDirParser { public: - QmlDirParser(); - ~QmlDirParser(); - + void clear(); bool parse(const QString &source); bool hasError() const; - void setError(const QmlError &); - QList errors(const QString &uri) const; + void setError(const QmlJS::DiagnosticMessage &); + QList errors(const QString &uri) const; QString typeNamespace() const; void setTypeNamespace(const QString &s); + static void checkNonRelative(const char *item, const QString &typeName, const QString &fileName) + { + if (fileName.startsWith(QLatin1Char('/'))) { + qWarning() << item << typeName + << "is specified with non-relative URL" << fileName << "in a qmldir file." + << "URLs in qmldir files should be relative to the qmldir file's directory."; + } + } + struct Plugin { - Plugin() {} + Plugin() = default; Plugin(const QString &name, const QString &path) - : name(name), path(path) {} + : name(name), path(path) + { + checkNonRelative("Plugin", name, path); + } QString name; QString path; @@ -74,11 +84,14 @@ public: struct Component { - Component() {} + Component() = default; Component(const QString &typeName, const QString &fileName, int majorVersion, int minorVersion) : typeName(typeName), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion), - internal(false), singleton(false) {} + internal(false), singleton(false) + { + checkNonRelative("Component", typeName, fileName); + } QString typeName; QString fileName; @@ -90,10 +103,13 @@ public: struct Script { - Script() {} + Script() = default; Script(const QString &nameSpace, const QString &fileName, int majorVersion, int minorVersion) - : nameSpace(nameSpace), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion) {} + : nameSpace(nameSpace), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion) + { + checkNonRelative("Script", nameSpace, fileName); + } QString nameSpace; QString fileName; @@ -101,16 +117,16 @@ public: int minorVersion = 0; }; - QHash components() const; + QMultiHash components() const; QHash dependencies() const; + QStringList imports() const; QList