aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@qt.io>2023-06-27 15:20:18 +0200
committerEike Ziller <eike.ziller@qt.io>2023-06-27 15:20:18 +0200
commit3e65778d6632027a932e78a771ec877f72042cff (patch)
tree8ad63a32967e477e482c4199c2ddefb70cba7af4
parenta8cab6f5a19f1355e9de1d95354cb25baf62515d (diff)
parent372e2ba6155a37c94d534d9176bb4c9a3b8024fe (diff)
Merge remote-tracking branch 'origin/11.0'
-rw-r--r--doc/qtcreator/config/qtcreator-project.qdocconf5
-rw-r--r--src/libs/qmljs/qmljscheck.cpp36
-rw-r--r--src/libs/solutions/tasking/barrier.h2
-rw-r--r--src/libs/solutions/tasking/tasktree.cpp370
-rw-r--r--src/libs/solutions/tasking/tasktree.h24
-rw-r--r--src/plugins/autotest/boost/boosttestsettings.cpp8
-rw-r--r--src/plugins/autotest/ctest/ctestsettings.cpp3
-rw-r--r--src/plugins/autotest/gtest/gtestsettings.cpp6
-rw-r--r--src/plugins/autotest/testresultmodel.cpp5
-rw-r--r--src/plugins/autotest/testresultspane.cpp2
-rw-r--r--src/plugins/clangformat/clangformatfile.cpp19
-rw-r--r--src/plugins/clangformat/clangformatutils.cpp6
-rw-r--r--src/plugins/clangtools/readexporteddiagnosticstest.cpp31
-rw-r--r--src/plugins/clangtools/readexporteddiagnosticstest.h3
-rw-r--r--src/plugins/projectexplorer/projectwizardpage.cpp11
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt14
-rw-r--r--src/plugins/qmldesignerbase/CMakeLists.txt14
-rw-r--r--src/plugins/qmlprojectmanager/CMakeLists.txt2
-rw-r--r--src/plugins/qtsupport/examplesparser.cpp24
-rw-r--r--tests/auto/qml/codemodel/check/accessById.qml39
20 files changed, 532 insertions, 92 deletions
diff --git a/doc/qtcreator/config/qtcreator-project.qdocconf b/doc/qtcreator/config/qtcreator-project.qdocconf
index 6d0690a134..ec98529c14 100644
--- a/doc/qtcreator/config/qtcreator-project.qdocconf
+++ b/doc/qtcreator/config/qtcreator-project.qdocconf
@@ -70,4 +70,9 @@ macro.see = "\\sa"
macro.function = "\\fn"
navigation.landingpage = "$IDE_DISPLAY_NAME Manual"
+
+# Auto-generate navigation linking based on "All Topics":
+navigation.toctitles = "All Topics"
+navigation.toctitles.inclusive = false
+
buildversion = "$IDE_DISPLAY_NAME Manual $QTC_VERSION"
diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp
index 2a41f472d7..f1e72a7dc2 100644
--- a/src/libs/qmljs/qmljscheck.cpp
+++ b/src/libs/qmljs/qmljscheck.cpp
@@ -2003,10 +2003,20 @@ bool Check::visit(TypeOfExpression *ast)
/// ### Maybe put this into the context as a helper function.
const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
{
-
if (!_importsOk)
return nullptr;
+ if (!id)
+ return nullptr; // ### error?
+
+ if (id->name.isEmpty()) // possible after error recovery
+ return nullptr;
+
+ QString propertyName = id->name.toString();
+
+ if (propertyName == "id" && !id->next)
+ return nullptr; // ### should probably be a special value
+
QList<const ObjectValue *> scopeObjects = _scopeChain.qmlScopeObjects();
if (scopeObjects.isEmpty())
return nullptr;
@@ -2021,24 +2031,9 @@ const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
return isAttachedProperty;
};
-
- if (! id)
- return nullptr; // ### error?
-
- if (id->name.isEmpty()) // possible after error recovery
- return nullptr;
-
- QString propertyName = id->name.toString();
-
- if (propertyName == "id" && !id->next)
- return nullptr; // ### should probably be a special value
-
// attached properties
bool isAttachedProperty = getAttachedTypes(propertyName);
- if (scopeObjects.isEmpty())
- return nullptr;
-
// global lookup for first part of id
const Value *value = nullptr;
for (int i = scopeObjects.size() - 1; i >= 0; --i) {
@@ -2053,7 +2048,14 @@ const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
return nullptr;
if (!value) {
- addMessage(ErrInvalidPropertyName, id->identifierToken, propertyName);
+ // We omit M16 messages if the type using ImmediateProperties
+ // Ideally, we should obtain them through metaobject information
+ const bool omitMessage = !m_typeStack.isEmpty()
+ && ((m_typeStack.last() == "PropertyChanges")
+ || m_typeStack.last() == "Binding")
+ && !m_idStack.isEmpty() && m_idStack.last().contains(propertyName);
+ if (!omitMessage)
+ addMessage(ErrInvalidPropertyName, id->identifierToken, propertyName);
return nullptr;
}
diff --git a/src/libs/solutions/tasking/barrier.h b/src/libs/solutions/tasking/barrier.h
index 705ddd5f5b..64a59ec873 100644
--- a/src/libs/solutions/tasking/barrier.h
+++ b/src/libs/solutions/tasking/barrier.h
@@ -82,7 +82,7 @@ public:
"is not reachable in the running tree. "
"It is possible that no barrier was added to the tree, "
"or the storage is not reachable from where it is referenced. "
- "The WaitForBarrier task will finish with error. ");
+ "The WaitForBarrier task finishes with an error. ");
return SetupResult::StopWithError;
}
Barrier *activeSharedBarrier = activeBarrier->barrier();
diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp
index b9417a6e46..ff43b3a612 100644
--- a/src/libs/solutions/tasking/tasktree.cpp
+++ b/src/libs/solutions/tasking/tasktree.cpp
@@ -139,6 +139,369 @@ private:
*/
/*!
+ \class Tasking::GroupItem
+ \inheaderfile solutions/tasking/tasktree.h
+ \inmodule TaskingSolution
+ \brief GroupItem represents the basic element that may be a part of any
+ \l {Tasking::Group} {Group}.
+
+ GroupItem is a basic element that may be a part of any \l {Tasking::Group} {Group}.
+ It encapsulates the functionality provided by any GroupItem's subclass.
+ It is a value type and it is safe to copy the GroupItem instance,
+ even when it is originally created via the subclass' constructor.
+
+ There are four main kinds of GroupItem:
+ \table
+ \header
+ \li GroupItem Kind
+ \li Brief Description
+ \row
+ \li \l CustomTask
+ \li Defines asynchronous task type and task's start, done, and error handlers.
+ Aliased with a unique task name, such as, \c ConcurrentCallTask<ResultType>
+ or \l NetworkQueryTask. Asynchronous tasks are the main reason for using a task tree.
+ \row
+ \li \l Group
+ \li A container for other group items. Since the group is of the GroupItem type,
+ it's possible to nest it inside another group. The group is seen by its parent
+ as a single asynchronous task.
+ \row
+ \li \l Storage
+ \li Enables the child tasks of a group to exchange data.
+ When Storage is placed inside a group, the task tree instantiates
+ the storage object just before the group is entered,
+ and destroys it just after the group is finished.
+ \row
+ \li Other group control items
+ \li The items returned by \l {Tasking::parallelLimit()} {parallelLimit()} or
+ \l {Tasking::workflowPolicy()} {workflowPolicy()} influence the group's behavior.
+ The items returned by \l {Tasking::onGroupSetup()} {onGroupSetup()},
+ \l {Tasking::onGroupDone()} {onGroupDone()} or
+ \l {Tasking::onGroupError()} {onGroupError()} define custom handlers called when
+ the group starts or ends execution.
+ \endtable
+*/
+
+/*!
+ \class Tasking::Group
+ \inheaderfile solutions/tasking/tasktree.h
+ \inmodule TaskingSolution
+ \brief Group represents the basic element for composing declarative recipes describing
+ how to execute and handle a nested tree of asynchronous tasks.
+
+ Group is a container for other group items. It encloses child tasks into one unit,
+ which is seen by the group's parent as a single, asynchronous task.
+ Since Group is of the GroupItem type, it may also be a child of Group.
+
+ Insert child tasks into the group by using aliased custom task names, such as,
+ \c ConcurrentCallTask<ResultType> or \c NetworkQueryTask:
+
+ \code
+ const Group group {
+ NetworkQueryTask(...),
+ ConcurrentCallTask<int>(...)
+ };
+ \endcode
+
+ The group's behavior may be customized by inserting the items returned by
+ \l {Tasking::parallelLimit()} {parallelLimit()} or
+ \l {Tasking::workflowPolicy()} {workflowPolicy()} functions:
+
+ \code
+ const Group group {
+ parallel,
+ continueOnError,
+ NetworkQueryTask(...),
+ NetworkQueryTask(...)
+ };
+ \endcode
+
+ The group may contain nested groups:
+
+ \code
+ const Group group {
+ finishAllAndDone,
+ NetworkQueryTask(...),
+ Group {
+ NetworkQueryTask(...),
+ Group {
+ parallel,
+ NetworkQueryTask(...),
+ NetworkQueryTask(...),
+ }
+ ConcurrentCallTask<QString>(...)
+ }
+ };
+ \endcode
+
+ The group may dynamically instantiate a custom storage structure, which may be used for
+ inter-task data exchange:
+
+ \code
+ struct MyCustomStruct { QByteArray data; };
+
+ TreeStorage<MyCustomStruct> storage;
+
+ const auto onFirstSetup = [](NetworkQuery &task) { ... };
+ const auto onFirstDone = [storage](const NetworkQuery &task) {
+ // storage-> gives a pointer to MyCustomStruct instance,
+ // created dynamically by the running task tree.
+ storage->data = task.reply()->readAll();
+ };
+ const auto onSecondSetup = [storage](ConcurrentCall<QImage> &task) {
+ // storage-> gives a pointer to MyCustomStruct. Since the group is sequential,
+ // the stored MyCustomStruct was already updated inside the onFirstDone handler.
+ const QByteArray storedData = storage->data;
+ };
+
+ const Group group {
+ // When the group is entered by a running task tree, it creates MyCustomStruct
+ // instance dynamically. It is later accessible from all handlers via
+ // the *storage or storage-> operators.
+ sequential,
+ Storage(storage),
+ NetworkQueryTask(onFirstSetup, onFirstDone),
+ ConcurrentCallTask<QImage>(onSecondSetup)
+ };
+ \endcode
+*/
+
+/*!
+ \fn Group::Group(const QList<GroupItem> &children)
+
+ Constructs a group with a given list of \a children.
+
+ This constructor is useful when the child items of the group are not known at compile time,
+ but later, at runtime:
+
+ \code
+ const QStringList sourceList = ...;
+
+ QList<GroupItem> groupItems { parallel };
+
+ for (const QString &source : sourceList) {
+ const NetworkQueryTask task(...); // use source for setup handler
+ groupItems << task;
+ }
+
+ const Group group(groupItems);
+ \endcode
+*/
+
+/*!
+ \fn Group::Group(std::initializer_list<GroupItem> children)
+
+ Constructs a group from std::initializer_list given by \a children.
+
+ This constructor is useful when all child items of the group are known at compile time:
+
+ \code
+ const Group group {
+ finishAllAndDone,
+ NetworkQueryTask(...),
+ Group {
+ NetworkQueryTask(...),
+ Group {
+ parallel,
+ NetworkQueryTask(...),
+ NetworkQueryTask(...),
+ }
+ ConcurrentCallTask<QString>(...)
+ }
+ };
+ \endcode
+*/
+
+/*!
+ \fn GroupItem Group::withTimeout(std::chrono::milliseconds timeout, const GroupEndHandler &handler) const
+
+ Attaches \c TimeoutTask to a copy of \c this group, elapsing after \a timeout in milliseconds,
+ with an optionally provided timeout \a handler, and returns the coupled item.
+
+ When the group finishes before \a timeout passes,
+ the returned item finishes immediately with the group's result.
+ Otherwise, the \a handler is invoked (if provided), the group is stopped,
+ and the returned item finishes with an error.
+*/
+
+/*!
+ \class Tasking::CustomTask
+ \inheaderfile solutions/tasking/tasktree.h
+ \inmodule TaskingSolution
+ \brief A class template used for declaring task items and defining their setup,
+ done, and error handlers.
+
+ The CustomTask class template is used inside TaskTree for describing custom task items.
+
+ Custom task names are aliased with unique names inside the \l Tasking namespace
+ via the TASKING_DECLARE_TASK or TASKING_DECLARE_TEMPLATE_TASK macros.
+ For example, \c ConcurrentCallTask<T> is an alias to the CustomTask that is defined
+ to work with \c ConcurrentCall<T> as an associated task class.
+ The following table contains all the built-in tasks and their associated task classes:
+
+ \table
+ \header
+ \li Aliased Task Name (Tasking Namespace)
+ \li Associated Task Class
+ \li Brief Description
+ \row
+ \li ConcurrentCallTask<ReturnType>
+ \li ConcurrentCall<ReturnType>
+ \li Starts an asynchronous task. Runs in a separate thread.
+ \row
+ \li NetworkQueryTask
+ \li NetworkQuery
+ \li Sends a network query.
+ \row
+ \li TaskTreeTask
+ \li TaskTree
+ \li Starts a nested task tree.
+ \row
+ \li TimeoutTask
+ \li \c std::chrono::milliseconds
+ \li Starts a timer.
+ \row
+ \li WaitForBarrierTask
+ \li MultiBarrier<Limit>
+ \li Starts an asynchronous task waiting for the barrier to pass.
+ \endtable
+*/
+
+/*!
+ \typealias CustomTask::Task
+
+ Type alias for \c Adapter::Type.
+
+ This is the associated task's type.
+*/
+
+/*!
+ \typealias CustomTask::EndHandler
+
+ Type alias for \c std::function<void(const Task &)>.
+*/
+
+/*!
+ \fn template <typename Adapter> template <typename SetupHandler> CustomTask<Adapter>::CustomTask<Adapter>(SetupHandler &&setup, const EndHandler &done, const EndHandler &error)
+
+ Constructs the CustomTask instance and attaches the \a setup, \a done, and \a error
+ handlers to the task. When the running task tree is about to start the task,
+ it instantiates the associated \l Task object, invokes \a setup handler with a \e reference
+ to the created task, and starts it. When the running task finishes with success or an error,
+ the task tree invokes \a done or \a error handler, respectively,
+ with a \e {const reference} to the created task.
+
+ The passed \a setup handler is either of the \c std::function<SetupResult(Task &)> or
+ \c std::function<void(Task &)> type. For example:
+
+ \code
+ static void parseAndLog(const QString &input);
+
+ ...
+
+ const QString input = ...;
+
+ const auto onFirstSetup = [input](ConcurrentCall<void> &task) {
+ if (input == "Skip")
+ return SetupResult::StopWithDone; // This task won't start, the next one will
+ if (input == "Error")
+ return SetupResult::StopWithError; // This task and the next one won't start
+ task.setConcurrentCallData(parseAndLog, input);
+ // This task will start, and the next one will start after this one finished with success
+ return SetupResult::Continue;
+ };
+
+ const auto onSecondSetup = [input](ConcurrentCall<void> &task) {
+ task.setConcurrentCallData(parseAndLog, input);
+ };
+
+ const Group group {
+ ConcurrentCallTask<void>(onFirstSetup),
+ ConcurrentCallTask<void>(onSecondSetup)
+ };
+ \endcode
+
+ When the passed \a setup handler is of the \c std::function<SetupResult(Task &)> type,
+ the return value of the handler instructs the running tree on how to proceed after
+ the handler's invocation is finished. The default return value of SetupResult::Continue
+ instructs the tree to continue running, i.e. to execute the associated \c Task.
+ The return value of SetupResult::StopWithDone or SetupResult::StopWithError instructs
+ the tree to skip the task's execution and finish immediately with success or an error,
+ respectively.
+ When the return type is either SetupResult::StopWithDone or SetupResult::StopWithError,
+ the task's \a done or \a error handler (even if provided) are not called afterwards.
+
+ The \a setup handler may be of a shortened form of std::function<void(Task &)>,
+ i.e. the return value is void. In this case it's assumed that the return value is
+ SetupResult::Continue by default.
+
+ When the running task finishes, one of \a done or \a error handlers is called,
+ depending on whether it finished with success or an error, respectively.
+ Both handlers are of std::function<void(const Task &)> type.
+
+ \sa onSetup(), onDone(), onError()
+*/
+
+/*!
+ \fn template <typename Adapter> template <typename SetupHandler> CustomTask<Adapter> &CustomTask<Adapter>::onSetup(SetupHandler &&handler)
+
+ Attaches the setup \a handler to \c this task.
+ The \a handler is invoked when the task is about to be started.
+
+ This function enables defining the task's details with a
+ \l {https://en.wikipedia.org/wiki/Fluent_interface}{fluent interface} style:
+
+ \code
+ const auto onQuerySetup = [](NetworkQuery &task) { ... };
+ const auto onQueryError = [](const NetworkQuery &task) { ... };
+
+ const Group group {
+ NetworkQueryTask(onQuerySetup, {}, onQueryError),
+ NetworkQueryTask().onSetup(onQuerySetup).onError(onQueryError), // fluent interface style
+ NetworkQueryTask(onQuerySetup, {}, onQueryError).withTimeout(500ms)
+ }
+ \endcode
+
+ \sa CustomTask(), onDone(), onError()
+*/
+
+/*!
+ \fn template <typename Adapter> CustomTask<Adapter> &CustomTask<Adapter>::onDone(const EndHandler &handler)
+
+ Attaches the done \a handler to \c this task.
+ The handler is invoked when the task finishes with success.
+
+ This function enables defining the task's details with a fluent interface style.
+
+ \sa CustomTask(), onSetup(), onError()
+*/
+
+/*!
+ \fn template <typename Adapter> CustomTask<Adapter> &CustomTask<Adapter>::onError(const EndHandler &handler)
+
+ Attaches the error \a handler to \c this task.
+ The handler is invoked when the task finishes with an error.
+
+ This function enables defining the task's details with a fluent interface style.
+
+ \sa CustomTask(), onSetup(), onDone()
+*/
+
+/*!
+ \fn template <typename Adapter> GroupItem CustomTask<Adapter>::withTimeout(std::chrono::milliseconds timeout, const GroupItem::GroupEndHandler &handler) const
+
+ Attaches \c TimeoutTask to a copy of \c this task, elapsing after \a timeout in milliseconds,
+ with an optionally provided timeout \a handler, and returns the coupled item.
+
+ When the task finishes before \a timeout passes,
+ the returned item finishes immediately with the task's result.
+ Otherwise, the \a handler is invoked (if provided), the task is stopped,
+ and the returned item finishes with an error.
+
+ \sa onSetup()
+*/
+
+/*!
\macro TASKING_DECLARE_TASK(CustomTaskName, TaskAdapterClass)
\relates Tasking
@@ -159,13 +522,6 @@ private:
*/
/*!
- \class Tasking::GroupItem
- \inheaderfile solutions/tasking/tasktree.h
- \inmodule TaskingSolution
- \brief The GroupItem class represents the basic element for composing nested tree structures.
-*/
-
-/*!
\enum Tasking::WorkflowPolicy
This enum describes the possible behavior of the Group element when any group's child task
diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h
index 47ad221728..88f89ef0c5 100644
--- a/src/libs/solutions/tasking/tasktree.h
+++ b/src/libs/solutions/tasking/tasktree.h
@@ -321,14 +321,14 @@ public:
using EndHandler = std::function<void(const Task &)>;
static Adapter *createAdapter() { return new Adapter; }
CustomTask() : GroupItem({&createAdapter}) {}
- template <typename SetupFunction>
- CustomTask(SetupFunction &&function, const EndHandler &done = {}, const EndHandler &error = {})
- : GroupItem({&createAdapter, wrapSetup(std::forward<SetupFunction>(function)),
+ template <typename SetupHandler>
+ CustomTask(SetupHandler &&setup, const EndHandler &done = {}, const EndHandler &error = {})
+ : GroupItem({&createAdapter, wrapSetup(std::forward<SetupHandler>(setup)),
wrapEnd(done), wrapEnd(error)}) {}
- template <typename SetupFunction>
- CustomTask &onSetup(SetupFunction &&function) {
- setTaskSetupHandler(wrapSetup(std::forward<SetupFunction>(function)));
+ template <typename SetupHandler>
+ CustomTask &onSetup(SetupHandler &&handler) {
+ setTaskSetupHandler(wrapSetup(std::forward<SetupHandler>(handler)));
return *this;
}
CustomTask &onDone(const EndHandler &handler) {
@@ -346,20 +346,20 @@ public:
}
private:
- template<typename SetupFunction>
- static GroupItem::TaskSetupHandler wrapSetup(SetupFunction &&function) {
+ template<typename SetupHandler>
+ static GroupItem::TaskSetupHandler wrapSetup(SetupHandler &&handler) {
static constexpr bool isDynamic = std::is_same_v<SetupResult,
- std::invoke_result_t<std::decay_t<SetupFunction>, typename Adapter::Type &>>;
+ std::invoke_result_t<std::decay_t<SetupHandler>, typename Adapter::Type &>>;
constexpr bool isVoid = std::is_same_v<void,
- std::invoke_result_t<std::decay_t<SetupFunction>, typename Adapter::Type &>>;
+ std::invoke_result_t<std::decay_t<SetupHandler>, typename Adapter::Type &>>;
static_assert(isDynamic || isVoid,
"Task setup handler needs to take (Task &) as an argument and has to return "
"void or SetupResult. The passed handler doesn't fulfill these requirements.");
return [=](TaskInterface &taskInterface) {
Adapter &adapter = static_cast<Adapter &>(taskInterface);
if constexpr (isDynamic)
- return std::invoke(function, *adapter.task());
- std::invoke(function, *adapter.task());
+ return std::invoke(handler, *adapter.task());
+ std::invoke(handler, *adapter.task());
return SetupResult::Continue;
};
};
diff --git a/src/plugins/autotest/boost/boosttestsettings.cpp b/src/plugins/autotest/boost/boosttestsettings.cpp
index ed0bad6bca..4cf9225173 100644
--- a/src/plugins/autotest/boost/boosttestsettings.cpp
+++ b/src/plugins/autotest/boost/boosttestsettings.cpp
@@ -66,22 +66,22 @@ BoostTestSettings::BoostTestSettings(Id settingsId)
seed.setEnabler(&randomize);
randomize.setSettingsKey("Randomize");
- randomize.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBox);
+ randomize.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBoxWithoutDummyLabel);
randomize.setLabelText(Tr::tr("Randomize"));
randomize.setToolTip(Tr::tr("Randomize execution order."));
systemErrors.setSettingsKey("SystemErrors");
- systemErrors.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBox);
+ systemErrors.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBoxWithoutDummyLabel);
systemErrors.setLabelText(Tr::tr("Catch system errors"));
systemErrors.setToolTip(Tr::tr("Catch or ignore system errors."));
fpExceptions.setSettingsKey("FPExceptions");
- fpExceptions.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBox);
+ fpExceptions.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBoxWithoutDummyLabel);
fpExceptions.setLabelText(Tr::tr("Floating point exceptions"));
fpExceptions.setToolTip(Tr::tr("Enable floating point exception traps."));
memLeaks.setSettingsKey("MemoryLeaks");
- memLeaks.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBox);
+ memLeaks.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBoxWithoutDummyLabel);
memLeaks.setDefaultValue(true);
memLeaks.setLabelText(Tr::tr("Detect memory leaks"));
memLeaks.setToolTip(Tr::tr("Enable memory leak detection."));
diff --git a/src/plugins/autotest/ctest/ctestsettings.cpp b/src/plugins/autotest/ctest/ctestsettings.cpp
index a2f3e90427..70016f7920 100644
--- a/src/plugins/autotest/ctest/ctestsettings.cpp
+++ b/src/plugins/autotest/ctest/ctestsettings.cpp
@@ -44,6 +44,7 @@ CTestSettings::CTestSettings(Id settingsId)
outputOnFail.setSettingsKey("OutputOnFail");
outputOnFail.setLabelText(Tr::tr("Output on failure"));
+ outputOnFail.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBoxWithoutDummyLabel);
outputOnFail.setDefaultValue(true);
outputMode.setSettingsKey("OutputMode");
@@ -70,9 +71,11 @@ CTestSettings::CTestSettings(Id settingsId)
scheduleRandom.setSettingsKey("ScheduleRandom");
scheduleRandom.setLabelText(Tr::tr("Schedule random"));
+ scheduleRandom.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBoxWithoutDummyLabel);
stopOnFailure.setSettingsKey("StopOnFail");
stopOnFailure.setLabelText(Tr::tr("Stop on failure"));
+ stopOnFailure.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBoxWithoutDummyLabel);
parallel.setSettingsKey("Parallel");
parallel.setToolTip(Tr::tr("Run tests in parallel mode using given number of jobs."));
diff --git a/src/plugins/autotest/gtest/gtestsettings.cpp b/src/plugins/autotest/gtest/gtestsettings.cpp
index ca31c99f12..7fa1e53479 100644
--- a/src/plugins/autotest/gtest/gtestsettings.cpp
+++ b/src/plugins/autotest/gtest/gtestsettings.cpp
@@ -26,6 +26,7 @@ GTestSettings::GTestSettings(Id settingsId)
setLayouter([this] {
return Row { Form {
runDisabled, br,
+ throwOnFailure, br,
breakOnFailure, br,
repeat, iterations, br,
shuffle, seed, br,
@@ -49,24 +50,29 @@ GTestSettings::GTestSettings(Id settingsId)
runDisabled.setSettingsKey("RunDisabled");
runDisabled.setLabelText(Tr::tr("Run disabled tests"));
+ runDisabled.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBoxWithoutDummyLabel);
runDisabled.setToolTip(Tr::tr("Executes disabled tests when performing a test run."));
shuffle.setSettingsKey("Shuffle");
shuffle.setLabelText(Tr::tr("Shuffle tests"));
+ shuffle.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBoxWithoutDummyLabel);
shuffle.setToolTip(Tr::tr("Shuffles tests automatically on every iteration by the given seed."));
repeat.setSettingsKey("Repeat");
repeat.setLabelText(Tr::tr("Repeat tests"));
+ repeat.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBoxWithoutDummyLabel);
repeat.setToolTip(Tr::tr("Repeats a test run (you might be required to increase the timeout to "
"avoid canceling the tests)."));
throwOnFailure.setSettingsKey("ThrowOnFailure");
throwOnFailure.setLabelText(Tr::tr("Throw on failure"));
+ throwOnFailure.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBoxWithoutDummyLabel);
throwOnFailure.setToolTip(Tr::tr("Turns assertion failures into C++ exceptions."));
breakOnFailure.setSettingsKey("BreakOnFailure");
breakOnFailure.setDefaultValue(true);
breakOnFailure.setLabelText(Tr::tr("Break on failure while debugging"));
+ breakOnFailure.setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBoxWithoutDummyLabel);
breakOnFailure.setToolTip(Tr::tr("Turns failures into debugger breakpoints."));
groupMode.setSettingsKey("GroupMode");
diff --git a/src/plugins/autotest/testresultmodel.cpp b/src/plugins/autotest/testresultmodel.cpp
index f03cd8c685..fcb02ec595 100644
--- a/src/plugins/autotest/testresultmodel.cpp
+++ b/src/plugins/autotest/testresultmodel.cpp
@@ -296,9 +296,8 @@ void TestResultModel::addTestResult(const TestResult &testResult, bool autoExpan
if (parentItem) {
parentItem->appendChild(newItem);
if (autoExpand) {
- parentItem->expand();
- newItem->expand();
- newItem->forAllChildren([](TreeItem *it) { it->expand(); });
+ QMetaObject::invokeMethod(this, [parentItem]{ parentItem->expand(); },
+ Qt::QueuedConnection);
}
updateParent(newItem);
} else {
diff --git a/src/plugins/autotest/testresultspane.cpp b/src/plugins/autotest/testresultspane.cpp
index 3dbad31ea9..457b273a4a 100644
--- a/src/plugins/autotest/testresultspane.cpp
+++ b/src/plugins/autotest/testresultspane.cpp
@@ -142,7 +142,7 @@ TestResultsPane::TestResultsPane(QObject *parent) :
onCopyItemTriggered(getTestResult(m_treeView->currentIndex()));
});
connect(m_model, &TestResultModel::requestExpansion, this, [this](const QModelIndex &idx) {
- m_treeView->expand(m_filterModel->mapFromSource(idx));
+ m_treeView->expandRecursively(m_filterModel->mapFromSource(idx));
});
connect(TestRunner::instance(), &TestRunner::testRunStarted,
this, &TestResultsPane::onTestRunStarted);
diff --git a/src/plugins/clangformat/clangformatfile.cpp b/src/plugins/clangformat/clangformatfile.cpp
index 16209c3094..66eb58d6ea 100644
--- a/src/plugins/clangformat/clangformatfile.cpp
+++ b/src/plugins/clangformat/clangformatfile.cpp
@@ -152,14 +152,17 @@ CppEditor::CppCodeStyleSettings ClangFormatFile::toCppCodeStyleSettings(
// to be false
settings.indentAccessSpecifiers = (style.AccessModifierOffset != -1 * int(style.IndentWidth));
- settings.indentNamespaceBody = style.NamespaceIndentation
- == FormatStyle::NamespaceIndentationKind::NI_All;
- settings.indentNamespaceBraces = settings.indentNamespaceBody;
-
- settings.indentClassBraces = style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;
- settings.indentEnumBraces = settings.indentClassBraces;
- settings.indentBlockBraces = settings.indentClassBraces;
- settings.indentFunctionBraces = settings.indentClassBraces;
+ if (style.NamespaceIndentation == FormatStyle::NamespaceIndentationKind::NI_All) {
+ settings.indentNamespaceBody = true;
+ settings.indentNamespaceBraces = settings.indentNamespaceBody;
+ }
+
+ if (style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {
+ settings.indentClassBraces = true;
+ settings.indentEnumBraces = settings.indentClassBraces;
+ settings.indentBlockBraces = settings.indentClassBraces;
+ settings.indentFunctionBraces = settings.indentClassBraces;
+ }
settings.indentSwitchLabels = style.IndentCaseLabels;
#if LLVM_VERSION_MAJOR >= 11
diff --git a/src/plugins/clangformat/clangformatutils.cpp b/src/plugins/clangformat/clangformatutils.cpp
index 949911fe5e..7b9a896fc1 100644
--- a/src/plugins/clangformat/clangformatutils.cpp
+++ b/src/plugins/clangformat/clangformatutils.cpp
@@ -207,13 +207,13 @@ void fromCppCodeStyleSettings(clang::format::FormatStyle &style,
else
style.AccessModifierOffset = -1 * style.IndentWidth;
- if (settings.indentNamespaceBody || settings.indentNamespaceBraces)
+ if (settings.indentNamespaceBody && settings.indentNamespaceBraces)
style.NamespaceIndentation = FormatStyle::NamespaceIndentationKind::NI_All;
else
style.NamespaceIndentation = FormatStyle::NamespaceIndentationKind::NI_None;
- if (settings.indentClassBraces || settings.indentEnumBraces || settings.indentBlockBraces
- || settings.indentFunctionBraces)
+ if (settings.indentClassBraces && settings.indentEnumBraces && settings.indentBlockBraces
+ && settings.indentFunctionBraces)
style.BreakBeforeBraces = FormatStyle::BS_Whitesmiths;
else
style.BreakBeforeBraces = FormatStyle::BS_Custom;
diff --git a/src/plugins/clangtools/readexporteddiagnosticstest.cpp b/src/plugins/clangtools/readexporteddiagnosticstest.cpp
index d839108451..f6bf5e1118 100644
--- a/src/plugins/clangtools/readexporteddiagnosticstest.cpp
+++ b/src/plugins/clangtools/readexporteddiagnosticstest.cpp
@@ -64,9 +64,8 @@ static QString appendYamlSuffix(const char *filePathFragment)
void ReadExportedDiagnosticsTest::testTidy()
{
const FilePath sourceFile = filePath("tidy.modernize-use-nullptr.cpp");
- const FilePath exportedFile = createFile(
- filePath(appendYamlSuffix("tidy.modernize-use-nullptr")).toString(),
- sourceFile.toString());
+ const FilePath exportedFile
+ = createFile(filePath(appendYamlSuffix("tidy.modernize-use-nullptr")), sourceFile);
Diagnostic expectedDiag;
expectedDiag.name = "modernize-use-nullptr";
expectedDiag.location = {sourceFile, 2, 25};
@@ -86,9 +85,9 @@ void ReadExportedDiagnosticsTest::testTidy()
void ReadExportedDiagnosticsTest::testAcceptDiagsFromFilePaths_None()
{
- const QString sourceFile = filePath("tidy.modernize-use-nullptr.cpp").toString();
- const FilePath exportedFile = createFile(filePath("tidy.modernize-use-nullptr.yaml").toString(),
- sourceFile);
+ const FilePath sourceFile = filePath("tidy.modernize-use-nullptr.cpp");
+ const FilePath exportedFile = createFile(filePath("tidy.modernize-use-nullptr.yaml"),
+ sourceFile);
const auto acceptNone = [](const FilePath &) { return false; };
const expected_str<Diagnostics> diags
= readExportedDiagnostics(exportedFile, acceptNone);
@@ -101,8 +100,7 @@ void ReadExportedDiagnosticsTest::testTidy_ClangAnalyzer()
{
const FilePath sourceFile = filePath("clang-analyzer.dividezero.cpp");
const FilePath exportedFile
- = createFile(filePath(appendYamlSuffix("clang-analyzer.dividezero")).toString(),
- sourceFile.toString());
+ = createFile(filePath(appendYamlSuffix("clang-analyzer.dividezero")), sourceFile);
Diagnostic expectedDiag;
expectedDiag.name = "clang-analyzer-core.DivideZero";
expectedDiag.location = {sourceFile, 4, 15};
@@ -134,8 +132,8 @@ void ReadExportedDiagnosticsTest::testTidy_ClangAnalyzer()
void ReadExportedDiagnosticsTest::testClazy()
{
const FilePath sourceFile = filePath("clazy.qgetenv.cpp");
- const FilePath exportedFile = createFile(filePath(appendYamlSuffix("clazy.qgetenv")).toString(),
- sourceFile.toString());
+ const FilePath exportedFile = createFile(filePath(appendYamlSuffix("clazy.qgetenv")),
+ sourceFile);
Diagnostic expectedDiag;
expectedDiag.name = "clazy-qgetenv";
expectedDiag.location = {sourceFile, 7, 5};
@@ -259,17 +257,16 @@ void ReadExportedDiagnosticsTest::testOffsetMultiByteCodePoint2()
}
// Replace FILE_PATH with a real absolute file path in the *.yaml files.
-FilePath ReadExportedDiagnosticsTest::createFile(const QString &yamlFilePath,
- const QString &filePathToInject) const
+FilePath ReadExportedDiagnosticsTest::createFile(const Utils::FilePath &yamlFilePath,
+ const Utils::FilePath &filePathToInject) const
{
- QTC_ASSERT(QDir::isAbsolutePath(filePathToInject), return {});
- const FilePath newFileName = m_baseDir->absolutePath(QFileInfo(yamlFilePath).fileName());
+ QTC_ASSERT(filePathToInject.isAbsolutePath(), return {});
+ const FilePath newFileName = m_baseDir->filePath().resolvePath(yamlFilePath);
FileReader reader;
- if (QTC_GUARD(reader.fetch(FilePath::fromString(yamlFilePath),
- QIODevice::ReadOnly | QIODevice::Text))) {
+ if (QTC_GUARD(reader.fetch(yamlFilePath, QIODevice::ReadOnly | QIODevice::Text))) {
QByteArray contents = reader.data();
- contents.replace("FILE_PATH", filePathToInject.toLocal8Bit());
+ contents.replace("FILE_PATH", filePathToInject.toString().toLocal8Bit());
FileSaver fileSaver(newFileName, QIODevice::WriteOnly | QIODevice::Text);
QTC_CHECK(fileSaver.write(contents));
diff --git a/src/plugins/clangtools/readexporteddiagnosticstest.h b/src/plugins/clangtools/readexporteddiagnosticstest.h
index 54bde6b75c..0cf9ef3737 100644
--- a/src/plugins/clangtools/readexporteddiagnosticstest.h
+++ b/src/plugins/clangtools/readexporteddiagnosticstest.h
@@ -44,7 +44,8 @@ private slots:
void testOffsetMultiByteCodePoint2();
private:
- Utils::FilePath createFile(const QString &yamlFilePath, const QString &filePathToInject) const;
+ Utils::FilePath createFile(const Utils::FilePath &yamlFilePath,
+ const Utils::FilePath &filePathToInject) const;
Utils::FilePath filePath(const QString &fileName) const;
CppEditor::Tests::TemporaryCopiedDir * const m_baseDir;
diff --git a/src/plugins/projectexplorer/projectwizardpage.cpp b/src/plugins/projectexplorer/projectwizardpage.cpp
index 83fd4d2cba..75f573430d 100644
--- a/src/plugins/projectexplorer/projectwizardpage.cpp
+++ b/src/plugins/projectexplorer/projectwizardpage.cpp
@@ -298,10 +298,6 @@ ProjectWizardPage::ProjectWizardPage(QWidget *parent)
scrollArea,
}.attachTo(this);
- connect(m_projectComboBox, &QComboBox::currentIndexChanged,
- this, &ProjectWizardPage::projectChanged);
- connect(m_addToVersionControlComboBox, &QComboBox::currentIndexChanged,
- this, &ProjectWizardPage::versionControlChanged);
connect(m_vcsManageButton, &QAbstractButton::clicked, this, &ProjectWizardPage::manageVcs);
setProperty(SHORT_TITLE_PROPERTY, Tr::tr("Summary"));
@@ -376,6 +372,7 @@ void ProjectWizardPage::initializeVersionControls()
// 2) Directory is managed and VCS does not support "Add" -> None available
// 3) Directory is not managed -> Offer all VCS that support "CreateRepository"
+ m_addToVersionControlComboBox->disconnect();
QList<IVersionControl *> versionControls = VcsManager::versionControls();
if (versionControls.isEmpty())
hideVersionControlUiElements();
@@ -419,6 +416,9 @@ void ProjectWizardPage::initializeVersionControls()
int newIdx = m_activeVersionControls.indexOf(currentSelection) + 1;
setVersionControlIndex(newIdx);
}
+
+ connect(m_addToVersionControlComboBox, &QComboBox::currentIndexChanged,
+ this, &ProjectWizardPage::versionControlChanged);
}
bool ProjectWizardPage::runVersionControl(const QList<GeneratedFile> &files, QString *errorMessage)
@@ -457,6 +457,7 @@ void ProjectWizardPage::initializeProjectTree(Node *context, const FilePaths &pa
IWizardFactory::WizardKind kind,
ProjectAction action)
{
+ m_projectComboBox->disconnect();
BestNodeSelector selector(m_commonDirectory, paths);
TreeItem *root = m_model.rootItem();
@@ -489,6 +490,8 @@ void ProjectWizardPage::initializeProjectTree(Node *context, const FilePaths &pa
setAddingSubProject(action == AddSubProject);
m_projectComboBox->setEnabled(m_model.rowCount(QModelIndex()) > 1);
+ connect(m_projectComboBox, &QComboBox::currentIndexChanged,
+ this, &ProjectWizardPage::projectChanged);
}
void ProjectWizardPage::setNoneLabel(const QString &label)
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index 5935933f64..feba07e446 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -31,7 +31,7 @@ add_qtc_library(QmlDesignerUtils STATIC
)
extend_qtc_library(QmlDesignerUtils
- CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ CONDITION ENABLE_COMPILE_WARNING_AS_ERROR
PROPERTIES COMPILE_WARNING_AS_ERROR ON
)
@@ -84,7 +84,7 @@ endif()
extend_qtc_library(QmlDesignerCore
- CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ CONDITION ENABLE_COMPILE_WARNING_AS_ERROR
PROPERTIES COMPILE_WARNING_AS_ERROR ON
)
@@ -481,7 +481,7 @@ add_qtc_plugin(QmlDesigner
)
extend_qtc_plugin(QmlDesigner
- CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ CONDITION ENABLE_COMPILE_WARNING_AS_ERROR
PROPERTIES COMPILE_WARNING_AS_ERROR ON
)
@@ -1088,7 +1088,7 @@ add_qtc_plugin(assetexporterplugin
)
extend_qtc_plugin(assetexporterplugin
- CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ CONDITION ENABLE_COMPILE_WARNING_AS_ERROR
PROPERTIES COMPILE_WARNING_AS_ERROR ON
)
@@ -1121,7 +1121,7 @@ add_qtc_plugin(componentsplugin
)
extend_qtc_plugin(componentsplugin
- CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ CONDITION ENABLE_COMPILE_WARNING_AS_ERROR
PROPERTIES COMPILE_WARNING_AS_ERROR ON
)
@@ -1141,7 +1141,7 @@ add_qtc_plugin(qmlpreviewplugin
)
extend_qtc_plugin(qmlpreviewplugin
- CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ CONDITION ENABLE_COMPILE_WARNING_AS_ERROR
PROPERTIES COMPILE_WARNING_AS_ERROR ON
)
@@ -1163,7 +1163,7 @@ add_qtc_plugin(qtquickplugin
)
extend_qtc_plugin(qtquickplugin
- CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ CONDITION ENABLE_COMPILE_WARNING_AS_ERROR
PROPERTIES COMPILE_WARNING_AS_ERROR ON
)
diff --git a/src/plugins/qmldesignerbase/CMakeLists.txt b/src/plugins/qmldesignerbase/CMakeLists.txt
index 628403874c..a191b6d43c 100644
--- a/src/plugins/qmldesignerbase/CMakeLists.txt
+++ b/src/plugins/qmldesignerbase/CMakeLists.txt
@@ -1,6 +1,12 @@
-env_with_default("QDS_DISABLE_COMPILE_WARNING_AS_ERROR" ENV_QDS_DISABLE_COMPILE_WARNING_AS_ERROR OFF)
-option(DISABLE_COMPILE_WARNING_AS_ERROR "Dont treat warnings as errors" ${ENV_QDS_DISABLE_COMPILE_WARNING_AS_ERROR})
-add_feature_info("Treat warnings as errors" ${DISABLE_COMPILE_WARNING_AS_ERROR} "")
+if(BUILD_DESIGNSTUDIO AND ($<CONFIG:Debug> OR WITH_TESTS))
+ set(ENABLE_COMPILE_WARNING_AS_ERROR_DEFAULT ON)
+else()
+ set(ENABLE_COMPILE_WARNING_AS_ERROR_DEFAULT OFF)
+endif()
+env_with_default("QDS_ENABLE_COMPILE_WARNING_AS_ERROR" ENV_ENABLE_COMPILE_WARNING_AS_ERROR
+ ${ENABLE_COMPILE_WARNING_AS_ERROR_DEFAULT})
+option(ENABLE_COMPILE_WARNING_AS_ERROR "Treat warnings as errors in QmlDesigner" ${ENV_ENABLE_COMPILE_WARNING_AS_ERROR})
+add_feature_info("Treat warnings as errors in QmlDesigner" ${ENABLE_COMPILE_WARNING_AS_ERROR} "")
add_qtc_plugin(QmlDesignerBase
CONDITION TARGET Qt::QuickWidgets
@@ -12,7 +18,7 @@ add_qtc_plugin(QmlDesignerBase
)
extend_qtc_plugin(QmlDesignerBase
- CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ CONDITION ENABLE_COMPILE_WARNING_AS_ERROR
PROPERTIES COMPILE_WARNING_AS_ERROR ON
)
diff --git a/src/plugins/qmlprojectmanager/CMakeLists.txt b/src/plugins/qmlprojectmanager/CMakeLists.txt
index ad71e3fbff..a1212e8bc1 100644
--- a/src/plugins/qmlprojectmanager/CMakeLists.txt
+++ b/src/plugins/qmlprojectmanager/CMakeLists.txt
@@ -25,7 +25,7 @@ add_qtc_plugin(QmlProjectManager
)
extend_qtc_plugin(QmlProjectManager
- CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ CONDITION ENABLE_COMPILE_WARNING_AS_ERROR
PROPERTIES COMPILE_WARNING_AS_ERROR ON
)
diff --git a/src/plugins/qtsupport/examplesparser.cpp b/src/plugins/qtsupport/examplesparser.cpp
index 84469ca2c4..d115dcf3fe 100644
--- a/src/plugins/qtsupport/examplesparser.cpp
+++ b/src/plugins/qtsupport/examplesparser.cpp
@@ -301,6 +301,21 @@ expected_str<QList<ExampleItem *>> parseExamples(const QByteArray &manifestData,
return items;
}
+// ordered list of "known" categories
+// TODO this should be defined in the manifest
+Q_GLOBAL_STATIC_WITH_ARGS(QList<QString>,
+ defaultOrder,
+ {QStringList() << "Application Examples"
+ << "Desktop"
+ << "Mobile"
+ << "Embedded"
+ << "Graphics"
+ << "Input/Output"
+ << "Connectivity"
+ << "Networking"
+ << "Positioning & Location"
+ << "Internationalization"});
+
static bool sortByHighlightedAndName(ExampleItem *first, ExampleItem *second)
{
if (first->isHighlighted && !second->isHighlighted)
@@ -350,15 +365,20 @@ QList<std::pair<Core::Section, QList<ExampleItem *>>> getCategories(const QList<
} else {
// All original items have been copied into a category or other, delete.
qDeleteAll(items);
+ static const int defaultOrderSize = defaultOrder->size();
int index = 0;
const auto end = categoryMap.constKeyValueEnd();
for (auto it = categoryMap.constKeyValueBegin(); it != end; ++it) {
- categories.append({{it->first, index, /*maxRows=*/index == 0 ? 2 : 1}, it->second});
+ // order "known" categories as wanted, others come afterwards
+ const int defaultIndex = defaultOrder->indexOf(it->first);
+ const int priority = defaultIndex >= 0 ? defaultIndex : (index + defaultOrderSize);
+ categories.append({{it->first, priority, /*maxRows=*/index == 0 ? 2 : 1}, it->second});
++index;
}
if (!other.isEmpty())
- categories.append({{otherDisplayName, index, /*maxRows=*/1}, other});
+ categories.append({{otherDisplayName, index + defaultOrderSize, /*maxRows=*/1}, other});
}
+
const auto end = categories.end();
for (auto it = categories.begin(); it != end; ++it)
sort(it->second, sortByHighlightedAndName);
diff --git a/tests/auto/qml/codemodel/check/accessById.qml b/tests/auto/qml/codemodel/check/accessById.qml
new file mode 100644
index 0000000000..dd91ac671e
--- /dev/null
+++ b/tests/auto/qml/codemodel/check/accessById.qml
@@ -0,0 +1,39 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Window
+
+Window {
+ id: root
+ width: 640
+ height: 480
+ visible: true
+ title: qsTr("Hello World")
+
+ Rectangle {
+ id: rect
+
+ Rectangle {
+ id: innerRect
+ }
+ }
+
+ Text {
+ id: myText
+ width: 50
+ wrapMode: Text.WordWrap
+ text: "a text string that is longer than 50 pixels"
+
+ Text {
+ id: innerText
+ }
+ states: State {
+ name: "widerText"
+ PropertyChanges { myText.width: undefined }
+ AnchorChanges { innerRect.width: undefined } // 16 29 37
+ }
+ }
+
+ Binding {rect.width: innerText.width}
+}