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
|
||||
SOURCES_PREFIX designercore/projectstorage
|
||||
SOURCES
|
||||
commontypecache.h
|
||||
directorypathcompressor.h
|
||||
filesysteminterface.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
|
||||
|
||||
#include "commontypecache.h"
|
||||
#include "projectstorageexceptions.h"
|
||||
#include "projectstorageinterface.h"
|
||||
#include "sourcepathcachetypes.h"
|
||||
@@ -116,15 +117,17 @@ public:
|
||||
|
||||
synchronizeProjectDatas(package.projectDatas, package.updatedProjectSourceIds);
|
||||
|
||||
commonTypeCache.resetTypeIds();
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
ModuleId moduleId(Utils::SmallStringView moduleName) override
|
||||
ModuleId moduleId(Utils::SmallStringView moduleName) const override
|
||||
{
|
||||
return moduleCache.id(moduleName);
|
||||
}
|
||||
|
||||
Utils::SmallString moduleName(ModuleId moduleId)
|
||||
Utils::SmallString moduleName(ModuleId moduleId) const
|
||||
{
|
||||
if (!moduleId)
|
||||
throw ModuleDoesNotExists{};
|
||||
@@ -134,7 +137,7 @@ public:
|
||||
|
||||
TypeId typeId(ModuleId moduleId,
|
||||
Utils::SmallStringView exportedTypeName,
|
||||
Storage::Synchronization::Version version)
|
||||
Storage::Synchronization::Version version) const
|
||||
{
|
||||
if (version.minor)
|
||||
return selectTypeIdByModuleIdAndExportedNameAndVersionStatement
|
||||
@@ -208,6 +211,24 @@ public:
|
||||
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,
|
||||
Utils::SmallStringView name)
|
||||
{
|
||||
@@ -2515,7 +2536,8 @@ private:
|
||||
public:
|
||||
Database &database;
|
||||
Initializer initializer;
|
||||
ModuleCache moduleCache{ModuleStorageAdapter{*this}};
|
||||
mutable ModuleCache moduleCache{ModuleStorageAdapter{*this}};
|
||||
Storage::Info::CommonTypeCache<ProjectStorage<Database>> commonTypeCache{*this};
|
||||
ReadWriteStatement<1, 3> upsertTypeStatement{
|
||||
"INSERT INTO types(sourceId, name, traits) VALUES(?1, ?2, ?3) ON CONFLICT DO "
|
||||
"UPDATE SET traits=excluded.traits WHERE traits IS NOT "
|
||||
|
@@ -35,7 +35,7 @@ class ProjectStorageInterface
|
||||
public:
|
||||
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 Storage::Synchronization::ProjectDatas fetchProjectDatas(SourceId sourceId) const = 0;
|
||||
|
@@ -378,6 +378,41 @@ protected:
|
||||
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 package{createSimpleSynchronizationPackage()};
|
||||
@@ -983,6 +1018,7 @@ protected:
|
||||
ModuleId pathToModuleId{storage.moduleId("/path/to")};
|
||||
ModuleId qtQuick3DModuleId{storage.moduleId("QtQuick3D")};
|
||||
ModuleId myModuleModuleId{storage.moduleId("MyModule")};
|
||||
ModuleId QMLModuleId{storage.moduleId("QML")};
|
||||
Storage::Synchronization::Imports importsSourceId1;
|
||||
Storage::Synchronization::Imports importsSourceId2;
|
||||
Storage::Synchronization::Imports importsSourceId3;
|
||||
@@ -5896,4 +5932,114 @@ TEST_F(ProjectStorage, DontGetTypeForInvalidId)
|
||||
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
|
||||
|
@@ -41,7 +41,7 @@ public:
|
||||
(QmlDesigner::Storage::Synchronization::SynchronizationPackage package),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD(QmlDesigner::ModuleId, moduleId, (Utils::SmallStringView), (override));
|
||||
MOCK_METHOD(QmlDesigner::ModuleId, moduleId, (Utils::SmallStringView), (const, override));
|
||||
|
||||
MOCK_METHOD(QmlDesigner::FileStatus,
|
||||
fetchFileStatus,
|
||||
|
Reference in New Issue
Block a user