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);
60 connect(&m_processScheduler, &QProcessScheduler::started,
this,
61 &QQmlCodeModelManager::backgroundBuildStarted);
62 connect(&m_processScheduler, &QProcessScheduler::cancelled,
this,
63 &QQmlCodeModelManager::backgroundBuildCancelled);
66void QQmlCodeModelManager::onBuildFinished(
const QByteArray &url)
68 auto it = findWorkspace(url);
69 if (it == m_workspaces.end())
73 const QStringList buildPaths = it->codeModel->buildPaths();
74 m_buildInformation.loadSettingsFrom(buildPaths, ForceUpdate);
75 setBuildPathsOn(&*it, buildPaths, DontAppendPathsFromFallback);
76 it->codeModel->reloadAllOpenFiles();
77 emit backgroundBuildFinished(url);
94QQmlCodeModelManager::findWorkspaceForFile(
const QByteArray &url)
96 Q_ASSERT(!m_workspaces.empty());
98 if (
auto it = m_file2CodeModel.find(url); it != m_file2CodeModel.end()) {
99 const auto result = findWorkspace(it->second);
100 Q_ASSERT(result != m_workspaces.end());
104 long longestRootUrl = 0;
105 WorkspaceIterator result = m_workspaces.begin();
106 for (
auto it = m_workspaces.begin(), end = m_workspaces.end(); it != end; ++it) {
109 const QByteArray rootUrl = it->url;
110 if (!url.startsWith(rootUrl))
113 if (rootUrl.size() == url.size())
116 const long rootUrlLength = rootUrl.length();
117 if (rootUrlLength > longestRootUrl) {
118 longestRootUrl = rootUrlLength;
124 if (
const ModuleSetting moduleSetting =
125 m_buildInformation.settingFor(QUrl::fromEncoded(url).toLocalFile());
126 !moduleSetting.importPaths.isEmpty()) {
127 const QByteArray rootUrl = QUrl::fromLocalFile(moduleSetting.sourceFolder).toEncoded();
128 if (longestRootUrl < rootUrl.size()) {
129 appendWorkspace(rootUrl, ManagedByServer);
130 return --m_workspaces.end();
133 Q_ASSERT(result != m_workspaces.end());
149void QQmlCodeModelManager::setBuildPathsOn(
const QQmlWorkspace *ws,
const QStringList &buildFolder,
174void QQmlCodeModelManager::appendWorkspace(
const QByteArray &url, ManagedBy managedBy)
178 ws.codeModel = std::make_unique<QQmlCodeModel>(url,
this, m_settings);
181 if (!url.isEmpty()) {
182 ws.codeModel->setCMakeJobs(defaultCMakeJobs());
183 ws.codeModel->setDocumentationRootPath(defaultDocumentationRootPath());
185 setBuildPathsOn(&ws, {}, AppendPathsFromFallback);
188 QObject::connect(ws.codeModel.get(), &QQmlCodeModel::updatedSnapshot,
this,
189 &QQmlCodeModelManager::updatedSnapshot);
190 ws.managedByClient = managedBy == ManagedByClient;
192 switch (m_cmakeStatus) {
193 case DoesNotHaveCMake:
194 ws.codeModel->disableCMakeCalls();
197 ws.codeModel->tryEnableCMakeCalls(&m_processScheduler);
203 m_workspaces.emplace_back(std::move(ws));
207QQmlCodeModelManager::workspaceFromBuildFolder(
const QString &fileName,
208 const QStringList &buildFolders)
210 m_buildInformation.loadSettingsFrom(buildFolders);
211 const ModuleSetting setting = m_buildInformation.settingFor(fileName);
212 QByteArray url = QUrl::fromLocalFile(setting.sourceFolder).toEncoded();
213 if (
auto it = findWorkspace(url); it != m_workspaces.end())
215 appendWorkspace(url, ManagedByServer);
216 return --m_workspaces.end();
241void QQmlCodeModelManager::newOpenFile(
const QByteArray &url,
int version,
const QString &docText)
243 const auto ws = findWorkspaceForFile(url);
244 m_file2CodeModel[url] = ws->url;
245 ws->codeModel->newOpenFile(url, version, docText);
258void QQmlCodeModelManager::closeOpenFile(
const QByteArray &url)
260 m_file2CodeModel.erase(url);
261 const auto it = findWorkspaceForFile(url);
262 it->codeModel->closeOpenFile(url);
265 if (it->url.isEmpty())
269 if ((it->managedByClient && it->toBeClosed) || !it->managedByClient) {
270 if (it->codeModel->isEmpty())
271 m_workspaces.erase(it);
285void QQmlCodeModelManager::addRootUrls(
const QList<QByteArray> &urls)
287 for (
const QByteArray &url : urls) {
288 if (
const auto it = findWorkspace(url); it != m_workspaces.end()) {
289 it->toBeClosed =
false;
293 appendWorkspace(url, ManagedByClient);
327QByteArray QQmlCodeModelManager::shortestRootUrlForFile(
const QByteArray &fileUrl)
const
330 QByteArray candidate;
333 Q_ASSERT(m_workspaces.size() > 0);
334 Q_ASSERT(m_workspaces.front().url.isEmpty());
335 auto it = std::find_if(
336 ++m_workspaces.cbegin(), m_workspaces.cend(),
337 [&fileUrl](
const QQmlWorkspace &ws) {
return fileUrl.startsWith(ws.url); });
339 if (it != m_workspaces.cend())
342 for (; it != m_workspaces.cend(); ++it) {
343 if (it->url.length() < candidate.length() && fileUrl.startsWith(it->url))
372void QQmlCodeModelManager::setBuildPathsForRootUrl(
const QByteArray &url,
const QStringList &paths)
374 m_buildInformation.loadSettingsFrom(paths);
378 setBuildPathsOn(&*fallbackWorkspace(), paths, DontAppendPathsFromFallback);
380 for (
auto it = beginNonFallbackWorkspace(), end = endNonFallbackWorkspace(); it != end;
382 setBuildPathsOn(&*it, {}, AppendPathsFromFallback);
387 auto ws = findWorkspaceForFile(url);
388 setBuildPathsOn(&*ws, paths, AppendPathsFromFallback);