QmlFormat | ScriptExpression | extract parse function from ::setCode

This is a preparotory change before introducing support of the module
js.
Once .mjs files are supported ScriptExpression should support parsing of
the module js (parseModule), which will be incorporated within this
 parse() function
To avoid passing boolean as argument ParseMode Enum helper has been
introduced.

Task-number: QTBUG-117849
Change-Id: Ie12a8bb1d8420c3500a9d4061452ba669dbc194a
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
This commit is contained in:
Dmitrii Akshintsev 2024-02-06 16:30:31 +01:00
parent c792846af9
commit 4eba50d8a8
2 changed files with 55 additions and 19 deletions

View File

@ -1654,11 +1654,10 @@ AST::Node *firstNodeInRange(AST::Node *n, quint32 minStart = 0, quint32 maxEnd =
void ScriptExpression::setCode(const QString &code, const QString &preCode, const QString &postCode)
{
//TODO refactor and move parsing outside?
// TODO QTBUG-121933
m_codeStr = code;
const bool qmlMode = (m_expressionType == ExpressionType::BindingExpression);
QString resolvedPreCode, resolvedPostCode;
if (qmlMode && preCode.isEmpty()) {
if (m_expressionType == ExpressionType::BindingExpression && preCode.isEmpty()) {
resolvedPreCode = Binding::preCodeForName(u"binding");
resolvedPostCode = Binding::postCodeForName(u"binding");
} else {
@ -1682,21 +1681,8 @@ void ScriptExpression::setCode(const QString &code, const QString &preCode, cons
m_localOffset.startLine = preChange.nNewlines;
m_engine = std::make_shared<QQmlJS::Engine>();
m_astComments = std::make_shared<AstComments>(m_engine);
QQmlJS::Lexer lexer(m_engine.get());
lexer.setCode(m_codeStr, /*lineno = */ 1, /*qmlMode=*/true);
QQmlJS::Parser parser(m_engine.get());
if ((qmlMode && !parser.parse()) || (!qmlMode && !parser.parseScript()))
addErrorLocal(domParsingErrors().error(tr("Parsing of code failed")));
const auto messages = parser.diagnosticMessages();
for (const DiagnosticMessage &msg : messages) {
ErrorMessage err = domParsingErrors().errorMessage(msg);
err.location.offset -= m_localOffset.offset;
err.location.startLine -= m_localOffset.startLine;
if (err.location.startLine == 1)
err.location.startColumn -= m_localOffset.startColumn;
addErrorLocal(std::move(err));
}
m_ast = parser.rootNode();
m_ast = parse(resolveParseMode());
if (AST::Program *programPtr = AST::cast<AST::Program *>(m_ast)) {
m_ast = programPtr->statements;
}
@ -1717,10 +1703,41 @@ void ScriptExpression::setCode(const QString &code, const QString &preCode, cons
m_ast = exp->expression;
CommentCollector collector;
collector.collectComments(m_engine, parser.rootNode(), m_astComments);
collector.collectComments(m_engine, m_ast, m_astComments);
}
}
AST::Node *ScriptExpression::parse(const ParseMode mode)
{
QQmlJS::Lexer lexer(m_engine.get());
lexer.setCode(m_codeStr, /*lineno = */ 1, /*qmlMode=*/mode == ParseMode::QML);
QQmlJS::Parser parser(m_engine.get());
const bool parserSucceeded = [mode, &parser]() {
switch (mode) {
case ParseMode::QML:
return parser.parse();
case ParseMode::JS:
return parser.parseScript();
default:
Q_UNREACHABLE_RETURN(false);
}
}();
if (!parserSucceeded) {
addErrorLocal(domParsingErrors().error(tr("Parsing of code failed")));
}
const auto messages = parser.diagnosticMessages();
for (const DiagnosticMessage &msg : messages) {
ErrorMessage err = domParsingErrors().errorMessage(msg);
err.location.offset -= m_localOffset.offset;
err.location.startLine -= m_localOffset.startLine;
if (err.location.startLine == 1)
err.location.startColumn -= m_localOffset.startColumn;
addErrorLocal(std::move(err));
}
return parser.rootNode();
}
void ScriptExpression::astDumper(const Sink &s, AstDumperOptions options) const
{
astNodeDumper(s, ast(), options, 1, 0, [this](SourceLocation astL) {

View File

@ -384,6 +384,7 @@ public:
};
// TODO: rename? it may contain statements and stuff, not only expressions
// TODO QTBUG-121933
class QMLDOM_EXPORT ScriptExpression final : public OwningItem
{
Q_GADGET
@ -506,7 +507,25 @@ protected:
}
private:
enum class ParseMode {
QML,
JS,
};
inline ParseMode resolveParseMode()
{
switch (m_expressionType) {
case ExpressionType::BindingExpression:
// unfortunately there are no documentation explaining this resolution
// this was just moved from the original implementation
return ParseMode::QML;
default:
return ParseMode::JS;
}
}
void setCode(const QString &code, const QString &preCode, const QString &postCode);
[[nodiscard]] AST::Node *parse(ParseMode mode);
ExpressionType m_expressionType;
QString m_codeStr;
QStringView m_code;