QmlDesigner: Trace project storage exceptions

Change-Id: I58c261bea4cca6c5bede0d2ad504be8bc687ddc6
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2024-03-18 12:23:42 +01:00
parent 99def2c337
commit 26870406cd
7 changed files with 170 additions and 35 deletions

View File

@@ -3,22 +3,6 @@
#include "projectstorage.h" #include "projectstorage.h"
#include <tracing/qmldesignertracing.h>
#include <sqlitedatabase.h> #include <sqlitedatabase.h>
namespace QmlDesigner {
NanotraceHR::StringViewWithStringArgumentsCategory<projectStorageTracingStatus()> &projectStorageCategory()
{
thread_local NanotraceHR::StringViewWithStringArgumentsCategory<projectStorageTracingStatus()>
projectStorageCategory_{"project storage"_t,
Tracing::eventQueueWithStringArguments(),
projectStorageCategory};
return projectStorageCategory_;
}
} // namespace QmlDesigner
template class QmlDesigner::ProjectStorage<Sqlite::Database>; template class QmlDesigner::ProjectStorage<Sqlite::Database>;

View File

@@ -9,6 +9,8 @@
#include "sourcepathcachetypes.h" #include "sourcepathcachetypes.h"
#include "storagecache.h" #include "storagecache.h"
#include <tracing/qmldesignertracing.h>
#include <sqlitealgorithms.h> #include <sqlitealgorithms.h>
#include <sqlitedatabase.h> #include <sqlitedatabase.h>
#include <sqlitetable.h> #include <sqlitetable.h>
@@ -28,17 +30,7 @@ namespace QmlDesigner {
using namespace NanotraceHR::Literals; using namespace NanotraceHR::Literals;
constexpr NanotraceHR::Tracing projectStorageTracingStatus() using ProjectStorageTracing::projectStorageCategory;
{
#ifdef ENABLE_PROJECT_STORAGE_TRACING
return NanotraceHR::Tracing::IsEnabled;
#else
return NanotraceHR::Tracing::IsDisabled;
#endif
}
[[gnu::pure]] NanotraceHR::StringViewWithStringArgumentsCategory<projectStorageTracingStatus()> &
projectStorageCategory();
template<typename Database> template<typename Database>
class ProjectStorage final : public ProjectStorageInterface class ProjectStorage final : public ProjectStorageInterface

View File

@@ -3,38 +3,85 @@
#include "projectstorageexceptions.h" #include "projectstorageexceptions.h"
#include <tracing/qmldesignertracing.h>
namespace QmlDesigner { namespace QmlDesigner {
using namespace NanotraceHR::Literals;
using NanotraceHR::keyValue;
namespace {
auto &category()
{
return ProjectStorageTracing::projectStorageCategory();
}
} // namespace
NoSourcePathForInvalidSourceId::NoSourcePathForInvalidSourceId()
{
category().threadEvent("NoSourcePathForInvalidSourceId"_t);
}
const char *NoSourcePathForInvalidSourceId::what() const noexcept const char *NoSourcePathForInvalidSourceId::what() const noexcept
{ {
return "You cannot get a file path for an invalid file path id!"; return "You cannot get a file path for an invalid file path id!";
} }
NoSourceContextPathForInvalidSourceContextId::NoSourceContextPathForInvalidSourceContextId()
{
category().threadEvent("NoSourceContextPathForInvalidSourceContextId"_t);
}
const char *NoSourceContextPathForInvalidSourceContextId::what() const noexcept const char *NoSourceContextPathForInvalidSourceContextId::what() const noexcept
{ {
return "You cannot get a directory path for an invalid directory path id!"; return "You cannot get a directory path for an invalid directory path id!";
} }
SourceContextIdDoesNotExists::SourceContextIdDoesNotExists()
{
category().threadEvent("SourceContextIdDoesNotExists"_t);
}
const char *SourceContextIdDoesNotExists::what() const noexcept const char *SourceContextIdDoesNotExists::what() const noexcept
{ {
return "The source context id does not exist in the database!"; return "The source context id does not exist in the database!";
} }
SourceIdDoesNotExists::SourceIdDoesNotExists()
{
category().threadEvent("SourceIdDoesNotExists"_t);
}
const char *SourceIdDoesNotExists::what() const noexcept const char *SourceIdDoesNotExists::what() const noexcept
{ {
return "The source id does not exist in the database!"; return "The source id does not exist in the database!";
} }
TypeHasInvalidSourceId::TypeHasInvalidSourceId()
{
category().threadEvent("TypeHasInvalidSourceId"_t);
}
const char *TypeHasInvalidSourceId::what() const noexcept const char *TypeHasInvalidSourceId::what() const noexcept
{ {
return "The source id is invalid!"; return "The source id is invalid!";
} }
ModuleDoesNotExists::ModuleDoesNotExists()
{
category().threadEvent("ModuleDoesNotExists"_t);
}
const char *ModuleDoesNotExists::what() const noexcept const char *ModuleDoesNotExists::what() const noexcept
{ {
return "The module does not exist!"; return "The module does not exist!";
} }
ModuleAlreadyExists::ModuleAlreadyExists()
{
category().threadEvent("ModuleAlreadyExists"_t);
}
const char *ModuleAlreadyExists::what() const noexcept const char *ModuleAlreadyExists::what() const noexcept
{ {
return "The module does already exist!"; return "The module does already exist!";
@@ -45,48 +92,97 @@ TypeNameDoesNotExists::TypeNameDoesNotExists(std::string_view typeName, SourceId
"TypeNameDoesNotExists"sv, "TypeNameDoesNotExists"sv,
Utils::SmallString::join( Utils::SmallString::join(
{"type: ", typeName, ", source id: ", Utils::SmallString::number(sourceId.internalId())})} {"type: ", typeName, ", source id: ", Utils::SmallString::number(sourceId.internalId())})}
{} {
category().threadEvent("TypeNameDoesNotExists"_t,
keyValue("type name", typeName),
keyValue("source id", sourceId));
}
PropertyNameDoesNotExists::PropertyNameDoesNotExists()
{
category().threadEvent("PropertyNameDoesNotExists"_t);
}
const char *PropertyNameDoesNotExists::what() const noexcept const char *PropertyNameDoesNotExists::what() const noexcept
{ {
return "The property name does not exist!"; return "The property name does not exist!";
} }
PrototypeChainCycle::PrototypeChainCycle()
{
category().threadEvent("PrototypeChainCycle"_t);
}
const char *PrototypeChainCycle::what() const noexcept const char *PrototypeChainCycle::what() const noexcept
{ {
return "There is a prototype chain cycle!"; return "There is a prototype chain cycle!";
} }
AliasChainCycle::AliasChainCycle()
{
category().threadEvent("AliasChainCycle"_t);
}
const char *AliasChainCycle::what() const noexcept const char *AliasChainCycle::what() const noexcept
{ {
return "There is a prototype chain cycle!"; return "There is a prototype chain cycle!";
} }
CannotParseQmlTypesFile::CannotParseQmlTypesFile()
{
category().threadEvent("CannotParseQmlTypesFile"_t);
}
const char *CannotParseQmlTypesFile::what() const noexcept const char *CannotParseQmlTypesFile::what() const noexcept
{ {
return "Cannot parse qml types file!"; return "Cannot parse qml types file!";
} }
CannotParseQmlDocumentFile::CannotParseQmlDocumentFile()
{
category().threadEvent("CannotParseQmlDocumentFile"_t);
}
const char *CannotParseQmlDocumentFile::what() const noexcept const char *CannotParseQmlDocumentFile::what() const noexcept
{ {
return "Cannot parse qml types file!"; return "Cannot parse qml types file!";
} }
ProjectDataHasInvalidProjectSourceId::ProjectDataHasInvalidProjectSourceId()
{
category().threadEvent("ProjectDataHasInvalidProjectSourceId"_t);
}
const char *ProjectDataHasInvalidProjectSourceId::what() const noexcept const char *ProjectDataHasInvalidProjectSourceId::what() const noexcept
{ {
return "The project source id is invalid!"; return "The project source id is invalid!";
} }
ProjectDataHasInvalidSourceId::ProjectDataHasInvalidSourceId()
{
category().threadEvent("ProjectDataHasInvalidSourceId"_t);
}
const char *ProjectDataHasInvalidSourceId::what() const noexcept const char *ProjectDataHasInvalidSourceId::what() const noexcept
{ {
return "The source id is invalid!"; return "The source id is invalid!";
} }
ProjectDataHasInvalidModuleId::ProjectDataHasInvalidModuleId()
{
category().threadEvent("ProjectDataHasInvalidModuleId"_t);
}
const char *ProjectDataHasInvalidModuleId::what() const noexcept const char *ProjectDataHasInvalidModuleId::what() const noexcept
{ {
return "The module id is invalid!"; return "The module id is invalid!";
} }
FileStatusHasInvalidSourceId::FileStatusHasInvalidSourceId()
{
category().threadEvent("FileStatusHasInvalidSourceId"_t);
}
const char *FileStatusHasInvalidSourceId::what() const noexcept const char *FileStatusHasInvalidSourceId::what() const noexcept
{ {
return "The source id in file status is invalid!"; return "The source id in file status is invalid!";
@@ -113,7 +209,14 @@ const char *ProjectStorageErrorWithMessage::what() const noexcept
ExportedTypeCannotBeInserted::ExportedTypeCannotBeInserted(std::string_view errorMessage) ExportedTypeCannotBeInserted::ExportedTypeCannotBeInserted(std::string_view errorMessage)
: ProjectStorageErrorWithMessage{"ExportedTypeCannotBeInserted"sv, errorMessage} : ProjectStorageErrorWithMessage{"ExportedTypeCannotBeInserted"sv, errorMessage}
{} {
category().threadEvent("ExportedTypeCannotBeInserted"_t, keyValue("error message", errorMessage));
}
TypeAnnotationHasInvalidSourceId::TypeAnnotationHasInvalidSourceId()
{
category().threadEvent("TypeAnnotationHasInvalidSourceId"_t);
}
const char *TypeAnnotationHasInvalidSourceId::what() const noexcept const char *TypeAnnotationHasInvalidSourceId::what() const noexcept
{ {

View File

@@ -15,15 +15,19 @@ using namespace std::literals::string_view_literals;
class QMLDESIGNERCORE_EXPORT ProjectStorageError : public std::exception class QMLDESIGNERCORE_EXPORT ProjectStorageError : public std::exception
{ {
protected:
ProjectStorageError() = default;
public: public:
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class ProjectStorageErrorWithMessage : public ProjectStorageError class ProjectStorageErrorWithMessage : public ProjectStorageError
{ {
public: protected:
ProjectStorageErrorWithMessage(std::string_view error, std::string_view errorMessage); ProjectStorageErrorWithMessage(std::string_view error, std::string_view errorMessage);
public:
const char *what() const noexcept override; const char *what() const noexcept override;
public: public:
@@ -33,42 +37,49 @@ public:
class QMLDESIGNERCORE_EXPORT NoSourcePathForInvalidSourceId : public ProjectStorageError class QMLDESIGNERCORE_EXPORT NoSourcePathForInvalidSourceId : public ProjectStorageError
{ {
public: public:
NoSourcePathForInvalidSourceId();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT NoSourceContextPathForInvalidSourceContextId : public ProjectStorageError class QMLDESIGNERCORE_EXPORT NoSourceContextPathForInvalidSourceContextId : public ProjectStorageError
{ {
public: public:
NoSourceContextPathForInvalidSourceContextId();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT SourceContextIdDoesNotExists : public ProjectStorageError class QMLDESIGNERCORE_EXPORT SourceContextIdDoesNotExists : public ProjectStorageError
{ {
public: public:
SourceContextIdDoesNotExists();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT SourceIdDoesNotExists : public ProjectStorageError class QMLDESIGNERCORE_EXPORT SourceIdDoesNotExists : public ProjectStorageError
{ {
public: public:
SourceIdDoesNotExists();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT TypeHasInvalidSourceId : public ProjectStorageError class QMLDESIGNERCORE_EXPORT TypeHasInvalidSourceId : public ProjectStorageError
{ {
public: public:
TypeHasInvalidSourceId();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT ModuleDoesNotExists : public ProjectStorageError class QMLDESIGNERCORE_EXPORT ModuleDoesNotExists : public ProjectStorageError
{ {
public: public:
ModuleDoesNotExists();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT ModuleAlreadyExists : public ProjectStorageError class QMLDESIGNERCORE_EXPORT ModuleAlreadyExists : public ProjectStorageError
{ {
public: public:
ModuleAlreadyExists();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
@@ -87,60 +98,70 @@ public:
class QMLDESIGNERCORE_EXPORT PropertyNameDoesNotExists : public ProjectStorageError class QMLDESIGNERCORE_EXPORT PropertyNameDoesNotExists : public ProjectStorageError
{ {
public: public:
PropertyNameDoesNotExists();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT PrototypeChainCycle : public ProjectStorageError class QMLDESIGNERCORE_EXPORT PrototypeChainCycle : public ProjectStorageError
{ {
public: public:
PrototypeChainCycle();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT AliasChainCycle : public ProjectStorageError class QMLDESIGNERCORE_EXPORT AliasChainCycle : public ProjectStorageError
{ {
public: public:
AliasChainCycle();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT CannotParseQmlTypesFile : public ProjectStorageError class QMLDESIGNERCORE_EXPORT CannotParseQmlTypesFile : public ProjectStorageError
{ {
public: public:
CannotParseQmlTypesFile();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT CannotParseQmlDocumentFile : public ProjectStorageError class QMLDESIGNERCORE_EXPORT CannotParseQmlDocumentFile : public ProjectStorageError
{ {
public: public:
CannotParseQmlDocumentFile();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidProjectSourceId : public ProjectStorageError class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidProjectSourceId : public ProjectStorageError
{ {
public: public:
ProjectDataHasInvalidProjectSourceId();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidSourceId : public ProjectStorageError class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidSourceId : public ProjectStorageError
{ {
public: public:
ProjectDataHasInvalidSourceId();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidModuleId : public ProjectStorageError class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidModuleId : public ProjectStorageError
{ {
public: public:
ProjectDataHasInvalidModuleId();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT FileStatusHasInvalidSourceId : public ProjectStorageError class QMLDESIGNERCORE_EXPORT FileStatusHasInvalidSourceId : public ProjectStorageError
{ {
public: public:
FileStatusHasInvalidSourceId();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class QMLDESIGNERCORE_EXPORT TypeAnnotationHasInvalidSourceId : public ProjectStorageError class QMLDESIGNERCORE_EXPORT TypeAnnotationHasInvalidSourceId : public ProjectStorageError
{ {
public: public:
TypeAnnotationHasInvalidSourceId();
const char *what() const noexcept override; const char *what() const noexcept override;
}; };

View File

@@ -6,6 +6,9 @@
#include <sqlitebasestatement.h> #include <sqlitebasestatement.h>
namespace QmlDesigner { namespace QmlDesigner {
using namespace NanotraceHR::Literals;
namespace Tracing { namespace Tracing {
namespace { namespace {
@@ -51,7 +54,6 @@ StringEventQueue &stringEventQueue()
namespace ModelTracing { namespace ModelTracing {
namespace { namespace {
using namespace NanotraceHR::Literals;
thread_local Category category_{"model"_t, Tracing::stringEventQueue(), category}; thread_local Category category_{"model"_t, Tracing::stringEventQueue(), category};
@@ -63,4 +65,19 @@ Category &category()
} }
} // namespace ModelTracing } // namespace ModelTracing
namespace ProjectStorageTracing {
NanotraceHR::StringViewWithStringArgumentsCategory<projectStorageTracingStatus()> &projectStorageCategory()
{
thread_local NanotraceHR::StringViewWithStringArgumentsCategory<projectStorageTracingStatus()>
projectStorageCategory_{"project storage"_t,
Tracing::eventQueueWithStringArguments(),
projectStorageCategory};
return projectStorageCategory_;
}
} // namespace ProjectStorageTracing
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -44,4 +44,18 @@ using AsynchronousToken = Category::AsynchronousTokenType;
[[gnu::pure]] QMLDESIGNERCORE_EXPORT Category &category(); [[gnu::pure]] QMLDESIGNERCORE_EXPORT Category &category();
} // namespace ModelTracing } // namespace ModelTracing
namespace ProjectStorageTracing {
constexpr NanotraceHR::Tracing projectStorageTracingStatus()
{
#ifdef ENABLE_PROJECT_STORAGE_TRACING
return NanotraceHR::Tracing::IsEnabled;
#else
return NanotraceHR::Tracing::IsDisabled;
#endif
}
[[gnu::pure]] NanotraceHR::StringViewWithStringArgumentsCategory<projectStorageTracingStatus()> &
projectStorageCategory();
} // namespace ProjectStorageTracing
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -3210,7 +3210,8 @@ TEST_F(ProjectStorageUpdater, errors_for_watcher_updates_are_handled)
SecondType 2.2 Second.qml)"}; SecondType 2.2 Second.qml)"};
setContent(u"/path/qmldir", qmldir); setContent(u"/path/qmldir", qmldir);
ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Throw(QmlDesigner::ProjectStorageError{})); ON_CALL(projectStorageMock, synchronize(_))
.WillByDefault(Throw(QmlDesigner::NoSourcePathForInvalidSourceId{}));
ASSERT_NO_THROW(updater.pathsWithIdsChanged({{directoryProjectChunkId, {directoryPathSourceId}}})); ASSERT_NO_THROW(updater.pathsWithIdsChanged({{directoryProjectChunkId, {directoryPathSourceId}}}));
} }
@@ -3227,7 +3228,8 @@ TEST_F(ProjectStorageUpdater, input_is_reused_next_call_if_an_error_happens)
{{directoryPathSourceId, qmltypesPathSourceId, exampleModuleId, FileType::QmlTypes}, {{directoryPathSourceId, qmltypesPathSourceId, exampleModuleId, FileType::QmlTypes},
{directoryPathSourceId, qmltypes2PathSourceId, exampleModuleId, FileType::QmlTypes}}); {directoryPathSourceId, qmltypes2PathSourceId, exampleModuleId, FileType::QmlTypes}});
setFilesDontChanged({directoryPathSourceId, qmlDirPathSourceId}); setFilesDontChanged({directoryPathSourceId, qmlDirPathSourceId});
ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Throw(QmlDesigner::ProjectStorageError{})); ON_CALL(projectStorageMock, synchronize(_))
.WillByDefault(Throw(QmlDesigner::NoSourcePathForInvalidSourceId{}));
updater.pathsWithIdsChanged( updater.pathsWithIdsChanged(
{{qmltypesProjectChunkId, {qmltypesPathSourceId, qmltypes2PathSourceId}}}); {{qmltypesProjectChunkId, {qmltypesPathSourceId, qmltypes2PathSourceId}}});
ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Return()); ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Return());
@@ -3286,7 +3288,8 @@ TEST_F(ProjectStorageUpdater, input_is_reused_next_call_if_an_error_happens_and_
{{directoryPathSourceId, qmltypesPathSourceId, exampleModuleId, FileType::QmlTypes}, {{directoryPathSourceId, qmltypesPathSourceId, exampleModuleId, FileType::QmlTypes},
{directoryPathSourceId, qmltypes2PathSourceId, exampleModuleId, FileType::QmlTypes}}); {directoryPathSourceId, qmltypes2PathSourceId, exampleModuleId, FileType::QmlTypes}});
setFilesDontChanged({directoryPathSourceId, qmlDirPathSourceId}); setFilesDontChanged({directoryPathSourceId, qmlDirPathSourceId});
ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Throw(QmlDesigner::ProjectStorageError{})); ON_CALL(projectStorageMock, synchronize(_))
.WillByDefault(Throw(QmlDesigner::NoSourcePathForInvalidSourceId{}));
updater.pathsWithIdsChanged( updater.pathsWithIdsChanged(
{{qmltypesProjectChunkId, {qmltypesPathSourceId, qmltypes2PathSourceId}}}); {{qmltypesProjectChunkId, {qmltypesPathSourceId, qmltypes2PathSourceId}}});
ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Return()); ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Return());
@@ -3348,7 +3351,8 @@ TEST_F(ProjectStorageUpdater, input_is_reused_next_call_if_an_error_happens_and_
{directoryPathSourceId, qmlDocumentSourceId1, QmlDesigner::ModuleId{}, FileType::QmlDocument}, {directoryPathSourceId, qmlDocumentSourceId1, QmlDesigner::ModuleId{}, FileType::QmlDocument},
{directoryPathSourceId, qmlDocumentSourceId1, QmlDesigner::ModuleId{}, FileType::QmlDocument}}); {directoryPathSourceId, qmlDocumentSourceId1, QmlDesigner::ModuleId{}, FileType::QmlDocument}});
setFilesDontChanged({directoryPathSourceId, qmlDirPathSourceId}); setFilesDontChanged({directoryPathSourceId, qmlDirPathSourceId});
ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Throw(QmlDesigner::ProjectStorageError{})); ON_CALL(projectStorageMock, synchronize(_))
.WillByDefault(Throw(QmlDesigner::NoSourcePathForInvalidSourceId{}));
updater.pathsWithIdsChanged( updater.pathsWithIdsChanged(
{{qmlDocumentProjectChunkId, {qmlDocumentSourceId1, qmlDocumentSourceId2}}}); {{qmlDocumentProjectChunkId, {qmlDocumentSourceId1, qmlDocumentSourceId2}}});
ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Return()); ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Return());