From 11d01e3b74c84e465246a8f164b3f3b8ff92d8a4 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 18 Mar 2019 10:31:10 +0100 Subject: Handle recursion depth errors when parsing JavaScript Implementations of QQmlJS::AST::Visitor are required to do so. Fixes: QTBUG-74510 Change-Id: I061240f15ce082a05dd7829d225a5bfc3edd896a Reviewed-by: Simon Hausmann --- src/qdoc/jscodemarker.cpp | 4 ++++ src/qdoc/qmlcodemarker.cpp | 4 ++++ src/qdoc/qmlcodeparser.cpp | 4 ++++ src/qdoc/qmlmarkupvisitor.cpp | 11 +++++++++++ src/qdoc/qmlmarkupvisitor.h | 3 +++ src/qdoc/qmlvisitor.cpp | 11 +++++++++++ src/qdoc/qmlvisitor.h | 4 ++++ 7 files changed, 41 insertions(+) diff --git a/src/qdoc/jscodemarker.cpp b/src/qdoc/jscodemarker.cpp index f283ab485..575ffbb58 100644 --- a/src/qdoc/jscodemarker.cpp +++ b/src/qdoc/jscodemarker.cpp @@ -130,6 +130,10 @@ QString JsCodeMarker::addMarkUp(const QString &code, // unhandled source text can be output. QmlMarkupVisitor visitor(code, pragmas, &engine); QQmlJS::AST::Node::accept(ast, &visitor); + if (visitor.hasError()) { + location.warning(location.fileName() + + tr("Unable to analyze JavaScript. The output is incomplete.")); + } output = visitor.markedUpCode(); } else { location.warning(location.fileName() + diff --git a/src/qdoc/qmlcodemarker.cpp b/src/qdoc/qmlcodemarker.cpp index 1ceba8016..a6f97f031 100644 --- a/src/qdoc/qmlcodemarker.cpp +++ b/src/qdoc/qmlcodemarker.cpp @@ -181,6 +181,10 @@ QString QmlCodeMarker::addMarkUp(const QString &code, // unhandled source text can be output. QmlMarkupVisitor visitor(code, pragmas, &engine); QQmlJS::AST::Node::accept(ast, &visitor); + if (visitor.hasError()) { + location.warning(location.fileName() + + tr("Unable to analyze QML snippet. The output is incomplete.")); + } output = visitor.markedUpCode(); } else { location.warning(tr("Unable to parse QML snippet: \"%1\" at line %2, column %3").arg( diff --git a/src/qdoc/qmlcodeparser.cpp b/src/qdoc/qmlcodeparser.cpp index 31775bb1b..882f83304 100644 --- a/src/qdoc/qmlcodeparser.cpp +++ b/src/qdoc/qmlcodeparser.cpp @@ -192,6 +192,10 @@ void QmlCodeParser::parseSourceFile(const Location& location, const QString& fil metacommandsAllowed, topicCommandsAllowed); QQmlJS::AST::Node::accept(ast, &visitor); + if (visitor.hasError()) { + qDebug().nospace() << qPrintable(filePath) << ": Could not analyze QML file. " + << "The output is incomplete."; + } } foreach (const QQmlJS::DiagnosticMessage &msg, parser->diagnosticMessages()) { qDebug().nospace() << qPrintable(filePath) << ':' << msg.loc.startLine diff --git a/src/qdoc/qmlmarkupvisitor.cpp b/src/qdoc/qmlmarkupvisitor.cpp index 7fd6e7c28..6d0f2470b 100644 --- a/src/qdoc/qmlmarkupvisitor.cpp +++ b/src/qdoc/qmlmarkupvisitor.cpp @@ -115,6 +115,11 @@ QString QmlMarkupVisitor::markedUpCode() return output; } +bool QmlMarkupVisitor::hasError() const +{ + return hasRecursionDepthError; +} + void QmlMarkupVisitor::addExtra(quint32 start, quint32 finish) { if (extraIndex >= extraLocations.length()) { @@ -804,6 +809,12 @@ bool QmlMarkupVisitor::visit(QQmlJS::AST::UiObjectDefinition *definition) QQmlJS::AST::Node::accept(definition->initializer, this); return false; } + +void QmlMarkupVisitor::throwRecursionDepthError() +{ + hasRecursionDepthError = true; +} + #endif QT_END_NAMESPACE diff --git a/src/qdoc/qmlmarkupvisitor.h b/src/qdoc/qmlmarkupvisitor.h index e01bf0e5d..d369454ff 100644 --- a/src/qdoc/qmlmarkupvisitor.h +++ b/src/qdoc/qmlmarkupvisitor.h @@ -55,6 +55,7 @@ public: virtual ~QmlMarkupVisitor(); QString markedUpCode(); + bool hasError() const; bool visit(QQmlJS::AST::UiImport *) override; void endVisit(QQmlJS::AST::UiImport *) override; @@ -152,6 +153,7 @@ private: void addVerbatim(QQmlJS::AST::SourceLocation first, QQmlJS::AST::SourceLocation last = QQmlJS::AST::SourceLocation()); QString sourceText(QQmlJS::AST::SourceLocation &location); + void throwRecursionDepthError(); QQmlJS::Engine *engine; QVector extraTypes; @@ -160,6 +162,7 @@ private: QString output; quint32 cursor; int extraIndex; + bool hasRecursionDepthError = false; }; Q_DECLARE_TYPEINFO(QmlMarkupVisitor::ExtraType, Q_PRIMITIVE_TYPE); #endif diff --git a/src/qdoc/qmlvisitor.cpp b/src/qdoc/qmlvisitor.cpp index d54378331..2834af2d6 100644 --- a/src/qdoc/qmlvisitor.cpp +++ b/src/qdoc/qmlvisitor.cpp @@ -843,6 +843,17 @@ void QmlDocVisitor::endVisit(QQmlJS::AST::UiQualifiedId* ) { // nothing. } + +void QmlDocVisitor::throwRecursionDepthError() +{ + hasRecursionDepthError = true; +} + +bool QmlDocVisitor::hasError() const +{ + return hasRecursionDepthError; +} + #endif QT_END_NAMESPACE diff --git a/src/qdoc/qmlvisitor.h b/src/qdoc/qmlvisitor.h index 321819457..6e73171dc 100644 --- a/src/qdoc/qmlvisitor.h +++ b/src/qdoc/qmlvisitor.h @@ -92,6 +92,9 @@ public: bool visit(QQmlJS::AST::UiQualifiedId *) override; void endVisit(QQmlJS::AST::UiQualifiedId *) override; + void throwRecursionDepthError(); + bool hasError() const; + private: QString getFullyQualifiedId(QQmlJS::AST::UiQualifiedId *id); QQmlJS::AST::SourceLocation precedingComment(quint32 offset) const; @@ -112,6 +115,7 @@ private: QSet topics_; QSet usedComments; Aggregate *current; + bool hasRecursionDepthError = false; }; #endif -- cgit v1.2.3