forked from qt-creator/qt-creator
QmlDesigner: Add module scanner
For performance reason we want to get the qml modules directly from the file system. When the project storage is finished we can get the modules from there. Task-number: QDS-9542 Change-Id: I26d4b028fbf5ebc541fcd8e34d285ded1fb14935 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
committed by
Thomas Hartmann
parent
79b5a9f03e
commit
6035ff939d
@@ -57,6 +57,7 @@ add_qtc_library(QmlDesignerCore STATIC
|
||||
Utils
|
||||
Qt::Widgets
|
||||
Qt::Qml
|
||||
Qt::QmlPrivate
|
||||
Core
|
||||
ProjectExplorer
|
||||
QmakeProjectManager
|
||||
@@ -92,7 +93,7 @@ extend_qtc_library(QmlDesignerCore
|
||||
CONDITION TARGET Qt6::QmlDomPrivate AND TARGET Qt6::QmlCompilerPrivate AND Qt6_VERSION VERSION_GREATER_EQUAL 6.5.0
|
||||
|
||||
DEPENDS Qt6::QmlDomPrivate Qt6::QmlCompilerPrivate
|
||||
DEFINES QDS_HAS_QMLDOM
|
||||
PUBLIC_DEFINES QDS_HAS_QMLPRIVATE
|
||||
)
|
||||
|
||||
extend_qtc_library(QmlDesignerCore
|
||||
@@ -400,6 +401,7 @@ extend_qtc_library(QmlDesignerCore
|
||||
filesystem.cpp filesystem.h
|
||||
filestatus.h
|
||||
filestatuscache.cpp filestatuscache.h
|
||||
modulescanner.cpp modulescanner.h
|
||||
nonlockingmutex.h
|
||||
projectstorageexceptions.cpp projectstorageexceptions.h
|
||||
projectstorageinterface.h
|
||||
|
||||
@@ -95,7 +95,7 @@ void DesignerActionManagerView::nodeOrderChanged(const NodeListProperty &)
|
||||
setupContext(SelectionContext::UpdateMode::NodeHierachy);
|
||||
}
|
||||
|
||||
void DesignerActionManagerView::importsChanged(const QList<Import> &, const QList<Import> &)
|
||||
void DesignerActionManagerView::importsChanged(const Imports &, const Imports &)
|
||||
{
|
||||
setupContext();
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
void selectedNodesChanged(const QList<ModelNode> &,
|
||||
const QList<ModelNode> &) override;
|
||||
void nodeOrderChanged(const NodeListProperty &) override;
|
||||
void importsChanged(const QList<Import> &, const QList<Import> &) override;
|
||||
void importsChanged(const Imports &, const Imports &) override;
|
||||
void signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty> &/*propertyList*/, PropertyChangeFlags /*propertyChange*/) override;
|
||||
void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChangeFlag) override;
|
||||
void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChangeFlag) override;
|
||||
|
||||
@@ -183,7 +183,7 @@ void ConnectionView::auxiliaryDataChanged([[maybe_unused]] const ModelNode &node
|
||||
selectionModel->clearSelection();
|
||||
}
|
||||
|
||||
void ConnectionView::importsChanged(const QList<Import> & /*addedImports*/, const QList<Import> & /*removedImports*/)
|
||||
void ConnectionView::importsChanged(const Imports & /*addedImports*/, const Imports & /*removedImports*/)
|
||||
{
|
||||
backendModel()->resetModel();
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
AuxiliaryDataKeyView key,
|
||||
const QVariant &data) override;
|
||||
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
|
||||
void currentStateChanged(const ModelNode &node) override;
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ void ContentLibraryView::modelAboutToBeDetached(Model *model)
|
||||
AbstractView::modelAboutToBeDetached(model);
|
||||
}
|
||||
|
||||
void ContentLibraryView::importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
|
||||
void ContentLibraryView::importsChanged(const Imports &addedImports, const Imports &removedImports)
|
||||
{
|
||||
Q_UNUSED(addedImports)
|
||||
Q_UNUSED(removedImports)
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
// AbstractView
|
||||
void modelAttached(Model *model) override;
|
||||
void modelAboutToBeDetached(Model *model) override;
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
void active3DSceneChanged(qint32 sceneId) override;
|
||||
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
|
||||
const QList<ModelNode> &lastSelectedNodeList) override;
|
||||
|
||||
@@ -65,7 +65,7 @@ void DebugView::modelAboutToBeDetached(Model *model)
|
||||
AbstractView::modelAboutToBeDetached(model);
|
||||
}
|
||||
|
||||
void DebugView::importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
|
||||
void DebugView::importsChanged(const Imports &addedImports, const Imports &removedImports)
|
||||
{
|
||||
if (isDebugViewEnabled()) {
|
||||
QString message;
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
void modelAttached(Model *model) override;
|
||||
void modelAboutToBeDetached(Model *model) override;
|
||||
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
|
||||
void nodeCreated(const ModelNode &createdNode) override;
|
||||
void nodeAboutToBeRemoved(const ModelNode &removedNode) override;
|
||||
|
||||
@@ -312,8 +312,8 @@ void Edit3DView::modelAboutToBeDetached(Model *model)
|
||||
AbstractView::modelAboutToBeDetached(model);
|
||||
}
|
||||
|
||||
void Edit3DView::importsChanged([[maybe_unused]] const QList<Import> &addedImports,
|
||||
[[maybe_unused]] const QList<Import> &removedImports)
|
||||
void Edit3DView::importsChanged([[maybe_unused]] const Imports &addedImports,
|
||||
[[maybe_unused]] const Imports &removedImports)
|
||||
{
|
||||
checkImports();
|
||||
}
|
||||
@@ -920,7 +920,7 @@ void Edit3DView::addQuick3DImport()
|
||||
{
|
||||
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||
if (document && !document->inFileComponentModelActive() && model()) {
|
||||
const QList<Import> imports = model()->possibleImports();
|
||||
const Imports imports = model()->possibleImports();
|
||||
for (const auto &import : imports) {
|
||||
if (import.url() == "QtQuick3D") {
|
||||
if (!import.version().isEmpty() && import.majorVersion() >= 6) {
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
void updateActiveScene3D(const QVariantMap &sceneState) override;
|
||||
void modelAttached(Model *model) override;
|
||||
void modelAboutToBeDetached(Model *model) override;
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
|
||||
void nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos3d) override;
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@ void FormEditorView::modelAboutToBeDetached(Model *model)
|
||||
AbstractView::modelAboutToBeDetached(model);
|
||||
}
|
||||
|
||||
void FormEditorView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
|
||||
void FormEditorView::importsChanged(const Imports &/*addedImports*/, const Imports &/*removedImports*/)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
void modelAttached(Model *model) override;
|
||||
void modelAboutToBeDetached(Model *model) override;
|
||||
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
|
||||
void nodeCreated(const ModelNode &createdNode) override;
|
||||
void nodeAboutToBeRemoved(const ModelNode &removedNode) override;
|
||||
|
||||
@@ -56,14 +56,14 @@ QHash<int, QByteArray> ItemLibraryAddImportModel::roleNames() const
|
||||
return m_roleNames;
|
||||
}
|
||||
|
||||
void ItemLibraryAddImportModel::update(const QList<Import> &possibleImports)
|
||||
void ItemLibraryAddImportModel::update(const Imports &possibleImports)
|
||||
{
|
||||
beginResetModel();
|
||||
m_importList.clear();
|
||||
|
||||
const DesignerMcuManager &mcuManager = DesignerMcuManager::instance();
|
||||
const bool isQtForMCUs = mcuManager.isMCUProject();
|
||||
QList<Import> filteredImports;
|
||||
Imports filteredImports;
|
||||
if (isQtForMCUs) {
|
||||
const QStringList mcuAllowedList = mcuManager.allowedImports();
|
||||
const QStringList mcuBannedList = mcuManager.bannedImports();
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
void update(const QList<Import> &possibleImports);
|
||||
void update(const Imports &possibleImports);
|
||||
void setSearchText(const QString &searchText);
|
||||
Import getImportAt(int index) const;
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
|
||||
private:
|
||||
QString m_searchText;
|
||||
QList<Import> m_importList;
|
||||
Imports m_importList;
|
||||
QSet<QString> m_importFilterList;
|
||||
QHash<int, QByteArray> m_roleNames;
|
||||
QSet<QString> m_priorityImports;
|
||||
|
||||
@@ -709,9 +709,9 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport()
|
||||
model->rewriterView()->textModifier()->replace(0, 0, {});
|
||||
} else if (counter < 100) {
|
||||
try {
|
||||
const QList<Import> posImports = model->possibleImports();
|
||||
const QList<Import> currentImports = model->imports();
|
||||
QList<Import> newImportsToAdd;
|
||||
const Imports posImports = model->possibleImports();
|
||||
const Imports currentImports = model->imports();
|
||||
Imports newImportsToAdd;
|
||||
|
||||
for (auto &imp : std::as_const(m_requiredImports)) {
|
||||
const bool isPos = Utils::contains(posImports, [imp](const Import &posImp) {
|
||||
|
||||
@@ -107,7 +107,7 @@ private:
|
||||
int m_currentImportId = 0;
|
||||
QHash<int, ParseData> m_parseData;
|
||||
QString m_progressTitle;
|
||||
QList<Import> m_requiredImports;
|
||||
Imports m_requiredImports;
|
||||
QList<int> m_puppetQueue;
|
||||
};
|
||||
} // QmlDesigner
|
||||
|
||||
@@ -343,7 +343,7 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
|
||||
materialBundlePrefix.append(".MaterialBundle");
|
||||
|
||||
// create import sections
|
||||
const QList<Import> usedImports = model->usedImports();
|
||||
const Imports usedImports = model->usedImports();
|
||||
QHash<QString, ItemLibraryImport *> importHash;
|
||||
for (const Import &import : model->imports()) {
|
||||
if (import.url() != projectName) {
|
||||
@@ -550,7 +550,7 @@ ItemLibraryImport *ItemLibraryModel::importByUrl(const QString &importUrl) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ItemLibraryModel::updateUsedImports(const QList<Import> &usedImports)
|
||||
void ItemLibraryModel::updateUsedImports(const Imports &usedImports)
|
||||
{
|
||||
// imports in the excludeList are not marked used and thus can always be removed even when in use.
|
||||
const QList<QString> excludeList = {"SimulinkConnector"};
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
ItemLibraryImport *importByUrl(const QString &importName) const;
|
||||
|
||||
void update(ItemLibraryInfo *itemLibraryInfo, Model *model);
|
||||
void updateUsedImports(const QList<Import> &usedImports);
|
||||
void updateUsedImports(const Imports &usedImports);
|
||||
|
||||
QMimeData *getMimeData(const ItemLibraryEntry &itemLibraryEntry);
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ void ItemLibraryView::modelAboutToBeDetached(Model *model)
|
||||
m_widget->setModel(nullptr);
|
||||
}
|
||||
|
||||
void ItemLibraryView::importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
|
||||
void ItemLibraryView::importsChanged(const Imports &addedImports, const Imports &removedImports)
|
||||
{
|
||||
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||
for (const auto &import : addedImports)
|
||||
@@ -111,7 +111,7 @@ void ItemLibraryView::importsChanged(const QList<Import> &addedImports, const QL
|
||||
}
|
||||
}
|
||||
|
||||
void ItemLibraryView::possibleImportsChanged(const QList<Import> &possibleImports)
|
||||
void ItemLibraryView::possibleImportsChanged(const Imports &possibleImports)
|
||||
{
|
||||
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||
for (const auto &import : possibleImports)
|
||||
@@ -120,7 +120,7 @@ void ItemLibraryView::possibleImportsChanged(const QList<Import> &possibleImport
|
||||
m_widget->updatePossibleImports(possibleImports);
|
||||
}
|
||||
|
||||
void ItemLibraryView::usedImportsChanged(const QList<Import> &usedImports)
|
||||
void ItemLibraryView::usedImportsChanged(const Imports &usedImports)
|
||||
{
|
||||
m_widget->updateUsedImports(usedImports);
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@ public:
|
||||
// AbstractView
|
||||
void modelAttached(Model *model) override;
|
||||
void modelAboutToBeDetached(Model *model) override;
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void possibleImportsChanged(const QList<Import> &possibleImports) override;
|
||||
void usedImportsChanged(const QList<Import> &usedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
void possibleImportsChanged(const Imports &possibleImports) override;
|
||||
void usedImportsChanged(const Imports &usedImports) override;
|
||||
void documentMessagesChanged(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &warnings) override;
|
||||
void updateImport3DSupport(const QVariantMap &supportMap) override;
|
||||
void customNotification(const AbstractView *view, const QString &identifier,
|
||||
|
||||
@@ -86,7 +86,7 @@ bool ItemLibraryWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
Import fileImport = Import::createFileImport(entry.requiredImport());
|
||||
if (!m_model->hasImport(libImport, true, true)
|
||||
&& !m_model->hasImport(fileImport, true, true)) {
|
||||
const QList<Import> possImports = m_model->possibleImports();
|
||||
const Imports possImports = m_model->possibleImports();
|
||||
for (const auto &possImport : possImports) {
|
||||
if ((!possImport.url().isEmpty() && possImport.url() == libImport.url())
|
||||
|| (!possImport.file().isEmpty() && possImport.file() == fileImport.file())) {
|
||||
@@ -246,7 +246,7 @@ void ItemLibraryWidget::handleAddImport(int index)
|
||||
+ importStr);
|
||||
}
|
||||
|
||||
QList<Import> imports;
|
||||
Imports imports;
|
||||
const QString dependency = getDependencyImport(import);
|
||||
|
||||
auto document = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||
@@ -346,13 +346,13 @@ void ItemLibraryWidget::updateModel()
|
||||
updateSearch();
|
||||
}
|
||||
|
||||
void ItemLibraryWidget::updatePossibleImports(const QList<Import> &possibleImports)
|
||||
void ItemLibraryWidget::updatePossibleImports(const Imports &possibleImports)
|
||||
{
|
||||
m_addModuleModel->update(possibleImports);
|
||||
delayedUpdateModel();
|
||||
}
|
||||
|
||||
void ItemLibraryWidget::updateUsedImports(const QList<Import> &usedImports)
|
||||
void ItemLibraryWidget::updateUsedImports(const Imports &usedImports)
|
||||
{
|
||||
m_itemLibraryModel->updateUsedImports(usedImports);
|
||||
}
|
||||
|
||||
@@ -60,8 +60,8 @@ public:
|
||||
void switchToComponentsView();
|
||||
void delayedUpdateModel();
|
||||
void updateModel();
|
||||
void updatePossibleImports(const QList<Import> &possibleImports);
|
||||
void updateUsedImports(const QList<Import> &usedImports);
|
||||
void updatePossibleImports(const Imports &possibleImports);
|
||||
void updateUsedImports(const Imports &usedImports);
|
||||
|
||||
void setModel(Model *model);
|
||||
void setFlowMode(bool b);
|
||||
|
||||
@@ -469,8 +469,8 @@ ModelNode MaterialBrowserView::getMaterialOfModel(const ModelNode &model, int id
|
||||
return mat;
|
||||
}
|
||||
|
||||
void MaterialBrowserView::importsChanged([[maybe_unused]] const QList<Import> &addedImports,
|
||||
[[maybe_unused]] const QList<Import> &removedImports)
|
||||
void MaterialBrowserView::importsChanged([[maybe_unused]] const Imports &addedImports,
|
||||
[[maybe_unused]] const Imports &removedImports)
|
||||
{
|
||||
bool hasQuick3DImport = model()->hasImport("QtQuick3D");
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
void nodeAboutToBeRemoved(const ModelNode &removedNode) override;
|
||||
void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty,
|
||||
PropertyChangeFlags propertyChange) override;
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
void customNotification(const AbstractView *view, const QString &identifier,
|
||||
const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
|
||||
void instancesCompleted(const QVector<ModelNode> &completedNodeList) override;
|
||||
|
||||
@@ -974,8 +974,8 @@ void MaterialEditorView::modelNodePreviewPixmapChanged(const ModelNode &node, co
|
||||
m_qmlBackEnd->updateMaterialPreview(pixmap);
|
||||
}
|
||||
|
||||
void MaterialEditorView::importsChanged([[maybe_unused]] const QList<Import> &addedImports,
|
||||
[[maybe_unused]] const QList<Import> &removedImports)
|
||||
void MaterialEditorView::importsChanged([[maybe_unused]] const Imports &addedImports,
|
||||
[[maybe_unused]] const Imports &removedImports)
|
||||
{
|
||||
m_hasQuick3DImport = model()->hasImport("QtQuick3D");
|
||||
m_qmlBackEnd->contextObject()->setHasQuick3DImport(m_hasQuick3DImport);
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
void nodeTypeChanged(const ModelNode& node, const TypeName &type, int majorVersion, int minorVersion) override;
|
||||
void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) override;
|
||||
void modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap) override;
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
void customNotification(const AbstractView *view, const QString &identifier,
|
||||
const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
|
||||
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent,
|
||||
|
||||
@@ -901,7 +901,7 @@ void NavigatorTreeModel::addImport(const QString &importName)
|
||||
{
|
||||
Import import = Import::createLibraryImport(importName);
|
||||
if (!m_view->model()->hasImport(import, true, true)) {
|
||||
const QList<Import> possImports = m_view->model()->possibleImports();
|
||||
const Imports possImports = m_view->model()->possibleImports();
|
||||
for (const auto &possImport : possImports) {
|
||||
if (possImport.url() == import.url()) {
|
||||
import = possImport;
|
||||
|
||||
@@ -228,7 +228,7 @@ void NavigatorView::modelAboutToBeDetached(Model *model)
|
||||
AbstractView::modelAboutToBeDetached(model);
|
||||
}
|
||||
|
||||
void NavigatorView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
|
||||
void NavigatorView::importsChanged(const Imports &/*addedImports*/, const Imports &/*removedImports*/)
|
||||
{
|
||||
treeWidget()->update();
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
void modelAttached(Model *model) override;
|
||||
void modelAboutToBeDetached(Model *model) override;
|
||||
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
|
||||
void nodeAboutToBeRemoved(const ModelNode &removedNode) override;
|
||||
void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange) override;
|
||||
|
||||
@@ -103,7 +103,7 @@ void TextEditorView::modelAboutToBeDetached(Model *model)
|
||||
}
|
||||
}
|
||||
|
||||
void TextEditorView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
|
||||
void TextEditorView::importsChanged(const Imports &/*addedImports*/, const Imports &/*removedImports*/)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
void modelAttached(Model *model) override;
|
||||
void modelAboutToBeDetached(Model *model) override;
|
||||
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
|
||||
void nodeAboutToBeRemoved(const ModelNode &removedNode) override;
|
||||
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange) override;
|
||||
|
||||
@@ -720,8 +720,8 @@ void TextureEditorView::instancePropertyChanged(const QList<QPair<ModelNode, Pro
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
void TextureEditorView::importsChanged([[maybe_unused]] const QList<Import> &addedImports,
|
||||
[[maybe_unused]] const QList<Import> &removedImports)
|
||||
void TextureEditorView::importsChanged([[maybe_unused]] const Imports &addedImports,
|
||||
[[maybe_unused]] const Imports &removedImports)
|
||||
{
|
||||
m_hasQuick3DImport = model()->hasImport("QtQuick3D");
|
||||
m_qmlBackEnd->contextObject()->setHasQuick3DImport(m_hasQuick3DImport);
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
void currentStateChanged(const ModelNode &node) override;
|
||||
void instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &propertyList) override;
|
||||
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
void customNotification(const AbstractView *view, const QString &identifier,
|
||||
const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
|
||||
|
||||
|
||||
@@ -195,9 +195,9 @@ public:
|
||||
const ModelNode &movedNode,
|
||||
int oldIndex);
|
||||
|
||||
virtual void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports);
|
||||
virtual void possibleImportsChanged(const QList<Import> &possibleImports);
|
||||
virtual void usedImportsChanged(const QList<Import> &usedImports);
|
||||
virtual void importsChanged(const Imports &addedImports, const Imports &removedImports);
|
||||
virtual void possibleImportsChanged(const Imports &possibleImports);
|
||||
virtual void usedImportsChanged(const Imports &usedImports);
|
||||
|
||||
virtual void auxiliaryDataChanged(const ModelNode &node,
|
||||
AuxiliaryDataKeyView type,
|
||||
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
virtual PuppetStartData puppetStartData(const class Model &model) const = 0;
|
||||
virtual bool instantQmlTextUpdate() const = 0;
|
||||
virtual Utils::FilePath qmlPuppetPath() const = 0;
|
||||
virtual QStringList modulePaths() const = 0;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
void fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl) override;
|
||||
|
||||
void nodeOrderChanged(const NodeListProperty &listProperty) override;
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
|
||||
void auxiliaryDataChanged(const ModelNode &node, const PropertyName &name, const QVariant &data) override;
|
||||
|
||||
@@ -197,7 +197,7 @@ void ForwardView<ViewType>::nodeOrderChanged(const NodeListProperty &listPropert
|
||||
}
|
||||
|
||||
template <class ViewType>
|
||||
void ForwardView<ViewType>::importChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
|
||||
void ForwardView<ViewType>::importChanged(const Imports &addedImports, const Imports &removedImports)
|
||||
{
|
||||
for (const ViewTypePointer &view : std::as_const(m_targetViewList))
|
||||
view->importChanged(addedImport, removedImport);
|
||||
|
||||
@@ -56,6 +56,8 @@ private:
|
||||
|
||||
QMLDESIGNERCORE_EXPORT size_t qHash(const Import &import);
|
||||
|
||||
using Imports = QList<Import>;
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
||||
Q_DECLARE_METATYPE(QmlDesigner::Import)
|
||||
|
||||
@@ -115,12 +115,12 @@ public:
|
||||
// Editing sub-components:
|
||||
|
||||
// Imports:
|
||||
const QList<Import> &imports() const;
|
||||
const QList<Import> &possibleImports() const;
|
||||
const QList<Import> &usedImports() const;
|
||||
void changeImports(const QList<Import> &importsToBeAdded, const QList<Import> &importsToBeRemoved);
|
||||
void setPossibleImports(const QList<Import> &possibleImports);
|
||||
void setUsedImports(const QList<Import> &usedImports);
|
||||
const Imports &imports() const;
|
||||
const Imports &possibleImports() const;
|
||||
const Imports &usedImports() const;
|
||||
void changeImports(const Imports &importsToBeAdded, const Imports &importsToBeRemoved);
|
||||
void setPossibleImports(const Imports &possibleImports);
|
||||
void setUsedImports(const Imports &usedImports);
|
||||
bool hasImport(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false) const;
|
||||
bool isImportPossible(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false) const;
|
||||
QString pathForImport(const Import &import);
|
||||
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
void fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl) override;
|
||||
void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId) override;
|
||||
void nodeOrderChanged(const NodeListProperty &listProperty) override;
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
void auxiliaryDataChanged(const ModelNode &node,
|
||||
AuxiliaryDataKeyView key,
|
||||
const QVariant &data) override;
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
void rewriterBeginTransaction() override;
|
||||
void rewriterEndTransaction() override;
|
||||
|
||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
|
||||
TextModifier *textModifier() const;
|
||||
void setTextModifier(TextModifier *textModifier);
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
explicit SubComponentManager(Model *model,
|
||||
class ExternalDependenciesInterface &externalDependencies);
|
||||
|
||||
void update(const QUrl &fileUrl, const QList<Import> &imports);
|
||||
void update(const QUrl &fileUrl, const Imports &imports);
|
||||
void addAndParseImport(const Import &import);
|
||||
|
||||
QStringList qmlFiles() const;
|
||||
@@ -53,7 +53,7 @@ private: // functions
|
||||
|
||||
private: // variables
|
||||
QFileSystemWatcher m_watcher;
|
||||
QList<Import> m_imports;
|
||||
Imports m_imports;
|
||||
// key: canonical directory path
|
||||
QMultiHash<QString,QString> m_dirToQualifier;
|
||||
QUrl m_filePath;
|
||||
|
||||
@@ -625,7 +625,7 @@ void NodeInstanceView::nodeOrderChanged(const NodeListProperty &listProperty)
|
||||
m_nodeInstanceServer->reparentInstances(ReparentInstancesCommand(containerList));
|
||||
}
|
||||
|
||||
void NodeInstanceView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
|
||||
void NodeInstanceView::importsChanged(const Imports &/*addedImports*/, const Imports &/*removedImports*/)
|
||||
{
|
||||
restartProcess();
|
||||
}
|
||||
|
||||
@@ -768,7 +768,7 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, TypeName type, int maj, i
|
||||
}
|
||||
} else {
|
||||
m_isFileComponent = true;
|
||||
const Imports *imports = context()->imports(document());
|
||||
const auto *imports = context()->imports(document());
|
||||
const ImportInfo importInfo = imports->info(lookupNameComponent().constLast(),
|
||||
context().data());
|
||||
|
||||
@@ -791,7 +791,7 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, TypeName type, int maj, i
|
||||
} else {
|
||||
// Special case for aliased types for the rewriter
|
||||
|
||||
const Imports *imports = context()->imports(document());
|
||||
const auto *imports = context()->imports(document());
|
||||
const ImportInfo importInfo = imports->info(QString::fromUtf8(m_qualfiedTypeName),
|
||||
context().data());
|
||||
if (importInfo.isValid()) {
|
||||
@@ -1198,7 +1198,7 @@ QString NodeMetaInfoPrivate::importDirectoryPath() const
|
||||
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
|
||||
|
||||
if (isValid()) {
|
||||
const Imports *imports = context()->imports(document());
|
||||
const auto *imports = context()->imports(document());
|
||||
ImportInfo importInfo = imports->info(lookupNameComponent().constLast(), context().data());
|
||||
|
||||
if (importInfo.type() == ImportType::Directory) {
|
||||
@@ -1333,7 +1333,7 @@ void NodeMetaInfoPrivate::setupPrototypes()
|
||||
m_prototypes.append(description);
|
||||
} else {
|
||||
if (context()->lookupType(document(), {ov->className()})) {
|
||||
const Imports *allImports = context()->imports(document());
|
||||
const auto *allImports = context()->imports(document());
|
||||
ImportInfo importInfo = allImports->info(description.className, context().data());
|
||||
|
||||
if (importInfo.isValid()) {
|
||||
|
||||
@@ -491,7 +491,7 @@ QStringList SubComponentManager::qmlFiles() const
|
||||
return m_watcher.files();
|
||||
}
|
||||
|
||||
void SubComponentManager::update(const QUrl &filePath, const QList<Import> &imports)
|
||||
void SubComponentManager::update(const QUrl &filePath, const Imports &imports)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << filePath << imports.size();
|
||||
|
||||
@@ -315,15 +315,15 @@ void AbstractView::nodeTypeChanged(const ModelNode & /*node*/, const TypeName &
|
||||
|
||||
}
|
||||
|
||||
void AbstractView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
|
||||
void AbstractView::importsChanged(const Imports &/*addedImports*/, const Imports &/*removedImports*/)
|
||||
{
|
||||
}
|
||||
|
||||
void AbstractView::possibleImportsChanged(const QList<Import> &/*possibleImports*/)
|
||||
void AbstractView::possibleImportsChanged(const Imports &/*possibleImports*/)
|
||||
{
|
||||
}
|
||||
|
||||
void AbstractView::usedImportsChanged(const QList<Import> &/*usedImports*/)
|
||||
void AbstractView::usedImportsChanged(const Imports &/*usedImports*/)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -893,7 +893,7 @@ QmlTimeline AbstractView::currentTimeline() const
|
||||
|
||||
static int getMinorVersionFromImport(const Model *model)
|
||||
{
|
||||
const QList<Import> imports = model->imports();
|
||||
const Imports imports = model->imports();
|
||||
for (const Import &import : imports) {
|
||||
if (import.isLibraryImport() && import.url() == "QtQuick") {
|
||||
const QString versionString = import.version();
|
||||
@@ -909,7 +909,7 @@ static int getMinorVersionFromImport(const Model *model)
|
||||
|
||||
static int getMajorVersionFromImport(const Model *model)
|
||||
{
|
||||
const QList<Import> imports = model->imports();
|
||||
const Imports imports = model->imports();
|
||||
for (const Import &import : imports) {
|
||||
if (import.isLibraryImport() && import.url() == QStringLiteral("QtQuick")) {
|
||||
const QString versionString = import.version();
|
||||
|
||||
@@ -108,10 +108,10 @@ void ModelPrivate::detachAllViews()
|
||||
}
|
||||
}
|
||||
|
||||
void ModelPrivate::changeImports(const QList<Import> &toBeAddedImportList,
|
||||
const QList<Import> &toBeRemovedImportList)
|
||||
void ModelPrivate::changeImports(const Imports &toBeAddedImportList,
|
||||
const Imports &toBeRemovedImportList)
|
||||
{
|
||||
QList<Import> removedImportList;
|
||||
Imports removedImportList;
|
||||
for (const Import &import : toBeRemovedImportList) {
|
||||
if (m_imports.contains(import)) {
|
||||
removedImportList.append(import);
|
||||
@@ -119,7 +119,7 @@ void ModelPrivate::changeImports(const QList<Import> &toBeAddedImportList,
|
||||
}
|
||||
}
|
||||
|
||||
QList<Import> addedImportList;
|
||||
Imports addedImportList;
|
||||
for (const Import &import : toBeAddedImportList) {
|
||||
if (!m_imports.contains(import)) {
|
||||
addedImportList.append(import);
|
||||
@@ -131,8 +131,7 @@ void ModelPrivate::changeImports(const QList<Import> &toBeAddedImportList,
|
||||
notifyImportsChanged(addedImportList, removedImportList);
|
||||
}
|
||||
|
||||
void ModelPrivate::notifyImportsChanged(const QList<Import> &addedImports,
|
||||
const QList<Import> &removedImports)
|
||||
void ModelPrivate::notifyImportsChanged(const Imports &addedImports, const Imports &removedImports)
|
||||
{
|
||||
bool resetModel = false;
|
||||
QString description;
|
||||
@@ -157,7 +156,7 @@ void ModelPrivate::notifyImportsChanged(const QList<Import> &addedImports,
|
||||
resetModelByRewriter(description);
|
||||
}
|
||||
|
||||
void ModelPrivate::notifyPossibleImportsChanged(const QList<Import> &possibleImports)
|
||||
void ModelPrivate::notifyPossibleImportsChanged(const Imports &possibleImports)
|
||||
{
|
||||
for (const QPointer<AbstractView> &view : enabledViews()) {
|
||||
Q_ASSERT(view != nullptr);
|
||||
@@ -165,7 +164,7 @@ void ModelPrivate::notifyPossibleImportsChanged(const QList<Import> &possibleImp
|
||||
}
|
||||
}
|
||||
|
||||
void ModelPrivate::notifyUsedImportsChanged(const QList<Import> &usedImports)
|
||||
void ModelPrivate::notifyUsedImportsChanged(const Imports &usedImports)
|
||||
{
|
||||
for (const QPointer<AbstractView> &view : enabledViews()) {
|
||||
Q_ASSERT(view != nullptr);
|
||||
@@ -1400,28 +1399,27 @@ Model::Model(const TypeName &typeName, int major, int minor, Model *metaInfoProx
|
||||
|
||||
Model::~Model() = default;
|
||||
|
||||
const QList<Import> &Model::imports() const
|
||||
const Imports &Model::imports() const
|
||||
{
|
||||
return d->imports();
|
||||
}
|
||||
|
||||
const QList<Import> &Model::possibleImports() const
|
||||
const Imports &Model::possibleImports() const
|
||||
{
|
||||
return d->m_possibleImportList;
|
||||
}
|
||||
|
||||
const QList<Import> &Model::usedImports() const
|
||||
const Imports &Model::usedImports() const
|
||||
{
|
||||
return d->m_usedImportList;
|
||||
}
|
||||
|
||||
void Model::changeImports(const QList<Import> &importsToBeAdded,
|
||||
const QList<Import> &importsToBeRemoved)
|
||||
void Model::changeImports(const Imports &importsToBeAdded, const Imports &importsToBeRemoved)
|
||||
{
|
||||
d->changeImports(importsToBeAdded, importsToBeRemoved);
|
||||
}
|
||||
|
||||
void Model::setPossibleImports(const QList<Import> &possibleImports)
|
||||
void Model::setPossibleImports(const Imports &possibleImports)
|
||||
{
|
||||
if (d->m_possibleImportList != possibleImports) {
|
||||
d->m_possibleImportList = possibleImports;
|
||||
@@ -1429,7 +1427,7 @@ void Model::setPossibleImports(const QList<Import> &possibleImports)
|
||||
}
|
||||
}
|
||||
|
||||
void Model::setUsedImports(const QList<Import> &usedImports)
|
||||
void Model::setUsedImports(const Imports &usedImports)
|
||||
{
|
||||
if (d->m_usedImportList != usedImports) {
|
||||
d->m_usedImportList = usedImports;
|
||||
|
||||
@@ -202,13 +202,13 @@ public:
|
||||
void resetModelByRewriter(const QString &description);
|
||||
|
||||
// Imports:
|
||||
const QList<Import> &imports() const { return m_imports; }
|
||||
const Imports &imports() const { return m_imports; }
|
||||
void addImport(const Import &import);
|
||||
void removeImport(const Import &import);
|
||||
void changeImports(const QList<Import> &importsToBeAdded, const QList<Import> &importToBeRemoved);
|
||||
void notifyImportsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports);
|
||||
void notifyPossibleImportsChanged(const QList<Import> &possibleImports);
|
||||
void notifyUsedImportsChanged(const QList<Import> &usedImportsChanged);
|
||||
void changeImports(const Imports &importsToBeAdded, const Imports &importToBeRemoved);
|
||||
void notifyImportsChanged(const Imports &addedImports, const Imports &removedImports);
|
||||
void notifyPossibleImportsChanged(const Imports &possibleImports);
|
||||
void notifyUsedImportsChanged(const Imports &usedImportsChanged);
|
||||
|
||||
//node state property manipulation
|
||||
void addProperty(const InternalNodePointer &node, const PropertyName &name);
|
||||
@@ -269,9 +269,9 @@ private:
|
||||
private:
|
||||
Model *m_model = nullptr;
|
||||
MetaInfo m_metaInfo;
|
||||
QList<Import> m_imports;
|
||||
QList<Import> m_possibleImportList;
|
||||
QList<Import> m_usedImportList;
|
||||
Imports m_imports;
|
||||
Imports m_possibleImportList;
|
||||
Imports m_usedImportList;
|
||||
QList<QPointer<AbstractView>> m_viewList;
|
||||
QList<QPointer<AbstractView>> m_enabledViewList;
|
||||
QList<InternalNodePointer> m_selectedInternalNodeList;
|
||||
|
||||
@@ -173,7 +173,7 @@ ModelNode ModelMerger::insertModel(const ModelNode &modelNode, const MergePredic
|
||||
return {};
|
||||
RewriterTransaction transaction(view()->beginRewriterTransaction(QByteArrayLiteral("ModelMerger::insertModel")));
|
||||
|
||||
QList<Import> newImports;
|
||||
Imports newImports;
|
||||
|
||||
for (const Import &import : modelNode.model()->imports()) {
|
||||
if (!view()->model()->hasImport(import, true, true))
|
||||
|
||||
@@ -261,7 +261,7 @@ void RewriterView::nodeReparented(const ModelNode &node, const NodeAbstractPrope
|
||||
applyChanges();
|
||||
}
|
||||
|
||||
void RewriterView::importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
|
||||
void RewriterView::importsChanged(const Imports &addedImports, const Imports &removedImports)
|
||||
{
|
||||
for (const Import &import : addedImports)
|
||||
importAdded(import);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "signalhandlerproperty.h"
|
||||
#include "variantproperty.h"
|
||||
#include <externaldependenciesinterface.h>
|
||||
#include <projectstorage/modulescanner.h>
|
||||
#include <rewritingexception.h>
|
||||
|
||||
#include <enumeration.h>
|
||||
@@ -44,6 +45,7 @@
|
||||
#include <QSet>
|
||||
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
|
||||
using namespace LanguageUtils;
|
||||
using namespace QmlJS;
|
||||
@@ -716,7 +718,7 @@ bool TextToModelMerger::isActive() const
|
||||
void TextToModelMerger::setupImports(const Document::Ptr &doc,
|
||||
DifferenceHandler &differenceHandler)
|
||||
{
|
||||
QList<Import> existingImports = m_rewriterView->model()->imports();
|
||||
Imports existingImports = m_rewriterView->model()->imports();
|
||||
|
||||
m_hasVersionlessImport = false;
|
||||
|
||||
@@ -756,87 +758,87 @@ void TextToModelMerger::setupImports(const Document::Ptr &doc,
|
||||
differenceHandler.importAbsentInQMl(import);
|
||||
}
|
||||
|
||||
static bool isLatestImportVersion(const ImportKey &importKey, const QHash<QString, ImportKey> &filteredPossibleImportKeys)
|
||||
namespace {
|
||||
|
||||
bool skipByMetaInfo(QStringView moduleName, const QStringList &skipModuleNames)
|
||||
{
|
||||
return !filteredPossibleImportKeys.contains(importKey.path())
|
||||
|| filteredPossibleImportKeys.value(importKey.path()).majorVersion < importKey.majorVersion
|
||||
|| (filteredPossibleImportKeys.value(importKey.path()).majorVersion == importKey.majorVersion
|
||||
&& filteredPossibleImportKeys.value(importKey.path()).minorVersion < importKey.minorVersion);
|
||||
return std::any_of(skipModuleNames.begin(),
|
||||
skipModuleNames.end(),
|
||||
[&](const QString &skipModuleName) {
|
||||
return moduleName.contains(skipModuleName);
|
||||
});
|
||||
}
|
||||
|
||||
static bool filterByMetaInfo(const ImportKey &importKey, Model *model)
|
||||
class StartsWith : public QStringView
|
||||
{
|
||||
if (model) {
|
||||
for (const QString &filter : model->metaInfo().itemLibraryInfo()->blacklistImports()) {
|
||||
if (importKey.libraryQualifiedPath().contains(filter))
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
using QStringView::QStringView;
|
||||
bool operator()(QStringView moduleName) const { return moduleName.startsWith(*this); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isBlacklistImport(const ImportKey &importKey, Model *model)
|
||||
class EndsWith : public QStringView
|
||||
{
|
||||
const QString &importPathFirst = importKey.splitPath.constFirst();
|
||||
const QString &importPathLast = importKey.splitPath.constLast();
|
||||
return importPathFirst == QStringLiteral("<cpp>")
|
||||
|| importPathFirst == QStringLiteral("QML")
|
||||
|| importPathFirst == QStringLiteral("QtQml")
|
||||
|| (importPathFirst == QStringLiteral("QtQuick") && importPathLast == QStringLiteral("PrivateWidgets"))
|
||||
|| importPathLast == QStringLiteral("Private")
|
||||
|| importPathLast == QStringLiteral("private")
|
||||
|| importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Particles") //Unsupported
|
||||
|| importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Dialogs") //Unsupported
|
||||
|| importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Controls.Styles") //Unsupported
|
||||
|| importKey.libraryQualifiedPath() == QStringLiteral("QtNfc") //Unsupported
|
||||
|| importKey.libraryQualifiedPath() == QStringLiteral("Qt.WebSockets")
|
||||
|| importKey.libraryQualifiedPath() == QStringLiteral("QtWebkit")
|
||||
|| importKey.libraryQualifiedPath() == QStringLiteral("QtLocation")
|
||||
|| importKey.libraryQualifiedPath() == QStringLiteral("QtWebChannel")
|
||||
|| importKey.libraryQualifiedPath() == QStringLiteral("QtWinExtras")
|
||||
|| importKey.libraryQualifiedPath() == QStringLiteral("QtPurchasing")
|
||||
|| importKey.libraryQualifiedPath() == QStringLiteral("QtBluetooth")
|
||||
|| importKey.libraryQualifiedPath() == QStringLiteral("Enginio")
|
||||
public:
|
||||
using QStringView::QStringView;
|
||||
bool operator()(QStringView moduleName) const { return moduleName.endsWith(*this); }
|
||||
};
|
||||
|
||||
|| filterByMetaInfo(importKey, model);
|
||||
}
|
||||
|
||||
static QHash<QString, ImportKey> filterPossibleImportKeys(const QSet<ImportKey> &possibleImportKeys, Model *model)
|
||||
class StartsAndEndsWith : public std::pair<QStringView, QStringView>
|
||||
{
|
||||
QHash<QString, ImportKey> filteredPossibleImportKeys;
|
||||
for (const ImportKey &importKey : possibleImportKeys) {
|
||||
if (isLatestImportVersion(importKey, filteredPossibleImportKeys) && !isBlacklistImport(importKey, model))
|
||||
filteredPossibleImportKeys.insert(importKey.path(), importKey);
|
||||
}
|
||||
|
||||
return filteredPossibleImportKeys;
|
||||
}
|
||||
|
||||
static void removeUsedImports(QHash<QString, ImportKey> &filteredPossibleImportKeys, const QList<QmlJS::Import> &usedImports)
|
||||
public:
|
||||
using Base = std::pair<QStringView, QStringView>;
|
||||
using Base::Base;
|
||||
bool operator()(QStringView moduleName) const
|
||||
{
|
||||
for (const QmlJS::Import &import : usedImports)
|
||||
filteredPossibleImportKeys.remove(import.info.path());
|
||||
return moduleName.startsWith(first) && moduleName.endsWith(second);
|
||||
}
|
||||
};
|
||||
|
||||
class Equals : public QStringView
|
||||
{
|
||||
public:
|
||||
using QStringView::QStringView;
|
||||
bool operator()(QStringView moduleName) const { return moduleName == *this; }
|
||||
};
|
||||
|
||||
constexpr auto skipModules = std::make_tuple(EndsWith(u".impl"),
|
||||
StartsWith(u"QML"),
|
||||
StartsWith(u"QtQml"),
|
||||
StartsAndEndsWith(u"QtQuick", u".PrivateWidgets"),
|
||||
EndsWith(u".private"),
|
||||
EndsWith(u".Private"),
|
||||
Equals(u"QtQuick.Particles"),
|
||||
Equals(u"QtQuick.Dialogs"),
|
||||
Equals(u"QtQuick.Controls.Styles"),
|
||||
Equals(u"QtNfc"),
|
||||
Equals(u"Qt.WebSockets"),
|
||||
Equals(u"QtWebkit"),
|
||||
Equals(u"QtLocation"),
|
||||
Equals(u"QtWebChannel"),
|
||||
Equals(u"QtWinExtras"),
|
||||
Equals(u"QtPurchasing"),
|
||||
Equals(u"QtBluetooth"),
|
||||
Equals(u"Enginio"));
|
||||
|
||||
bool skipModule(QStringView moduleName)
|
||||
{
|
||||
return std::apply([=](const auto &...skipModule) { return (skipModule(moduleName) || ...); },
|
||||
skipModules);
|
||||
}
|
||||
|
||||
static QList<QmlDesigner::Import> generatePossibleFileImports(const QString &path,
|
||||
const QList<QmlJS::Import> &usedImports)
|
||||
bool skipModule(QStringView moduleName, const QStringList &skipModuleNames)
|
||||
{
|
||||
QSet<QString> usedImportsSet;
|
||||
for (const QmlJS::Import &i : usedImports)
|
||||
usedImportsSet.insert(i.info.path());
|
||||
return skipModule(moduleName) || skipByMetaInfo(moduleName, skipModuleNames);
|
||||
}
|
||||
|
||||
QList<QmlDesigner::Import> possibleImports;
|
||||
void collectPossibleFileImports(const QString &checkPath,
|
||||
QSet<QString> usedImportsSet,
|
||||
QList<QmlDesigner::Import> &possibleImports)
|
||||
{
|
||||
const QStringList qmlList("*.qml");
|
||||
const QStringList qmldirList("qmldir");
|
||||
|
||||
QStringList fileImportPaths;
|
||||
const QChar delimeter('/');
|
||||
|
||||
std::function<void(const QString &)> checkDir;
|
||||
checkDir = [&](const QString &checkPath) {
|
||||
|
||||
if (QFileInfo(checkPath).isRoot())
|
||||
return;
|
||||
|
||||
@@ -848,70 +850,33 @@ static QList<QmlDesigner::Import> generatePossibleFileImports(const QString &pat
|
||||
if (!dir.entryInfoList(qmlList, QDir::Files).isEmpty()
|
||||
&& dir.entryInfoList(qmldirList, QDir::Files).isEmpty()
|
||||
&& !usedImportsSet.contains(dirPath)) {
|
||||
const QString importName = dir.path().mid(path.size() + 1);
|
||||
const QString importName = dir.path().mid(checkPath.size() + 1);
|
||||
QmlDesigner::Import import = QmlDesigner::Import::createFileImport(importName);
|
||||
possibleImports.append(import);
|
||||
}
|
||||
checkDir(dirPath);
|
||||
collectPossibleFileImports(dirPath, usedImportsSet, possibleImports);
|
||||
}
|
||||
};
|
||||
checkDir(path);
|
||||
|
||||
return possibleImports;
|
||||
}
|
||||
|
||||
static QList<QmlDesigner::Import> generatePossibleLibraryImports(const QHash<QString, ImportKey> &filteredPossibleImportKeys)
|
||||
QList<QmlDesigner::Import> generatePossibleFileImports(const QString &path,
|
||||
const QList<QmlJS::Import> &usedImports)
|
||||
{
|
||||
QSet<QString> usedImportsSet;
|
||||
for (const QmlJS::Import &i : usedImports)
|
||||
usedImportsSet.insert(i.info.path());
|
||||
|
||||
QList<QmlDesigner::Import> possibleImports;
|
||||
QSet<QString> controlsImplVersions;
|
||||
bool hasVersionedControls = false;
|
||||
bool hasVersionlessControls = false;
|
||||
const QString controlsName = "QtQuick.Controls";
|
||||
const QString controlsImplName = "QtQuick.Controls.impl";
|
||||
|
||||
for (const ImportKey &importKey : filteredPossibleImportKeys) {
|
||||
QString libraryName = importKey.splitPath.join(QLatin1Char('.'));
|
||||
int majorVersion = importKey.majorVersion;
|
||||
if (majorVersion >= 0) {
|
||||
int minorVersion = (importKey.minorVersion == LanguageUtils::ComponentVersion::NoVersion) ? 0 : importKey.minorVersion;
|
||||
|
||||
if (libraryName.contains("QtQuick.Studio")) {
|
||||
majorVersion = 1;
|
||||
minorVersion = 0;
|
||||
}
|
||||
|
||||
QString version = QStringLiteral("%1.%2").arg(majorVersion).arg(minorVersion);
|
||||
if (!libraryName.endsWith(".impl"))
|
||||
possibleImports.append(QmlDesigner::Import::createLibraryImport(libraryName, version));
|
||||
|
||||
// In Qt6, QtQuick.Controls itself doesn't have any version as it has no types,
|
||||
// so it never gets added normally to possible imports.
|
||||
// We work around this by injecting corresponding QtQuick.Controls version for each
|
||||
// found impl version, if no valid QtQuick.Controls versions are found.
|
||||
if (!hasVersionedControls) {
|
||||
if (libraryName == controlsImplName)
|
||||
controlsImplVersions.insert(version);
|
||||
else if (libraryName == controlsName)
|
||||
hasVersionedControls = true;
|
||||
}
|
||||
} else if (!hasVersionlessControls && libraryName == controlsName) {
|
||||
// If QtQuick.Controls module is not included even in non-versioned, it means
|
||||
// QtQuick.Controls is either in use or not available at all,
|
||||
// so we shouldn't inject it.
|
||||
hasVersionlessControls = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasVersionlessControls && !hasVersionedControls && !controlsImplVersions.isEmpty()) {
|
||||
for (const auto &version : std::as_const(controlsImplVersions))
|
||||
possibleImports.append(QmlDesigner::Import::createLibraryImport(controlsName, version));
|
||||
}
|
||||
QStringList fileImportPaths;
|
||||
|
||||
collectPossibleFileImports(path, usedImportsSet, possibleImports);
|
||||
|
||||
return possibleImports;
|
||||
}
|
||||
|
||||
void TextToModelMerger::setupPossibleImports(const QmlJS::Snapshot &snapshot, const QmlJS::ViewerContext &viewContext)
|
||||
} // namespace
|
||||
|
||||
void TextToModelMerger::setupPossibleImports()
|
||||
{
|
||||
if (!m_rewriterView->possibleImportsEnabled())
|
||||
return;
|
||||
@@ -919,27 +884,25 @@ void TextToModelMerger::setupPossibleImports(const QmlJS::Snapshot &snapshot, co
|
||||
static QUrl lastProjectUrl;
|
||||
auto &externalDependencies = m_rewriterView->externalDependencies();
|
||||
auto projectUrl = externalDependencies.projectUrl();
|
||||
auto allUsedImports = m_scopeChain->context()->imports(m_document.data())->all();
|
||||
|
||||
if (m_possibleImportKeys.isEmpty() || projectUrl != lastProjectUrl)
|
||||
m_possibleImportKeys = snapshot.importDependencies()->libraryImports(viewContext);
|
||||
if (m_possibleModules.isEmpty() || projectUrl != lastProjectUrl) {
|
||||
const auto skipModuleNames = m_rewriterView->model()->metaInfo().itemLibraryInfo()->blacklistImports();
|
||||
ModuleScanner moduleScanner{
|
||||
[&](QStringView moduleName) { return skipModule(moduleName, skipModuleNames); }};
|
||||
moduleScanner.scan(m_rewriterView->externalDependencies().modulePaths());
|
||||
m_possibleModules = moduleScanner.modules();
|
||||
}
|
||||
|
||||
lastProjectUrl = projectUrl;
|
||||
|
||||
QHash<QString, ImportKey> filteredPossibleImportKeys = filterPossibleImportKeys(
|
||||
m_possibleImportKeys, m_rewriterView->model());
|
||||
|
||||
const QmlJS::Imports *imports = m_scopeChain->context()->imports(m_document.data());
|
||||
if (imports)
|
||||
removeUsedImports(filteredPossibleImportKeys, imports->all());
|
||||
|
||||
QList<QmlDesigner::Import> possibleImports = generatePossibleLibraryImports(filteredPossibleImportKeys);
|
||||
auto modules = m_possibleModules;
|
||||
|
||||
if (document()->fileName() != "<internal>")
|
||||
possibleImports.append(
|
||||
generatePossibleFileImports(document()->path().toString(), imports->all()));
|
||||
modules.append(generatePossibleFileImports(document()->path().toString(), allUsedImports));
|
||||
|
||||
if (m_rewriterView->isAttached())
|
||||
m_rewriterView->model()->setPossibleImports(possibleImports);
|
||||
m_rewriterView->model()->setPossibleImports(modules);
|
||||
}
|
||||
|
||||
void TextToModelMerger::setupUsedImports()
|
||||
@@ -951,7 +914,7 @@ void TextToModelMerger::setupUsedImports()
|
||||
const QList<QmlJS::Import> allImports = imports->all();
|
||||
|
||||
QSet<QString> usedImportsSet;
|
||||
QList<Import> usedImports;
|
||||
Imports usedImports;
|
||||
|
||||
// populate usedImportsSet from current model nodes
|
||||
const QList<ModelNode> allModelNodes = m_rewriterView->allModelNodes();
|
||||
@@ -964,9 +927,6 @@ void TextToModelMerger::setupUsedImports()
|
||||
for (const QmlJS::Import &import : allImports) {
|
||||
QString version = import.info.version().toString();
|
||||
|
||||
if (!import.info.version().isValid())
|
||||
version = getHighestPossibleImport(import.info.name());
|
||||
|
||||
if (!import.info.name().isEmpty() && usedImportsSet.contains(import.info.name())) {
|
||||
if (import.info.type() == ImportType::Library)
|
||||
usedImports.append(
|
||||
@@ -1077,7 +1037,7 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
|
||||
collectLinkErrors(&errors, ctxt);
|
||||
}
|
||||
|
||||
setupPossibleImports(snapshot, m_vContext);
|
||||
setupPossibleImports();
|
||||
|
||||
qCInfo(rewriterBenchmark) << "possible imports:" << time.elapsed();
|
||||
|
||||
@@ -1115,12 +1075,6 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
|
||||
|
||||
setActive(false);
|
||||
|
||||
// Clear possible imports cache if code model hasn't settled yet
|
||||
const int importKeysSize = m_possibleImportKeys.size();
|
||||
if (m_previousPossibleImportsSize != importKeysSize)
|
||||
m_possibleImportKeys.clear();
|
||||
m_previousPossibleImportsSize = importKeysSize;
|
||||
|
||||
return true;
|
||||
} catch (Exception &e) {
|
||||
DocumentMessage error(&e);
|
||||
@@ -2387,8 +2341,8 @@ QList<QmlTypeData> TextToModelMerger::getQMLSingletons() const
|
||||
|
||||
void TextToModelMerger::clearPossibleImportKeys()
|
||||
{
|
||||
m_possibleImportKeys.clear();
|
||||
m_previousPossibleImportsSize = -1;
|
||||
m_possibleModules.clear();
|
||||
m_previousPossibleModulesSize = -1;
|
||||
}
|
||||
|
||||
QString TextToModelMerger::textAt(const Document::Ptr &doc,
|
||||
@@ -2403,19 +2357,3 @@ QString TextToModelMerger::textAt(const Document::Ptr &doc,
|
||||
{
|
||||
return doc->source().mid(from.offset, to.end() - from.begin());
|
||||
}
|
||||
|
||||
QString TextToModelMerger::getHighestPossibleImport(const QString &importName) const
|
||||
{
|
||||
QString version = "2.15";
|
||||
int maj = -1;
|
||||
const auto imports = m_possibleImportKeys.values();
|
||||
for (const ImportKey &import : imports) {
|
||||
if (importName == import.libraryQualifiedPath()) {
|
||||
if (import.majorVersion > maj) {
|
||||
version = QString("%1.%2").arg(import.majorVersion).arg(import.minorVersion);
|
||||
maj = import.majorVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
bool isActive() const;
|
||||
|
||||
void setupImports(const QmlJS::Document::Ptr &doc, DifferenceHandler &differenceHandler);
|
||||
void setupPossibleImports(const QmlJS::Snapshot &snapshot, const QmlJS::ViewerContext &viewContext);
|
||||
void setupPossibleImports();
|
||||
void setupUsedImports();
|
||||
bool load(const QString &data, DifferenceHandler &differenceHandler);
|
||||
|
||||
@@ -137,8 +137,6 @@ private:
|
||||
const QmlJS::SourceLocation &from,
|
||||
const QmlJS::SourceLocation &to);
|
||||
|
||||
QString getHighestPossibleImport(const QString &importName) const;
|
||||
|
||||
private:
|
||||
RewriterView *m_rewriterView;
|
||||
bool m_isActive;
|
||||
@@ -150,8 +148,8 @@ private:
|
||||
QSet<ModelNode> m_clearImplicitComponentList;
|
||||
QmlJS::ViewerContext m_vContext;
|
||||
QSet<QPair<QString, QString> > m_qrcMapping;
|
||||
QSet<QmlJS::ImportKey> m_possibleImportKeys;
|
||||
int m_previousPossibleImportsSize = -1;
|
||||
Imports m_possibleModules;
|
||||
int m_previousPossibleModulesSize = -1;
|
||||
bool m_hasVersionlessImport = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "modulescanner.h"
|
||||
|
||||
#ifdef QDS_HAS_QMLPRIVATE
|
||||
#include <private/qqmldirparser_p.h>
|
||||
#endif
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
namespace {
|
||||
|
||||
std::optional<QString> contentAsQString(const QString &filePath)
|
||||
{
|
||||
QFile file{filePath};
|
||||
if (file.open(QIODevice::ReadOnly))
|
||||
return {QString::fromUtf8(file.readAll())};
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ModuleScanner::scan(const QStringList &modulePaths)
|
||||
{
|
||||
for (const QString &modulePath : modulePaths)
|
||||
scan(modulePath.toStdString());
|
||||
}
|
||||
|
||||
void ModuleScanner::scan(std::string_view modulePath)
|
||||
{
|
||||
#ifdef QDS_HAS_QMLPRIVATE
|
||||
try {
|
||||
const std::filesystem::path installDirectoryPath{modulePath};
|
||||
|
||||
auto current = std::filesystem::recursive_directory_iterator{installDirectoryPath};
|
||||
auto end = std::filesystem::end(current);
|
||||
|
||||
for (; current != end; ++current) {
|
||||
const auto &entry = *current;
|
||||
auto path = entry.path();
|
||||
|
||||
if (path.filename() == "qmldir") {
|
||||
QQmlDirParser parser;
|
||||
|
||||
auto content = contentAsQString(QString::fromStdU16String(path.u16string()));
|
||||
if (!content)
|
||||
continue;
|
||||
|
||||
bool hasError = parser.parse(*content);
|
||||
if (hasError)
|
||||
continue;
|
||||
|
||||
auto moduleName = parser.typeNamespace();
|
||||
|
||||
if (moduleName.isEmpty() || m_skip(moduleName))
|
||||
continue;
|
||||
|
||||
m_modules.push_back(Import::createLibraryImport(moduleName));
|
||||
}
|
||||
}
|
||||
} catch (const std::filesystem::filesystem_error &) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <qmldesignercorelib_global.h>
|
||||
|
||||
#include <import.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class QMLDESIGNERCORE_EXPORT ModuleScanner
|
||||
{
|
||||
public:
|
||||
using SkipFunction = std::function<bool(QStringView)>;
|
||||
|
||||
ModuleScanner(SkipFunction skip)
|
||||
: m_skip{std::move(skip)}
|
||||
{
|
||||
m_modules.reserve(128);
|
||||
}
|
||||
|
||||
void scan(const QStringList &modulePaths);
|
||||
|
||||
const Imports &modules() const { return m_modules; }
|
||||
|
||||
private:
|
||||
void scan(std::string_view modulePaths);
|
||||
|
||||
private:
|
||||
SkipFunction m_skip;
|
||||
Imports m_modules;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include <sqlitedatabase.h>
|
||||
|
||||
#ifdef QDS_HAS_QMLDOM
|
||||
#ifdef QDS_HAS_QMLPRIVATE
|
||||
#include <private/qqmldomtop_p.h>
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
#ifdef QDS_HAS_QMLDOM
|
||||
#ifdef QDS_HAS_QMLPRIVATE
|
||||
|
||||
namespace QmlDom = QQmlJS::Dom;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
|
||||
using PathCache = QmlDesigner::SourcePathCache<ProjectStorage, NonLockingMutex>;
|
||||
|
||||
#ifdef QDS_HAS_QMLDOM
|
||||
#ifdef QDS_HAS_QMLPRIVATE
|
||||
QmlDocumentParser(ProjectStorage &storage, PathCache &pathCache)
|
||||
: m_storage{storage}
|
||||
, m_pathCache{pathCache}
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
|
||||
private:
|
||||
// m_pathCache and m_storage are only used when compiled for QDS
|
||||
#ifdef QDS_HAS_QMLDOM
|
||||
#ifdef QDS_HAS_QMLPRIVATE
|
||||
ProjectStorage &m_storage;
|
||||
PathCache &m_pathCache;
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include <sqlitedatabase.h>
|
||||
|
||||
#ifdef QDS_HAS_QMLDOM
|
||||
#ifdef QDS_HAS_QMLPRIVATE
|
||||
#include <private/qqmldomtop_p.h>
|
||||
#include <private/qqmljstypedescriptionreader_p.h>
|
||||
#endif
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
#ifdef QDS_HAS_QMLDOM
|
||||
#ifdef QDS_HAS_QMLPRIVATE
|
||||
|
||||
namespace QmlDom = QQmlJS::Dom;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
|
||||
using PathCache = QmlDesigner::SourcePathCache<ProjectStorage, NonLockingMutex>;
|
||||
|
||||
#ifdef QDS_HAS_QMLDOM
|
||||
#ifdef QDS_HAS_QMLPRIVATE
|
||||
QmlTypesParser(PathCache &pathCache, ProjectStorage &storage)
|
||||
: m_pathCache{pathCache}
|
||||
, m_storage{storage}
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
|
||||
private:
|
||||
// m_pathCache and m_storage are only used when compiled for QDS
|
||||
#ifdef QDS_HAS_QMLDOM
|
||||
#ifdef QDS_HAS_QMLPRIVATE
|
||||
PathCache &m_pathCache;
|
||||
ProjectStorage &m_storage;
|
||||
#endif
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
#include <edit3d/edit3dviewconfig.h>
|
||||
#include <itemlibraryimport.h>
|
||||
#include <projectexplorer/kit.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <puppetenvironmentbuilder.h>
|
||||
#include <qmlprojectmanager/qmlproject.h>
|
||||
#include <qmlpuppetpaths.h>
|
||||
#include <qtsupport/baseqtversion.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
@@ -186,4 +188,50 @@ Utils::FilePath ExternalDependencies::qmlPuppetPath() const
|
||||
return puppetPath;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
QString qmlPath(ProjectExplorer::Target *target)
|
||||
{
|
||||
auto kit = target->kit();
|
||||
|
||||
if (!kit)
|
||||
return {};
|
||||
|
||||
auto qtVersion = QtSupport::QtKitAspect::qtVersion(kit);
|
||||
if (!qtVersion)
|
||||
return {};
|
||||
|
||||
return qtVersion->qmlPath().toString();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
QStringList ExternalDependencies::modulePaths() const
|
||||
{
|
||||
QStringList modulePaths;
|
||||
|
||||
auto project = ProjectExplorer::SessionManager::startupProject();
|
||||
|
||||
if (!project)
|
||||
return modulePaths;
|
||||
|
||||
auto target = project->activeTarget();
|
||||
|
||||
if (!target)
|
||||
return modulePaths;
|
||||
|
||||
if (auto path = qmlPath(target); !path.isEmpty())
|
||||
modulePaths.push_back(path);
|
||||
|
||||
const auto qmlBuildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(
|
||||
target->buildSystem());
|
||||
|
||||
if (!qmlBuildSystem)
|
||||
return modulePaths;
|
||||
|
||||
for (const QString &modulePath : qmlBuildSystem->customImportPaths())
|
||||
modulePaths.append(project->projectDirectory().pathAppended(modulePath).toString());
|
||||
|
||||
return modulePaths;
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
||||
@@ -36,6 +36,7 @@ public:
|
||||
PuppetStartData puppetStartData(const class Model &model) const override;
|
||||
bool instantQmlTextUpdate() const override;
|
||||
Utils::FilePath qmlPuppetPath() const override;
|
||||
QStringList modulePaths() const override;
|
||||
|
||||
private:
|
||||
const DesignerSettings &m_designerSettings;
|
||||
|
||||
@@ -342,7 +342,7 @@ void projectQmldirPaths(::ProjectExplorer::Target *target, QStringList &qmldirPa
|
||||
qmldirPaths.push_back(QDir::cleanPath(pojectDirectory.absoluteFilePath(importPath))
|
||||
+ "/qmldir");
|
||||
}
|
||||
#ifdef QDS_HAS_QMLDOM
|
||||
#ifdef QDS_HAS_QMLPRIVATE
|
||||
bool skipPath(const std::filesystem::path &path)
|
||||
{
|
||||
auto directory = path.filename();
|
||||
@@ -359,10 +359,11 @@ bool skipPath(const std::filesystem::path &path)
|
||||
}
|
||||
#endif
|
||||
|
||||
void qtQmldirPaths([[maybe_unused]] ::ProjectExplorer::Target *target,
|
||||
[[maybe_unused]] QStringList &qmldirPaths)
|
||||
void qtQmldirPaths(::ProjectExplorer::Target *target, QStringList &qmldirPaths)
|
||||
{
|
||||
#ifdef QDS_HAS_QMLDOM
|
||||
#ifdef QDS_HAS_QMLPRIVATE
|
||||
|
||||
if (useProjectStorage()) {
|
||||
const QString installDirectory = qmlPath(target).toString();
|
||||
|
||||
const std::filesystem::path installDirectoryPath{installDirectory.toStdString()};
|
||||
@@ -380,6 +381,7 @@ void qtQmldirPaths([[maybe_unused]] ::ProjectExplorer::Target *target,
|
||||
qmldirPaths.push_back(QString::fromStdU16String(path.generic_u16string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -160,6 +160,7 @@ public:
|
||||
PuppetStartData puppetStartData(const class Model &) const override { return {}; }
|
||||
bool instantQmlTextUpdate() const override { return true; }
|
||||
Utils::FilePath qmlPuppetPath() const override { return {}; }
|
||||
QStringList modulePaths() const override { return {}; }
|
||||
|
||||
public:
|
||||
QSettings qsettings;
|
||||
@@ -1074,10 +1075,10 @@ void tst_TestCore::testRewriterChangeImports()
|
||||
//
|
||||
Import webkitImport = Import::createLibraryImport("QtWebKit", "1.0");
|
||||
|
||||
QList<Import> importList;
|
||||
Imports importList;
|
||||
importList << webkitImport;
|
||||
|
||||
model->changeImports(importList, QList<Import>());
|
||||
model->changeImports(importList, Imports());
|
||||
|
||||
const QLatin1String qmlWithImport("\n"
|
||||
"import QtQuick 2.1\n"
|
||||
@@ -1086,7 +1087,7 @@ void tst_TestCore::testRewriterChangeImports()
|
||||
"Rectangle {}\n");
|
||||
QCOMPARE(textEdit.toPlainText(), qmlWithImport);
|
||||
|
||||
model->changeImports(QList<Import>(), importList);
|
||||
model->changeImports(Imports(), importList);
|
||||
|
||||
QCOMPARE(model->imports().size(), 1);
|
||||
QCOMPARE(model->imports().first(), Import::createLibraryImport("QtQuick", "2.1"));
|
||||
@@ -1100,7 +1101,7 @@ void tst_TestCore::testRewriterChangeImports()
|
||||
|
||||
Import webkitImportAlias = Import::createLibraryImport("QtWebKit", "1.0", "Web");
|
||||
|
||||
model->changeImports(QList<Import>() << webkitImportAlias, QList<Import>() << webkitImport);
|
||||
model->changeImports(Imports() << webkitImportAlias, Imports() << webkitImport);
|
||||
|
||||
const QLatin1String qmlWithAliasImport("\n"
|
||||
"import QtQuick 2.1\n"
|
||||
@@ -1109,7 +1110,7 @@ void tst_TestCore::testRewriterChangeImports()
|
||||
"Rectangle {}\n");
|
||||
QCOMPARE(textEdit.toPlainText(), qmlWithAliasImport);
|
||||
|
||||
model->changeImports(QList<Import>(), QList<Import>() << webkitImportAlias);
|
||||
model->changeImports(Imports(), Imports() << webkitImportAlias);
|
||||
QCOMPARE(model->imports().first(), Import::createLibraryImport("QtQuick", "2.1"));
|
||||
|
||||
QCOMPARE(textEdit.toPlainText(), qmlString);
|
||||
|
||||
@@ -25,7 +25,7 @@ add_qtc_test(unittest GTEST
|
||||
BEFORE "../mockup/qmldesigner/designercore/include"
|
||||
DEPENDS
|
||||
Qt::Core Qt::Network Qt::Widgets
|
||||
Qt::Xml Qt::Concurrent Qt::Qml Qt::Gui
|
||||
Qt::Xml Qt::Concurrent Qt::QmlPrivate Qt::Gui
|
||||
Qt6Core5Compat QmlJS Sqlite SqliteC
|
||||
Googletest
|
||||
DEFINES
|
||||
@@ -36,6 +36,7 @@ add_qtc_test(unittest GTEST
|
||||
QTC_RESOURCE_DIR="${CMAKE_CURRENT_LIST_DIR}/../../../share/qtcreator"
|
||||
TESTDATA_DIR="${CMAKE_CURRENT_BINARY_DIR}/data"
|
||||
TEST_RELATIVE_LIBEXEC_PATH="${TEST_RELATIVE_LIBEXEC_PATH}"
|
||||
QT6_INSTALL_PREFIX="${QT6_INSTALL_PREFIX}"
|
||||
SOURCES
|
||||
abstractviewmock.h
|
||||
compare-operators.h
|
||||
@@ -97,6 +98,7 @@ add_qtc_test(unittest GTEST
|
||||
mockimagecachestorage.h
|
||||
asynchronousexplicitimagecache-test.cpp
|
||||
asynchronousimagefactory-test.cpp
|
||||
modulescanner-test.cpp
|
||||
)
|
||||
|
||||
if (NOT TARGET unittest)
|
||||
@@ -250,6 +252,7 @@ extend_qtc_test(unittest
|
||||
projectstorage/filesystem.cpp projectstorage/filesystem.h
|
||||
projectstorage/filestatus.h
|
||||
projectstorage/filestatuscache.cpp projectstorage/filestatuscache.h
|
||||
projectstorage/modulescanner.cpp projectstorage/modulescanner.h
|
||||
projectstorage/nonlockingmutex.h
|
||||
projectstorage/projectstorageexceptions.cpp projectstorage/projectstorageexceptions.h
|
||||
projectstorage/projectstorageinterface.h
|
||||
@@ -335,7 +338,7 @@ extend_qtc_test(unittest
|
||||
CONDITION TARGET Qt6::QmlDomPrivate AND TARGET Qt6::QmlCompilerPrivate AND Qt6_VERSION VERSION_GREATER_EQUAL 6.5.0
|
||||
SOURCES_PREFIX "${QmlDesignerDir}/designercore"
|
||||
DEPENDS Qt6::QmlDomPrivate Qt6::QmlCompilerPrivate
|
||||
DEFINES QDS_HAS_QMLDOM
|
||||
DEFINES QDS_HAS_QMLPRIVATE
|
||||
SOURCES
|
||||
projectstorage/qmldocumentparser.cpp projectstorage/qmldocumentparser.h
|
||||
projectstorage/qmltypesparser.cpp projectstorage/qmltypesparser.h
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
|
||||
using testing::_;
|
||||
using testing::A;
|
||||
using testing::AllOf;
|
||||
@@ -21,6 +20,7 @@ using testing::ByRef;
|
||||
using testing::ContainerEq;
|
||||
using testing::Contains;
|
||||
using testing::ElementsAre;
|
||||
using testing::EndsWith;
|
||||
using testing::Eq;
|
||||
using testing::Exactly;
|
||||
using testing::Field;
|
||||
@@ -29,7 +29,6 @@ using testing::Gt;
|
||||
using testing::HasSubstr;
|
||||
using testing::InSequence;
|
||||
using testing::Invoke;
|
||||
using testing::IsEmpty;
|
||||
using testing::IsNull;
|
||||
using testing::Le;
|
||||
using testing::Lt;
|
||||
|
||||
53
tests/unit/unittest/modulescanner-test.cpp
Normal file
53
tests/unit/unittest/modulescanner-test.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "googletest.h"
|
||||
|
||||
#include <projectstorage/modulescanner.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename Matcher>
|
||||
auto UrlProperty(const Matcher &matcher)
|
||||
{
|
||||
return Property(&QmlDesigner::Import::url, matcher);
|
||||
}
|
||||
|
||||
class ModuleScanner : public testing::Test
|
||||
{
|
||||
protected:
|
||||
QmlDesigner::ModuleScanner scanner{
|
||||
[](QStringView moduleName) { return moduleName.endsWith(u"impl"); }};
|
||||
};
|
||||
|
||||
TEST_F(ModuleScanner, ReturnEmptyOptionalForWrongPath)
|
||||
{
|
||||
scanner.scan(QStringList{""});
|
||||
|
||||
ASSERT_THAT(scanner.modules(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(ModuleScanner, GetQtQuick)
|
||||
{
|
||||
scanner.scan(QStringList{QT6_INSTALL_PREFIX});
|
||||
|
||||
ASSERT_THAT(scanner.modules(), Contains(UrlProperty("QtQuick")));
|
||||
}
|
||||
|
||||
TEST_F(ModuleScanner, SkipEmptyModules)
|
||||
{
|
||||
scanner.scan(QStringList{QT6_INSTALL_PREFIX});
|
||||
|
||||
ASSERT_THAT(scanner.modules(), Not(Contains(UrlProperty(IsEmpty()))));
|
||||
}
|
||||
|
||||
TEST_F(ModuleScanner, UseSkipFunction)
|
||||
{
|
||||
scanner.scan(QStringList{QT6_INSTALL_PREFIX});
|
||||
|
||||
ASSERT_THAT(scanner.modules(), Not(Contains(UrlProperty(EndsWith(QStringView{u"impl"})))));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -9,8 +9,6 @@
|
||||
#include <utils/smallstringio.h>
|
||||
#include <utils/smallstringvector.h>
|
||||
|
||||
using namespace ::testing;
|
||||
|
||||
using Utils::PathString;
|
||||
using Utils::SmallString;
|
||||
using Utils::SmallStringLiteral;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <utils/smallstringio.h>
|
||||
|
||||
namespace UnitTests {
|
||||
namespace Internal {
|
||||
|
||||
template <typename StringType>
|
||||
class EndsWithMatcher
|
||||
@@ -46,10 +46,68 @@ private:
|
||||
const StringType m_suffix;
|
||||
};
|
||||
|
||||
inline
|
||||
testing::PolymorphicMatcher<EndsWithMatcher<Utils::SmallString> >
|
||||
EndsWith(const Utils::SmallString &suffix)
|
||||
class QStringEndsWithMatcher
|
||||
{
|
||||
return testing::MakePolymorphicMatcher(EndsWithMatcher<Utils::SmallString>(suffix));
|
||||
public:
|
||||
explicit QStringEndsWithMatcher(const QString &suffix)
|
||||
: m_suffix(suffix)
|
||||
{}
|
||||
|
||||
template<typename MatcheeStringType>
|
||||
bool MatchAndExplain(const MatcheeStringType &s, testing::MatchResultListener * /* listener */) const
|
||||
{
|
||||
return s.endsWith(m_suffix);
|
||||
}
|
||||
|
||||
void DescribeTo(::std::ostream *os) const
|
||||
{
|
||||
*os << "ends with " << testing::PrintToString(m_suffix);
|
||||
}
|
||||
|
||||
void DescribeNegationTo(::std::ostream *os) const
|
||||
{
|
||||
*os << "doesn't end with " << testing::PrintToString(m_suffix);
|
||||
}
|
||||
|
||||
private:
|
||||
const QString m_suffix;
|
||||
};
|
||||
|
||||
class IsEmptyMatcher : public testing::internal::IsEmptyMatcher
|
||||
{
|
||||
public:
|
||||
using Base = testing::internal::IsEmptyMatcher;
|
||||
|
||||
using Base::MatchAndExplain;
|
||||
|
||||
bool MatchAndExplain(const QString &s, testing::MatchResultListener *listener) const
|
||||
{
|
||||
if (s.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
*listener << "whose size is " << s.size();
|
||||
return false;
|
||||
}
|
||||
|
||||
void DescribeTo(std::ostream *os) const { *os << "is empty"; }
|
||||
|
||||
void DescribeNegationTo(std::ostream *os) const { *os << "isn't empty"; }
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
inline auto EndsWith(const Utils::SmallString &suffix)
|
||||
{
|
||||
return Internal::EndsWithMatcher(suffix);
|
||||
}
|
||||
|
||||
inline auto EndsWith(const QStringView &suffix)
|
||||
{
|
||||
return ::testing::PolymorphicMatcher(Internal::QStringEndsWithMatcher(suffix.toString()));
|
||||
}
|
||||
|
||||
inline auto IsEmpty()
|
||||
{
|
||||
return ::testing::PolymorphicMatcher(Internal::IsEmptyMatcher());
|
||||
}
|
||||
|
||||
@@ -15,10 +15,9 @@ bool operator==(const QString &first, const char *second)
|
||||
|
||||
namespace UnitTest {
|
||||
|
||||
inline
|
||||
Utils::PathString temporaryDirPath()
|
||||
inline ::Utils::PathString temporaryDirPath()
|
||||
{
|
||||
return Utils::PathString::fromQString(Utils::TemporaryDirectory::masterDirectoryPath());
|
||||
return ::Utils::PathString::fromQString(Utils::TemporaryDirectory::masterDirectoryPath());
|
||||
}
|
||||
|
||||
} // namespace UnitTest
|
||||
|
||||
Reference in New Issue
Block a user