Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmlcodemodel.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "qqmlcodemodel_p.h"
5#include "qtextdocument_p.h"
6
7#include <QtCore/qfileinfo.h>
8#include <QtCore/qdir.h>
9#include <QtCore/qthreadpool.h>
10#include <QtCore/qlibraryinfo.h>
11#include <QtQmlDom/private/qqmldomtop_p.h>
12
13#include <memory>
14#include <algorithm>
15
17
18namespace QmlLsp {
19
20Q_LOGGING_CATEGORY(codeModelLog, "qt.languageserver.codemodel")
21
22using namespace QQmlJS::Dom;
23using namespace Qt::StringLiterals;
24
81 : QObject { parent },
82 m_currentEnv(std::make_shared<DomEnvironment>(
83 QStringList(QLibraryInfo::path(QLibraryInfo::QmlImportsPath)),
84 DomEnvironment::Option::SingleThreaded)),
85 m_validEnv(std::make_shared<DomEnvironment>(
86 QStringList(QLibraryInfo::path(QLibraryInfo::QmlImportsPath)),
87 DomEnvironment::Option::SingleThreaded)),
88 m_settings(settings)
89{
90}
91
93{
94 while (true) {
95 bool shouldWait;
96 {
97 QMutexLocker l(&m_mutex);
98 m_state = State::Stopping;
99 m_openDocumentsToUpdate.clear();
100 shouldWait = m_nIndexInProgress != 0 || m_nUpdateInProgress != 0;
101 }
102 if (!shouldWait)
103 break;
105 }
106}
107
109{
111}
112
113int QQmlCodeModel::indexEvalProgress() const
114{
115 Q_ASSERT(!m_mutex.tryLock()); // should be called while locked
116 const int dirCost = 10;
117 int costToDo = 1;
118 for (const ToIndex &el : std::as_const(m_toIndex))
119 costToDo += dirCost * el.leftDepth;
120 costToDo += m_indexInProgressCost;
121 return m_indexDoneCost * 100 / (costToDo + m_indexDoneCost);
122}
123
124void QQmlCodeModel::indexStart()
125{
126 Q_ASSERT(!m_mutex.tryLock()); // should be called while locked
127 qCDebug(codeModelLog) << "indexStart";
128}
129
130void QQmlCodeModel::indexEnd()
131{
132 Q_ASSERT(!m_mutex.tryLock()); // should be called while locked
133 qCDebug(codeModelLog) << "indexEnd";
134 m_lastIndexProgress = 0;
135 m_nIndexInProgress = 0;
136 m_toIndex.clear();
137 m_indexInProgressCost = 0;
138 m_indexDoneCost = 0;
139}
140
141void QQmlCodeModel::indexSendProgress(int progress)
142{
143 if (progress <= m_lastIndexProgress)
144 return;
145 m_lastIndexProgress = progress;
146 // ### actually send progress
147}
148
149bool QQmlCodeModel::indexCancelled()
150{
151 QMutexLocker l(&m_mutex);
152 if (m_state == State::Stopping)
153 return true;
154 return false;
155}
156
157void QQmlCodeModel::indexDirectory(const QString &path, int depthLeft)
158{
159 if (indexCancelled())
160 return;
161 QDir dir(path);
162 if (depthLeft > 1) {
163 const QStringList dirs =
165 for (const QString &child : dirs)
166 addDirectory(dir.filePath(child), --depthLeft);
167 }
168 const QStringList qmljs =
169 dir.entryList(QStringList({ u"*.qml"_s, u"*.js"_s, u"*.mjs"_s }), QDir::Files);
170 int progress = 0;
171 {
172 QMutexLocker l(&m_mutex);
173 m_indexInProgressCost += qmljs.size();
174 progress = indexEvalProgress();
175 }
176 indexSendProgress(progress);
177 if (qmljs.isEmpty())
178 return;
179 DomItem newCurrent = m_currentEnv.makeCopy(DomItem::CopyOption::EnvConnected).item();
180 for (const QString &file : qmljs) {
181 if (indexCancelled())
182 return;
183 QString fPath = dir.filePath(file);
184 DomCreationOptions options;
185 options.setFlag(DomCreationOption::WithScriptExpressions);
186 options.setFlag(DomCreationOption::WithSemanticAnalysis);
187 FileToLoad fileToLoad =
188 FileToLoad::fromFileSystem(newCurrent.ownerAs<DomEnvironment>(), fPath, options);
189 if (!fileToLoad.canonicalPath().isEmpty()) {
190 newCurrent.loadBuiltins();
191 newCurrent.loadFile(fileToLoad, [](Path, DomItem &, DomItem &) {}, {});
192 newCurrent.loadPendingDependencies();
193 newCurrent.commitToBase(m_validEnv.ownerAs<DomEnvironment>());
194 }
195 {
196 QMutexLocker l(&m_mutex);
197 ++m_indexDoneCost;
198 --m_indexInProgressCost;
199 progress = indexEvalProgress();
200 }
201 indexSendProgress(progress);
202 }
203}
204
206{
208 // ### create progress, &scan in a separate instance
209 const int maxDepth = 5;
210 for (const auto &path : paths)
211 addDirectory(path, maxDepth);
213}
214
215void QQmlCodeModel::addDirectory(const QString &path, int depthLeft)
216{
217 if (depthLeft < 1)
218 return;
219 {
220 QMutexLocker l(&m_mutex);
221 for (auto it = m_toIndex.begin(); it != m_toIndex.end();) {
222 if (it->path.startsWith(path)) {
223 if (it->path.size() == path.size())
224 return;
225 if (it->path.at(path.size()) == u'/') {
226 it = m_toIndex.erase(it);
227 continue;
228 }
229 } else if (path.startsWith(it->path) && path.at(it->path.size()) == u'/')
230 return;
231 ++it;
232 }
233 m_toIndex.append({ path, depthLeft });
234 }
235}
236
238{
239 {
240 QMutexLocker l(&m_mutex);
241 auto toRemove = [path](const QString &p) {
242 return p.startsWith(path) && (p.size() == path.size() || p.at(path.size()) == u'/');
243 };
244 auto it = m_toIndex.begin();
245 auto end = m_toIndex.end();
246 while (it != end) {
247 if (toRemove(it->path))
248 it = m_toIndex.erase(it);
249 else
250 ++it;
251 }
252 }
253 if (auto validEnvPtr = m_validEnv.ownerAs<DomEnvironment>())
254 validEnvPtr->removePath(path);
255 if (auto currentEnvPtr = m_currentEnv.ownerAs<DomEnvironment>())
256 currentEnvPtr->removePath(path);
257}
258
260{
261 QString res;
262 {
263 QMutexLocker l(&m_mutex);
264 res = m_url2path.value(url);
265 }
266 if (!res.isEmpty() && options == UrlLookup::Caching)
267 return res;
269 QFileInfo f(qurl.toLocalFile());
270 QString cPath = f.canonicalFilePath();
271 if (cPath.isEmpty())
272 cPath = f.filePath();
273 {
274 QMutexLocker l(&m_mutex);
275 if (!res.isEmpty() && res != cPath)
276 m_path2url.remove(res);
277 m_url2path.insert(url, cPath);
278 m_path2url.insert(cPath, url);
279 }
280 return cPath;
281}
282
283void QQmlCodeModel::newOpenFile(const QByteArray &url, int version, const QString &docText)
284{
285 {
286 QMutexLocker l(&m_mutex);
287 auto &openDoc = m_openDocuments[url];
288 if (!openDoc.textDocument)
289 openDoc.textDocument = std::make_shared<Utils::TextDocument>();
290 QMutexLocker l2(openDoc.textDocument->mutex());
291 openDoc.textDocument->setVersion(version);
292 openDoc.textDocument->setPlainText(docText);
293 }
296}
297
299{
300 QMutexLocker l(&m_mutex);
301 return m_openDocuments.value(url);
302}
303
305{
306 const int maxIndexThreads = 1;
307 {
308 QMutexLocker l(&m_mutex);
309 if (m_toIndex.isEmpty() || m_nIndexInProgress >= maxIndexThreads)
310 return;
311 if (++m_nIndexInProgress == 1)
312 indexStart();
313 }
315 while (indexSome()) { }
316 });
317}
318
319bool QQmlCodeModel::indexSome()
320{
321 qCDebug(codeModelLog) << "indexSome";
323 {
324 QMutexLocker l(&m_mutex);
325 if (m_toIndex.isEmpty()) {
326 if (--m_nIndexInProgress == 0)
327 indexEnd();
328 return false;
329 }
330 toIndex = m_toIndex.last();
331 m_toIndex.removeLast();
332 }
333 bool hasMore = false;
334 {
335 auto guard = qScopeGuard([this, &hasMore]() {
336 QMutexLocker l(&m_mutex);
337 if (m_toIndex.isEmpty()) {
338 if (--m_nIndexInProgress == 0)
339 indexEnd();
340 hasMore = false;
341 } else {
342 hasMore = true;
343 }
344 });
345 indexDirectory(toIndex.path, toIndex.leftDepth);
346 }
347 return hasMore;
348}
349
351{
352 qCDebug(codeModelLog) << "openNeedUpdate";
353 const int maxIndexThreads = 1;
354 {
355 QMutexLocker l(&m_mutex);
356 if (m_openDocumentsToUpdate.isEmpty() || m_nUpdateInProgress >= maxIndexThreads)
357 return;
358 if (++m_nUpdateInProgress == 1)
359 openUpdateStart();
360 }
362 while (openUpdateSome()) { }
363 });
364}
365
366bool QQmlCodeModel::openUpdateSome()
367{
368 qCDebug(codeModelLog) << "openUpdateSome start";
369 QByteArray toUpdate;
370 {
371 QMutexLocker l(&m_mutex);
372 if (m_openDocumentsToUpdate.isEmpty()) {
373 if (--m_nUpdateInProgress == 0)
374 openUpdateEnd();
375 return false;
376 }
377 auto it = m_openDocumentsToUpdate.find(m_lastOpenDocumentUpdated);
378 auto end = m_openDocumentsToUpdate.end();
379 if (it == end)
380 it = m_openDocumentsToUpdate.begin();
381 else if (++it == end)
382 it = m_openDocumentsToUpdate.begin();
383 toUpdate = *it;
384 m_openDocumentsToUpdate.erase(it);
385 }
386 bool hasMore = false;
387 {
388 auto guard = qScopeGuard([this, &hasMore]() {
389 QMutexLocker l(&m_mutex);
390 if (m_openDocumentsToUpdate.isEmpty()) {
391 if (--m_nUpdateInProgress == 0)
392 openUpdateEnd();
393 hasMore = false;
394 } else {
395 hasMore = true;
396 }
397 });
398 openUpdate(toUpdate);
399 }
400 return hasMore;
401}
402
403void QQmlCodeModel::openUpdateStart()
404{
405 qCDebug(codeModelLog) << "openUpdateStart";
406}
407
408void QQmlCodeModel::openUpdateEnd()
409{
410 qCDebug(codeModelLog) << "openUpdateEnd";
411}
412
413void QQmlCodeModel::newDocForOpenFile(const QByteArray &url, int version, const QString &docText)
414{
415 qCDebug(codeModelLog) << "updating doc" << url << "to version" << version << "("
416 << docText.size() << "chars)";
417 DomItem newCurrent = m_currentEnv.makeCopy(DomItem::CopyOption::EnvConnected).item();
420 if (std::shared_ptr<DomEnvironment> newCurrentPtr = newCurrent.ownerAs<DomEnvironment>()) {
421 newCurrentPtr->setLoadPaths(loadPaths);
422 }
424 Path p;
425 DomCreationOptions options;
426 options.setFlag(DomCreationOption::WithScriptExpressions);
427 options.setFlag(DomCreationOption::WithSemanticAnalysis);
428 newCurrent.loadFile(
429 FileToLoad::fromMemory(newCurrent.ownerAs<DomEnvironment>(), fPath, docText, options),
430 [&p](Path, DomItem &, DomItem &newValue) { p = newValue.fileObject().canonicalPath(); },
431 {});
432 newCurrent.loadPendingDependencies();
433 if (p) {
434 newCurrent.commitToBase(m_validEnv.ownerAs<DomEnvironment>());
435 DomItem item = m_currentEnv.path(p);
436 {
437 QMutexLocker l(&m_mutex);
438 OpenDocument &doc = m_openDocuments[url];
439 if (!doc.textDocument) {
440 qCWarning(lspServerLog)
441 << "ignoring update to closed document" << QString::fromUtf8(url);
442 return;
443 } else {
444 QMutexLocker l(doc.textDocument->mutex());
445 if (doc.textDocument->version() && *doc.textDocument->version() > version) {
446 qCWarning(lspServerLog)
447 << "docUpdate: version" << version << "of document"
448 << QString::fromUtf8(url) << "is not the latest anymore";
449 return;
450 }
451 }
452 if (!doc.snapshot.docVersion || *doc.snapshot.docVersion < version) {
453 doc.snapshot.docVersion = version;
454 doc.snapshot.doc = item;
455 } else {
456 qCWarning(lspServerLog) << "skipping update of current doc to obsolete version"
457 << version << "of document" << QString::fromUtf8(url);
458 }
459 if (item.field(Fields::isValid).value().toBool(false)) {
460 if (!doc.snapshot.validDocVersion || *doc.snapshot.validDocVersion < version) {
461 DomItem vDoc = m_validEnv.path(p);
462 doc.snapshot.validDocVersion = version;
463 doc.snapshot.validDoc = vDoc;
464 } else {
465 qCWarning(lspServerLog) << "skippig update of valid doc to obsolete version"
466 << version << "of document" << QString::fromUtf8(url);
467 }
468 } else {
469 qCWarning(lspServerLog)
470 << "avoid update of validDoc to " << version << "of document"
471 << QString::fromUtf8(url) << "as it is invalid";
472 }
473 }
474 }
475 if (codeModelLog().isDebugEnabled()) {
476 qCDebug(codeModelLog) << "finished update doc of " << url << "to version" << version;
477 snapshotByUrl(url).dump(qDebug() << "postSnapshot",
479 }
480 // we should update the scope in the future thus call addOpen(url)
482}
483
485{
486 QMutexLocker l(&m_mutex);
487 m_openDocuments.remove(url);
488}
489
491{
492 QMutexLocker l(&m_mutex);
493 m_rootUrls = urls;
494}
495
497{
498 QMutexLocker l(&m_mutex);
499 for (const QByteArray &url : urls) {
500 if (!m_rootUrls.contains(url))
501 m_rootUrls.append(url);
502 }
503}
504
506{
507 QMutexLocker l(&m_mutex);
508 for (const QByteArray &url : urls)
509 m_rootUrls.removeOne(url);
510}
511
513{
514 QMutexLocker l(&m_mutex);
515 return m_rootUrls;
516}
517
519{
520 QMutexLocker l(&m_mutex);
521 return m_buildPathsForRootUrl.value(url);
522}
523
524static bool isNotSeparator(char c)
525{
526 return c != '/';
527}
528
530{
531 QList<QByteArray> roots;
532 {
533 QMutexLocker l(&m_mutex);
534 roots = m_buildPathsForRootUrl.keys();
535 }
536 // we want to longest match to be first, as it should override shorter matches
537 std::sort(roots.begin(), roots.end(), [](const QByteArray &el1, const QByteArray &el2) {
538 if (el1.size() > el2.size())
539 return true;
540 if (el1.size() < el2.size())
541 return false;
542 return el1 < el2;
543 });
544 QStringList buildPaths;
545 QStringList defaultValues;
546 if (!roots.isEmpty() && roots.last().isEmpty())
547 roots.removeLast();
548 QByteArray urlSlash(url);
549 if (!urlSlash.isEmpty() && isNotSeparator(urlSlash.at(urlSlash.size() - 1)))
550 urlSlash.append('/');
551 // look if the file has a know prefix path
552 for (const QByteArray &root : roots) {
553 if (urlSlash.startsWith(root)) {
554 buildPaths += buildPathsForRootUrl(root);
555 break;
556 }
557 }
559
560 // fallback to the empty root, if is has an entry.
561 // This is the buildPath that is passed to qmlls via --build-dir.
562 if (buildPaths.isEmpty()) {
563 buildPaths += buildPathsForRootUrl(QByteArray());
564 }
565
566 // look in the QMLLS_BUILD_DIRS environment variable
567 if (buildPaths.isEmpty()) {
568 QStringList envPaths = qEnvironmentVariable("QMLLS_BUILD_DIRS")
570 buildPaths += envPaths;
571 }
572
573 // look in the settings.
574 // This is the one that is passed via the .qmlls.ini file.
575 if (buildPaths.isEmpty() && m_settings) {
576 m_settings->search(path);
577 QString buildDir = QStringLiteral(u"buildDir");
578 if (m_settings->isSet(buildDir))
579 buildPaths += m_settings->value(buildDir).toString().split(QDir::listSeparator(),
581 }
582
583 // heuristic to find build directory
584 if (buildPaths.isEmpty()) {
585 QDir d(path);
586 d.setNameFilters(QStringList({ u"build*"_s }));
587 const int maxDirDepth = 8;
588 int iDir = maxDirDepth;
589 QString dirName = d.dirName();
590 QDateTime lastModified;
591 while (d.cdUp() && --iDir > 0) {
592 for (const QFileInfo &fInfo : d.entryInfoList(QDir::Dirs)) {
593 if (fInfo.completeBaseName() == u"build"
594 || fInfo.completeBaseName().startsWith(u"build-%1"_s.arg(dirName))) {
595 if (iDir > 1)
596 iDir = 1;
597 if (!lastModified.isValid() || lastModified < fInfo.lastModified()) {
598 buildPaths.clear();
599 buildPaths.append(fInfo.absoluteFilePath());
600 }
601 }
602 }
603 }
604 }
605 // add dependent build directories
607 std::reverse(buildPaths.begin(), buildPaths.end());
608 const int maxDeps = 4;
609 while (!buildPaths.isEmpty()) {
610 QString bPath = buildPaths.last();
611 buildPaths.removeLast();
612 res += bPath;
613 if (QFile::exists(bPath + u"/_deps") && bPath.split(u"/_deps/"_s).size() < maxDeps) {
614 QDir d(bPath + u"/_deps");
615 for (const QFileInfo &fInfo : d.entryInfoList(QDir::Dirs))
616 buildPaths.append(fInfo.absoluteFilePath());
617 }
618 }
619 return res;
620}
621
623{
624 QMutexLocker l(&m_mutex);
625 if (!url.isEmpty() && isNotSeparator(url.at(url.size() - 1)))
626 url.append('/');
627 if (paths.isEmpty())
628 m_buildPathsForRootUrl.remove(url);
629 else
630 m_buildPathsForRootUrl.insert(url, paths);
631}
632
633void QQmlCodeModel::openUpdate(const QByteArray &url)
634{
635 bool updateDoc = false;
636 bool updateScope = false;
637 std::optional<int> rNow = 0;
638 QString docText;
639 DomItem validDoc;
640 std::shared_ptr<Utils::TextDocument> document;
641 {
642 QMutexLocker l(&m_mutex);
643 OpenDocument &doc = m_openDocuments[url];
644 document = doc.textDocument;
645 if (!document)
646 return;
647 {
648 QMutexLocker l2(document->mutex());
649 rNow = document->version();
650 }
651 if (rNow && (!doc.snapshot.docVersion || *doc.snapshot.docVersion != *rNow))
652 updateDoc = true;
653 else if (doc.snapshot.validDocVersion
654 && (!doc.snapshot.scopeVersion
656 updateScope = true;
657 else
658 return;
659 if (updateDoc) {
660 QMutexLocker l2(doc.textDocument->mutex());
661 rNow = doc.textDocument->version();
662 docText = doc.textDocument->toPlainText();
663 } else {
664 validDoc = doc.snapshot.validDoc;
665 rNow = doc.snapshot.validDocVersion;
666 }
667 }
668 if (updateDoc) {
669 newDocForOpenFile(url, *rNow, docText);
670 }
671 if (updateScope) {
672 // to do
673 }
674}
675
677{
678 QMutexLocker l(&m_mutex);
679 m_openDocumentsToUpdate.insert(url);
680}
681
682QDebug OpenDocumentSnapshot::dump(QDebug dbg, DumpOptions options)
683{
684 dbg.noquote().nospace() << "{";
685 dbg << " url:" << QString::fromUtf8(url) << "\n";
686 dbg << " docVersion:" << (docVersion ? QString::number(*docVersion) : u"*none*"_s) << "\n";
687 if (options & DumpOption::LatestCode) {
688 dbg << " doc: ------------\n"
689 << doc.field(Fields::code).value().toString() << "\n==========\n";
690 } else {
691 dbg << u" doc:"
692 << (doc ? u"%1chars"_s.arg(doc.field(Fields::code).value().toString().size())
693 : u"*none*"_s)
694 << "\n";
695 }
696 dbg << " validDocVersion:"
697 << (validDocVersion ? QString::number(*validDocVersion) : u"*none*"_s) << "\n";
698 if (options & DumpOption::ValidCode) {
699 dbg << " validDoc: ------------\n"
700 << validDoc.field(Fields::code).value().toString() << "\n==========\n";
701 } else {
702 dbg << u" validDoc:"
703 << (validDoc ? u"%1chars"_s.arg(validDoc.field(Fields::code).value().toString().size())
704 : u"*none*"_s)
705 << "\n";
706 }
707 dbg << " scopeVersion:" << (scopeVersion ? QString::number(*scopeVersion) : u"*none*"_s)
708 << "\n";
709 dbg << " scopeDependenciesLoadTime:" << scopeDependenciesLoadTime << "\n";
710 dbg << " scopeDependenciesChanged" << scopeDependenciesChanged << "\n";
711 dbg << "}";
712 return dbg;
713}
714
715} // namespace QmlLsp
716
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
bool startsWith(QByteArrayView bv) const
Definition qbytearray.h:170
char at(qsizetype i) const
Returns the byte at index position i in the byte array.
Definition qbytearray.h:523
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:106
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString toString(const QString &defaultValue={}) const
Returns the string value stored in this QCborValue, if it is of the string type.
\inmodule QtCore\reentrant
Definition qdatetime.h:257
bool isValid() const
Returns true if this datetime represents a definite moment, otherwise false.
\inmodule QtCore
\inmodule QtCore
Definition qdir.h:19
@ Files
Definition qdir.h:22
@ NoSymLinks
Definition qdir.h:24
@ NoDotAndDotDot
Definition qdir.h:43
@ Dirs
Definition qdir.h:21
static constexpr QChar listSeparator() noexcept
Definition qdir.h:197
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
bool remove(const Key &key)
Removes the item that has the key from the hash.
Definition qhash.h:956
QList< Key > keys() const
Returns a list containing all the keys in the hash, in an arbitrary order.
Definition qhash.h:1076
T value(const Key &key) const noexcept
Definition qhash.h:1044
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
Implements a server for the language server protocol.
\inmodule QtCore
static QString path(LibraryPath p)
Definition qlist.h:74
bool isEmpty() const noexcept
Definition qlist.h:390
T & last()
Definition qlist.h:631
bool removeOne(const AT &t)
Definition qlist.h:581
iterator end()
Definition qlist.h:609
iterator begin()
Definition qlist.h:608
void removeLast() noexcept
Definition qlist.h:808
void append(parameter_type t)
Definition qlist.h:441
\inmodule QtCore
Definition qmutex.h:317
bool tryLock(int timeout=0) noexcept
Attempts to lock the mutex.
Definition qmutex.h:291
\inmodule QtCore
Definition qobject.h:90
Represents a consistent set of types organized in modules, it is the top level of the DOM.
std::shared_ptr< T > ownerAs()
MutableDomItem makeCopy(CopyOption option=CopyOption::EnvConnected)
void loadPendingDependencies()
bool commitToBase(std::shared_ptr< DomEnvironment > validPtr=nullptr)
DomItem path(Path p, ErrorHandler h=&defaultErrorHandler)
void loadFile(const FileToLoad &file, std::function< void(Path, DomItem &, DomItem &)> callback, LoadOptions loadOptions, std::optional< DomType > fileType=std::optional< DomType >())
QCborValue value()
DomItem field(QStringView name)
QString canonicalPath() const
static FileToLoad fromMemory(const std::weak_ptr< DomEnvironment > &environment, const QString &path, const QString &data, DomCreationOptions options=None)
static FileToLoad fromFileSystem(const std::weak_ptr< DomEnvironment > &environment, const QString &canonicalPath, DomCreationOptions options=None)
bool search(const QString &path)
bool isSet(QString name) const
QVariant value(QString name) const
qsizetype size() const
Definition qset.h:50
iterator begin()
Definition qset.h:136
iterator end()
Definition qset.h:140
bool isEmpty() const
Definition qset.h:52
void clear()
Definition qset.h:61
iterator erase(const_iterator i)
Definition qset.h:145
iterator find(const T &value)
Definition qset.h:159
iterator insert(const T &value)
Definition qset.h:155
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
Definition qstring.cpp:7956
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
void start(QRunnable *runnable, int priority=0)
Reserves a thread and uses it to run runnable, unless this thread will make the current thread count ...
static QThreadPool * globalInstance()
Returns the global QThreadPool instance.
static void yieldCurrentThread()
Definition qthread.cpp:976
\inmodule QtCore
Definition qurl.h:94
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1888
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition qurl.cpp:3411
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
std::optional< int > scopeVersion
std::optional< int > docVersion
std::optional< int > validDocVersion
QDebug dump(QDebug dbg, DumpOptions dump=DumpOption::NoCode)
QQmlJS::Dom::DomItem validDoc
std::shared_ptr< Utils::TextDocument > textDocument
OpenDocumentSnapshot snapshot
void newOpenFile(const QByteArray &url, int version, const QString &docText)
void addRootUrls(const QList< QByteArray > &urls)
QList< QByteArray > rootUrls() const
QQmlCodeModel(QObject *parent=nullptr, QQmlToolingSettings *settings=nullptr)
void setBuildPathsForRootUrl(QByteArray url, const QStringList &paths)
OpenDocumentSnapshot snapshotByUrl(const QByteArray &url)
void addOpenToUpdate(const QByteArray &)
QString url2Path(const QByteArray &url, UrlLookup options=UrlLookup::Caching)
OpenDocument openDocumentByUrl(const QByteArray &url)
QStringList buildPathsForFileUrl(const QByteArray &url)
void setRootUrls(const QList< QByteArray > &urls)
void removeDirectory(const QString &path)
void removeRootUrls(const QList< QByteArray > &urls)
void addDirectoriesToIndex(const QStringList &paths, QLanguageServer *server)
void newDocForOpenFile(const QByteArray &url, int version, const QString &docText)
void updatedSnapshot(const QByteArray &url)
QStringList buildPathsForRootUrl(const QByteArray &url)
void closeOpenFile(const QByteArray &url)
QSet< QString >::iterator it
Combined button and popup list for selecting options.
static bool isNotSeparator(char c)
@ SkipEmptyParts
Definition qnamespace.h:127
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage return DBusPendingCall DBusPendingCall return DBusPendingCall return dbus_int32_t return DBusServer * server
#define qDebug
[1]
Definition qlogging.h:160
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
GLuint GLuint end
GLfloat GLfloat f
GLsizei const GLuint * paths
GLuint res
const GLubyte * c
GLsizei const GLchar *const * path
GLfloat GLfloat p
[1]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
#define QStringLiteral(str)
QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
#define emit
#define Q_UNUSED(x)
static uint toIndex(ExecutionEngine *e, const Value &v)
QFile file
[0]
QSettings settings("MySoft", "Star Runner")
[0]
QUrl url("example.com")
[constructor-url-reference]
QString dir
[11]
QGraphicsItem * item
QLayoutItem * child
[0]
QStringView el
bool contains(const AT &t) const noexcept
Definition qlist.h:44
IUIAutomation __RPC__in_opt IUIAutomationElement * el2
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent