Dom : simplify ScriptExpression a bit

this commit removes dead code. Some of the things were there, but never
used. For example, wrapping script expression into object defitinion,
however there is no reason/usages for that. Most of the complexity in
ScriptExpression::setCode was coming from it.

Change-Id: I1e1653a3f052fb138e4ab31cf3c9b375e90842bb
Task-number: QTBUG-121933
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
This commit is contained in:
Dmitrii Akshintsev 2025-08-27 23:31:58 +02:00
parent 663ff3cb00
commit 288e03a84d
2 changed files with 37 additions and 106 deletions

View File

@ -1619,9 +1619,8 @@ void BindingValue::clearValue()
ScriptExpression::ScriptExpression(QStringView code, const std::shared_ptr<QQmlJS::Engine> &engine, ScriptExpression::ScriptExpression(QStringView code, const std::shared_ptr<QQmlJS::Engine> &engine,
AST::Node *ast, const std::shared_ptr<AstComments> &comments, AST::Node *ast, const std::shared_ptr<AstComments> &comments,
ExpressionType expressionType, SourceLocation localOffset, ExpressionType expressionType, SourceLocation localOffset)
int derivedFrom) : OwningItem(),
: OwningItem(derivedFrom),
m_expressionType(expressionType), m_expressionType(expressionType),
m_code(code), m_code(code),
m_engine(engine), m_engine(engine),
@ -1651,16 +1650,6 @@ ScriptExpression::ScriptExpression(const ScriptExpression &e) : OwningItem(e)
m_astComments = e.m_astComments; m_astComments = e.m_astComments;
} }
// TODO can be deleted atm used only in MutableItem setCode (which is unused atm)
std::shared_ptr<ScriptExpression> ScriptExpression::copyWithUpdatedCode(
const DomItem &self, const QString &code) const
{
std::shared_ptr<ScriptExpression> copy = makeCopy(self);
DomItem container = self.containingObject();
copy->setCode(code);
return copy;
}
bool ScriptExpression::iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const bool ScriptExpression::iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const
{ {
bool cont = OwningItem::iterateDirectSubpaths(self, visitor); bool cont = OwningItem::iterateDirectSubpaths(self, visitor);
@ -1713,70 +1702,47 @@ AST::Node *firstNodeInRange(AST::Node *n, qsizetype minStart = 0, qsizetype maxE
void ScriptExpression::setCode(const QString &code) void ScriptExpression::setCode(const QString &code)
{ {
// TODO QTBUG-121933 // TODO QTBUG-121933
if (code.isEmpty()) {
return;
}
m_codeStr = code; m_codeStr = code;
QString resolvedPreCode, resolvedPostCode; m_code = QStringView(m_codeStr);
if (m_expressionType == ExpressionType::BindingExpression) {
resolvedPreCode = Binding::preCodeForName(u"binding");
resolvedPostCode = Binding::postCodeForName(u"binding");
}
if (!resolvedPreCode.isEmpty() || !resolvedPostCode.isEmpty())
m_codeStr = resolvedPreCode + code + resolvedPostCode;
m_code = QStringView(m_codeStr).mid(resolvedPreCode.size(), code.size());
auto preCode = QStringView(m_codeStr).mid(0, resolvedPreCode.size());
m_engine = nullptr;
m_ast = nullptr;
m_localOffset = SourceLocation(); m_localOffset = SourceLocation();
if (!m_code.isEmpty()) { m_localOffset.length = m_code.size();
IndentInfo preChange(preCode, 4);
m_localOffset.offset = preCode.size();
m_localOffset.length = m_code.size();
m_localOffset.startColumn = preChange.trailingString.size();
m_localOffset.startLine = preChange.nNewlines;
m_engine = std::make_shared<QQmlJS::Engine>();
m_astComments = std::make_shared<AstComments>(m_engine);
m_ast = parse(resolveParseMode());
if (AST::Program *programPtr = AST::cast<AST::Program *>(m_ast)) { m_engine = std::make_shared<QQmlJS::Engine>();
m_ast = programPtr->statements; m_astComments = std::make_shared<AstComments>(m_engine);
} m_ast = parse();
if (!preCode.isEmpty())
m_ast = firstNodeInRange(m_ast, preCode.size(), preCode.size() + m_code.size());
if (auto *sList = AST::cast<AST::FormalParameterList *>(m_ast)) {
m_ast = sList->element;
}
if (m_expressionType != ExpressionType::FunctionBody) {
if (AST::StatementList *sList = AST::cast<AST::StatementList *>(m_ast)) {
if (!sList->next)
m_ast = sList->statement;
}
}
if (m_expressionType == ExpressionType::BindingExpression)
if (AST::ExpressionStatement *exp = AST::cast<AST::ExpressionStatement *>(m_ast))
m_ast = exp->expression;
CommentCollector collector; if (AST::Program *programPtr = AST::cast<AST::Program *>(m_ast)) {
collector.collectComments(m_engine, m_ast, m_astComments); m_ast = programPtr->statements;
} }
if (auto *sList = AST::cast<AST::FormalParameterList *>(m_ast)) {
m_ast = sList->element;
}
if (m_expressionType != ExpressionType::FunctionBody) {
if (AST::StatementList *sList = AST::cast<AST::StatementList *>(m_ast)) {
if (!sList->next)
m_ast = sList->statement;
}
}
if (m_expressionType == ExpressionType::BindingExpression)
if (AST::ExpressionStatement *exp = AST::cast<AST::ExpressionStatement *>(m_ast))
m_ast = exp->expression;
CommentCollector collector;
collector.collectComments(m_engine, m_ast, m_astComments);
} }
AST::Node *ScriptExpression::parse(const ParseMode mode) AST::Node *ScriptExpression::parse()
{ {
QQmlJS::Lexer lexer(m_engine.get()); QQmlJS::Lexer lexer(m_engine.get());
lexer.setCode(m_codeStr, /*lineno = */ 1, /*qmlMode=*/mode == ParseMode::QML); lexer.setCode(m_codeStr, /*lineno = */ 1, /*qmlMode=*/false /* it's EcmaScript */);
QQmlJS::Parser parser(m_engine.get()); QQmlJS::Parser parser(m_engine.get());
const bool parserSucceeded = [mode, &parser]() { const bool parserSucceeded = m_expressionType == ExpressionType::ESMCode ? parser.parseModule()
switch (mode) { : parser.parseScript();
case ParseMode::QML:
return parser.parse();
case ParseMode::JS:
return parser.parseScript();
case ParseMode::ESM:
return parser.parseModule();
default:
Q_UNREACHABLE_RETURN(false);
}
}();
if (!parserSucceeded) { if (!parserSucceeded) {
addErrorLocal(domParsingErrors().error(tr("Parsing of code failed"))); addErrorLocal(domParsingErrors().error(tr("Parsing of code failed")));
} }

View File

@ -407,18 +407,17 @@ public:
explicit ScriptExpression(QStringView code, const std::shared_ptr<QQmlJS::Engine> &engine, explicit ScriptExpression(QStringView code, const std::shared_ptr<QQmlJS::Engine> &engine,
AST::Node *ast, const std::shared_ptr<AstComments> &comments, AST::Node *ast, const std::shared_ptr<AstComments> &comments,
ExpressionType expressionType, ExpressionType expressionType,
SourceLocation localOffset = SourceLocation(), int derivedFrom = 0); SourceLocation localOffset = SourceLocation());
ScriptExpression() ScriptExpression()
: ScriptExpression(QStringView(), std::shared_ptr<QQmlJS::Engine>(), nullptr, : ScriptExpression(QStringView(), std::shared_ptr<QQmlJS::Engine>(), nullptr,
std::shared_ptr<AstComments>(), ExpressionType::BindingExpression, std::shared_ptr<AstComments>(), ExpressionType::BindingExpression,
SourceLocation(), 0) SourceLocation())
{ {
} }
explicit ScriptExpression(const QString &code, ExpressionType expressionType, explicit ScriptExpression(const QString &code, ExpressionType expressionType)
int derivedFrom = 0) : OwningItem(), m_expressionType(expressionType)
: OwningItem(derivedFrom), m_expressionType(expressionType)
{ {
setCode(code); setCode(code);
} }
@ -430,10 +429,6 @@ public:
return std::static_pointer_cast<ScriptExpression>(doCopy(self)); return std::static_pointer_cast<ScriptExpression>(doCopy(self));
} }
// TODO can be deleted atm used only in MutableItem setCode (which is unused atm)
std::shared_ptr<ScriptExpression> copyWithUpdatedCode(const DomItem &self,
const QString &code) const;
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const override; bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const override;
Path canonicalPath(const DomItem &self) const override { return self.m_ownerPath; } Path canonicalPath(const DomItem &self) const override { return self.m_ownerPath; }
@ -481,18 +476,6 @@ protected:
return std::make_shared<ScriptExpression>(*this); return std::make_shared<ScriptExpression>(*this);
} }
std::function<SourceLocation(SourceLocation)> locationToGlobalF(const DomItem &self) const
{
SourceLocation loc = globalLocation(self);
return [loc, this](SourceLocation x) {
return SourceLocation(x.offset - m_localOffset.offset + loc.offset, x.length,
x.startLine - m_localOffset.startLine + loc.startLine,
((x.startLine == m_localOffset.startLine) ? x.startColumn
- m_localOffset.startColumn + loc.startColumn
: x.startColumn));
};
}
SourceLocation locationToLocal(SourceLocation x) const SourceLocation locationToLocal(SourceLocation x) const
{ {
return SourceLocation( return SourceLocation(
@ -502,11 +485,6 @@ protected:
: x.startColumn)); // are line and column 1 based? then we should + 1 : x.startColumn)); // are line and column 1 based? then we should + 1
} }
std::function<SourceLocation(SourceLocation)> locationToLocalF(const DomItem &) const
{
return [this](SourceLocation x) { return locationToLocal(x); };
}
private: private:
enum class ParseMode { enum class ParseMode {
QML, QML,
@ -514,21 +492,8 @@ private:
ESM, // ECMAScript module ESM, // ECMAScript module
}; };
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;
case ExpressionType::ESMCode:
return ParseMode::ESM;
default:
return ParseMode::JS;
}
}
void setCode(const QString &code); void setCode(const QString &code);
[[nodiscard]] AST::Node *parse(ParseMode mode); [[nodiscard]] AST::Node *parse();
ExpressionType m_expressionType; ExpressionType m_expressionType;
QString m_codeStr; QString m_codeStr;