forked from qt-creator/qt-creator
QmlDesigner: Add ProjectStorageUpdater
Adding a skeleton for the ProjectStorageUpdater. Task-number: QDS-4819 Task-number: QDS-4793 Change-Id: I230d68f71480d360d71019883510ef22dd276802 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
@@ -34,6 +34,7 @@ namespace QmlDesigner {
|
|||||||
class FileStatus
|
class FileStatus
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
explicit FileStatus() = default;
|
||||||
explicit FileStatus(SourceId sourceId, long long size, long long lastModified)
|
explicit FileStatus(SourceId sourceId, long long size, long long lastModified)
|
||||||
: sourceId{sourceId}
|
: sourceId{sourceId}
|
||||||
, size{size}
|
, size{size}
|
||||||
@@ -49,7 +50,8 @@ public:
|
|||||||
friend bool operator==(const FileStatus &first, const FileStatus &second)
|
friend bool operator==(const FileStatus &first, const FileStatus &second)
|
||||||
{
|
{
|
||||||
return first.sourceId == second.sourceId && first.size == second.size
|
return first.sourceId == second.sourceId && first.size == second.size
|
||||||
&& first.lastModified == second.lastModified;
|
&& first.lastModified == second.lastModified && first.size >= 0
|
||||||
|
&& first.lastModified >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator!=(const FileStatus &first, const FileStatus &second)
|
friend bool operator!=(const FileStatus &first, const FileStatus &second)
|
||||||
@@ -72,10 +74,14 @@ public:
|
|||||||
return first.sourceId < second;
|
return first.sourceId < second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isValid() const { return sourceId && size >= 0 && lastModified >= 0; }
|
||||||
|
|
||||||
|
explicit operator bool() const { return isValid(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SourceId sourceId;
|
SourceId sourceId;
|
||||||
long long size;
|
long long size = -1;
|
||||||
long long lastModified;
|
long long lastModified = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
using FileStatuses = std::vector<FileStatus>;
|
using FileStatuses = std::vector<FileStatus>;
|
||||||
|
@@ -40,6 +40,7 @@ public:
|
|||||||
virtual long long lastModified(SourceId sourceId) const = 0;
|
virtual long long lastModified(SourceId sourceId) const = 0;
|
||||||
virtual FileStatus fileStatus(SourceId sourceId) const = 0;
|
virtual FileStatus fileStatus(SourceId sourceId) const = 0;
|
||||||
virtual void remove(const SourceIds &sourceIds) = 0;
|
virtual void remove(const SourceIds &sourceIds) = 0;
|
||||||
|
virtual QString contentAsQString(const QString &filePath) const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~FileSystemInterface() = default;
|
~FileSystemInterface() = default;
|
||||||
|
@@ -0,0 +1,39 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 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
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class ProjectManagerInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual QStringList qtQmlDirs() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~ProjectManagerInterface() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -25,10 +25,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "filestatus.h"
|
|
||||||
#include "projectstorageexceptions.h"
|
#include "projectstorageexceptions.h"
|
||||||
#include "projectstorageids.h"
|
#include "projectstorageinterface.h"
|
||||||
#include "projectstoragetypes.h"
|
|
||||||
#include "sourcepathcachetypes.h"
|
#include "sourcepathcachetypes.h"
|
||||||
|
|
||||||
#include <sqlitealgorithms.h>
|
#include <sqlitealgorithms.h>
|
||||||
@@ -43,7 +41,7 @@
|
|||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
template<typename Database>
|
template<typename Database>
|
||||||
class ProjectStorage
|
class ProjectStorage final : public ProjectStorageInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<int ResultCount>
|
template<int ResultCount>
|
||||||
@@ -61,7 +59,7 @@ public:
|
|||||||
Storage::Documents documents,
|
Storage::Documents documents,
|
||||||
Storage::Types types,
|
Storage::Types types,
|
||||||
SourceIds sourceIds,
|
SourceIds sourceIds,
|
||||||
FileStatuses fileStatuses)
|
FileStatuses fileStatuses) override
|
||||||
{
|
{
|
||||||
Sqlite::ImmediateTransaction transaction{database};
|
Sqlite::ImmediateTransaction transaction{database};
|
||||||
|
|
||||||
@@ -299,6 +297,14 @@ public:
|
|||||||
return selectAllFileStatusesStatement.template rangeWithTransaction<FileStatus>();
|
return selectAllFileStatusesStatement.template rangeWithTransaction<FileStatus>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileStatus fetchFileStatus(SourceId sourceId) const override
|
||||||
|
{
|
||||||
|
return selectFileStatusesForSourceIdStatement.template valueWithTransaction<FileStatus>(
|
||||||
|
&sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceIds fetchSourceDependencieIds(SourceId sourceId) const override { return {}; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class AliasPropertyDeclaration
|
class AliasPropertyDeclaration
|
||||||
{
|
{
|
||||||
@@ -1240,6 +1246,11 @@ private:
|
|||||||
|
|
||||||
TypeId declareType(Storage::Type &type)
|
TypeId declareType(Storage::Type &type)
|
||||||
{
|
{
|
||||||
|
if (type.import.name.isEmpty() && type.typeName.isEmpty()) {
|
||||||
|
type.typeId = selectTypeIdBySourceIdStatement.template value<TypeId>(&type.sourceId);
|
||||||
|
return type.typeId;
|
||||||
|
}
|
||||||
|
|
||||||
ImportId importId = fetchImportId(type.import);
|
ImportId importId = fetchImportId(type.import);
|
||||||
|
|
||||||
if (!importId)
|
if (!importId)
|
||||||
@@ -2186,11 +2197,16 @@ public:
|
|||||||
"SELECT sourceId, size, lastModified FROM fileStatuses WHERE sourceId IN carray(?1) ORDER "
|
"SELECT sourceId, size, lastModified FROM fileStatuses WHERE sourceId IN carray(?1) ORDER "
|
||||||
"BY sourceId",
|
"BY sourceId",
|
||||||
database};
|
database};
|
||||||
|
mutable ReadStatement<3> selectFileStatusesForSourceIdStatement{
|
||||||
|
"SELECT sourceId, size, lastModified FROM fileStatuses WHERE sourceId=?1 ORDER BY sourceId",
|
||||||
|
database};
|
||||||
WriteStatement insertFileStatusStatement{
|
WriteStatement insertFileStatusStatement{
|
||||||
"INSERT INTO fileStatuses(sourceId, size, lastModified) VALUES(?1, ?2, ?3)", database};
|
"INSERT INTO fileStatuses(sourceId, size, lastModified) VALUES(?1, ?2, ?3)", database};
|
||||||
WriteStatement deleteFileStatusStatement{"DELETE FROM fileStatuses WHERE sourceId=?1", database};
|
WriteStatement deleteFileStatusStatement{"DELETE FROM fileStatuses WHERE sourceId=?1", database};
|
||||||
WriteStatement updateFileStatusStatement{
|
WriteStatement updateFileStatusStatement{
|
||||||
"UPDATE fileStatuses SET size=?2, lastModified=?3 WHERE sourceId=?1", database};
|
"UPDATE fileStatuses SET size=?2, lastModified=?3 WHERE sourceId=?1", database};
|
||||||
|
ReadStatement<1> selectTypeIdBySourceIdStatement{"SELECT typeId FROM types WHERE sourceId=?",
|
||||||
|
database};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -0,0 +1,50 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 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 "filestatus.h"
|
||||||
|
#include "projectstoragetypes.h"
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class ProjectStorageInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void synchronize(Storage::ImportDependencies importDependencies,
|
||||||
|
Storage::Documents documents,
|
||||||
|
Storage::Types types,
|
||||||
|
SourceIds sourceIds,
|
||||||
|
FileStatuses fileStatuses)
|
||||||
|
= 0;
|
||||||
|
|
||||||
|
virtual FileStatus fetchFileStatus(SourceId sourceId) const = 0;
|
||||||
|
virtual SourceIds fetchSourceDependencieIds(SourceId sourceId) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~ProjectStorageInterface() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -145,6 +145,11 @@ public:
|
|||||||
: name{name}
|
: name{name}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
friend bool operator==(const ExportedType &first, const ExportedType &second)
|
||||||
|
{
|
||||||
|
return first.name == second.name;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Utils::SmallString name;
|
Utils::SmallString name;
|
||||||
};
|
};
|
||||||
@@ -158,6 +163,11 @@ public:
|
|||||||
, import{std::move(import)}
|
, import{std::move(import)}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
friend bool operator==(const ExplicitExportedType &first, const ExplicitExportedType &second)
|
||||||
|
{
|
||||||
|
return first.name == second.name && first.import == second.import;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Utils::SmallString name;
|
Utils::SmallString name;
|
||||||
Import import;
|
Import import;
|
||||||
@@ -173,6 +183,11 @@ public:
|
|||||||
: name{name}
|
: name{name}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
friend bool operator==(const NativeType &first, const NativeType &second)
|
||||||
|
{
|
||||||
|
return first.name == second.name;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Utils::SmallString name;
|
Utils::SmallString name;
|
||||||
};
|
};
|
||||||
@@ -422,6 +437,13 @@ public:
|
|||||||
, kind{PropertyKind::Alias}
|
, kind{PropertyKind::Alias}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
friend bool operator==(const PropertyDeclaration &first, const PropertyDeclaration &second)
|
||||||
|
{
|
||||||
|
return first.name == second.name && first.typeName == second.typeName
|
||||||
|
&& first.aliasPropertyName == second.aliasPropertyName
|
||||||
|
&& first.traits == second.traits && first.kind == second.kind;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Utils::SmallString name;
|
Utils::SmallString name;
|
||||||
TypeName typeName;
|
TypeName typeName;
|
||||||
@@ -516,10 +538,20 @@ public:
|
|||||||
, typeId{typeId}
|
, typeId{typeId}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
friend bool operator==(const Type &first, const Type &second) noexcept
|
||||||
|
{
|
||||||
|
return first.typeName == second.typeName && first.prototype == second.prototype
|
||||||
|
&& first.exportedTypes == second.exportedTypes
|
||||||
|
&& first.propertyDeclarations == second.propertyDeclarations
|
||||||
|
&& first.functionDeclarations == second.functionDeclarations
|
||||||
|
&& first.signalDeclarations == second.signalDeclarations
|
||||||
|
&& first.import == second.import && first.sourceId == second.sourceId
|
||||||
|
&& first.sourceId == second.sourceId;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Utils::SmallString typeName;
|
Utils::SmallString typeName;
|
||||||
TypeName prototype;
|
TypeName prototype;
|
||||||
Utils::SmallString attachedType;
|
|
||||||
ExportedTypes exportedTypes;
|
ExportedTypes exportedTypes;
|
||||||
PropertyDeclarations propertyDeclarations;
|
PropertyDeclarations propertyDeclarations;
|
||||||
FunctionDeclarations functionDeclarations;
|
FunctionDeclarations functionDeclarations;
|
||||||
@@ -529,7 +561,6 @@ public:
|
|||||||
TypeAccessSemantics accessSemantics = TypeAccessSemantics::Invalid;
|
TypeAccessSemantics accessSemantics = TypeAccessSemantics::Invalid;
|
||||||
SourceId sourceId;
|
SourceId sourceId;
|
||||||
TypeId typeId;
|
TypeId typeId;
|
||||||
bool isCreatable = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using Types = std::vector<Type>;
|
using Types = std::vector<Type>;
|
||||||
@@ -591,8 +622,8 @@ public:
|
|||||||
|
|
||||||
friend bool operator==(const ImportView &first, const ImportView &second)
|
friend bool operator==(const ImportView &first, const ImportView &second)
|
||||||
{
|
{
|
||||||
return first.name == second.name
|
return first.name == second.name && first.version == second.version
|
||||||
&& first.version == second.version && first.sourceId == second.sourceId;
|
&& first.sourceId == second.sourceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@@ -0,0 +1,200 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2017 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "projectstorageupdater.h"
|
||||||
|
|
||||||
|
#include "filestatuscache.h"
|
||||||
|
#include "filesysteminterface.h"
|
||||||
|
#include "projectmanagerinterface.h"
|
||||||
|
#include "projectstorage.h"
|
||||||
|
#include "qmldocumentparserinterface.h"
|
||||||
|
#include "qmltypesparserinterface.h"
|
||||||
|
#include "sourcepathcache.h"
|
||||||
|
|
||||||
|
#include <sqlitedatabase.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
ComponentReferences createComponentReferences(const QMultiHash<QString, QmlDirParser::Component> &components)
|
||||||
|
{
|
||||||
|
ComponentReferences componentReferences;
|
||||||
|
componentReferences.reserve(static_cast<std::size_t>(components.size()));
|
||||||
|
|
||||||
|
for (const QmlDirParser::Component &component : components)
|
||||||
|
componentReferences.push_back(std::cref(component));
|
||||||
|
|
||||||
|
return componentReferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectUpdater::update()
|
||||||
|
{
|
||||||
|
Storage::ImportDependencies importDependencies;
|
||||||
|
Storage::Documents documents;
|
||||||
|
Storage::Types types;
|
||||||
|
SourceIds sourceIds;
|
||||||
|
FileStatuses fileStatuses;
|
||||||
|
|
||||||
|
for (const QString &qmldirPath : m_projectManager.qtQmlDirs()) {
|
||||||
|
SourcePath qmldirSourcePath{qmldirPath};
|
||||||
|
SourceId qmlDirSourceId = m_pathCache.sourceId(qmldirSourcePath);
|
||||||
|
|
||||||
|
switch (fileState(qmlDirSourceId)) {
|
||||||
|
case FileState::Changed: {
|
||||||
|
QmlDirParser parser;
|
||||||
|
parser.parse(m_fileSystem.contentAsQString(qmldirPath));
|
||||||
|
|
||||||
|
sourceIds.push_back(qmlDirSourceId);
|
||||||
|
|
||||||
|
Utils::SmallString moduleName{parser.typeNamespace()};
|
||||||
|
SourceContextId directoryId = m_pathCache.sourceContextId(qmlDirSourceId);
|
||||||
|
|
||||||
|
parseTypeInfos(parser.typeInfos(), directoryId, importDependencies, types, sourceIds);
|
||||||
|
parseQmlComponents(createComponentReferences(parser.components()),
|
||||||
|
directoryId,
|
||||||
|
moduleName,
|
||||||
|
importDependencies,
|
||||||
|
types,
|
||||||
|
sourceIds);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FileState::NotChanged: {
|
||||||
|
SourceIds qmltypesSourceIds = m_projectStorage.fetchSourceDependencieIds(qmlDirSourceId);
|
||||||
|
parseTypeInfos(qmltypesSourceIds, importDependencies, types, sourceIds);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FileState::NotExists: {
|
||||||
|
// sourceIds.push_back(qmlDirSourceId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_projectStorage.synchronize(std::move(importDependencies),
|
||||||
|
std::move(documents),
|
||||||
|
std::move(types),
|
||||||
|
std::move(sourceIds),
|
||||||
|
std::move(fileStatuses));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectUpdater::parseTypeInfos(const QStringList &typeInfos,
|
||||||
|
SourceContextId directoryId,
|
||||||
|
Storage::ImportDependencies &importDependencies,
|
||||||
|
Storage::Types &types,
|
||||||
|
SourceIds &sourceIds)
|
||||||
|
{
|
||||||
|
QString directory{m_pathCache.sourceContextPath(directoryId)};
|
||||||
|
|
||||||
|
for (const QString &typeInfo : typeInfos) {
|
||||||
|
SourceId sourceId = m_pathCache.sourceId(directoryId, Utils::SmallString{typeInfo});
|
||||||
|
QString qmltypesPath = directory + "/" + typeInfo;
|
||||||
|
|
||||||
|
parseTypeInfo(sourceId, qmltypesPath, importDependencies, types, sourceIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectUpdater::parseTypeInfos(const SourceIds &qmltypesSourceIds,
|
||||||
|
Storage::ImportDependencies &importDependencies,
|
||||||
|
Storage::Types &types,
|
||||||
|
SourceIds &sourceIds)
|
||||||
|
{
|
||||||
|
for (SourceId sourceId : qmltypesSourceIds) {
|
||||||
|
QString qmltypesPath = m_pathCache.sourcePath(sourceId).toQString();
|
||||||
|
|
||||||
|
parseTypeInfo(sourceId, qmltypesPath, importDependencies, types, sourceIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectUpdater::parseTypeInfo(SourceId sourceId,
|
||||||
|
const QString &qmltypesPath,
|
||||||
|
Storage::ImportDependencies &importDependencies,
|
||||||
|
Storage::Types &types,
|
||||||
|
SourceIds &sourceIds)
|
||||||
|
{
|
||||||
|
if (fileState(sourceId) == FileState::Changed) {
|
||||||
|
sourceIds.push_back(sourceId);
|
||||||
|
const auto content = m_fileSystem.contentAsQString(qmltypesPath);
|
||||||
|
m_qmlTypesParser.parse(content, importDependencies, types, sourceIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectUpdater::parseQmlComponents(ComponentReferences components,
|
||||||
|
SourceContextId directoryId,
|
||||||
|
Utils::SmallStringView moduleName,
|
||||||
|
Storage::ImportDependencies &importDependencies,
|
||||||
|
Storage::Types &types,
|
||||||
|
SourceIds &sourceIds)
|
||||||
|
{
|
||||||
|
std::sort(components.begin(), components.end(), [](auto &&first, auto &&second) {
|
||||||
|
return std::tie(first.get().typeName, first.get().majorVersion, first.get().minorVersion)
|
||||||
|
> std::tie(second.get().typeName, second.get().majorVersion, second.get().minorVersion);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto newEnd = std::unique(components.begin(), components.end(), [](auto &&first, auto &&second) {
|
||||||
|
return first.get().typeName == second.get().typeName
|
||||||
|
&& first.get().majorVersion == second.get().majorVersion;
|
||||||
|
});
|
||||||
|
|
||||||
|
components.erase(newEnd, components.end());
|
||||||
|
|
||||||
|
QString directory{m_pathCache.sourceContextPath(directoryId)};
|
||||||
|
|
||||||
|
for (const QmlDirParser::Component &component : components) {
|
||||||
|
Utils::SmallString fileName{component.fileName};
|
||||||
|
SourceId sourceId = m_pathCache.sourceId(directoryId, fileName);
|
||||||
|
|
||||||
|
sourceIds.push_back(sourceId);
|
||||||
|
|
||||||
|
const auto content = m_fileSystem.contentAsQString(directory + "/" + component.fileName);
|
||||||
|
auto type = m_qmlDocumentParser.parse(content);
|
||||||
|
|
||||||
|
type.typeName = fileName;
|
||||||
|
type.import.name = moduleName;
|
||||||
|
type.import.version.version = component.majorVersion;
|
||||||
|
type.accessSemantics = Storage::TypeAccessSemantics::Reference;
|
||||||
|
type.sourceId = sourceId;
|
||||||
|
type.exportedTypes.push_back(Storage::ExportedType{Utils::SmallString{component.typeName}});
|
||||||
|
|
||||||
|
types.push_back(std::move(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectUpdater::FileState ProjectUpdater::fileState(SourceId sourceId) const
|
||||||
|
{
|
||||||
|
auto currentFileStatus = m_fileStatusCache.find(sourceId);
|
||||||
|
|
||||||
|
if (!currentFileStatus.isValid())
|
||||||
|
return FileState::NotExists;
|
||||||
|
|
||||||
|
auto projectStorageFileStatus = m_projectStorage.fetchFileStatus(sourceId);
|
||||||
|
|
||||||
|
if (!projectStorageFileStatus.isValid() || projectStorageFileStatus != currentFileStatus)
|
||||||
|
return FileState::Changed;
|
||||||
|
|
||||||
|
return FileState::NotChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,119 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2017 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 "nonlockingmutex.h"
|
||||||
|
#include "projectstorageids.h"
|
||||||
|
#include "projectstoragetypes.h"
|
||||||
|
|
||||||
|
#include <qmljs/parser/qmldirparser_p.h>
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Sqlite {
|
||||||
|
class Database;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
class ProjectManagerInterface;
|
||||||
|
class FileSystemInterface;
|
||||||
|
class ProjectStorageInterface;
|
||||||
|
template<typename ProjectStorage, typename Mutex>
|
||||||
|
class SourcePathCache;
|
||||||
|
class FileStatusCache;
|
||||||
|
template<typename Database>
|
||||||
|
class ProjectStorage;
|
||||||
|
class QmlDocumentParserInterface;
|
||||||
|
class QmlTypesParserInterface;
|
||||||
|
|
||||||
|
using ComponentReferences = std::vector<std::reference_wrapper<const QmlDirParser::Component>>;
|
||||||
|
|
||||||
|
class ProjectUpdater
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using PathCache = SourcePathCache<ProjectStorage<Sqlite::Database>, NonLockingMutex>;
|
||||||
|
|
||||||
|
ProjectUpdater(ProjectManagerInterface &projectManager,
|
||||||
|
FileSystemInterface &fileSystem,
|
||||||
|
ProjectStorageInterface &projectStorage,
|
||||||
|
FileStatusCache &fileStatusCache,
|
||||||
|
PathCache &pathCache,
|
||||||
|
QmlDocumentParserInterface &qmlDocumentParser,
|
||||||
|
QmlTypesParserInterface &qmlTypesParser)
|
||||||
|
: m_projectManager{projectManager}
|
||||||
|
, m_fileSystem{fileSystem}
|
||||||
|
, m_projectStorage{projectStorage}
|
||||||
|
, m_fileStatusCache{fileStatusCache}
|
||||||
|
, m_pathCache{pathCache}
|
||||||
|
, m_qmlDocumentParser{qmlDocumentParser}
|
||||||
|
, m_qmlTypesParser{qmlTypesParser}
|
||||||
|
{}
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class FileState {
|
||||||
|
NotChanged,
|
||||||
|
Changed,
|
||||||
|
NotExists,
|
||||||
|
};
|
||||||
|
|
||||||
|
void parseTypeInfos(const QStringList &typeInfos,
|
||||||
|
SourceContextId directoryId,
|
||||||
|
Storage::ImportDependencies &importDependencies,
|
||||||
|
Storage::Types &types,
|
||||||
|
SourceIds &sourceIds);
|
||||||
|
void parseTypeInfos(const SourceIds &qmltypesSourceIds,
|
||||||
|
Storage::ImportDependencies &importDependencies,
|
||||||
|
Storage::Types &types,
|
||||||
|
SourceIds &sourceIds);
|
||||||
|
void parseTypeInfo(SourceId sourceId,
|
||||||
|
const QString &qmltypesPath,
|
||||||
|
Storage::ImportDependencies &importDependencies,
|
||||||
|
Storage::Types &types,
|
||||||
|
SourceIds &sourceIds);
|
||||||
|
void parseQmlComponents(ComponentReferences components,
|
||||||
|
SourceContextId directoryId,
|
||||||
|
Utils::SmallStringView moduleName,
|
||||||
|
Storage::ImportDependencies &importDependencies,
|
||||||
|
Storage::Types &types,
|
||||||
|
SourceIds &sourceIds);
|
||||||
|
|
||||||
|
FileState fileState(SourceId sourceId) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ProjectManagerInterface &m_projectManager;
|
||||||
|
FileSystemInterface &m_fileSystem;
|
||||||
|
ProjectStorageInterface &m_projectStorage;
|
||||||
|
FileStatusCache &m_fileStatusCache;
|
||||||
|
PathCache &m_pathCache;
|
||||||
|
QmlDocumentParserInterface &m_qmlDocumentParser;
|
||||||
|
QmlTypesParserInterface &m_qmlTypesParser;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,42 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 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 <QString>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class QmlDocumentParserInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual Storage::Type parse(const QString &sourceContent) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~QmlDocumentParserInterface() = default;
|
||||||
|
};
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,46 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 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 <QString>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class QmlTypesParserInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void parse(const QString &sourceContent,
|
||||||
|
Storage::ImportDependencies &importDependencies,
|
||||||
|
Storage::Types &types,
|
||||||
|
SourceIds &sourceIds)
|
||||||
|
= 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~QmlTypesParserInterface() = default;
|
||||||
|
};
|
||||||
|
} // namespace QmlDesigner
|
@@ -78,6 +78,11 @@ public:
|
|||||||
return m_sourcePathCache.id({sourceName, sourceContextId});
|
return m_sourcePathCache.id({sourceName, sourceContextId});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SourceId sourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName) const
|
||||||
|
{
|
||||||
|
return m_sourcePathCache.id({sourceName, sourceContextId});
|
||||||
|
}
|
||||||
|
|
||||||
SourceContextId sourceContextId(Utils::SmallStringView sourceContextPath) const
|
SourceContextId sourceContextId(Utils::SmallStringView sourceContextPath) const
|
||||||
{
|
{
|
||||||
Utils::SmallStringView path = sourceContextPath.back() == '/'
|
Utils::SmallStringView path = sourceContextPath.back() == '/'
|
||||||
|
@@ -33,7 +33,7 @@ add_qtc_test(unittest GTEST
|
|||||||
DEPENDS
|
DEPENDS
|
||||||
Qt5::Core Qt5::Network Qt5::Widgets
|
Qt5::Core Qt5::Network Qt5::Widgets
|
||||||
Qt5::Xml Qt5::Concurrent Qt5::Qml Qt5::Gui
|
Qt5::Xml Qt5::Concurrent Qt5::Qml Qt5::Gui
|
||||||
Qt6Core5Compat
|
Qt6Core5Compat QmlJS
|
||||||
Googletest
|
Googletest
|
||||||
DEFINES
|
DEFINES
|
||||||
QT_NO_CAST_TO_ASCII
|
QT_NO_CAST_TO_ASCII
|
||||||
@@ -342,6 +342,8 @@ extend_qtc_test(unittest
|
|||||||
projectstorage/filestatus.h
|
projectstorage/filestatus.h
|
||||||
projectstorage/filestatuscache.cpp projectstorage/filestatuscache.h
|
projectstorage/filestatuscache.cpp projectstorage/filestatuscache.h
|
||||||
projectstorage/nonlockingmutex.h
|
projectstorage/nonlockingmutex.h
|
||||||
|
projectstorage/projectmanagerinterface.h
|
||||||
|
projectstorage/projectstorageinterface.h
|
||||||
projectstorage/projectstorage.h
|
projectstorage/projectstorage.h
|
||||||
projectstorage/projectstoragepathwatcher.h
|
projectstorage/projectstoragepathwatcher.h
|
||||||
projectstorage/projectstoragepathwatcherinterface.h
|
projectstorage/projectstoragepathwatcherinterface.h
|
||||||
@@ -351,6 +353,7 @@ extend_qtc_test(unittest
|
|||||||
projectstorage/projectstoragepathwatcher.h
|
projectstorage/projectstoragepathwatcher.h
|
||||||
projectstorage/projectstoragepathwatchertypes.h
|
projectstorage/projectstoragepathwatchertypes.h
|
||||||
projectstorage/projectstoragetypes.h
|
projectstorage/projectstoragetypes.h
|
||||||
|
projectstorage/projectstorageupdater.cpp projectstorage/projectstorageupdater.h
|
||||||
projectstorage/sourcepath.h
|
projectstorage/sourcepath.h
|
||||||
projectstorage/sourcepathcache.h
|
projectstorage/sourcepathcache.h
|
||||||
projectstorage/sourcepathcache.h
|
projectstorage/sourcepathcache.h
|
||||||
@@ -359,6 +362,8 @@ extend_qtc_test(unittest
|
|||||||
projectstorage/storagecache.h
|
projectstorage/storagecache.h
|
||||||
projectstorage/storagecacheentry.h
|
projectstorage/storagecacheentry.h
|
||||||
projectstorage/storagecachefwd.h
|
projectstorage/storagecachefwd.h
|
||||||
|
projectstorage/qmldocumentparserinterface.h
|
||||||
|
projectstorage/qmltypesparserinterface.h
|
||||||
rewritertransaction.cpp
|
rewritertransaction.cpp
|
||||||
rewritertransaction.h
|
rewritertransaction.h
|
||||||
EXPLICIT_MOC
|
EXPLICIT_MOC
|
||||||
@@ -373,7 +378,9 @@ extend_qtc_test(unittest
|
|||||||
filesystemmock.h
|
filesystemmock.h
|
||||||
filestatuscache-test.cpp
|
filestatuscache-test.cpp
|
||||||
listmodeleditor-test.cpp
|
listmodeleditor-test.cpp
|
||||||
|
projectmanagermock.h
|
||||||
projectstorage-test.cpp
|
projectstorage-test.cpp
|
||||||
|
projectstorageupdater-test.cpp
|
||||||
projectstoragesqlitefunctionregistry-test.cpp
|
projectstoragesqlitefunctionregistry-test.cpp
|
||||||
projectstoragepathwatchermock.h
|
projectstoragepathwatchermock.h
|
||||||
projectstoragepathwatchernotifiermock.h
|
projectstoragepathwatchernotifiermock.h
|
||||||
@@ -383,7 +390,8 @@ extend_qtc_test(unittest
|
|||||||
sourcepathcachemock.h
|
sourcepathcachemock.h
|
||||||
sourcepathview-test.cpp
|
sourcepathview-test.cpp
|
||||||
storagecache-test.cpp
|
storagecache-test.cpp
|
||||||
|
qmldocumentparsermock.h
|
||||||
|
qmltypesparsermock.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# QmlDesigner tests END
|
# QmlDesigner tests END
|
||||||
|
@@ -40,4 +40,5 @@ public:
|
|||||||
MOCK_METHOD(long long, lastModified, (QmlDesigner::SourceId sourceId), (const, override));
|
MOCK_METHOD(long long, lastModified, (QmlDesigner::SourceId sourceId), (const, override));
|
||||||
MOCK_METHOD(QmlDesigner::FileStatus, fileStatus, (QmlDesigner::SourceId sourceId), (const, override));
|
MOCK_METHOD(QmlDesigner::FileStatus, fileStatus, (QmlDesigner::SourceId sourceId), (const, override));
|
||||||
MOCK_METHOD(void, remove, (const QmlDesigner::SourceIds &sourceIds), (override));
|
MOCK_METHOD(void, remove, (const QmlDesigner::SourceIds &sourceIds), (override));
|
||||||
|
MOCK_METHOD(QString, contentAsQString, (const QString &filePath), (const, override));
|
||||||
};
|
};
|
||||||
|
36
tests/unit/unittest/projectmanagermock.h
Normal file
36
tests/unit/unittest/projectmanagermock.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 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 "googletest.h"
|
||||||
|
|
||||||
|
#include <projectstorage/projectmanagerinterface.h>
|
||||||
|
|
||||||
|
class ProjectManagerMock : public QmlDesigner::ProjectManagerInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOCK_METHOD(QStringList, qtQmlDirs, (), (const));
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
@@ -29,36 +29,55 @@
|
|||||||
|
|
||||||
#include "sqlitedatabasemock.h"
|
#include "sqlitedatabasemock.h"
|
||||||
|
|
||||||
#include <projectstorage/projectstoragetypes.h>
|
#include <projectstorage/filestatus.h>
|
||||||
|
#include <projectstorage/projectstorageinterface.h>
|
||||||
#include <projectstorage/sourcepathcache.h>
|
#include <projectstorage/sourcepathcache.h>
|
||||||
#include <projectstorageids.h>
|
|
||||||
|
|
||||||
class ProjectStorageMock
|
class ProjectStorageMock : public QmlDesigner::ProjectStorageInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProjectStorageMock(SqliteDatabaseMock &databaseMock)
|
MOCK_METHOD(void,
|
||||||
: databaseMock{databaseMock}
|
synchronize,
|
||||||
{}
|
(QmlDesigner::Storage::ImportDependencies importDependencies,
|
||||||
|
QmlDesigner::Storage::Documents documents,
|
||||||
|
QmlDesigner::Storage::Types types,
|
||||||
|
QmlDesigner::SourceIds sourceIds,
|
||||||
|
QmlDesigner::FileStatuses fileStatuses),
|
||||||
|
(override));
|
||||||
|
|
||||||
MOCK_METHOD1(fetchSourceContextId,
|
MOCK_METHOD(QmlDesigner::FileStatus,
|
||||||
QmlDesigner::SourceContextId(Utils::SmallStringView SourceContextPath));
|
fetchFileStatus,
|
||||||
MOCK_METHOD2(fetchSourceId,
|
(QmlDesigner::SourceId sourceId),
|
||||||
QmlDesigner::SourceId(QmlDesigner::SourceContextId SourceContextId,
|
(const, override));
|
||||||
Utils::SmallStringView sourceName));
|
|
||||||
MOCK_METHOD1(fetchSourceContextIdUnguarded,
|
|
||||||
QmlDesigner::SourceContextId(Utils::SmallStringView SourceContextPath));
|
|
||||||
MOCK_METHOD2(fetchSourceIdUnguarded,
|
|
||||||
QmlDesigner::SourceId(QmlDesigner::SourceContextId SourceContextId,
|
|
||||||
Utils::SmallStringView sourceName));
|
|
||||||
MOCK_METHOD1(fetchSourceContextPath,
|
|
||||||
Utils::PathString(QmlDesigner::SourceContextId sourceContextId));
|
|
||||||
MOCK_METHOD1(fetchSourceNameAndSourceContextId,
|
|
||||||
QmlDesigner::Cache::SourceNameAndSourceContextId(QmlDesigner::SourceId sourceId));
|
|
||||||
MOCK_METHOD0(fetchAllSourceContexts, std::vector<QmlDesigner::Cache::SourceContext>());
|
|
||||||
MOCK_METHOD0(fetchAllSources, std::vector<QmlDesigner::Cache::Source>());
|
|
||||||
|
|
||||||
SqliteDatabaseMock &database() { return databaseMock; }
|
MOCK_METHOD(QmlDesigner::SourceIds,
|
||||||
|
fetchSourceDependencieIds,
|
||||||
|
(QmlDesigner::SourceId sourceId),
|
||||||
|
(const, override));
|
||||||
|
|
||||||
SqliteDatabaseMock &databaseMock;
|
MOCK_METHOD(QmlDesigner::SourceContextId,
|
||||||
|
fetchSourceContextId,
|
||||||
|
(Utils::SmallStringView SourceContextPath),
|
||||||
|
());
|
||||||
|
MOCK_METHOD(QmlDesigner::SourceId,
|
||||||
|
fetchSourceId,
|
||||||
|
(QmlDesigner::SourceContextId SourceContextId, Utils::SmallStringView sourceName),
|
||||||
|
());
|
||||||
|
MOCK_METHOD(QmlDesigner::SourceContextId,
|
||||||
|
fetchSourceContextIdUnguarded,
|
||||||
|
(Utils::SmallStringView SourceContextPath),
|
||||||
|
());
|
||||||
|
MOCK_METHOD(QmlDesigner::SourceId,
|
||||||
|
fetchSourceIdUnguarded,
|
||||||
|
(QmlDesigner::SourceContextId SourceContextId, Utils::SmallStringView sourceName),
|
||||||
|
());
|
||||||
|
MOCK_METHOD(Utils::PathString,
|
||||||
|
fetchSourceContextPath,
|
||||||
|
(QmlDesigner::SourceContextId sourceContextId));
|
||||||
|
MOCK_METHOD(QmlDesigner::Cache::SourceNameAndSourceContextId,
|
||||||
|
fetchSourceNameAndSourceContextId,
|
||||||
|
(QmlDesigner::SourceId sourceId));
|
||||||
|
MOCK_METHOD(std::vector<QmlDesigner::Cache::SourceContext>, fetchAllSourceContexts, (), ());
|
||||||
|
MOCK_METHOD(std::vector<QmlDesigner::Cache::Source>, fetchAllSources, (), ());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -41,6 +41,7 @@ namespace {
|
|||||||
using Watcher = QmlDesigner::ProjectStoragePathWatcher<NiceMock<MockQFileSytemWatcher>,
|
using Watcher = QmlDesigner::ProjectStoragePathWatcher<NiceMock<MockQFileSytemWatcher>,
|
||||||
NiceMock<MockTimer>,
|
NiceMock<MockTimer>,
|
||||||
NiceMock<SourcePathCacheMock>>;
|
NiceMock<SourcePathCacheMock>>;
|
||||||
|
using QmlDesigner::FileStatus;
|
||||||
using QmlDesigner::IdPaths;
|
using QmlDesigner::IdPaths;
|
||||||
using QmlDesigner::ProjectChunkId;
|
using QmlDesigner::ProjectChunkId;
|
||||||
using QmlDesigner::ProjectChunkIds;
|
using QmlDesigner::ProjectChunkIds;
|
||||||
@@ -81,7 +82,9 @@ protected:
|
|||||||
.WillByDefault(Return(sourceContextIds[1]));
|
.WillByDefault(Return(sourceContextIds[1]));
|
||||||
ON_CALL(sourcePathCacheMock, sourceContextId(TypedEq<SourceId>(pathIds[4])))
|
ON_CALL(sourcePathCacheMock, sourceContextId(TypedEq<SourceId>(pathIds[4])))
|
||||||
.WillByDefault(Return(sourceContextIds[2]));
|
.WillByDefault(Return(sourceContextIds[2]));
|
||||||
ON_CALL(mockFileSystem, lastModified(_)).WillByDefault(Return(1));
|
ON_CALL(mockFileSystem, fileStatus(_)).WillByDefault([](auto sourceId) {
|
||||||
|
return FileStatus{sourceId, 1, 1};
|
||||||
|
});
|
||||||
ON_CALL(sourcePathCacheMock,
|
ON_CALL(sourcePathCacheMock,
|
||||||
sourceContextId(TypedEq<Utils::SmallStringView>(sourceContextPathString)))
|
sourceContextId(TypedEq<Utils::SmallStringView>(sourceContextPathString)))
|
||||||
.WillByDefault(Return(sourceContextIds[0]));
|
.WillByDefault(Return(sourceContextIds[0]));
|
||||||
@@ -359,9 +362,12 @@ TEST_F(ProjectStoragePathWatcher, TwoNotifyFileChanges)
|
|||||||
watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1], pathIds[2]}},
|
watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1], pathIds[2]}},
|
||||||
{id2, {pathIds[0], pathIds[1], pathIds[2], pathIds[3], pathIds[4]}},
|
{id2, {pathIds[0], pathIds[1], pathIds[2], pathIds[3], pathIds[4]}},
|
||||||
{id3, {pathIds[4]}}});
|
{id3, {pathIds[4]}}});
|
||||||
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[0]))).WillByDefault(Return(2));
|
ON_CALL(mockFileSystem, fileStatus(Eq(pathIds[0])))
|
||||||
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[1]))).WillByDefault(Return(2));
|
.WillByDefault(Return(FileStatus{pathIds[0], 1, 2}));
|
||||||
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[3]))).WillByDefault(Return(2));
|
ON_CALL(mockFileSystem, fileStatus(Eq(pathIds[1])))
|
||||||
|
.WillByDefault(Return(FileStatus{pathIds[1], 1, 2}));
|
||||||
|
ON_CALL(mockFileSystem, fileStatus(Eq(pathIds[3])))
|
||||||
|
.WillByDefault(Return(FileStatus{pathIds[3], 1, 2}));
|
||||||
|
|
||||||
EXPECT_CALL(notifier,
|
EXPECT_CALL(notifier,
|
||||||
pathsWithIdsChanged(
|
pathsWithIdsChanged(
|
||||||
@@ -376,8 +382,11 @@ TEST_F(ProjectStoragePathWatcher, NotifyForPathChanges)
|
|||||||
{
|
{
|
||||||
watcher.updateIdPaths(
|
watcher.updateIdPaths(
|
||||||
{{id1, {pathIds[0], pathIds[1], pathIds[2]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}});
|
{{id1, {pathIds[0], pathIds[1], pathIds[2]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}});
|
||||||
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[0]))).WillByDefault(Return(2));
|
ON_CALL(mockFileSystem, fileStatus(Eq(pathIds[0])))
|
||||||
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[3]))).WillByDefault(Return(2));
|
.WillByDefault(Return(FileStatus{pathIds[0], 1, 2}));
|
||||||
|
|
||||||
|
ON_CALL(mockFileSystem, fileStatus(Eq(pathIds[3])))
|
||||||
|
.WillByDefault(Return(FileStatus{pathIds[3], 1, 2}));
|
||||||
|
|
||||||
EXPECT_CALL(notifier, pathsChanged(ElementsAre(pathIds[0])));
|
EXPECT_CALL(notifier, pathsChanged(ElementsAre(pathIds[0])));
|
||||||
|
|
||||||
@@ -397,7 +406,8 @@ TEST_F(ProjectStoragePathWatcher, NoDuplicatePathChanges)
|
|||||||
{
|
{
|
||||||
watcher.updateIdPaths(
|
watcher.updateIdPaths(
|
||||||
{{id1, {pathIds[0], pathIds[1], pathIds[2]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}});
|
{{id1, {pathIds[0], pathIds[1], pathIds[2]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}});
|
||||||
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[0]))).WillByDefault(Return(2));
|
ON_CALL(mockFileSystem, fileStatus(Eq(pathIds[0])))
|
||||||
|
.WillByDefault(Return(FileStatus{pathIds[0], 1, 2}));
|
||||||
|
|
||||||
EXPECT_CALL(notifier, pathsChanged(ElementsAre(pathIds[0])));
|
EXPECT_CALL(notifier, pathsChanged(ElementsAre(pathIds[0])));
|
||||||
|
|
||||||
|
368
tests/unit/unittest/projectstorageupdater-test.cpp
Normal file
368
tests/unit/unittest/projectstorageupdater-test.cpp
Normal file
@@ -0,0 +1,368 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "googletest.h"
|
||||||
|
|
||||||
|
#include "filesystemmock.h"
|
||||||
|
#include "projectmanagermock.h"
|
||||||
|
#include "projectstoragemock.h"
|
||||||
|
#include "qmldocumentparsermock.h"
|
||||||
|
#include "qmltypesparsermock.h"
|
||||||
|
|
||||||
|
#include <projectstorage/filestatuscache.h>
|
||||||
|
#include <projectstorage/projectstorage.h>
|
||||||
|
#include <projectstorage/projectstorageupdater.h>
|
||||||
|
#include <projectstorage/sourcepathcache.h>
|
||||||
|
#include <sqlitedatabase.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
namespace Storage = QmlDesigner::Storage;
|
||||||
|
|
||||||
|
using QmlDesigner::FileStatus;
|
||||||
|
using QmlDesigner::SourceId;
|
||||||
|
using QmlDesigner::Storage::TypeAccessSemantics;
|
||||||
|
|
||||||
|
MATCHER_P5(IsStorageType,
|
||||||
|
import,
|
||||||
|
typeName,
|
||||||
|
prototype,
|
||||||
|
accessSemantics,
|
||||||
|
sourceId,
|
||||||
|
std::string(negation ? "isn't " : "is ")
|
||||||
|
+ PrintToString(Storage::Type{import, typeName, prototype, accessSemantics, sourceId}))
|
||||||
|
{
|
||||||
|
const Storage::Type &type = arg;
|
||||||
|
|
||||||
|
return type.import == import && type.typeName == typeName
|
||||||
|
&& type.accessSemantics == accessSemantics && type.sourceId == sourceId
|
||||||
|
&& Storage::TypeName{prototype} == type.prototype;
|
||||||
|
}
|
||||||
|
|
||||||
|
MATCHER_P3(IsPropertyDeclaration,
|
||||||
|
name,
|
||||||
|
typeName,
|
||||||
|
traits,
|
||||||
|
std::string(negation ? "isn't " : "is ")
|
||||||
|
+ PrintToString(Storage::PropertyDeclaration{name, typeName, traits}))
|
||||||
|
{
|
||||||
|
const Storage::PropertyDeclaration &propertyDeclaration = arg;
|
||||||
|
|
||||||
|
return propertyDeclaration.name == name
|
||||||
|
&& Storage::TypeName{typeName} == propertyDeclaration.typeName
|
||||||
|
&& propertyDeclaration.traits == traits;
|
||||||
|
}
|
||||||
|
|
||||||
|
MATCHER_P(IsExportedType,
|
||||||
|
name,
|
||||||
|
std::string(negation ? "isn't " : "is ") + PrintToString(Storage::ExportedType{name}))
|
||||||
|
{
|
||||||
|
const Storage::ExportedType &type = arg;
|
||||||
|
|
||||||
|
return type.name == name;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProjectStorageUpdater : public testing::Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ProjectStorageUpdater()
|
||||||
|
{
|
||||||
|
ON_CALL(fileSystemMock, fileStatus(Eq(qmltypesPathSourceId)))
|
||||||
|
.WillByDefault(Return(FileStatus{qmltypesPathSourceId, 21, 421}));
|
||||||
|
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmltypesPathSourceId)))
|
||||||
|
.WillByDefault(Return(FileStatus{qmltypesPathSourceId, 2, 421}));
|
||||||
|
|
||||||
|
ON_CALL(fileSystemMock, fileStatus(Eq(qmltypes2PathSourceId)))
|
||||||
|
.WillByDefault(Return(FileStatus{qmltypes2PathSourceId, 21, 421}));
|
||||||
|
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmltypes2PathSourceId)))
|
||||||
|
.WillByDefault(Return(FileStatus{qmltypes2PathSourceId, 2, 421}));
|
||||||
|
|
||||||
|
ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId)))
|
||||||
|
.WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 421}));
|
||||||
|
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDirPathSourceId)))
|
||||||
|
.WillByDefault(Return(FileStatus{qmlDirPathSourceId, 2, 421}));
|
||||||
|
|
||||||
|
ON_CALL(projectStorageMock, fetchSourceDependencieIds(Eq(qmlDirPathSourceId)))
|
||||||
|
.WillByDefault(Return(QmlDesigner::SourceIds{qmltypesPathSourceId, qmltypes2PathSourceId}));
|
||||||
|
|
||||||
|
QString qmldir{"module Example\ntypeinfo example.qmltypes\n"};
|
||||||
|
ON_CALL(projectManagerMock, qtQmlDirs()).WillByDefault(Return(QStringList{"/path/qmldir"}));
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir"))))
|
||||||
|
.WillByDefault(Return(qmldir));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
NiceMock<ProjectManagerMock> projectManagerMock;
|
||||||
|
NiceMock<FileSystemMock> fileSystemMock;
|
||||||
|
NiceMock<ProjectStorageMock> projectStorageMock;
|
||||||
|
NiceMock<QmlTypesParserMock> qmlTypesParserMock;
|
||||||
|
NiceMock<QmlDocumentParserMock> qmlDocumentParserMock;
|
||||||
|
QmlDesigner::FileStatusCache fileStatusCache{fileSystemMock};
|
||||||
|
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
||||||
|
QmlDesigner::ProjectStorage<Sqlite::Database> storage{database, database.isInitialized()};
|
||||||
|
QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage<Sqlite::Database>> sourcePathCache{
|
||||||
|
storage};
|
||||||
|
QmlDesigner::ProjectUpdater updater{projectManagerMock,
|
||||||
|
fileSystemMock,
|
||||||
|
projectStorageMock,
|
||||||
|
fileStatusCache,
|
||||||
|
sourcePathCache,
|
||||||
|
qmlDocumentParserMock,
|
||||||
|
qmlTypesParserMock};
|
||||||
|
SourceId objectTypeSourceId{sourcePathCache.sourceId("/path/Object")};
|
||||||
|
Storage::Type objectType{Storage::Import{"Qml", 2},
|
||||||
|
"QObject",
|
||||||
|
Storage::NativeType{},
|
||||||
|
Storage::TypeAccessSemantics::Reference,
|
||||||
|
objectTypeSourceId,
|
||||||
|
{Storage::ExportedType{"Object"}, Storage::ExportedType{"Obj"}}};
|
||||||
|
SourceId qmltypesPathSourceId = sourcePathCache.sourceId("/path/example.qmltypes");
|
||||||
|
SourceId qmltypes2PathSourceId = sourcePathCache.sourceId("/path/example2.qmltypes");
|
||||||
|
SourceId qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir");
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(ProjectStorageUpdater, GetContentForQmlDirPathsIfFileStatusIsDifferent)
|
||||||
|
{
|
||||||
|
SourceId qmlDir1PathSourceId = sourcePathCache.sourceId("/path/one/qmldir");
|
||||||
|
SourceId qmlDir2PathSourceId = sourcePathCache.sourceId("/path/two/qmldir");
|
||||||
|
SourceId qmlDir3PathSourceId = sourcePathCache.sourceId("/path/three/qmldir");
|
||||||
|
ON_CALL(projectManagerMock, qtQmlDirs())
|
||||||
|
.WillByDefault(
|
||||||
|
Return(QStringList{"/path/one/qmldir", "/path/two/qmldir", "/path/three/qmldir"}));
|
||||||
|
ON_CALL(fileSystemMock, fileStatus(_)).WillByDefault([](auto sourceId) {
|
||||||
|
return FileStatus{sourceId, 21, 421};
|
||||||
|
});
|
||||||
|
ON_CALL(projectStorageMock, fetchFileStatus(_)).WillByDefault([](auto sourceId) {
|
||||||
|
return FileStatus{sourceId, 2, 421};
|
||||||
|
});
|
||||||
|
ON_CALL(fileSystemMock, fileStatus(Eq(qmlDir3PathSourceId)))
|
||||||
|
.WillByDefault(Return(FileStatus{qmlDir3PathSourceId, 21, 421}));
|
||||||
|
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDir3PathSourceId)))
|
||||||
|
.WillByDefault(Return(FileStatus{qmlDir3PathSourceId, 21, 421}));
|
||||||
|
|
||||||
|
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/one/qmldir"))));
|
||||||
|
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/two/qmldir"))));
|
||||||
|
|
||||||
|
updater.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorageUpdater, RequestFileStatusFromFileSystem)
|
||||||
|
{
|
||||||
|
EXPECT_CALL(fileSystemMock, fileStatus(Ne(qmlDirPathSourceId))).Times(AnyNumber());
|
||||||
|
|
||||||
|
EXPECT_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId)));
|
||||||
|
|
||||||
|
updater.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorageUpdater, GetContentForQmlTypes)
|
||||||
|
{
|
||||||
|
QString qmldir{"module Example\ntypeinfo example.qmltypes\n"};
|
||||||
|
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir"))))
|
||||||
|
.WillRepeatedly(Return(qmldir));
|
||||||
|
|
||||||
|
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))));
|
||||||
|
|
||||||
|
updater.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorageUpdater, GetContentForQmlTypesIfProjectStorageFileStatusIsInvalid)
|
||||||
|
{
|
||||||
|
QString qmldir{"module Example\ntypeinfo example.qmltypes\n"};
|
||||||
|
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir"))))
|
||||||
|
.WillRepeatedly(Return(qmldir));
|
||||||
|
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmltypesPathSourceId)))
|
||||||
|
.WillByDefault(Return(FileStatus{}));
|
||||||
|
|
||||||
|
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))));
|
||||||
|
|
||||||
|
updater.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorageUpdater, DontGetContentForQmlTypesIfFileSystemFileStatusIsInvalid)
|
||||||
|
{
|
||||||
|
QString qmldir{"module Example\ntypeinfo example.qmltypes\n"};
|
||||||
|
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir"))))
|
||||||
|
.WillRepeatedly(Return(qmldir));
|
||||||
|
ON_CALL(fileSystemMock, fileStatus(Eq(qmltypesPathSourceId))).WillByDefault(Return(FileStatus{}));
|
||||||
|
|
||||||
|
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))).Times(0);
|
||||||
|
|
||||||
|
updater.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorageUpdater, ParseQmlTypes)
|
||||||
|
{
|
||||||
|
QString qmldir{"module Example\ntypeinfo example.qmltypes\ntypeinfo example2.qmltypes\n"};
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
|
||||||
|
QString qmltypes{"Module {\ndependencies: []}"};
|
||||||
|
QString qmltypes2{"Module {\ndependencies: [foo]}"};
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))))
|
||||||
|
.WillByDefault(Return(qmltypes));
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example2.qmltypes"))))
|
||||||
|
.WillByDefault(Return(qmltypes2));
|
||||||
|
|
||||||
|
EXPECT_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _));
|
||||||
|
EXPECT_CALL(qmlTypesParserMock, parse(qmltypes2, _, _, _));
|
||||||
|
|
||||||
|
updater.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorageUpdater, DISABLED_SynchronizeIsEmptyForNoChange)
|
||||||
|
{
|
||||||
|
EXPECT_CALL(projectStorageMock,
|
||||||
|
synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));
|
||||||
|
|
||||||
|
updater.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes)
|
||||||
|
{
|
||||||
|
auto qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir");
|
||||||
|
auto qmltypesPathSourceId = sourcePathCache.sourceId("/path/example.qmltypes");
|
||||||
|
QString qmltypes{"Module {\ndependencies: []}"};
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))))
|
||||||
|
.WillByDefault(Return(qmltypes));
|
||||||
|
ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _))
|
||||||
|
.WillByDefault([&](auto, auto &importDependencies, auto &types, auto &sourceIds) {
|
||||||
|
types.push_back(objectType);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_CALL(projectStorageMock,
|
||||||
|
synchronize(_,
|
||||||
|
_,
|
||||||
|
ElementsAre(Eq(objectType)),
|
||||||
|
UnorderedElementsAre(qmlDirPathSourceId, qmltypesPathSourceId),
|
||||||
|
_));
|
||||||
|
|
||||||
|
updater.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorageUpdater, SynchronizeQmlTypesAreEmptyIfFileDoesNotChanged)
|
||||||
|
{
|
||||||
|
QString qmltypes{"Module {\ndependencies: []}"};
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))))
|
||||||
|
.WillByDefault(Return(qmltypes));
|
||||||
|
ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _))
|
||||||
|
.WillByDefault([&](auto, auto &importDependencies, auto &types, auto &sourceIds) {
|
||||||
|
types.push_back(objectType);
|
||||||
|
});
|
||||||
|
ON_CALL(fileSystemMock, fileStatus(Eq(qmltypesPathSourceId)))
|
||||||
|
.WillByDefault(Return(FileStatus{qmltypesPathSourceId, 2, 421}));
|
||||||
|
ON_CALL(fileSystemMock, fileStatus(Eq(qmltypes2PathSourceId)))
|
||||||
|
.WillByDefault(Return(FileStatus{qmltypes2PathSourceId, 2, 421}));
|
||||||
|
ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId)))
|
||||||
|
.WillByDefault(Return(FileStatus{qmlDirPathSourceId, 2, 421}));
|
||||||
|
|
||||||
|
EXPECT_CALL(projectStorageMock,
|
||||||
|
synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));
|
||||||
|
|
||||||
|
updater.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorageUpdater, GetContentForQmlDocuments)
|
||||||
|
{
|
||||||
|
QString qmldir{"module Example\nFirstType 1.0 First.qml\nFirstTypeV2 2.2 "
|
||||||
|
"First.2.qml\nSecondType 2.1 OldSecond.qml\nSecondType 2.2 Second.qml\n"};
|
||||||
|
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir"))))
|
||||||
|
.WillRepeatedly(Return(qmldir));
|
||||||
|
|
||||||
|
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml"))));
|
||||||
|
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.2.qml"))));
|
||||||
|
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml"))));
|
||||||
|
|
||||||
|
updater.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorageUpdater, ParseQmlDocuments)
|
||||||
|
{
|
||||||
|
QString qmldir{"module Example\nFirstType 1.0 First.qml\nFirstTypeV2 2.2 "
|
||||||
|
"First.2.qml\nSecondType 2.1 OldSecond.qml\nSecondType 2.2 Second.qml\n"};
|
||||||
|
QString qmlDocument1{"First{}"};
|
||||||
|
QString qmlDocument2{"Second{}"};
|
||||||
|
QString qmlDocument3{"Third{}"};
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml"))))
|
||||||
|
.WillByDefault(Return(qmlDocument1));
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.2.qml"))))
|
||||||
|
.WillByDefault(Return(qmlDocument2));
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml"))))
|
||||||
|
.WillByDefault(Return(qmlDocument3));
|
||||||
|
|
||||||
|
EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument1));
|
||||||
|
EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument2));
|
||||||
|
EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument3));
|
||||||
|
|
||||||
|
updater.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments)
|
||||||
|
{
|
||||||
|
QString qmldir{"module Example\nFirstType 1.0 First.qml\nFirstTypeV2 2.2 "
|
||||||
|
"First.2.qml\nSecondType 2.1 OldSecond.qml\nSecondType 2.2 Second.qml\n"};
|
||||||
|
QString qmlDocument1{"First{}"};
|
||||||
|
QString qmlDocument2{"Second{}"};
|
||||||
|
QString qmlDocument3{"Third{}"};
|
||||||
|
auto qmlDocumentSourceId1 = sourcePathCache.sourceId("/path/First.qml");
|
||||||
|
auto qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First.2.qml");
|
||||||
|
auto qmlDocumentSourceId3 = sourcePathCache.sourceId("/path/Second.qml");
|
||||||
|
Storage::Type firstType;
|
||||||
|
firstType.prototype = Storage::ExportedType{"Object"};
|
||||||
|
Storage::Type secondType;
|
||||||
|
secondType.prototype = Storage::ExportedType{"Object2"};
|
||||||
|
Storage::Type thirdType;
|
||||||
|
thirdType.prototype = Storage::ExportedType{"Object3"};
|
||||||
|
auto firstQmlDocumentSourceId = sourcePathCache.sourceId("/path/First.qml");
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml"))))
|
||||||
|
.WillByDefault(Return(qmlDocument1));
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.2.qml"))))
|
||||||
|
.WillByDefault(Return(qmlDocument2));
|
||||||
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml"))))
|
||||||
|
.WillByDefault(Return(qmlDocument3));
|
||||||
|
ON_CALL(qmlDocumentParserMock, parse(qmlDocument1)).WillByDefault(Return(firstType));
|
||||||
|
ON_CALL(qmlDocumentParserMock, parse(qmlDocument2)).WillByDefault(Return(secondType));
|
||||||
|
ON_CALL(qmlDocumentParserMock, parse(qmlDocument3)).WillByDefault(Return(thirdType));
|
||||||
|
|
||||||
|
EXPECT_CALL(projectStorageMock,
|
||||||
|
synchronize(_,
|
||||||
|
_,
|
||||||
|
Contains(AllOf(IsStorageType(Storage::Import{"Example", 1},
|
||||||
|
"First.qml",
|
||||||
|
Storage::ExportedType{"Object"},
|
||||||
|
TypeAccessSemantics::Reference,
|
||||||
|
firstQmlDocumentSourceId),
|
||||||
|
Field(&Storage::Type::exportedTypes,
|
||||||
|
ElementsAre(IsExportedType("FirstType"))))),
|
||||||
|
UnorderedElementsAre(qmlDirPathSourceId,
|
||||||
|
qmlDocumentSourceId1,
|
||||||
|
qmlDocumentSourceId2,
|
||||||
|
qmlDocumentSourceId3),
|
||||||
|
_));
|
||||||
|
|
||||||
|
updater.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
36
tests/unit/unittest/qmldocumentparsermock.h
Normal file
36
tests/unit/unittest/qmldocumentparsermock.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 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 "googletest.h"
|
||||||
|
|
||||||
|
#include <projectstorage/qmldocumentparserinterface.h>
|
||||||
|
|
||||||
|
class QmlDocumentParserMock : public QmlDesigner::QmlDocumentParserInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOCK_METHOD(QmlDesigner::Storage::Type, parse, (const QString &), (override));
|
||||||
|
};
|
42
tests/unit/unittest/qmltypesparsermock.h
Normal file
42
tests/unit/unittest/qmltypesparsermock.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 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 "googletest.h"
|
||||||
|
|
||||||
|
#include <projectstorage/qmltypesparserinterface.h>
|
||||||
|
|
||||||
|
class QmlTypesParserMock : public QmlDesigner::QmlTypesParserInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOCK_METHOD(void,
|
||||||
|
parse,
|
||||||
|
(const QString &sourceContent,
|
||||||
|
QmlDesigner::Storage::ImportDependencies &importDependencies,
|
||||||
|
QmlDesigner::Storage::Types &types,
|
||||||
|
QmlDesigner::SourceIds &sourceIds),
|
||||||
|
(override));
|
||||||
|
};
|
@@ -76,10 +76,9 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NiceMock<SqliteDatabaseMock> databaseMock;
|
NiceMock<ProjectStorageMock> storageMock;
|
||||||
NiceMock<ProjectStorageMock> storageMock{databaseMock};
|
|
||||||
Cache cache{storageMock};
|
Cache cache{storageMock};
|
||||||
NiceMock<ProjectStorageMock> storageMockFilled{databaseMock};
|
NiceMock<ProjectStorageMock> storageMockFilled;
|
||||||
Cache cacheNotFilled{storageMockFilled};
|
Cache cacheNotFilled{storageMockFilled};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -104,6 +103,15 @@ TEST_F(SourcePathCache, SourceIdOfSourceIdWithOutAnyEntry)
|
|||||||
ASSERT_THAT(sourceId, SourceId{42});
|
ASSERT_THAT(sourceId, SourceId{42});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SourcePathCache, SourceIdWithSourceContextIdAndSourceName)
|
||||||
|
{
|
||||||
|
auto sourceContextId = cache.sourceContextId("/path/to"_sv);
|
||||||
|
|
||||||
|
auto sourceId = cache.sourceId(sourceContextId, "file.cpp"_sv);
|
||||||
|
|
||||||
|
ASSERT_THAT(sourceId, SourceId{42});
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(SourcePathCache, IfEntryExistsDontCallInStrorage)
|
TEST_F(SourcePathCache, IfEntryExistsDontCallInStrorage)
|
||||||
{
|
{
|
||||||
cache.sourceId(SourcePathView("/path/to/file.cpp"));
|
cache.sourceId(SourcePathView("/path/to/file.cpp"));
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
#include "googletest.h"
|
#include "googletest.h"
|
||||||
|
|
||||||
#include <cppeditor/usages.h>
|
#include <projectstorage/filestatus.h>
|
||||||
#include <projectstorage/projectstoragetypes.h>
|
#include <projectstorage/projectstoragetypes.h>
|
||||||
#include <projectstorage/sourcepathcachetypes.h>
|
#include <projectstorage/sourcepathcachetypes.h>
|
||||||
#include <projectstorageids.h>
|
#include <projectstorageids.h>
|
||||||
@@ -60,10 +60,6 @@ public:
|
|||||||
(Utils::SmallStringView, long long),
|
(Utils::SmallStringView, long long),
|
||||||
());
|
());
|
||||||
|
|
||||||
MOCK_METHOD(CppEditor::Usages, valuesReturnSourceUsages, (std::size_t, int, int, int), ());
|
|
||||||
|
|
||||||
MOCK_METHOD(CppEditor::Usages, valuesReturnSourceUsages, (std::size_t, int, int, int, int), ());
|
|
||||||
|
|
||||||
MOCK_METHOD(Utils::optional<int>, valueReturnInt32, (Utils::SmallStringView), ());
|
MOCK_METHOD(Utils::optional<int>, valueReturnInt32, (Utils::SmallStringView), ());
|
||||||
|
|
||||||
MOCK_METHOD(Utils::optional<int>, valueReturnInt32, (int, Utils::SmallStringView), ());
|
MOCK_METHOD(Utils::optional<int>, valueReturnInt32, (int, Utils::SmallStringView), ());
|
||||||
@@ -78,7 +74,7 @@ public:
|
|||||||
|
|
||||||
MOCK_METHOD(Utils::optional<Utils::SmallString>, valueReturnSmallString, (int), ());
|
MOCK_METHOD(Utils::optional<Utils::SmallString>, valueReturnSmallString, (int), ());
|
||||||
|
|
||||||
MOCK_METHOD(QmlDesigner::TypeId, valueReturnsTypeId, (Utils::SmallStringView name), ());
|
MOCK_METHOD(QmlDesigner::TypeId, valueReturnsTypeId, (long long, Utils::SmallStringView name), ());
|
||||||
MOCK_METHOD(QmlDesigner::TypeId, valueWithTransactionReturnsTypeId, (long long, long long), ());
|
MOCK_METHOD(QmlDesigner::TypeId, valueWithTransactionReturnsTypeId, (long long, long long), ());
|
||||||
MOCK_METHOD(QmlDesigner::PropertyDeclarationId,
|
MOCK_METHOD(QmlDesigner::PropertyDeclarationId,
|
||||||
valueWithTransactionReturnsPropertyDeclarationId,
|
valueWithTransactionReturnsPropertyDeclarationId,
|
||||||
@@ -151,6 +147,8 @@ public:
|
|||||||
(std::size_t, long long),
|
(std::size_t, long long),
|
||||||
());
|
());
|
||||||
|
|
||||||
|
MOCK_METHOD(QmlDesigner::FileStatuses, rangesReturnsFileStatuses, (Utils::span<const int>), ());
|
||||||
|
|
||||||
template<typename ResultType, typename... QueryTypes>
|
template<typename ResultType, typename... QueryTypes>
|
||||||
auto optionalValue(const QueryTypes &...queryValues)
|
auto optionalValue(const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
@@ -221,8 +219,6 @@ public:
|
|||||||
return valuesReturnStringVector(reserveSize);
|
return valuesReturnStringVector(reserveSize);
|
||||||
else if constexpr (std::is_same_v<ResultType, long long>)
|
else if constexpr (std::is_same_v<ResultType, long long>)
|
||||||
return valuesReturnRowIds(reserveSize);
|
return valuesReturnRowIds(reserveSize);
|
||||||
else if constexpr (std::is_same_v<ResultType, CppEditor::Usage>)
|
|
||||||
return valuesReturnSourceUsages(reserveSize, queryValues...);
|
|
||||||
else if constexpr (std::is_same_v<ResultType, QmlDesigner::Cache::SourceContext>)
|
else if constexpr (std::is_same_v<ResultType, QmlDesigner::Cache::SourceContext>)
|
||||||
return valuesReturnCacheSourceContexts(reserveSize);
|
return valuesReturnCacheSourceContexts(reserveSize);
|
||||||
else if constexpr (std::is_same_v<ResultType, QmlDesigner::Cache::Source>)
|
else if constexpr (std::is_same_v<ResultType, QmlDesigner::Cache::Source>)
|
||||||
@@ -255,6 +251,8 @@ public:
|
|||||||
return rangeReturnStorageSignalDeclarationViews(queryValues...);
|
return rangeReturnStorageSignalDeclarationViews(queryValues...);
|
||||||
else if constexpr (std::is_same_v<ResultType, QmlDesigner::Storage::EnumerationDeclarationView>)
|
else if constexpr (std::is_same_v<ResultType, QmlDesigner::Storage::EnumerationDeclarationView>)
|
||||||
return rangeReturnStorageEnumerationDeclarationViews(queryValues...);
|
return rangeReturnStorageEnumerationDeclarationViews(queryValues...);
|
||||||
|
else if constexpr (std::is_same_v<ResultType, QmlDesigner::FileStatus>)
|
||||||
|
return rangesReturnsFileStatuses(queryValues...);
|
||||||
else
|
else
|
||||||
static_assert(!std::is_same_v<ResultType, ResultType>,
|
static_assert(!std::is_same_v<ResultType, ResultType>,
|
||||||
"SqliteReadStatementMock::values does not handle result type!");
|
"SqliteReadStatementMock::values does not handle result type!");
|
||||||
|
@@ -44,6 +44,7 @@ public:
|
|||||||
MOCK_METHOD(void, write, (long long), ());
|
MOCK_METHOD(void, write, (long long), ());
|
||||||
MOCK_METHOD(void, write, (long long, long long), ());
|
MOCK_METHOD(void, write, (long long, long long), ());
|
||||||
MOCK_METHOD(void, write, (long long, long long, int), ());
|
MOCK_METHOD(void, write, (long long, long long, int), ());
|
||||||
|
MOCK_METHOD(void, write, (long long, long long, long long), ());
|
||||||
MOCK_METHOD(void, write, (long long, unsigned int), ());
|
MOCK_METHOD(void, write, (long long, unsigned int), ());
|
||||||
MOCK_METHOD(void, write, (Utils::SmallStringView, long long), ());
|
MOCK_METHOD(void, write, (Utils::SmallStringView, long long), ());
|
||||||
MOCK_METHOD(void, write, (Utils::SmallStringView, Utils::SmallStringView), ());
|
MOCK_METHOD(void, write, (Utils::SmallStringView, Utils::SmallStringView), ());
|
||||||
@@ -95,6 +96,7 @@ public:
|
|||||||
MOCK_METHOD(void, write, (void *, long long), ());
|
MOCK_METHOD(void, write, (void *, long long), ());
|
||||||
MOCK_METHOD(void, write, (int), ());
|
MOCK_METHOD(void, write, (int), ());
|
||||||
MOCK_METHOD(void, write, (int, long long), ());
|
MOCK_METHOD(void, write, (int, long long), ());
|
||||||
|
MOCK_METHOD(void, write, (int, long long, long long), ());
|
||||||
MOCK_METHOD(void, write, (int, int), ());
|
MOCK_METHOD(void, write, (int, int), ());
|
||||||
MOCK_METHOD(void, write, (uint, uint, uint), ());
|
MOCK_METHOD(void, write, (uint, uint, uint), ());
|
||||||
MOCK_METHOD(void, write, (int, off_t, time_t), ());
|
MOCK_METHOD(void, write, (int, off_t, time_t), ());
|
||||||
@@ -109,6 +111,7 @@ public:
|
|||||||
MOCK_METHOD(void, write, (uint, Utils::SmallStringView), ());
|
MOCK_METHOD(void, write, (uint, Utils::SmallStringView), ());
|
||||||
MOCK_METHOD(void, write, (int, Utils::SmallStringView), ());
|
MOCK_METHOD(void, write, (int, Utils::SmallStringView), ());
|
||||||
MOCK_METHOD(void, write, (int, Utils::SmallStringView, long long), ());
|
MOCK_METHOD(void, write, (int, Utils::SmallStringView, long long), ());
|
||||||
|
MOCK_METHOD(void, write, (long long, Sqlite::NullValue, Sqlite::NullValue), ());
|
||||||
|
|
||||||
MOCK_METHOD(void, write, (Utils::span<int>, Utils::span<long long>), ());
|
MOCK_METHOD(void, write, (Utils::span<int>, Utils::span<long long>), ());
|
||||||
MOCK_METHOD(void, write, (Utils::span<long long>), ());
|
MOCK_METHOD(void, write, (Utils::span<long long>), ());
|
||||||
|
@@ -101,8 +101,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NiceMock<SqliteDatabaseMock> databaseMock;
|
NiceMock<ProjectStorageMock> mockStorage;
|
||||||
NiceMock<ProjectStorageMock> mockStorage{databaseMock};
|
|
||||||
StorageAdapter storageAdapter{mockStorage};
|
StorageAdapter storageAdapter{mockStorage};
|
||||||
Cache cache{storageAdapter};
|
Cache cache{storageAdapter};
|
||||||
typename Cache::MutexType &mockMutex = cache.mutex();
|
typename Cache::MutexType &mockMutex = cache.mutex();
|
||||||
|
Reference in New Issue
Block a user