From c57f6a703b611e08e86365d8a98a58cbc9a5bd94 Mon Sep 17 00:00:00 2001 From: Fawzi Mohamed Date: Mon, 22 Feb 2021 14:50:36 +0100 Subject: [PATCH] qmljs: correctly handle required and readonly properties * correct indentation after required property QTCREATORBUG-24144 * handle required 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 --- src/libs/qmljs/qmljscodeformatter.cpp | 35 +++++++++++++++++----- src/libs/qmljs/qmljscodeformatter.h | 5 +++- src/libs/qmljs/qmljsreformatter.cpp | 8 +++++ tests/auto/qml/reformatter/qmlreadonly.qml | 9 ++++++ 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/libs/qmljs/qmljscodeformatter.cpp b/src/libs/qmljs/qmljscodeformatter.cpp index 63932e9ecdd..23d1c65cf05 100644 --- a/src/libs/qmljs/qmljscodeformatter.cpp +++ b/src/libs/qmljs/qmljscodeformatter.cpp @@ -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")) diff --git a/src/libs/qmljs/qmljscodeformatter.h b/src/libs/qmljs/qmljscodeformatter.h index c91b36ba27f..eab2cfc2405 100644 --- a/src/libs/qmljs/qmljscodeformatter.h +++ b/src/libs/qmljs/qmljscodeformatter.h @@ -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, diff --git a/src/libs/qmljs/qmljsreformatter.cpp b/src/libs/qmljs/qmljsreformatter.cpp index 60e32288c97..4d4aba71f96 100644 --- a/src/libs/qmljs/qmljsreformatter.cpp +++ b/src/libs/qmljs/qmljsreformatter.cpp @@ -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) { diff --git a/tests/auto/qml/reformatter/qmlreadonly.qml b/tests/auto/qml/reformatter/qmlreadonly.qml index f8a937586a5..0f68ccd32c0 100644 --- a/tests/auto/qml/reformatter/qmlreadonly.qml +++ b/tests/auto/qml/reformatter/qmlreadonly.qml @@ -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 + }) + } }