QmlDesigner: Add project storage error mechanism

Task-number: QDS-12761
Change-Id: If782b5d81b53979033e2738292dedac91e1adcbf
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2024-05-15 15:33:10 +02:00
parent f296f9d77c
commit d345254579
16 changed files with 174 additions and 78 deletions

View File

@@ -465,6 +465,8 @@ extend_qtc_library(QmlDesignerCore
projectstoragetypes.h
projectstorageupdater.cpp projectstorageupdater.h
projectstorage.cpp projectstorage.h
projectstorageerrornotifierinterface.h
projectstorageerrornotifier.cpp projectstorageerrornotifier.h
sourcepath.h
sourcepathcache.h
sourcepathcacheinterface.h

View File

@@ -1127,8 +1127,11 @@ public:
}
};
ProjectStorage::ProjectStorage(Database &database, bool isInitialized)
ProjectStorage::ProjectStorage(Database &database,
ProjectStorageErrorNotifierInterface &errorNotifier,
bool isInitialized)
: database{database}
, errorNotifier{errorNotifier}
, exclusiveTransaction{database}
, initializer{std::make_unique<ProjectStorage::Initializer>(database, isInitialized)}
, moduleCache{ModuleStorageAdapter{*this}}

View File

@@ -4,6 +4,7 @@
#pragma once
#include "commontypecache.h"
#include "projectstorageerrornotifier.h"
#include "projectstorageexceptions.h"
#include "projectstorageinterface.h"
#include "projectstoragetypes.h"
@@ -39,7 +40,9 @@ class ProjectStorage final : public ProjectStorageInterface
friend Storage::Info::CommonTypeCache<ProjectStorageType>;
public:
ProjectStorage(Database &database, bool isInitialized);
ProjectStorage(Database &database,
ProjectStorageErrorNotifierInterface &errorNotifier,
bool isInitialized);
~ProjectStorage();
void synchronize(Storage::Synchronization::SynchronizationPackage package) override;
@@ -967,6 +970,7 @@ private:
public:
Database &database;
ProjectStorageErrorNotifierInterface &errorNotifier;
Sqlite::ExclusiveNonThrowingDestructorTransaction<Database> exclusiveTransaction;
std::unique_ptr<Initializer> initializer;
mutable ModuleCache moduleCache{ModuleStorageAdapter{*this}};

View File

@@ -0,0 +1,17 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "projectstorageerrornotifier.h"
#include "sourcepathcache.h"
namespace QmlDesigner {
void ProjectStorageErrorNotifier::typeNameCannotBeResolved(Utils::SmallStringView typeName,
SourceId sourceId)
{
qDebug() << "Missing type name: " << typeName
<< " in file: " << m_pathCache.sourcePath(sourceId).toStringView();
}
} // namespace QmlDesigner

View File

@@ -0,0 +1,25 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include "projectstorageerrornotifierinterface.h"
#include <modelfwd.h>
namespace QmlDesigner {
class ProjectStorageErrorNotifier final : public ProjectStorageErrorNotifierInterface
{
public:
ProjectStorageErrorNotifier(PathCacheType &pathCache)
: m_pathCache{pathCache}
{}
void typeNameCannotBeResolved(Utils::SmallStringView typeName, SourceId souceId) override;
private:
PathCacheType &m_pathCache;
};
} // namespace QmlDesigner

View File

@@ -0,0 +1,27 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include "projectstorageids.h"
#include <utils/smallstringview.h>
namespace QmlDesigner {
class ProjectStorageErrorNotifierInterface
{
public:
ProjectStorageErrorNotifierInterface() = default;
ProjectStorageErrorNotifierInterface(ProjectStorageErrorNotifierInterface &&) = default;
ProjectStorageErrorNotifierInterface &operator=(ProjectStorageErrorNotifierInterface &&) = default;
ProjectStorageErrorNotifierInterface(const ProjectStorageErrorNotifierInterface &) = delete;
ProjectStorageErrorNotifierInterface &operator=(const ProjectStorageErrorNotifierInterface &) = delete;
virtual void typeNameCannotBeResolved(Utils::SmallStringView typeName, SourceId souceId) = 0;
protected:
~ProjectStorageErrorNotifierInterface() = default;
};
} // namespace QmlDesigner

View File

@@ -12,15 +12,16 @@
#include <projectstorage/filesystem.h>
#include <projectstorage/nonlockingmutex.h>
#include <projectstorage/projectstorage.h>
#include <projectstorage/projectstorageerrornotifier.h>
#include <projectstorage/projectstoragepathwatcher.h>
#include <projectstorage/projectstorageupdater.h>
#include <projectstorage/qmldocumentparser.h>
#include <projectstorage/qmltypesparser.h>
#include <projectstorage/sourcepathcache.h>
#include <sqlitedatabase.h>
#include <qmlprojectmanager/qmlproject.h>
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitaspect.h>
#include <sqlitedatabase.h>
#include <asynchronousexplicitimagecache.h>
#include <asynchronousimagecache.h>
@@ -181,7 +182,8 @@ public:
pathCache.sourceId(SourcePath{project->projectDirectory().toString() + "/."}).internalId())}
{}
Sqlite::Database database;
ProjectStorage storage{database, database.isInitialized()};
ProjectStorageErrorNotifier errorNotifier{pathCache};
ProjectStorage storage{database, errorNotifier, database.isInitialized()};
PathCacheType pathCache{storage};
FileSystem fileSystem{pathCache};
FileStatusCache fileStatusCache{fileSystem};

View File

@@ -22,6 +22,7 @@ add_qtc_library(TestMocks OBJECT
mocktimestampprovider.h
modelresourcemanagementmock.h
propertycomponentgeneratormock.h
projectstorageerrornotifiermock.h
projectstoragemock.cpp
projectstoragemock.h
projectstorageobservermock.h

View File

@@ -0,0 +1,16 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include "../utils/googletest.h"
#include <projectstorage/projectstorageerrornotifierinterface.h>
class ProjectStorageErrorNotifierMock : public QmlDesigner::ProjectStorageErrorNotifierInterface
{
MOCK_METHOD(void,
typeNameCannotBeResolved,
(Utils::SmallStringView typeName, QmlDesigner::SourceId souceId),
(override));
};

View File

@@ -125,6 +125,8 @@ add_qtc_library(TestDesignerCore OBJECT
projectstorage/projectstorageinterface.h
projectstorage/projectstorageobserver.h
projectstorage/projectstorage.cpp projectstorage/projectstorage.h
projectstorage/projectstorageerrornotifierinterface.h
projectstorage/projectstorageerrornotifier.cpp projectstorage/projectstorageerrornotifier.h
projectstorage/projectstoragepathwatcher.h
projectstorage/projectstoragepathwatcherinterface.h
projectstorage/projectstoragepathwatchernotifierinterface.h

View File

@@ -5,7 +5,8 @@
#include <matchers/info_exportedtypenames-matcher.h>
#include <matchers/projectstorage-matcher.h>
#include <mocks/projectstorageobservermock.h>
#include <projectstorageerrornotifiermock.h>
#include <projectstorageobservermock.h>
#include <modelnode.h>
#include <projectstorage/projectstorage.h>
@@ -274,21 +275,18 @@ MATCHER_P2(IsInfoType,
class ProjectStorage : public testing::Test
{
protected:
static void SetUpTestSuite()
struct StaticData
{
static_database = std::make_unique<Sqlite::Database>(":memory:", Sqlite::JournalMode::Memory);
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
NiceMock<ProjectStorageErrorNotifierMock> errorNotifierMock;
QmlDesigner::ProjectStorage storage{database, errorNotifierMock, database.isInitialized()};
};
static_projectStorage = std::make_unique<QmlDesigner::ProjectStorage>(
*static_database, static_database->isInitialized());
}
static void SetUpTestSuite() { staticData = std::make_unique<StaticData>(); }
static void TearDownTestSuite()
{
static_projectStorage.reset();
static_database.reset();
}
static void TearDownTestSuite() { staticData.reset(); }
~ProjectStorage() { static_projectStorage->resetForTestsOnly(); }
~ProjectStorage() { storage.resetForTestsOnly(); }
template<typename Range>
static auto toValues(Range &&range)
@@ -1141,12 +1139,11 @@ protected:
}
protected:
inline static std::unique_ptr<Sqlite::Database> static_database;
Sqlite::Database &database = *static_database;
inline static std::unique_ptr<QmlDesigner::ProjectStorage> static_projectStorage;
QmlDesigner::ProjectStorage &storage = *static_projectStorage;
QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage> sourcePathCache{
storage};
inline static std::unique_ptr<StaticData> staticData;
Sqlite::Database &database = staticData->database;
QmlDesigner::ProjectStorage &storage = staticData->storage;
ProjectStorageErrorNotifierMock &errorNotifierMock = staticData->errorNotifierMock;
QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage> sourcePathCache{storage};
QmlDesigner::SourcePathView path1{"/path1/to"};
QmlDesigner::SourcePathView path2{"/path2/to"};
QmlDesigner::SourcePathView path3{"/path3/to"};
@@ -5118,7 +5115,7 @@ TEST_F(ProjectStorage, populate_module_cache)
{
auto id = storage.moduleId("Qml", ModuleKind::QmlLibrary);
QmlDesigner::ProjectStorage newStorage{database, database.isInitialized()};
QmlDesigner::ProjectStorage newStorage{database, errorNotifierMock, database.isInitialized()};
ASSERT_THAT(newStorage.module(id), IsModule("Qml", ModuleKind::QmlLibrary));
}

View File

@@ -3,10 +3,11 @@
#include "../utils/googletest.h"
#include "../mocks/filesystemmock.h"
#include "../mocks/mockqfilesystemwatcher.h"
#include "../mocks/mocktimer.h"
#include "../mocks/projectstoragepathwatchernotifiermock.h"
#include <filesystemmock.h>
#include <mockqfilesystemwatcher.h>
#include <mocktimer.h>
#include <projectstorageerrornotifiermock.h>
#include <projectstoragepathwatchernotifiermock.h>
#include <projectstorage/projectstorage.h>
#include <projectstorage/projectstoragepathwatcher.h>
@@ -39,21 +40,18 @@ using QmlDesigner::WatcherEntry;
class ProjectStoragePathWatcher : public testing::Test
{
protected:
static void SetUpTestSuite()
struct StaticData
{
static_database = std::make_unique<Sqlite::Database>(":memory:", Sqlite::JournalMode::Memory);
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ProjectStorageErrorNotifierMock errorNotifierMock;
QmlDesigner::ProjectStorage storage{database, errorNotifierMock, database.isInitialized()};
};
static_projectStorage = std::make_unique<QmlDesigner::ProjectStorage>(
*static_database, static_database->isInitialized());
}
static void SetUpTestSuite() { staticData = std::make_unique<StaticData>(); }
static void TearDownTestSuite()
{
static_projectStorage.reset();
static_database.reset();
}
static void TearDownTestSuite() { staticData.reset(); }
~ProjectStoragePathWatcher() { static_projectStorage->resetForTestsOnly(); }
~ProjectStoragePathWatcher() { storage.resetForTestsOnly(); }
ProjectStoragePathWatcher()
{
@@ -79,10 +77,9 @@ protected:
protected:
NiceMock<ProjectStoragePathWatcherNotifierMock> notifier;
NiceMock<FileSystemMock> mockFileSystem;
inline static std::unique_ptr<Sqlite::Database> static_database;
Sqlite::Database &database = *static_database;
inline static std::unique_ptr<QmlDesigner::ProjectStorage> static_projectStorage;
QmlDesigner::ProjectStorage &storage = *static_projectStorage;
inline static std::unique_ptr<StaticData> staticData;
Sqlite::Database &database = staticData->database;
QmlDesigner::ProjectStorage &storage = staticData->storage;
SourcePathCache pathCache{storage};
Watcher watcher{pathCache, mockFileSystem, &notifier};
NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher();

View File

@@ -3,11 +3,12 @@
#include "../utils/googletest.h"
#include "../mocks/filesystemmock.h"
#include "../mocks/projectstoragemock.h"
#include "../mocks/projectstoragepathwatchermock.h"
#include "../mocks/qmldocumentparsermock.h"
#include "../mocks/qmltypesparsermock.h"
#include <filesystemmock.h>
#include <projectstorageerrornotifiermock.h>
#include <projectstoragemock.h>
#include <projectstoragepathwatchermock.h>
#include <qmldocumentparsermock.h>
#include <qmltypesparsermock.h>
#include <projectstorage-matcher.h>
@@ -142,19 +143,16 @@ auto IsPropertyEditorQmlPath(const ModuleIdMatcher &moduleIdMatcher,
class ProjectStorageUpdater : public testing::Test
{
public:
static void SetUpTestSuite()
struct StaticData
{
static_database = std::make_unique<Sqlite::Database>(":memory:", Sqlite::JournalMode::Memory);
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
NiceMock<ProjectStorageErrorNotifierMock> errorNotifierMock;
QmlDesigner::ProjectStorage storage{database, errorNotifierMock, database.isInitialized()};
};
static_projectStorage = std::make_unique<QmlDesigner::ProjectStorage>(
*static_database, static_database->isInitialized());
}
static void SetUpTestSuite() { staticData = std::make_unique<StaticData>(); }
static void TearDownTestSuite()
{
static_projectStorage.reset();
static_database.reset();
}
static void TearDownTestSuite() { staticData.reset(); }
ProjectStorageUpdater()
{
@@ -228,7 +226,7 @@ public:
});
}
~ProjectStorageUpdater() { static_projectStorage->resetForTestsOnly(); }
~ProjectStorageUpdater() { storage.resetForTestsOnly(); }
void setFilesDontChanged(const QmlDesigner::SourceIds &sourceIds)
{
@@ -327,10 +325,9 @@ protected:
NiceMock<QmlTypesParserMock> qmlTypesParserMock;
NiceMock<QmlDocumentParserMock> qmlDocumentParserMock;
QmlDesigner::FileStatusCache fileStatusCache{fileSystemMock};
inline static std::unique_ptr<Sqlite::Database> static_database;
Sqlite::Database &database = *static_database;
inline static std::unique_ptr<QmlDesigner::ProjectStorage> static_projectStorage;
QmlDesigner::ProjectStorage &storage = *static_projectStorage;
inline static std::unique_ptr<StaticData> staticData;
Sqlite::Database &database = staticData->database;
QmlDesigner::ProjectStorage &storage = staticData->storage;
QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage> sourcePathCache{
storage};
NiceMock<ProjectStoragePathWatcherMock> patchWatcherMock;

View File

@@ -3,6 +3,8 @@
#include "../utils/googletest.h"
#include <projectstorageerrornotifiermock.h>
#include <sqlitedatabase.h>
#include <projectstorage/projectstorage.h>
@@ -144,7 +146,8 @@ class QmlDocumentParser : public ::testing::Test
public:
protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
QmlDesigner::ProjectStorage storage{database, database.isInitialized()};
ProjectStorageErrorNotifierMock errorNotifierMock;
QmlDesigner::ProjectStorage storage{database, errorNotifierMock, database.isInitialized()};
QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage> sourcePathCache{
storage};
QmlDesigner::QmlDocumentParser parser{storage, sourcePathCache};

View File

@@ -3,6 +3,8 @@
#include "../utils/googletest.h"
#include <projectstorageerrornotifiermock.h>
#include <sqlitedatabase.h>
#include <projectstorage/projectstorage.h>
@@ -169,7 +171,8 @@ class QmlTypesParser : public ::testing::Test
public:
protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
QmlDesigner::ProjectStorage storage{database, database.isInitialized()};
ProjectStorageErrorNotifierMock errorNotifierMock;
QmlDesigner::ProjectStorage storage{database, errorNotifierMock, database.isInitialized()};
QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage> sourcePathCache{
storage};
QmlDesigner::QmlTypesParser parser{storage};

View File

@@ -4,6 +4,7 @@
#include "../utils/googletest.h"
#include <projectstorage-matcher.h>
#include <projectstorageerrornotifiermock.h>
#include <strippedstring-matcher.h>
#include <projectstorage/projectstorage.h>
@@ -26,19 +27,19 @@ protected:
traits.hasFormEditorItem = FlagIs::True;
traits.visibleInLibrary = FlagIs::True;
}
static void SetUpTestSuite()
{
static_database = std::make_unique<Sqlite::Database>(":memory:", Sqlite::JournalMode::Memory);
static_projectStorage = std::make_unique<QmlDesigner::ProjectStorage>(
*static_database, static_database->isInitialized());
}
~TypeAnnotationReader() { storage.resetForTestsOnly(); }
static void TearDownTestSuite()
struct StaticData
{
static_projectStorage.reset();
static_database.reset();
}
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ProjectStorageErrorNotifierMock errorNotifierMock;
QmlDesigner::ProjectStorage storage{database, errorNotifierMock, database.isInitialized()};
};
static void SetUpTestSuite() { staticData = std::make_unique<StaticData>(); }
static void TearDownTestSuite() { staticData.reset(); }
auto moduleId(Utils::SmallStringView name) const
{
@@ -46,10 +47,9 @@ protected:
}
protected:
inline static std::unique_ptr<Sqlite::Database> static_database;
Sqlite::Database &database = *static_database;
inline static std::unique_ptr<QmlDesigner::ProjectStorage> static_projectStorage;
QmlDesigner::ProjectStorage &storage = *static_projectStorage;
inline static std::unique_ptr<StaticData> staticData;
Sqlite::Database &database = staticData->database;
QmlDesigner::ProjectStorage &storage = staticData->storage;
QmlDesigner::Storage::TypeAnnotationReader reader{storage};
QmlDesigner::SourceId sourceId = QmlDesigner::SourceId::create(33);
QmlDesigner::SourceId directorySourceId = QmlDesigner::SourceId::create(77);