19void QQmlCodeModelManager::onCMakeProberFinished(
int exitCode, QProcess::ExitStatus exitStatus)
21 if (m_cmakeStatus == DoesNotHaveCMake)
24 if (exitStatus != QProcess::NormalExit || exitCode != 0) {
28 m_cmakeStatus = HasCMake;
29 for (
const auto &ws : m_workspaces)
30 ws.codeModel->tryEnableCMakeCalls(&m_processScheduler);
39void QQmlCodeModelManager::tryEnableCMakeCalls()
41 m_cmakeStatus = IsProbingCMake;
43 m_cmakeProber.setProgram(u"cmake"_s);
44 m_cmakeProber.setArguments({ u"--version"_s });
45 QObject::connect(&m_cmakeProber, &QProcess::finished,
this,
46 &QQmlCodeModelManager::onCMakeProberFinished);
47 QObject::connect(&m_cmakeProber, &QProcess::errorOccurred,
this,
48 &QQmlCodeModelManager::disableCMakeCalls);
50 m_cmakeProber.start();
53QQmlCodeModelManager::QQmlCodeModelManager(QObject *parent, QQmlToolingSharedSettings *settings)
56 const QByteArray defaultCodeModel;
57 appendWorkspace(defaultCodeModel, ManagedByServer);
58 connect(&m_processScheduler, &QProcessScheduler::done,
this,
59 &QQmlCodeModelManager::onBuildFinished);
61 connect(&m_processScheduler, &QProcessScheduler::done,
this,
62 &QQmlCodeModelManager::backgroundBuildFinished);
63 connect(&m_processScheduler, &QProcessScheduler::started,
this,
64 &QQmlCodeModelManager::backgroundBuildStarted);
65 connect(&m_processScheduler, &QProcessScheduler::cancelled,
this,
66 &QQmlCodeModelManager::backgroundBuildCancelled);
69void QQmlCodeModelManager::onBuildFinished(
const QByteArray &url)
71 auto it = findWorkspace(url);
72 if (it == m_workspaces.end())
76 const QStringList buildPaths = it->codeModel->buildPaths();
77 m_buildInformation.loadSettingsFrom(buildPaths, ForceUpdate);
78 setBuildPathsOn(&*it, buildPaths, DontAppendPathsFromFallback);
95QQmlCodeModelManager::findWorkspaceForFile(
const QByteArray &url)
97 Q_ASSERT(!m_workspaces.empty());
99 if (
auto it = m_file2CodeModel.find(url); it != m_file2CodeModel.end()) {
100 const auto result = findWorkspace(it->second);
101 Q_ASSERT(result != m_workspaces.end());
105 long longestRootUrl = 0;
106 WorkspaceIterator result = m_workspaces.begin();
107 for (
auto it = m_workspaces.begin(), end = m_workspaces.end(); it != end; ++it) {
110 const QByteArray rootUrl = it->url;
111 if (!url.startsWith(rootUrl))
114 if (rootUrl.size() == url.size())
117 const long rootUrlLength = rootUrl.length();
118 if (rootUrlLength > longestRootUrl) {
119 longestRootUrl = rootUrlLength;
125 if (
const ModuleSetting moduleSetting =
126 m_buildInformation.settingFor(QUrl::fromEncoded(url).toLocalFile());
127 !moduleSetting.importPaths.isEmpty()) {
128 const QByteArray rootUrl = QUrl::fromLocalFile(moduleSetting.sourceFolder).toEncoded();
129 if (longestRootUrl < rootUrl.size()) {
130 appendWorkspace(rootUrl, ManagedByServer);
131 return --m_workspaces.end();
134 Q_ASSERT(result != m_workspaces.end());
150void QQmlCodeModelManager::setBuildPathsOn(
const QQmlWorkspace *ws,
const QStringList &buildFolder,
175void QQmlCodeModelManager::appendWorkspace(
const QByteArray &url, ManagedBy managedBy)
179 ws.codeModel = std::make_unique<QQmlCodeModel>(url,
this, m_settings);
182 if (!url.isEmpty()) {
183 ws.codeModel->setCMakeJobs(defaultCMakeJobs());
184 ws.codeModel->setDocumentationRootPath(defaultDocumentationRootPath());
186 setBuildPathsOn(&ws, {}, AppendPathsFromFallback);
189 QObject::connect(ws.codeModel.get(), &QQmlCodeModel::updatedSnapshot,
this,
190 &QQmlCodeModelManager::updatedSnapshot);
191 ws.managedByClient = managedBy == ManagedByClient;
193 switch (m_cmakeStatus) {
194 case DoesNotHaveCMake:
195 ws.codeModel->disableCMakeCalls();
198 ws.codeModel->tryEnableCMakeCalls(&m_processScheduler);
204 m_workspaces.emplace_back(std::move(ws));
208QQmlCodeModelManager::workspaceFromBuildFolder(
const QString &fileName,
209 const QStringList &buildFolders)
211 m_buildInformation.loadSettingsFrom(buildFolders);
212 const ModuleSetting setting = m_buildInformation.settingFor(fileName);
213 QByteArray url = QUrl::fromLocalFile(setting.sourceFolder).toEncoded();
214 if (
auto it = findWorkspace(url); it != m_workspaces.end())
216 appendWorkspace(url, ManagedByServer);
217 return --m_workspaces.end();
242void QQmlCodeModelManager::newOpenFile(
const QByteArray &url,
int version,
const QString &docText)
244 const auto ws = findWorkspaceForFile(url);
245 m_file2CodeModel[url] = ws->url;
246 ws->codeModel->newOpenFile(url, version, docText);
259void QQmlCodeModelManager::closeOpenFile(
const QByteArray &url)
261 m_file2CodeModel.erase(url);
262 const auto it = findWorkspaceForFile(url);
263 it->codeModel->closeOpenFile(url);
266 if (it->url.isEmpty())
270 if ((it->managedByClient && it->toBeClosed) || !it->managedByClient) {
271 if (it->codeModel->isEmpty())
272 m_workspaces.erase(it);
286void QQmlCodeModelManager::addRootUrls(
const QList<QByteArray> &urls)
288 for (
const QByteArray &url : urls) {
289 if (
const auto it = findWorkspace(url); it != m_workspaces.end()) {
290 it->toBeClosed =
false;
294 appendWorkspace(url, ManagedByClient);
328QByteArray QQmlCodeModelManager::shortestRootUrlForFile(
const QByteArray &fileUrl)
const
331 QByteArray candidate;
334 Q_ASSERT(m_workspaces.size() > 0);
335 Q_ASSERT(m_workspaces.front().url.isEmpty());
336 auto it = std::find_if(
337 ++m_workspaces.cbegin(), m_workspaces.cend(),
338 [&fileUrl](
const QQmlWorkspace &ws) {
return fileUrl.startsWith(ws.url); });
340 if (it != m_workspaces.cend())
343 for (; it != m_workspaces.cend(); ++it) {
344 if (it->url.length() < candidate.length() && fileUrl.startsWith(it->url))
373void QQmlCodeModelManager::setBuildPathsForRootUrl(
const QByteArray &url,
const QStringList &paths)
375 m_buildInformation.loadSettingsFrom(paths);
379 setBuildPathsOn(&*fallbackWorkspace(), paths, DontAppendPathsFromFallback);
381 for (
auto it = beginNonFallbackWorkspace(), end = endNonFallbackWorkspace(); it != end;
383 setBuildPathsOn(&*it, {}, AppendPathsFromFallback);
388 auto ws = findWorkspaceForFile(url);
389 setBuildPathsOn(&*ws, paths, AppendPathsFromFallback);