diff options
Diffstat (limited to 'src/libs/qmljs/qmljsmodelmanagerinterface.cpp')
-rw-r--r-- | src/libs/qmljs/qmljsmodelmanagerinterface.cpp | 100 |
1 files changed, 76 insertions, 24 deletions
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp index 4417ddb240..dc4c855c26 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp @@ -38,6 +38,7 @@ #include <utils/algorithm.h> #include <utils/hostosinfo.h> #include <utils/runextensions.h> +#include <utils/stringutils.h> #include <QDir> #include <QDirIterator> @@ -90,7 +91,7 @@ static QStringList environmentImportPaths() QStringList paths; const QStringList importPaths = QString::fromLocal8Bit(qgetenv("QML_IMPORT_PATH")).split( - Utils::HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); + Utils::HostOsInfo::pathListSeparator(), Utils::SkipEmptyParts); for (const QString &path : importPaths) { const QString canonicalPath = QDir(path).canonicalPath(); @@ -267,8 +268,10 @@ void ModelManagerInterface::loadQmlTypeDescriptionsInternal(const QString &resou } // load the fallbacks for libraries - CppQmlTypesLoader::defaultLibraryObjects.unite( - CppQmlTypesLoader::loadQmlTypes(qmlTypesFiles, &errors, &warnings)); + const CppQmlTypesLoader::BuiltinObjects objs = + CppQmlTypesLoader::loadQmlTypes(qmlTypesFiles, &errors, &warnings); + for (auto it = objs.cbegin(); it != objs.cend(); ++it) + CppQmlTypesLoader::defaultLibraryObjects.insert(it.key(), it.value()); for (const QString &error : qAsConst(errors)) writeMessageInternal(error); @@ -306,6 +309,7 @@ void ModelManagerInterface::updateSourceFiles(const QStringList &files, void ModelManagerInterface::cleanupFutures() { + QMutexLocker lock(&m_futuresMutex); const int maxFutures = 10; if (m_futures.size() > maxFutures) { const QList<QFuture<void>> futures = m_futures; @@ -327,8 +331,7 @@ QFuture<void> ModelManagerInterface::refreshSourceFiles(const QStringList &sourc workingCopyInternal(), sourceFiles, this, Dialect(Dialect::Qml), emitDocumentOnDiskChanged); - cleanupFutures(); - m_futures.append(result); + addFuture(result); if (sourceFiles.count() > 1) addTaskInternal(result, tr("Parsing QML Files"), Constants::TASK_INDEX); @@ -561,11 +564,12 @@ void ModelManagerInterface::updateProjectInfo(const ProjectInfo &pinfo, ProjectE // parse any files not yet in the snapshot QStringList newFiles; for (const QString &file : qAsConst(pinfo.sourceFiles)) { + if (!m_fileToProject.contains(file, p)) + m_fileToProject.insert(file, p); if (!snapshot.document(file)) newFiles += file; } - for (const QString &newFile : qAsConst(newFiles)) - m_fileToProject.insert(newFile, p); + updateSourceFiles(newFiles, false); // update qrc cache @@ -636,7 +640,6 @@ QList<ModelManagerInterface::ProjectInfo> ModelManagerInterface::allProjectInfos infos.append(info); } std::sort(infos.begin(), infos.end(), &pInfoLessThanImports); - infos.append(m_defaultProjectInfo); return infos; } @@ -1133,13 +1136,11 @@ void ModelManagerInterface::maybeScan(const PathsAndLanguages &importPaths) pathToScan.maybeInsert(importPath); } - if (pathToScan.length() > 1) { + if (pathToScan.length() >= 1) { QFuture<void> result = Utils::runAsync(&ModelManagerInterface::importScan, workingCopyInternal(), pathToScan, this, true, true, false); - cleanupFutures(); - m_futures.append(result); - + addFuture(result); addTaskInternal(result, tr("Scanning QML Imports"), Constants::TASK_IMPORT_SCAN); } } @@ -1401,7 +1402,7 @@ ModelManagerInterface::CppDataHash ModelManagerInterface::cppData() const LibraryInfo ModelManagerInterface::builtins(const Document::Ptr &doc) const { const ProjectInfo info = projectInfoForPath(doc->fileName()); - if (!info.project.isNull() && !info.qtQmlPath.isEmpty()) + if (!info.qtQmlPath.isEmpty()) return m_validSnapshot.libraryInfo(info.qtQmlPath); return LibraryInfo(); } @@ -1409,6 +1410,13 @@ LibraryInfo ModelManagerInterface::builtins(const Document::Ptr &doc) const ViewerContext ModelManagerInterface::completeVContext(const ViewerContext &vCtx, const Document::Ptr &doc) const { + return getVContext(vCtx, doc, false); +} + +ViewerContext ModelManagerInterface::getVContext(const ViewerContext &vCtx, + const Document::Ptr &doc, + bool limitToProject) const +{ ViewerContext res = vCtx; if (!doc.isNull() @@ -1446,20 +1454,27 @@ ViewerContext ModelManagerInterface::completeVContext(const ViewerContext &vCtx, { if (res.language == Dialect::QmlQtQuick2 || res.language == Dialect::QmlQtQuick2Ui) maybeAddPath(res, info.qtQmlPath); - QList<ProjectInfo> allProjects; - { - QMutexLocker locker(&m_mutex); - allProjects = m_projects.values(); - } - std::sort(allProjects.begin(), allProjects.end(), &pInfoLessThanImports); + QList<Dialect> languages = res.language.companionLanguages(); - for (const ProjectInfo &pInfo : qAsConst(allProjects)) { - for (const auto &importPath : pInfo.importPaths) { + auto addPathsOnLanguageMatch = [&](const PathsAndLanguages &importPaths) { + for (const auto &importPath : importPaths) { if (languages.contains(importPath.language()) || importPath.language().companionLanguages().contains(res.language)) { maybeAddPath(res, importPath.path().toString()); } } + }; + if (limitToProject) { + addPathsOnLanguageMatch(info.importPaths); + } else { + QList<ProjectInfo> allProjects; + { + QMutexLocker locker(&m_mutex); + allProjects = m_projects.values(); + } + std::sort(allProjects.begin(), allProjects.end(), &pInfoLessThanImports); + for (const ProjectInfo &pInfo : qAsConst(allProjects)) + addPathsOnLanguageMatch(pInfo.importPaths); } const auto environmentPaths = environmentImportPaths(); for (const QString &path : environmentPaths) @@ -1518,6 +1533,13 @@ ViewerContext ModelManagerInterface::defaultVContext(Dialect language, return autoComplete ? completeVContext(defaultCtx, doc) : defaultCtx; } +ViewerContext ModelManagerInterface::projectVContext(Dialect language, const Document::Ptr &doc) const +{ + // Returns context limited to the project the file belongs to + ViewerContext defaultCtx = defaultVContext(language, doc, false); + return getVContext(defaultCtx, doc, true); +} + ModelManagerInterface::ProjectInfo ModelManagerInterface::defaultProjectInfo() const { QMutexLocker l(mutex()); @@ -1536,13 +1558,43 @@ void ModelManagerInterface::setDefaultVContext(const ViewerContext &vContext) m_defaultVContexts[vContext.language] = vContext; } -void ModelManagerInterface::joinAllThreads() +void ModelManagerInterface::test_joinAllThreads() { - for (QFuture<void> &future : m_futures) - future.waitForFinished(); + // Loop since futures can spawn more futures as they finish. + while (true) { + QFuture<void> f; + // get one future + { + QMutexLocker lock(&m_futuresMutex); + for (QFuture<void> &future : m_futures) { + if (!future.isFinished() && !future.isCanceled()) { + f = future; + break; + } + } + } + if (!f.isFinished() && !f.isCanceled()) { + f.waitForFinished(); + + // Some futures trigger more futures from connected signals + // and in tests, we care about finishing all of these too. + QEventLoop().processEvents(); + } else { + break; + } + } m_futures.clear(); } +void ModelManagerInterface::addFuture(const QFuture<void> &future) +{ + { + QMutexLocker lock(&m_futuresMutex); + m_futures.append(future); + } + cleanupFutures(); +} + Document::Ptr ModelManagerInterface::ensuredGetDocumentForPath(const QString &filePath) { QmlJS::Document::Ptr document = newestSnapshot().document(filePath); |