qmljs: correctly handle required and readonly properties

* correct indentation after required property QTCREATORBUG-24144
* handle required <name> statement
* allow default readoly required reordering
* more permissive than the actual parser (which then will show errors
for invalid sequences)
* backport form QmlDom

Fixes: QTCREATORBUG-24144
Change-Id: I19166ca65d108d533a1ed3748c09e35bcfdbc56d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Fawzi Mohamed
2021-02-22 14:50:36 +01:00
parent 5f2edec6cb
commit c57f6a703b
4 changed files with 49 additions and 8 deletions

View File

@@ -163,6 +163,8 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
case Import:
case Signal:
case Property:
case Required:
case Readonly:
case Identifier: enter(expression_or_objectdefinition); break;
// error recovery
@@ -175,8 +177,10 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
case objectdefinition_open:
switch (kind) {
case RightBrace: leave(true); break;
case Default: enter(default_property_start); break;
case Default:
case Readonly: enter(property_modifiers); break;
case Property: enter(property_start); break;
case Required: enter(required_property); break;
case Function: enter(function_start); break;
case Signal: enter(signal_start); break;
case Enum: enter(enum_start); break;
@@ -187,12 +191,14 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
case Identifier: enter(binding_or_objectdefinition); break;
} break;
case default_property_start:
if (kind != Property)
leave(true);
else
turnInto(property_start);
break;
case property_modifiers:
switch (kind) {
case Property: turnInto(property_start); break;
case Default:
case Readonly: break;
case Required: turnInto(required_property); break;
default: leave(true); break;
} break;
case property_start:
switch (kind) {
@@ -203,6 +209,15 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
default: leave(true); continue;
} break;
case required_property:
switch (kind) {
case Property: turnInto(property_start); break;
case Default:
case Readonly: turnInto(property_modifiers); break;
case Identifier: leave(true); break;
default: leave(true); continue;
} break;
case property_name:
turnInto(property_maybe_initializer);
break;
@@ -788,6 +803,8 @@ bool CodeFormatter::tryStatement()
case As:
case List:
case Property:
case Required:
case Readonly:
case Function:
case Number:
case String:
@@ -938,6 +955,10 @@ CodeFormatter::TokenKind CodeFormatter::extendedTokenKind(const QmlJS::Token &to
return Signal;
if (text == QLatin1String("property"))
return Property;
if (text == QLatin1String("readonly"))
return Readonly;
if (text == QLatin1String("required"))
return Required;
if (text == QLatin1String("on"))
return On;
if (text == QLatin1String("list"))

View File

@@ -104,7 +104,8 @@ public: // must be public to make Q_GADGET introspection work
import_as,
property_start, // after 'property'
default_property_start, // after 'default'
property_modifiers, // after 'default' or readonly
required_property, // after required
property_list_open, // after 'list' as a type
property_name, // after the type
property_maybe_initializer, // after the identifier
@@ -237,6 +238,8 @@ protected:
As,
List,
Property,
Required,
Readonly,
Question,
PlusPlus,

View File

@@ -669,6 +669,14 @@ protected:
return false;
}
bool visit(UiRequired *ast) override
{
out(ast->requiredToken);
out(" ");
out(ast->name.toString());
return true;
}
bool visit(UiObjectBinding *ast) override
{
if (ast->hasOnToken) {

View File

@@ -2,4 +2,13 @@ import QtQuick 2.0
Item {
readonly property int horse: 40
required property Item theItem
required data
function foo() {
theItem.foo("The issue is exacerbated if the object literal is wrapped onto the next line like so:",
{
"foo": theFoo
})
}
}