forked from qt-creator/qt-creator
QmlDesigner: Add comon type cache
There are common types like QtQuick.Item or double which are needed for a fast lookup. Task-number: QDS-7380 Change-Id: Ibbdf77e2cc351fc56eeca3b96ac1b83a3feb83c9 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
committed by
Thomas Hartmann
parent
35a773b2dc
commit
c7b6d83f94
@@ -456,6 +456,7 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
extend_qtc_plugin(QmlDesigner
|
extend_qtc_plugin(QmlDesigner
|
||||||
SOURCES_PREFIX designercore/projectstorage
|
SOURCES_PREFIX designercore/projectstorage
|
||||||
SOURCES
|
SOURCES
|
||||||
|
commontypecache.h
|
||||||
directorypathcompressor.h
|
directorypathcompressor.h
|
||||||
filesysteminterface.h
|
filesysteminterface.h
|
||||||
filesystem.cpp filesystem.h
|
filesystem.cpp filesystem.h
|
||||||
|
@@ -0,0 +1,100 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2022 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "projectstoragetypes.h"
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace QmlDesigner::Storage::Info {
|
||||||
|
|
||||||
|
inline constexpr char QtQuick[] = "QtQuick";
|
||||||
|
inline constexpr char QML[] = "QML";
|
||||||
|
inline constexpr char Item[] = "Item";
|
||||||
|
inline constexpr char DoubleType[] = "double";
|
||||||
|
inline constexpr char var[] = "var";
|
||||||
|
|
||||||
|
template<const auto &moduleName_, const auto &typeName_>
|
||||||
|
struct CacheType
|
||||||
|
{
|
||||||
|
QmlDesigner::ModuleId moduleId;
|
||||||
|
QmlDesigner::TypeId typeId;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ProjectStorage>
|
||||||
|
class CommonTypeCache
|
||||||
|
{
|
||||||
|
using CommonTypes = std::tuple<CacheType<QtQuick, Item>, CacheType<QML, DoubleType>, CacheType<QML, var>>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CommonTypeCache(const ProjectStorage &projectStorage)
|
||||||
|
: m_projectStorage{projectStorage}
|
||||||
|
{}
|
||||||
|
|
||||||
|
void resetTypeIds()
|
||||||
|
{
|
||||||
|
std::apply([](auto &...type) { ((type.typeId = QmlDesigner::TypeId{}), ...); }, m_types);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<const auto &moduleName, const auto &typeName>
|
||||||
|
auto typeId() const
|
||||||
|
{
|
||||||
|
auto &type = std::get<CacheType<moduleName, typeName>>(m_types);
|
||||||
|
if (type.typeId)
|
||||||
|
return type.typeId;
|
||||||
|
|
||||||
|
if (!type.moduleId)
|
||||||
|
type.moduleId = m_projectStorage.moduleId(moduleName);
|
||||||
|
|
||||||
|
type.typeId = m_projectStorage.typeId(type.moduleId,
|
||||||
|
typeName,
|
||||||
|
QmlDesigner::Storage::Synchronization::Version{});
|
||||||
|
|
||||||
|
return type.typeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<const auto &typeName>
|
||||||
|
auto builtinTypeId() const
|
||||||
|
{
|
||||||
|
return typeId<QML, typeName>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
auto builtinTypeId() const
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<Type, double>)
|
||||||
|
return builtinTypeId<DoubleType>();
|
||||||
|
else
|
||||||
|
return TypeId{};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ProjectStorage &m_projectStorage;
|
||||||
|
mutable CommonTypes m_types;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner::Storage::Info
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "commontypecache.h"
|
||||||
#include "projectstorageexceptions.h"
|
#include "projectstorageexceptions.h"
|
||||||
#include "projectstorageinterface.h"
|
#include "projectstorageinterface.h"
|
||||||
#include "sourcepathcachetypes.h"
|
#include "sourcepathcachetypes.h"
|
||||||
@@ -116,15 +117,17 @@ public:
|
|||||||
|
|
||||||
synchronizeProjectDatas(package.projectDatas, package.updatedProjectSourceIds);
|
synchronizeProjectDatas(package.projectDatas, package.updatedProjectSourceIds);
|
||||||
|
|
||||||
|
commonTypeCache.resetTypeIds();
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleId moduleId(Utils::SmallStringView moduleName) override
|
ModuleId moduleId(Utils::SmallStringView moduleName) const override
|
||||||
{
|
{
|
||||||
return moduleCache.id(moduleName);
|
return moduleCache.id(moduleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::SmallString moduleName(ModuleId moduleId)
|
Utils::SmallString moduleName(ModuleId moduleId) const
|
||||||
{
|
{
|
||||||
if (!moduleId)
|
if (!moduleId)
|
||||||
throw ModuleDoesNotExists{};
|
throw ModuleDoesNotExists{};
|
||||||
@@ -134,7 +137,7 @@ public:
|
|||||||
|
|
||||||
TypeId typeId(ModuleId moduleId,
|
TypeId typeId(ModuleId moduleId,
|
||||||
Utils::SmallStringView exportedTypeName,
|
Utils::SmallStringView exportedTypeName,
|
||||||
Storage::Synchronization::Version version)
|
Storage::Synchronization::Version version) const
|
||||||
{
|
{
|
||||||
if (version.minor)
|
if (version.minor)
|
||||||
return selectTypeIdByModuleIdAndExportedNameAndVersionStatement
|
return selectTypeIdByModuleIdAndExportedNameAndVersionStatement
|
||||||
@@ -208,6 +211,24 @@ public:
|
|||||||
propertyDeclarationId);
|
propertyDeclarationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<const auto &moduleName, const auto &typeName>
|
||||||
|
TypeId commonTypeId() const
|
||||||
|
{
|
||||||
|
return commonTypeCache.template typeId<moduleName, typeName>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename BuiltinType>
|
||||||
|
TypeId builtinTypeId() const
|
||||||
|
{
|
||||||
|
return commonTypeCache.template builtinTypeId<BuiltinType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<const auto &builtinType>
|
||||||
|
TypeId builtinTypeId() const
|
||||||
|
{
|
||||||
|
return commonTypeCache.template builtinTypeId<builtinType>();
|
||||||
|
}
|
||||||
|
|
||||||
PropertyDeclarationId fetchPropertyDeclarationByTypeIdAndName(TypeId typeId,
|
PropertyDeclarationId fetchPropertyDeclarationByTypeIdAndName(TypeId typeId,
|
||||||
Utils::SmallStringView name)
|
Utils::SmallStringView name)
|
||||||
{
|
{
|
||||||
@@ -2515,7 +2536,8 @@ private:
|
|||||||
public:
|
public:
|
||||||
Database &database;
|
Database &database;
|
||||||
Initializer initializer;
|
Initializer initializer;
|
||||||
ModuleCache moduleCache{ModuleStorageAdapter{*this}};
|
mutable ModuleCache moduleCache{ModuleStorageAdapter{*this}};
|
||||||
|
Storage::Info::CommonTypeCache<ProjectStorage<Database>> commonTypeCache{*this};
|
||||||
ReadWriteStatement<1, 3> upsertTypeStatement{
|
ReadWriteStatement<1, 3> upsertTypeStatement{
|
||||||
"INSERT INTO types(sourceId, name, traits) VALUES(?1, ?2, ?3) ON CONFLICT DO "
|
"INSERT INTO types(sourceId, name, traits) VALUES(?1, ?2, ?3) ON CONFLICT DO "
|
||||||
"UPDATE SET traits=excluded.traits WHERE traits IS NOT "
|
"UPDATE SET traits=excluded.traits WHERE traits IS NOT "
|
||||||
|
@@ -35,7 +35,7 @@ class ProjectStorageInterface
|
|||||||
public:
|
public:
|
||||||
virtual void synchronize(Storage::Synchronization::SynchronizationPackage package) = 0;
|
virtual void synchronize(Storage::Synchronization::SynchronizationPackage package) = 0;
|
||||||
|
|
||||||
virtual ModuleId moduleId(Utils::SmallStringView name) = 0;
|
virtual ModuleId moduleId(Utils::SmallStringView name) const = 0;
|
||||||
|
|
||||||
virtual FileStatus fetchFileStatus(SourceId sourceId) const = 0;
|
virtual FileStatus fetchFileStatus(SourceId sourceId) const = 0;
|
||||||
virtual Storage::Synchronization::ProjectDatas fetchProjectDatas(SourceId sourceId) const = 0;
|
virtual Storage::Synchronization::ProjectDatas fetchProjectDatas(SourceId sourceId) const = 0;
|
||||||
|
@@ -378,6 +378,41 @@ protected:
|
|||||||
return package;
|
return package;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto createBuiltinSynchronizationPackage()
|
||||||
|
{
|
||||||
|
SynchronizationPackage package;
|
||||||
|
|
||||||
|
package.imports.emplace_back(QMLModuleId, Storage::Synchronization::Version{}, sourceId1);
|
||||||
|
package.moduleDependencies.emplace_back(QMLModuleId,
|
||||||
|
Storage::Synchronization::Version{},
|
||||||
|
sourceId1);
|
||||||
|
package.updatedModuleDependencySourceIds.push_back(sourceId1);
|
||||||
|
|
||||||
|
importsSourceId1.emplace_back(QMLModuleId, Storage::Synchronization::Version{}, sourceId1);
|
||||||
|
moduleDependenciesSourceId1.emplace_back(QMLModuleId,
|
||||||
|
Storage::Synchronization::Version{},
|
||||||
|
sourceId1);
|
||||||
|
|
||||||
|
package.types.push_back(
|
||||||
|
Storage::Synchronization::Type{"double",
|
||||||
|
Storage::Synchronization::ImportedType{},
|
||||||
|
TypeTraits::Value,
|
||||||
|
sourceId1,
|
||||||
|
{Storage::Synchronization::ExportedType{QMLModuleId,
|
||||||
|
"double"}}});
|
||||||
|
package.types.push_back(
|
||||||
|
Storage::Synchronization::Type{"var",
|
||||||
|
Storage::Synchronization::ImportedType{},
|
||||||
|
TypeTraits::Value,
|
||||||
|
sourceId1,
|
||||||
|
{Storage::Synchronization::ExportedType{QMLModuleId,
|
||||||
|
"var"}}});
|
||||||
|
|
||||||
|
package.updatedSourceIds = {sourceId1};
|
||||||
|
|
||||||
|
return package;
|
||||||
|
}
|
||||||
|
|
||||||
auto createSynchronizationPackageWithAliases()
|
auto createSynchronizationPackageWithAliases()
|
||||||
{
|
{
|
||||||
auto package{createSimpleSynchronizationPackage()};
|
auto package{createSimpleSynchronizationPackage()};
|
||||||
@@ -983,6 +1018,7 @@ protected:
|
|||||||
ModuleId pathToModuleId{storage.moduleId("/path/to")};
|
ModuleId pathToModuleId{storage.moduleId("/path/to")};
|
||||||
ModuleId qtQuick3DModuleId{storage.moduleId("QtQuick3D")};
|
ModuleId qtQuick3DModuleId{storage.moduleId("QtQuick3D")};
|
||||||
ModuleId myModuleModuleId{storage.moduleId("MyModule")};
|
ModuleId myModuleModuleId{storage.moduleId("MyModule")};
|
||||||
|
ModuleId QMLModuleId{storage.moduleId("QML")};
|
||||||
Storage::Synchronization::Imports importsSourceId1;
|
Storage::Synchronization::Imports importsSourceId1;
|
||||||
Storage::Synchronization::Imports importsSourceId2;
|
Storage::Synchronization::Imports importsSourceId2;
|
||||||
Storage::Synchronization::Imports importsSourceId3;
|
Storage::Synchronization::Imports importsSourceId3;
|
||||||
@@ -5896,4 +5932,114 @@ TEST_F(ProjectStorage, DontGetTypeForInvalidId)
|
|||||||
ASSERT_THAT(type, Eq(Utils::nullopt));
|
ASSERT_THAT(type, Eq(Utils::nullopt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorage, GetCommonType)
|
||||||
|
{
|
||||||
|
auto package{createSimpleSynchronizationPackage()};
|
||||||
|
storage.synchronize(package);
|
||||||
|
|
||||||
|
auto typeId = storage.commonTypeId<QmlDesigner::Storage::Info::QtQuick,
|
||||||
|
QmlDesigner::Storage::Info::Item>();
|
||||||
|
|
||||||
|
ASSERT_THAT(typeId, fetchTypeId(sourceId1, "QQuickItem"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorage, GetCommonTypeAgain)
|
||||||
|
{
|
||||||
|
auto package{createSimpleSynchronizationPackage()};
|
||||||
|
storage.synchronize(package);
|
||||||
|
auto firstTypeId = storage.commonTypeId<QmlDesigner::Storage::Info::QtQuick,
|
||||||
|
QmlDesigner::Storage::Info::Item>();
|
||||||
|
|
||||||
|
auto typeId = storage.commonTypeId<QmlDesigner::Storage::Info::QtQuick,
|
||||||
|
QmlDesigner::Storage::Info::Item>();
|
||||||
|
|
||||||
|
ASSERT_THAT(typeId, firstTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorage, GetCommonTypeAfterChangingType)
|
||||||
|
{
|
||||||
|
auto package{createSimpleSynchronizationPackage()};
|
||||||
|
storage.synchronize(package);
|
||||||
|
auto oldTypeId = storage.commonTypeId<QmlDesigner::Storage::Info::QtQuick,
|
||||||
|
QmlDesigner::Storage::Info::Item>();
|
||||||
|
package.types.front().typeName = "QQuickItem2";
|
||||||
|
storage.synchronize(package);
|
||||||
|
|
||||||
|
auto typeId = storage.commonTypeId<QmlDesigner::Storage::Info::QtQuick,
|
||||||
|
QmlDesigner::Storage::Info::Item>();
|
||||||
|
|
||||||
|
ASSERT_THAT(typeId, Ne(oldTypeId));
|
||||||
|
ASSERT_THAT(typeId, fetchTypeId(sourceId1, "QQuickItem2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorage, GetBuiltinType)
|
||||||
|
{
|
||||||
|
auto package{createBuiltinSynchronizationPackage()};
|
||||||
|
storage.synchronize(package);
|
||||||
|
|
||||||
|
auto typeId = storage.builtinTypeId<double>();
|
||||||
|
|
||||||
|
ASSERT_THAT(typeId, fetchTypeId(sourceId1, "double"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorage, GetBuiltinTypeAgain)
|
||||||
|
{
|
||||||
|
auto package{createBuiltinSynchronizationPackage()};
|
||||||
|
storage.synchronize(package);
|
||||||
|
auto firstTypeId = storage.builtinTypeId<double>();
|
||||||
|
|
||||||
|
auto typeId = storage.builtinTypeId<double>();
|
||||||
|
|
||||||
|
ASSERT_THAT(typeId, firstTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorage, GetBuiltinTypeAfterChangingType)
|
||||||
|
{
|
||||||
|
auto package{createBuiltinSynchronizationPackage()};
|
||||||
|
storage.synchronize(package);
|
||||||
|
auto oldTypeId = storage.builtinTypeId<double>();
|
||||||
|
package.types.front().typeName = "float";
|
||||||
|
storage.synchronize(package);
|
||||||
|
|
||||||
|
auto typeId = storage.builtinTypeId<double>();
|
||||||
|
|
||||||
|
ASSERT_THAT(typeId, Ne(oldTypeId));
|
||||||
|
ASSERT_THAT(typeId, fetchTypeId(sourceId1, "float"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorage, GetBuiltinStringType)
|
||||||
|
{
|
||||||
|
auto package{createBuiltinSynchronizationPackage()};
|
||||||
|
storage.synchronize(package);
|
||||||
|
|
||||||
|
auto typeId = storage.builtinTypeId<QmlDesigner::Storage::Info::var>();
|
||||||
|
|
||||||
|
ASSERT_THAT(typeId, fetchTypeId(sourceId1, "var"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorage, GetBuiltinStringTypeAgain)
|
||||||
|
{
|
||||||
|
auto package{createBuiltinSynchronizationPackage()};
|
||||||
|
storage.synchronize(package);
|
||||||
|
auto firstTypeId = storage.builtinTypeId<QmlDesigner::Storage::Info::var>();
|
||||||
|
|
||||||
|
auto typeId = storage.builtinTypeId<QmlDesigner::Storage::Info::var>();
|
||||||
|
|
||||||
|
ASSERT_THAT(typeId, firstTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorage, GetBuiltinStringTypeAfterChangingType)
|
||||||
|
{
|
||||||
|
auto package{createBuiltinSynchronizationPackage()};
|
||||||
|
storage.synchronize(package);
|
||||||
|
auto oldTypeId = storage.builtinTypeId<QmlDesigner::Storage::Info::var>();
|
||||||
|
package.types.back().typeName = "variant";
|
||||||
|
storage.synchronize(package);
|
||||||
|
|
||||||
|
auto typeId = storage.builtinTypeId<QmlDesigner::Storage::Info::var>();
|
||||||
|
|
||||||
|
ASSERT_THAT(typeId, Ne(oldTypeId));
|
||||||
|
ASSERT_THAT(typeId, fetchTypeId(sourceId1, "variant"));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@@ -41,7 +41,7 @@ public:
|
|||||||
(QmlDesigner::Storage::Synchronization::SynchronizationPackage package),
|
(QmlDesigner::Storage::Synchronization::SynchronizationPackage package),
|
||||||
(override));
|
(override));
|
||||||
|
|
||||||
MOCK_METHOD(QmlDesigner::ModuleId, moduleId, (Utils::SmallStringView), (override));
|
MOCK_METHOD(QmlDesigner::ModuleId, moduleId, (Utils::SmallStringView), (const, override));
|
||||||
|
|
||||||
MOCK_METHOD(QmlDesigner::FileStatus,
|
MOCK_METHOD(QmlDesigner::FileStatus,
|
||||||
fetchFileStatus,
|
fetchFileStatus,
|
||||||
|
Reference in New Issue
Block a user