QmlJS::Check: Suspend warnings for ScriptAction defined in the .ui file

Connections were the only type that was allowed to have function
definitions, call expressions, etc. in the .ui file. It's now extended
with ScriptAction.

Task-number: QDS-10449
Change-Id: If55116a291c5c1d6441f6ab0c3a651861da69fba
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Rafal Stawarski
2025-02-19 11:39:10 +01:00
parent 193684b88e
commit 9f232746a5
3 changed files with 23 additions and 14 deletions

View File

@@ -21,6 +21,7 @@
using namespace QmlJS; using namespace QmlJS;
using namespace QmlJS::AST; using namespace QmlJS::AST;
using namespace QmlJS::StaticAnalysis; using namespace QmlJS::StaticAnalysis;
using namespace Qt::Literals::StringLiterals;
namespace { namespace {
@@ -1373,10 +1374,10 @@ bool Check::visit(FunctionExpression *ast)
} }
} }
const bool isDirectInConnectionsScope = const bool isDirectInConnectionsOrScriptActionScope
(!m_typeStack.isEmpty() && m_typeStack.last() == "Connections"); = isDirectInTypeScope("Connections"_L1, "ScriptAction"_L1);
if (!isDirectInConnectionsScope) if (!isDirectInConnectionsOrScriptActionScope)
addMessage(ErrFunctionsNotSupportedInQmlUi, locationFromRange(locfunc, loclparen)); addMessage(ErrFunctionsNotSupportedInQmlUi, locationFromRange(locfunc, loclparen));
DeclarationsCheck bodyCheck; DeclarationsCheck bodyCheck;
@@ -1433,10 +1434,10 @@ bool Check::visit(BinaryExpression *ast)
SourceLocation expressionSourceLocation = locationFromRange(ast->firstSourceLocation(), SourceLocation expressionSourceLocation = locationFromRange(ast->firstSourceLocation(),
ast->lastSourceLocation()); ast->lastSourceLocation());
const bool isDirectInConnectionsScope = (!m_typeStack.isEmpty() const bool isDirectInConnectionsOrScriptActionScope
&& m_typeStack.last() == "Connections"); = isDirectInTypeScope("Connections"_L1, "ScriptAction"_L1);
if (expressionAffectsVisualAspects(ast) && !isDirectInConnectionsScope) if (expressionAffectsVisualAspects(ast) && !isDirectInConnectionsOrScriptActionScope)
addMessage(WarnImperativeCodeNotEditableInVisualDesigner, expressionSourceLocation); addMessage(WarnImperativeCodeNotEditableInVisualDesigner, expressionSourceLocation);
// check ==, != // check ==, !=
@@ -1481,11 +1482,10 @@ bool Check::visit(BinaryExpression *ast)
bool Check::visit(Block *ast) bool Check::visit(Block *ast)
{ {
const bool isDirectInConnectionsOrScriptActionScope
= isDirectInTypeScope("Connections"_L1, "ScriptAction"_L1);
bool isDirectInConnectionsScope = if (!isDirectInConnectionsOrScriptActionScope)
(!m_typeStack.isEmpty() && m_typeStack.last() == "Connections");
if (!isDirectInConnectionsScope)
addMessage(ErrBlocksNotSupportedInQmlUi, locationFromRange(ast->firstSourceLocation(), ast->lastSourceLocation())); addMessage(ErrBlocksNotSupportedInQmlUi, locationFromRange(ast->firstSourceLocation(), ast->lastSourceLocation()));
if (Node *p = parent()) { if (Node *p = parent()) {
@@ -1910,9 +1910,11 @@ bool Check::visit(CallExpression *ast)
const bool isMathFunction = namespaceName == "Math"; const bool isMathFunction = namespaceName == "Math";
const bool isDateFunction = namespaceName == "Date"; const bool isDateFunction = namespaceName == "Date";
// allow adding connections with the help of the qt quick designer ui // allow adding connections with the help of the qt quick designer ui
bool isDirectInConnectionsScope = const bool isDirectInConnectionsOrScriptActionScope
(!m_typeStack.isEmpty() && m_typeStack.last() == QLatin1String("Connections")); = isDirectInTypeScope("Connections"_L1, "ScriptAction"_L1);
if (!whiteListedFunction && !isMathFunction && !isDateFunction && !isDirectInConnectionsScope)
if (!whiteListedFunction && !isMathFunction && !isDateFunction
&& !isDirectInConnectionsOrScriptActionScope)
addMessage(ErrFunctionsNotSupportedInQmlUi, location); addMessage(ErrFunctionsNotSupportedInQmlUi, location);
if (translationFunctions.contains(name)) { if (translationFunctions.contains(name)) {

View File

@@ -109,6 +109,12 @@ private:
bool isCaseOrDefault(AST::Node *n); bool isCaseOrDefault(AST::Node *n);
bool hasVarStatement(AST::Block *b) const; bool hasVarStatement(AST::Block *b) const;
template<typename... Args>
bool isDirectInTypeScope(Args... args)
{
return !m_typeStack.isEmpty() && ((m_typeStack.last() == args) || ...);
}
AST::Node *parent(int distance = 0); AST::Node *parent(int distance = 0);
Document::Ptr _doc; Document::Ptr _doc;

View File

@@ -212,7 +212,8 @@ StaticAnalysisMessages::StaticAnalysisMessages()
newMsg( newMsg(
ErrFunctionsNotSupportedInQmlUi, ErrFunctionsNotSupportedInQmlUi,
Error, Error,
Tr::tr("Arbitrary functions and function calls outside of a Connections object are not supported in a UI file (.ui.qml).")); Tr::tr("Arbitrary functions and function calls outside of a Connections or ScriptAction "
"objects are not supported in a UI file (.ui.qml)."));
newMsg(ErrBlocksNotSupportedInQmlUi, Error, newMsg(ErrBlocksNotSupportedInQmlUi, Error,
Tr::tr("JavaScript blocks are not supported in a UI file (.ui.qml).")); Tr::tr("JavaScript blocks are not supported in a UI file (.ui.qml)."));
newMsg(ErrBehavioursNotSupportedInQmlUi, Error, newMsg(ErrBehavioursNotSupportedInQmlUi, Error,