diff options
Diffstat (limited to 'src/qmldom')
-rw-r--r-- | src/qmldom/qqmldomattachedinfo.cpp | 2 | ||||
-rw-r--r-- | src/qmldom/qqmldomcomments.cpp | 2 | ||||
-rw-r--r-- | src/qmldom/qqmldomelements.cpp | 46 | ||||
-rw-r--r-- | src/qmldom/qqmldomelements_p.h | 2 | ||||
-rw-r--r-- | src/qmldom/qqmldomerrormessage.cpp | 2 | ||||
-rw-r--r-- | src/qmldom/qqmldomerrormessage_p.h | 63 | ||||
-rw-r--r-- | src/qmldom/qqmldomfieldfilter.cpp | 2 | ||||
-rw-r--r-- | src/qmldom/qqmldomfilewriter.cpp | 2 | ||||
-rw-r--r-- | src/qmldom/qqmldomitem.cpp | 95 | ||||
-rw-r--r-- | src/qmldom/qqmldomitem_p.h | 13 | ||||
-rw-r--r-- | src/qmldom/qqmldomlinewriter.cpp | 2 | ||||
-rw-r--r-- | src/qmldom/qqmldommoduleindex.cpp | 2 | ||||
-rw-r--r-- | src/qmldom/qqmldompath.cpp | 17 | ||||
-rw-r--r-- | src/qmldom/qqmldompath_p.h | 32 | ||||
-rw-r--r-- | src/qmldom/qqmldomreformatter.cpp | 62 | ||||
-rw-r--r-- | src/qmldom/qqmldomtop.cpp | 169 | ||||
-rw-r--r-- | src/qmldom/qqmldomtop_p.h | 13 |
17 files changed, 364 insertions, 162 deletions
diff --git a/src/qmldom/qqmldomattachedinfo.cpp b/src/qmldom/qqmldomattachedinfo.cpp index 707aae4283..eb48640d90 100644 --- a/src/qmldom/qqmldomattachedinfo.cpp +++ b/src/qmldom/qqmldomattachedinfo.cpp @@ -369,3 +369,5 @@ bool UpdatedScriptExpression::visitTree(Tree base, function_ref<bool(Path, Tree) } // namespace Dom } // namespace QQmlJS QT_END_NAMESPACE + +#include "moc_qqmldomattachedinfo_p.cpp" diff --git a/src/qmldom/qqmldomcomments.cpp b/src/qmldom/qqmldomcomments.cpp index af58b6d821..7edcc0c9d9 100644 --- a/src/qmldom/qqmldomcomments.cpp +++ b/src/qmldom/qqmldomcomments.cpp @@ -555,7 +555,7 @@ void AstComments::collectComments(std::shared_ptr<Engine> engine, AST::Node *n, } if (iPre == 0) preNewline = 1; - quint32 iPost = cLoc.end(); + qsizetype iPost = cLoc.end(); while (iPost < code.size()) { QChar c = code.at(iPost); if (!c.isSpace()) { diff --git a/src/qmldom/qqmldomelements.cpp b/src/qmldom/qqmldomelements.cpp index 914c72e34f..9a9a186833 100644 --- a/src/qmldom/qqmldomelements.cpp +++ b/src/qmldom/qqmldomelements.cpp @@ -57,6 +57,7 @@ #include <QtCore/QBasicMutex> #include <optional> +#include <limits> QT_BEGIN_NAMESPACE @@ -653,9 +654,14 @@ MutableDomItem QmlObject::addMethod(MutableDomItem &self, MethodInfo functionDef void QmlObject::writeOut(DomItem &self, OutWriter &ow, QString onTarget) const { + const quint32 posOfNewElements = std::numeric_limits<quint32>::max(); bool isRootObject = pathFromOwner().length() == 5 && pathFromOwner()[0] == Path::Field(Fields::components) && pathFromOwner()[3] == Path::Field(Fields::objects); + QString code; + DomItem owner = self.owner(); + if (std::shared_ptr<QmlFile> qmlFilePtr = self.ownerAs<QmlFile>()) + code = qmlFilePtr->code(); ow.writeRegion(u"name", name()); if (!onTarget.isEmpty()) ow.space().writeRegion(u"on", u"on").space().writeRegion(u"onTarget", onTarget).space(); @@ -678,10 +684,10 @@ void QmlObject::writeOut(DomItem &self, OutWriter &ow, QString onTarget) const DomItem component; if (isRootObject) component = self.containingObject(); - auto startLoc = [](FileLocations::Tree l) { + auto startLoc = [&](FileLocations::Tree l) { if (l) return l->info().fullRegion; - return SourceLocation(~quint32(0), 0, 0, 0); + return SourceLocation(posOfNewElements, 0, 0, 0); }; if (ow.lineWriter.options().attributesSequence == LineWriterOptions::AttributesSequence::Preserve) { @@ -749,10 +755,22 @@ void QmlObject::writeOut(DomItem &self, OutWriter &ow, QString onTarget) const qsizetype iAttr = 0; while (iAttr != attribs.size()) { auto &el = attribs[iAttr++]; - if (iAttr > 1 && el.second.internalKind() != attribs[iAttr - 2].second.internalKind()) - ow.ensureNewline(2); - else - ow.ensureNewline(); + // check for an empty line before the current element, and preserve it + int preNewlines = 0; + quint32 start = el.first.offset; + if (start != posOfNewElements && size_t(code.size()) >= start) { + while (start != 0) { + QChar c = code.at(--start); + if (c == u'\n') { + if (++preNewlines == 2) + break; + } else if (!c.isSpace()) + break; + } + } + if (preNewlines == 0) + ++preNewlines; + ow.ensureNewline(preNewlines); if (el.second.internalKind() == DomType::PropertyDefinition && iAttr != attribs.size() && el.first.offset != ~quint32(0)) { DomItem b; @@ -1197,9 +1215,10 @@ void EnumDecl::writeOut(DomItem &self, OutWriter &ow) const QList<Path> ImportScope::allSources(DomItem &self) const { - DomItem env = self.environment(); + DomItem top = self.top(); + DomItem env = top.environment(); Path selfPath = self.canonicalPath().field(Fields::allSources); - RefCacheEntry cached = RefCacheEntry::forPath(env, selfPath); + RefCacheEntry cached = (env ? RefCacheEntry::forPath(env, selfPath) : RefCacheEntry()); if (cached.cached == RefCacheEntry::Cached::All) return cached.canonicalPaths; QList<Path> res; @@ -1211,7 +1230,7 @@ QList<Path> ImportScope::allSources(DomItem &self) const continue; knownPaths.insert(pNow); res.append(pNow); - DomItem sourceBase = env.path(pNow); + DomItem sourceBase = top.path(pNow); for (DomItem autoExp : sourceBase.field(Fields::autoExports).values()) { if (const ModuleAutoExport *autoExpPtr = autoExp.as<ModuleAutoExport>()) { Path newSource; @@ -1241,7 +1260,8 @@ QList<Path> ImportScope::allSources(DomItem &self) const } } } - RefCacheEntry::addForPath(env, selfPath, RefCacheEntry { RefCacheEntry::Cached::All, res }); + if (env) + RefCacheEntry::addForPath(env, selfPath, RefCacheEntry { RefCacheEntry::Cached::All, res }); return res; } @@ -1447,10 +1467,10 @@ class FirstNodeVisitor : public VisitAll { public: quint32 minStart = 0; - quint32 maxEnd = ~quint32(0); + quint32 maxEnd = std::numeric_limits<quint32>::max(); AST::Node *firstNodeInRange = nullptr; - FirstNodeVisitor(quint32 minStart = 0, quint32 maxEnd = ~quint32(0)) + FirstNodeVisitor(quint32 minStart = 0, quint32 maxEnd = std::numeric_limits<quint32>::max()) : minStart(minStart), maxEnd(maxEnd) { } @@ -1769,3 +1789,5 @@ void EnumItem::writeOut(DomItem &self, OutWriter &ow) const } // end namespace QQmlJS QT_END_NAMESPACE + +#include "moc_qqmldomelements_p.cpp" diff --git a/src/qmldom/qqmldomelements_p.h b/src/qmldom/qqmldomelements_p.h index 69c2cc1a7d..023883dfd6 100644 --- a/src/qmldom/qqmldomelements_p.h +++ b/src/qmldom/qqmldomelements_p.h @@ -726,7 +726,6 @@ public: : CommentableDomElement(pathFromOwner), m_name(name), m_values(values) { } - EnumDecl &operator=(const EnumDecl &) = default; bool iterateDirectSubpaths(DomItem &self, DirectVisitor visitor) override; @@ -766,7 +765,6 @@ public: DomType kind() const override { return kindValue; } QmlObject(Path pathFromOwner = Path()); - QmlObject &operator=(const QmlObject &) = default; bool iterateDirectSubpaths(DomItem &self, DirectVisitor) override; bool iterateBaseDirectSubpaths(DomItem &self, DirectVisitor); QList<QString> fields() const; diff --git a/src/qmldom/qqmldomerrormessage.cpp b/src/qmldom/qqmldomerrormessage.cpp index e621ac775f..450ae558b8 100644 --- a/src/qmldom/qqmldomerrormessage.cpp +++ b/src/qmldom/qqmldomerrormessage.cpp @@ -560,3 +560,5 @@ ErrorLevel errorLevelFromQtMsgType(QtMsgType msgType) } // end namespace QQmlJS QT_END_NAMESPACE + +#include "moc_qqmldomerrormessage_p.cpp" diff --git a/src/qmldom/qqmldomerrormessage_p.h b/src/qmldom/qqmldomerrormessage_p.h index fc3e0a2e11..3e7233125e 100644 --- a/src/qmldom/qqmldomerrormessage_p.h +++ b/src/qmldom/qqmldomerrormessage_p.h @@ -160,6 +160,46 @@ public: void dump(Sink s) const; QString toString() const; QCborMap toCbor() const; + friend int compare(const ErrorMessage &msg1, const ErrorMessage &msg2) + { + int c; + c = msg1.location.offset - msg2.location.offset; + if (c != 0) + return c; + c = msg1.location.startLine - msg2.location.startLine; + if (c != 0) + return c; + c = msg1.errorId.compare(msg2.errorId); + if (c != 0) + return c; + if (!msg1.errorId.isEmpty()) + return 0; + c = msg1.message.compare(msg2.message); + if (c != 0) + return c; + c = msg1.file.compare(msg2.file); + if (c != 0) + return c; + c = Path::cmp(msg1.path, msg2.path); + if (c != 0) + return c; + c = int(msg1.level) - int(msg2.level); + if (c != 0) + return c; + c = int(msg1.errorGroups.groups.size() - msg2.errorGroups.groups.size()); + if (c != 0) + return c; + for (qsizetype i = 0; i < msg1.errorGroups.groups.size(); ++i) { + c = msg1.errorGroups.groups[i].groupId().compare(msg2.errorGroups.groups[i].groupId()); + if (c != 0) + return c; + } + c = msg1.location.length - msg2.location.length; + if (c != 0) + return c; + c = msg1.location.startColumn - msg2.location.startColumn; + return c; + } QLatin1String errorId; QString message; @@ -171,13 +211,26 @@ public: }; inline bool operator !=(const ErrorMessage &e1, const ErrorMessage &e2) { - return e1.errorId != e2.errorId || e1.message != e2.message || e1.errorGroups != e2.errorGroups - || e1.level != e2.level || e1.path != e2.path || e1.file != e2.file - || e1.location.startLine != e2.location.startLine || e1.location.offset != e2.location.offset - || e1.location.startColumn != e2.location.startColumn || e1.location.length != e2.location.length; + return compare(e1, e2) != 0; } inline bool operator ==(const ErrorMessage &e1, const ErrorMessage &e2) { - return !(e1 != e2); + return compare(e1, e2) == 0; +} +inline bool operator<(const ErrorMessage &e1, const ErrorMessage &e2) +{ + return compare(e1, e2) < 0; +} +inline bool operator<=(const ErrorMessage &e1, const ErrorMessage &e2) +{ + return compare(e1, e2) <= 0; +} +inline bool operator>(const ErrorMessage &e1, const ErrorMessage &e2) +{ + return compare(e1, e2) > 0; +} +inline bool operator>=(const ErrorMessage &e1, const ErrorMessage &e2) +{ + return compare(e1, e2) >= 0; } QMLDOM_EXPORT void silentError(const ErrorMessage &); diff --git a/src/qmldom/qqmldomfieldfilter.cpp b/src/qmldom/qqmldomfieldfilter.cpp index 3fa39b5b49..1ea27e0ee5 100644 --- a/src/qmldom/qqmldomfieldfilter.cpp +++ b/src/qmldom/qqmldomfieldfilter.cpp @@ -237,3 +237,5 @@ void FieldFilter::setFiltred() } // end namespace QQmlJS QT_END_NAMESPACE + +#include "moc_qqmldomfieldfilter_p.cpp" diff --git a/src/qmldom/qqmldomfilewriter.cpp b/src/qmldom/qqmldomfilewriter.cpp index b24e5518ba..b7b0e21d97 100644 --- a/src/qmldom/qqmldomfilewriter.cpp +++ b/src/qmldom/qqmldomfilewriter.cpp @@ -166,3 +166,5 @@ FileWriter::Status FileWriter::write(QString tFile, function_ref<bool(QTextStrea } // namespace Dom } // namespace QQmlJS QT_END_NAMESPACE + +#include "moc_qqmldomfilewriter_p.cpp" diff --git a/src/qmldom/qqmldomitem.cpp b/src/qmldom/qqmldomitem.cpp index 079fa5678e..3a3ab7bb26 100644 --- a/src/qmldom/qqmldomitem.cpp +++ b/src/qmldom/qqmldomitem.cpp @@ -1927,14 +1927,23 @@ MutableDomItem DomItem::makeCopy(DomItem::CopyOption option) return MutableDomItem(newItem.path(pathFromOwner())); } DomItem env = environment(); - std::shared_ptr<DomEnvironment> envPtr = env.ownerAs<DomEnvironment>(); - Q_ASSERT(envPtr); - std::shared_ptr<DomEnvironment> newEnvPtr( - new DomEnvironment(envPtr, envPtr->loadPaths(), envPtr->options())); - DomBase *eBase = envPtr.get(); - if (std::holds_alternative<DomEnvironment *>(m_element) && eBase - && std::get<DomEnvironment *>(m_element) == eBase) - return MutableDomItem(DomItem(newEnvPtr)); + std::shared_ptr<DomEnvironment> newEnvPtr; + if (std::shared_ptr<DomEnvironment> envPtr = env.ownerAs<DomEnvironment>()) { + newEnvPtr = std::shared_ptr<DomEnvironment>( + new DomEnvironment(envPtr, envPtr->loadPaths(), envPtr->options())); + DomBase *eBase = envPtr.get(); + if (std::holds_alternative<DomEnvironment *>(m_element) && eBase + && std::get<DomEnvironment *>(m_element) == eBase) + return MutableDomItem(DomItem(newEnvPtr)); + } else if (std::shared_ptr<DomUniverse> univPtr = top().ownerAs<DomUniverse>()) { + newEnvPtr = std::shared_ptr<DomEnvironment>(new DomEnvironment( + QStringList(), + DomEnvironment::Option::SingleThreaded | DomEnvironment::Option::NoDependencies, + univPtr)); + } else { + Q_ASSERT(false); + return {}; + } DomItem newItem = std::visit( [this, newEnvPtr, &o](auto &&el) { auto copyPtr = el->makeCopy(o); @@ -2279,21 +2288,23 @@ DomItem::DomItem(std::shared_ptr<DomUniverse> universePtr): } void DomItem::loadFile(QString canonicalFilePath, QString logicalPath, QString code, - QDateTime codeDate, DomTop::Callback callback, LoadOptions loadOptions) + QDateTime codeDate, DomTop::Callback callback, LoadOptions loadOptions, + std::optional<DomType> fileType) { DomItem topEl = top(); if (topEl.internalKind() == DomType::DomEnvironment || topEl.internalKind() == DomType::DomUniverse) { if (auto univ = topEl.ownerAs<DomUniverse>()) univ->loadFile(*this, canonicalFilePath, logicalPath, code, codeDate, callback, - loadOptions); + loadOptions, fileType); else if (auto env = topEl.ownerAs<DomEnvironment>()) { if (env->options() & DomEnvironment::Option::NoDependencies) env->loadFile(topEl, canonicalFilePath, logicalPath, code, codeDate, callback, - DomTop::Callback(), DomTop::Callback(), loadOptions); + DomTop::Callback(), DomTop::Callback(), loadOptions, fileType); else env->loadFile(topEl, canonicalFilePath, logicalPath, code, codeDate, - DomTop::Callback(), DomTop::Callback(), callback, loadOptions); + DomTop::Callback(), DomTop::Callback(), callback, loadOptions, + fileType); } else Q_ASSERT(false && "expected either DomUniverse or DomEnvironment cast to succeed"); } else { @@ -2303,7 +2314,7 @@ void DomItem::loadFile(QString canonicalFilePath, QString logicalPath, QString c } void DomItem::loadFile(QString filePath, QString logicalPath, DomTop::Callback callback, - LoadOptions loadOptions) + LoadOptions loadOptions, std::optional<DomType> fileType) { DomItem topEl = top(); if (topEl.internalKind() == DomType::DomEnvironment @@ -2313,10 +2324,10 @@ void DomItem::loadFile(QString filePath, QString logicalPath, DomTop::Callback c else if (auto env = topEl.ownerAs<DomEnvironment>()) { if (env->options() & DomEnvironment::Option::NoDependencies) env->loadFile(topEl, filePath, logicalPath, callback, DomTop::Callback(), - DomTop::Callback(), loadOptions); + DomTop::Callback(), loadOptions, fileType); else env->loadFile(topEl, filePath, logicalPath, DomTop::Callback(), DomTop::Callback(), - callback, loadOptions); + callback, loadOptions, fileType); } else Q_ASSERT(false && "expected either DomUniverse or DomEnvironment cast to succeed"); } else { @@ -2727,26 +2738,28 @@ DomItem Reference::get(DomItem &self, ErrorHandler h, QList<Path> *visitedRefs) Path cachedPath; if (shouldCache()) { env = self.environment(); - selfPath = self.canonicalPath(); - RefCacheEntry cached = RefCacheEntry::forPath(self, selfPath); - switch (cached.cached) { - case RefCacheEntry::Cached::None: - break; - case RefCacheEntry::Cached::First: - case RefCacheEntry::Cached::All: - if (!cached.canonicalPaths.isEmpty()) - cachedPath = cached.canonicalPaths.first(); - else - return res; - break; - } - if (cachedPath) { - res = env.path(cachedPath); - if (!res) - qCWarning(refLog) << "referenceCache outdated, reference at " << selfPath - << " leads to invalid path " << cachedPath; - else - return res; + if (env) { + selfPath = self.canonicalPath(); + RefCacheEntry cached = RefCacheEntry::forPath(self, selfPath); + switch (cached.cached) { + case RefCacheEntry::Cached::None: + break; + case RefCacheEntry::Cached::First: + case RefCacheEntry::Cached::All: + if (!cached.canonicalPaths.isEmpty()) + cachedPath = cached.canonicalPaths.first(); + else + return res; + break; + } + if (cachedPath) { + res = env.path(cachedPath); + if (!res) + qCWarning(refLog) << "referenceCache outdated, reference at " << selfPath + << " leads to invalid path " << cachedPath; + else + return res; + } } } QList<Path> visitedRefsLocal; @@ -2972,12 +2985,10 @@ void OwningItem::addError(DomItem &, ErrorMessage msg) void OwningItem::addErrorLocal(ErrorMessage msg) { QMutexLocker l(mutex()); - auto it = m_errors.constFind(msg.path); - while (it != m_errors.constEnd() && it->path == msg.path) { - if (*it++ == msg) - return; - } - m_errors.insert(msg.path, msg); + quint32 &c = m_errorsCounts[msg]; + c += 1; + if (c == 1) + m_errors.insert(msg.path, msg); } void OwningItem::clearErrors(ErrorGroups groups) @@ -3369,3 +3380,5 @@ void ListPBase::writeOut(DomItem &self, OutWriter &ow, bool compact) const } // end namespace QQmlJS QT_END_NAMESPACE + +#include "moc_qqmldomitem_p.cpp" diff --git a/src/qmldom/qqmldomitem_p.h b/src/qmldom/qqmldomitem_p.h index 469001709c..9388309bf7 100644 --- a/src/qmldom/qqmldomitem_p.h +++ b/src/qmldom/qqmldomitem_p.h @@ -588,7 +588,9 @@ public: } else if constexpr (domTypeIsObjWrap(T::kindValue)) { return m_value.value<T *>(); } else { - Q_ASSERT_X(false, "SimpleObjectWrapT", "wrapping of unexpected type"); + // need dependent static assert to not unconditially trigger + static_assert(!std::is_same_v<T, T>, "wrapping of unexpected type"); + return nullptr; // necessary to avoid warnings on INTEGRITY } } @@ -1036,11 +1038,11 @@ public: DomItem(std::shared_ptr<DomUniverse>); void loadFile(QString filePath, QString logicalPath, - std::function<void(Path, DomItem &, DomItem &)> callback, - LoadOptions loadOptions); + std::function<void(Path, DomItem &, DomItem &)> callback, LoadOptions loadOptions, + std::optional<DomType> fileType = std::optional<DomType>()); void loadFile(QString canonicalFilePath, QString logicalPath, QString code, QDateTime codeDate, - std::function<void(Path, DomItem &, DomItem &)> callback, - LoadOptions loadOptions); + std::function<void(Path, DomItem &, DomItem &)> callback, LoadOptions loadOptions, + std::optional<DomType> fileType = std::optional<DomType>()); void loadModuleDependency(QString uri, Version v, std::function<void(Path, DomItem &, DomItem &)> callback = nullptr, ErrorHandler = nullptr); @@ -1342,6 +1344,7 @@ private: QDateTime m_lastDataUpdateAt; QDateTime m_frozenAt; QMultiMap<Path, ErrorMessage> m_errors; + QMap<ErrorMessage, quint32> m_errorsCounts; }; template<typename T> diff --git a/src/qmldom/qqmldomlinewriter.cpp b/src/qmldom/qqmldomlinewriter.cpp index a2371c4ccd..6c04602a55 100644 --- a/src/qmldom/qqmldomlinewriter.cpp +++ b/src/qmldom/qqmldomlinewriter.cpp @@ -480,3 +480,5 @@ void LineWriter::commitLine(QString eol, TextAddType tType, int untilChar) } // namespace Dom } // namespace QQmlJS QT_END_NAMESPACE + +#include "moc_qqmldomlinewriter_p.cpp" diff --git a/src/qmldom/qqmldommoduleindex.cpp b/src/qmldom/qqmldommoduleindex.cpp index 700537d287..47a2d9192f 100644 --- a/src/qmldom/qqmldommoduleindex.cpp +++ b/src/qmldom/qqmldommoduleindex.cpp @@ -145,7 +145,7 @@ ModuleIndex::~ModuleIndex() auto it = scopes.begin(); auto end = scopes.end(); while (it != end) { - free(*it); + delete *it; ++it; } } diff --git a/src/qmldom/qqmldompath.cpp b/src/qmldom/qqmldompath.cpp index c2ceeaf3cc..d901813f3a 100644 --- a/src/qmldom/qqmldompath.cpp +++ b/src/qmldom/qqmldompath.cpp @@ -205,24 +205,25 @@ int PathComponent::cmp(const PathComponent &p1, const PathComponent &p2) } // namespace PathEls -PathEls::PathComponent Path::component(int i) const +const PathEls::PathComponent &Path::component(int i) const { + static Component emptyComponent; if (i < 0) i += m_length; if (i >= m_length || i < 0) { Q_ASSERT(false && "index out of bounds"); - return Component(); + return emptyComponent; } i = i - m_length - m_endOffset; auto data = m_data.get(); while (data) { i += data->components.length(); if (i >= 0) - return data->components.at(i); + return qAsConst(data)->components[i]; data = data->parent.get(); } Q_ASSERT(false && "Invalid data reached while resolving a seemengly valid index in Path (inconsisten Path object)"); - return Component(); + return emptyComponent; } Path Path::operator[](int i) const @@ -247,7 +248,7 @@ PathIterator Path::end() const PathRoot Path::headRoot() const { - auto comp = component(0); + auto &comp = component(0); if (PathEls::Root const * r = comp.base()->asRoot()) return r->contextKind; return PathRoot::Other; @@ -285,7 +286,7 @@ index_type Path::headIndex(index_type defaultValue) const function<bool (DomItem)> Path::headFilter() const { - auto comp = component(0); + auto &comp = component(0); if (PathEls::Filter const * f = comp.base()->asFilter()) { return f->filterFunction; } @@ -939,7 +940,7 @@ void Path::dump(Sink sink) const { bool first = true; for (int i = 0; i < m_length; ++i) { - auto c = component(i); + auto &c = component(i); if (!c.hasSquareBrackets()) { if (!first || (c.kind() != Kind::Root && c.kind() != Kind::Current)) sink(u"."); @@ -997,3 +998,5 @@ Path Path::fromString(QString s, ErrorHandler errorHandler) } // end namespace Dom } // end namespace QQmlJS QT_END_NAMESPACE + +#include "moc_qqmldompath_p.cpp" diff --git a/src/qmldom/qqmldompath_p.h b/src/qmldom/qqmldompath_p.h index 7fe68428d7..f0fddcabea 100644 --- a/src/qmldom/qqmldompath_p.h +++ b/src/qmldom/qqmldompath_p.h @@ -124,7 +124,8 @@ public: virtual const Filter *asFilter() const { return nullptr; } }; -class Empty: public Base { +class Empty final : public Base +{ public: Empty() = default; Kind kind() const override { return Kind::Empty; } @@ -133,7 +134,8 @@ public: const Empty * asEmpty() const override { return this; } }; -class Field: public Base { +class Field final : public Base +{ public: Field() = default; Field(QStringView n): fieldName(n) {} @@ -147,7 +149,8 @@ public: QStringView fieldName; }; -class Index: public Base { +class Index final : public Base +{ public: Index() = default; Index(index_type i): indexValue(i) {} @@ -161,7 +164,8 @@ public: index_type indexValue = -1; }; -class Key: public Base { +class Key final : public Base +{ public: Key() = default; Key(QString n) : keyValue(n) { } @@ -180,7 +184,8 @@ public: QString keyValue; }; -class Root: public Base { +class Root final : public Base +{ public: Root() = default; Root(PathRoot r): contextKind(r), contextName() {} @@ -229,7 +234,8 @@ public: QStringView contextName; }; -class Current: public Base { +class Current final : public Base +{ public: Current() = default; Current(PathCurrent c): contextKind(c) {} @@ -283,7 +289,8 @@ public: QStringView contextName; }; -class Any: public Base { +class Any final : public Base +{ public: Any() = default; Kind kind() const override { return Kind::Any; } @@ -293,7 +300,8 @@ public: const Any *asAny() const override { return this; } }; -class QMLDOM_EXPORT Filter: public Base { +class QMLDOM_EXPORT Filter final : public Base +{ public: Filter() = default; Filter(std::function<bool(DomItem)> f, QStringView filterDescription = u"<native code filter>"); @@ -718,10 +726,12 @@ public: using iterator_category = std::forward_iterator_tag; static int cmp(const Path &p1, const Path &p2); - Component component(int i) const; + private: + const Component &component(int i) const; explicit Path(quint16 endOffset, quint16 length, std::shared_ptr<PathEls::PathData> data); friend class QQmlJS::Dom::PathEls::TestPaths; + friend class FieldFilter; friend size_t qHash(const Path &, size_t); Path noEndOffset() const; @@ -762,8 +772,8 @@ public: Path operator *() const { return currentEl.head(); } PathIterator operator ++() { currentEl = currentEl.dropFront(); return *this; } PathIterator operator ++(int) { PathIterator res{currentEl}; currentEl = currentEl.dropFront(); return res; } - bool operator ==(const PathIterator &o) { return currentEl == o.currentEl; } - bool operator !=(const PathIterator &o) { return currentEl != o.currentEl; } + bool operator ==(const PathIterator &o) const { return currentEl == o.currentEl; } + bool operator !=(const PathIterator &o) const { return currentEl != o.currentEl; } }; class Source { diff --git a/src/qmldom/qqmldomreformatter.cpp b/src/qmldom/qqmldomreformatter.cpp index d627af12ef..ee48a71c29 100644 --- a/src/qmldom/qqmldomreformatter.cpp +++ b/src/qmldom/qqmldomreformatter.cpp @@ -972,7 +972,11 @@ protected: // to check bool visit(TypeExpression *) override { return true; } - bool visit(SuperLiteral *) override { return true; } + bool visit(SuperLiteral *) override + { + out("super"); + return true; + } bool visit(PatternProperty *) override { return true; } bool visit(ComputedPropertyName *) override { @@ -989,7 +993,61 @@ protected: } bool visit(YieldExpression *) override { return true; } bool visit(ClassExpression *) override { return true; } - bool visit(ClassDeclaration *) override { return true; } + + // Return false because we want to omit default function callsĀ in accept0 implementation. + bool visit(ClassDeclaration *ast) override + { + preVisit(ast); + out(ast->classToken); + out(" "); + out(ast->name); + if (ast->heritage) { + out(" extends "); + accept(ast->heritage); + } + out(" {"); + int baseIndent = lw.increaseIndent(); + for (ClassElementList *it = ast->elements; it; it = it->next) { + PatternProperty *property = it->property; + lw.newline(); + preVisit(property); + if (it->isStatic) + out("static "); + if (property->type == PatternProperty::Getter) + out("get "); + else if (property->type == PatternProperty::Setter) + out("set "); + FunctionExpression *f = AST::cast<FunctionExpression *>(property->initializer); + const bool scoped = f->lbraceToken.length != 0; + out(f->functionToken); + out(f->lparenToken); + accept(f->formals); + out(f->rparenToken); + out(f->lbraceToken); + if (scoped) + ++expressionDepth; + if (f->body) { + if (f->body->next || scoped) { + lnAcceptIndented(f->body); + lw.newline(); + } else { + baseIndent = lw.increaseIndent(1); + accept(f->body); + lw.decreaseIndent(1, baseIndent); + } + } + if (scoped) + --expressionDepth; + out(f->rbraceToken); + lw.newline(); + postVisit(property); + } + lw.decreaseIndent(1, baseIndent); + out("}"); + postVisit(ast); + return false; + } + bool visit(ClassElementList *) override { return true; } bool visit(Program *) override { return true; } bool visit(NameSpaceImport *) override { return true; } diff --git a/src/qmldom/qqmldomtop.cpp b/src/qmldom/qqmldomtop.cpp index c41402d761..7d2500488b 100644 --- a/src/qmldom/qqmldomtop.cpp +++ b/src/qmldom/qqmldomtop.cpp @@ -48,7 +48,6 @@ #include <QtQml/private/qqmljsastvisitor_p.h> #include <QtQml/private/qqmljsast_p.h> -#include <QtCore/QAtomicInt> #include <QtCore/QBasicMutex> #include <QtCore/QCborArray> #include <QtCore/QDebug> @@ -157,11 +156,14 @@ DomUniverse::DomUniverse(QString universeName, Options options): std::shared_ptr<DomUniverse> DomUniverse::guaranteeUniverse(std::shared_ptr<DomUniverse> univ) { - static QAtomicInt counter(0); + const auto next = [] { + static std::atomic<int> counter(0); + return counter.fetch_add(1, std::memory_order_relaxed) + 1; + }; if (univ) return univ; return std::shared_ptr<DomUniverse>( - new DomUniverse(QLatin1String("universe") + QString::number(++counter))); + new DomUniverse(QLatin1String("universe") + QString::number(next()))); } DomItem DomUniverse::create(QString universeName, Options options) @@ -248,56 +250,58 @@ std::shared_ptr<OwningItem> DomUniverse::doCopy(DomItem &) const } void DomUniverse::loadFile(DomItem &self, QString filePath, QString logicalPath, Callback callback, - LoadOptions loadOptions) + LoadOptions loadOptions, std::optional<DomType> fileType) { - loadFile(self, filePath, logicalPath, QString(), QDateTime::fromMSecsSinceEpoch(0), callback, loadOptions); + loadFile(self, filePath, logicalPath, QString(), QDateTime::fromMSecsSinceEpoch(0), callback, + loadOptions, fileType); } -void DomUniverse::loadFile(DomItem &self, QString canonicalFilePath, QString logicalPath, - QString code, QDateTime codeDate, Callback callback, - LoadOptions loadOptions) -{ - if (canonicalFilePath.endsWith(u".qml", Qt::CaseInsensitive) || - canonicalFilePath.endsWith(u".qmlannotation", Qt::CaseInsensitive) || - canonicalFilePath.endsWith(u".ui", Qt::CaseInsensitive)) { - m_queue.enqueue(ParsingTask{ - QDateTime::currentDateTime(), - loadOptions, - DomType::QmlFile, - canonicalFilePath, - logicalPath, - code, - codeDate, - self.ownerAs<DomUniverse>(), - callback}); +static DomType fileTypeForPath(DomItem &self, QString canonicalFilePath) +{ + if (canonicalFilePath.endsWith(u".qml", Qt::CaseInsensitive) + || canonicalFilePath.endsWith(u".qmlannotation", Qt::CaseInsensitive)) { + return DomType::QmlFile; } else if (canonicalFilePath.endsWith(u".qmltypes")) { - m_queue.enqueue(ParsingTask{ - QDateTime::currentDateTime(), - loadOptions, - DomType::QmltypesFile, - canonicalFilePath, - logicalPath, - code, - codeDate, - self.ownerAs<DomUniverse>(), - callback}); - } else if (QStringView(u"qmldir").compare(QFileInfo(canonicalFilePath).fileName(), Qt::CaseInsensitive) == 0) { - m_queue.enqueue(ParsingTask{ - QDateTime::currentDateTime(), - loadOptions, - DomType::QmldirFile, - canonicalFilePath, - logicalPath, - code, - codeDate, - self.ownerAs<DomUniverse>(), - callback}); + return DomType::QmltypesFile; + } else if (QStringView(u"qmldir").compare(QFileInfo(canonicalFilePath).fileName(), + Qt::CaseInsensitive) + == 0) { + return DomType::QmltypesFile; } else if (QFileInfo(canonicalFilePath).isDir()) { - m_queue.enqueue(ParsingTask { QDateTime::currentDateTime(), loadOptions, - DomType::QmlDirectory, canonicalFilePath, logicalPath, code, - codeDate, self.ownerAs<DomUniverse>(), callback }); + return DomType::QmlDirectory; } else { - self.addError(myErrors().error(tr("Ignoring request to load file of unknown type %1, calling callback immediately").arg(canonicalFilePath)).handle()); + self.addError(DomUniverse::myErrors() + .error(QCoreApplication::translate("Dom::filteTypeForPath", + "Could not detect type of file %1") + .arg(canonicalFilePath)) + .handle()); + } + return DomType::Empty; +} + +void DomUniverse::loadFile(DomItem &self, QString canonicalFilePath, QString logicalPath, + QString code, QDateTime codeDate, Callback callback, + LoadOptions loadOptions, std::optional<DomType> fileType) +{ + DomType fType = (bool(fileType) ? (*fileType) : fileTypeForPath(self, canonicalFilePath)); + switch (fType) { + case DomType::QmlFile: + case DomType::QmltypesFile: + case DomType::QmldirFile: + case DomType::QmlDirectory: { + // Protect the queue from concurrent access. + QMutexLocker l(mutex()); + m_queue.enqueue(ParsingTask { QDateTime::currentDateTime(), loadOptions, fType, + canonicalFilePath, logicalPath, code, codeDate, + self.ownerAs<DomUniverse>(), callback }); + break; + } + default: + self.addError(myErrors() + .error(tr("Ignoring request to load file %1 of unexpected type %2, " + "calling callback immediately") + .arg(canonicalFilePath, domTypeToString(fType))) + .handle()); Q_ASSERT(false && "loading non supported file type"); callback(Path(), DomItem::empty, DomItem::empty); return; @@ -350,7 +354,14 @@ updateEntry(DomItem &univ, std::shared_ptr<T> newItem, void DomUniverse::execQueue() { - ParsingTask t = m_queue.dequeue(); + ParsingTask t; + { + // Protect the queue from concurrent access. + QMutexLocker l(mutex()); + if (m_queue.isEmpty()) + return; + t = m_queue.dequeue(); + } shared_ptr<DomUniverse> topPtr = t.requestingUniverse.lock(); if (!topPtr) { myErrors().error(tr("Ignoring callback for loading of %1: universe is not valid anymore").arg(t.canonicalPath)).handle(); @@ -626,7 +637,8 @@ void LoadInfo::advanceLoad(DomItem &self) [this, self, dep](Path, DomItem &, DomItem &) mutable { finishedLoadingDep(self, dep); }, - nullptr, nullptr, LoadOption::DefaultLoad, self.errorHandler()); + nullptr, nullptr, LoadOption::DefaultLoad, dep.fileType, + self.errorHandler()); else Q_ASSERT(false && "missing environment"); } else { @@ -746,12 +758,13 @@ void LoadInfo::doAddDependencies(DomItem &self) DomItem import = currentImports.index(i); if (const Import *importPtr = import.as<Import>()) { if (!importPtr->filePath().isEmpty()) { - addDependency( - self, - Dependency { QString(), importPtr->version, importPtr->filePath() }); + addDependency(self, + Dependency { QString(), importPtr->version, importPtr->filePath(), + DomType::Empty }); } else { addDependency(self, - Dependency { importPtr->uri, importPtr->version, QString() }); + Dependency { importPtr->uri, importPtr->version, QString(), + DomType::ModuleIndex }); } } } @@ -763,7 +776,8 @@ void LoadInfo::doAddDependencies(DomItem &self) Path canonicalPath = ref->referredObjectPath[2]; if (canonicalPath && !canonicalPath.headName().isEmpty()) addDependency(self, - Dependency { QString(), Version(), canonicalPath.headName() }); + Dependency { QString(), Version(), canonicalPath.headName(), + DomType::QmltypesFile }); } } DomItem currentQmlFiles = el.field(Fields::currentItem).field(Fields::qmlFiles); @@ -772,9 +786,9 @@ void LoadInfo::doAddDependencies(DomItem &self) if (const Reference *ref = el.as<Reference>()) { Path canonicalPath = ref->referredObjectPath[2]; if (canonicalPath && !canonicalPath.headName().isEmpty()) - addDependency( - self, - Dependency { QString(), Version(), canonicalPath.headName() }); + addDependency(self, + Dependency { QString(), Version(), canonicalPath.headName(), + DomType::QmlFile }); } return true; }); @@ -783,7 +797,9 @@ void LoadInfo::doAddDependencies(DomItem &self) for (Path qmldirPath : elPtr->qmldirsToLoad(el)) { Path canonicalPath = qmldirPath[2]; if (canonicalPath && !canonicalPath.headName().isEmpty()) - addDependency(self, Dependency { QString(), Version(), canonicalPath.headName() }); + addDependency(self, + Dependency { QString(), Version(), canonicalPath.headName(), + DomType::QmldirFile }); } } else if (!el) { self.addError(DomEnvironment::myErrors().error( @@ -1147,10 +1163,11 @@ std::shared_ptr<DomEnvironment> DomEnvironment::makeCopy(DomItem &self) const void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPath, DomTop::Callback loadCallback, DomTop::Callback directDepsCallback, - DomTop::Callback endCallback, LoadOptions loadOptions, ErrorHandler h) + DomTop::Callback endCallback, LoadOptions loadOptions, + std::optional<DomType> fileType, ErrorHandler h) { loadFile(self, filePath, logicalPath, QString(), QDateTime::fromMSecsSinceEpoch(0), - loadCallback, directDepsCallback, endCallback, loadOptions, h); + loadCallback, directDepsCallback, endCallback, loadOptions, fileType, h); } std::shared_ptr<OwningItem> DomEnvironment::doCopy(DomItem &) const @@ -1167,11 +1184,10 @@ std::shared_ptr<OwningItem> DomEnvironment::doCopy(DomItem &) const void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPath, QString code, QDateTime codeDate, Callback loadCallback, Callback directDepsCallback, Callback endCallback, - LoadOptions loadOptions, ErrorHandler h) + LoadOptions loadOptions, std::optional<DomType> fileType, + ErrorHandler h) { QFileInfo fileInfo(filePath); - bool isDir = fileInfo.isDir(); - QString ext = fileInfo.suffix(); QString canonicalFilePath = fileInfo.canonicalFilePath(); if (canonicalFilePath.isEmpty()) { if (code.isNull()) { @@ -1190,7 +1206,9 @@ void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPa } } shared_ptr<ExternalItemInfoBase> oldValue, newValue; - if (isDir) { + DomType fType = (bool(fileType) ? (*fileType) : fileTypeForPath(self, canonicalFilePath)); + switch (fType) { + case DomType::QmlDirectory: { { QMutexLocker l(mutex()); auto it = m_qmlDirectoryWithPath.find(canonicalFilePath); @@ -1217,10 +1235,11 @@ void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPa self.universe().loadFile( canonicalFilePath, logicalPath, code, codeDate, callbackForQmlDirectory(self, loadCallback, directDepsCallback, endCallback), - loadOptions); + loadOptions, fType); return; } - } else if (ext == u"qml" || ext == u"ui" || ext == u"qmlannotation") { + } break; + case DomType::QmlFile: { { QMutexLocker l(mutex()); auto it = m_qmlFileWithPath.find(canonicalFilePath); @@ -1246,10 +1265,11 @@ void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPa self.universe().loadFile( canonicalFilePath, logicalPath, code, codeDate, callbackForQmlFile(self, loadCallback, directDepsCallback, endCallback), - loadOptions); + loadOptions, fType); return; } - } else if (ext == u"qmltypes") { + } break; + case DomType::QmltypesFile: { { QMutexLocker l(mutex()); auto it = m_qmltypesFileWithPath.find(canonicalFilePath); @@ -1276,10 +1296,11 @@ void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPa self.universe().loadFile( canonicalFilePath, logicalPath, code, codeDate, callbackForQmltypesFile(self, loadCallback, directDepsCallback, endCallback), - loadOptions); + loadOptions, fType); return; } - } else if (fileInfo.fileName() == u"qmldir") { + } break; + case DomType::QmldirFile: { { QMutexLocker l(mutex()); auto it = m_qmldirFileWithPath.find(canonicalFilePath); @@ -1305,10 +1326,11 @@ void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPa self.universe().loadFile( canonicalFilePath, logicalPath, code, codeDate, callbackForQmldirFile(self, loadCallback, directDepsCallback, endCallback), - loadOptions); + loadOptions, fType); return; } - } else { + } break; + default: { myErrors().error(tr("Unexpected file to load: '%1'").arg(filePath)).handle(h); if (loadCallback) loadCallback(self.canonicalPath(), DomItem::empty, DomItem::empty); @@ -1317,6 +1339,7 @@ void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPa if (endCallback) endCallback(self.canonicalPath(), DomItem::empty, DomItem::empty); return; + } break; } Path p = self.copy(newValue).canonicalPath(); std::shared_ptr<LoadInfo> lInfo = loadInfo(p); @@ -2310,3 +2333,5 @@ bool RefCacheEntry::addForPath(DomItem &el, Path canonicalPath, const RefCacheEn } // end namespace QQmlJS QT_END_NAMESPACE + +#include "moc_qqmldomtop_p.cpp" diff --git a/src/qmldom/qqmldomtop_p.h b/src/qmldom/qqmldomtop_p.h index 4c905991af..eeb0038d09 100644 --- a/src/qmldom/qqmldomtop_p.h +++ b/src/qmldom/qqmldomtop_p.h @@ -61,6 +61,7 @@ #include <QtCore/QCborMap> #include <memory> +#include <optional> QT_BEGIN_NAMESPACE @@ -253,9 +254,11 @@ public: } void loadFile(DomItem &self, QString filePath, QString logicalPath, Callback callback, - LoadOptions loadOptions); + LoadOptions loadOptions, + std::optional<DomType> fileType = std::optional<DomType>()); void loadFile(DomItem &self, QString canonicalFilePath, QString logicalPath, QString code, - QDateTime codeDate, Callback callback, LoadOptions loadOptions); + QDateTime codeDate, Callback callback, LoadOptions loadOptions, + std::optional<DomType> fileType = std::optional<DomType>()); void execQueue(); std::shared_ptr<ExternalItemPair<GlobalScope>> globalScopeWithName(QString name) const @@ -517,6 +520,7 @@ public: QString uri; // either dotted uri or file:, http: https: uri Version version; QString filePath; // for file deps + DomType fileType; }; class QMLDOM_EXPORT LoadInfo final : public OwningItem @@ -683,10 +687,13 @@ public: void loadFile(DomItem &self, QString filePath, QString logicalPath, Callback loadCallback, Callback directDepsCallback, Callback endCallback, LoadOptions loadOptions, + std::optional<DomType> fileType = std::optional<DomType>(), ErrorHandler h = nullptr); void loadFile(DomItem &self, QString canonicalFilePath, QString logicalPath, QString code, QDateTime codeDate, Callback loadCallback, Callback directDepsCallback, - Callback endCallback, LoadOptions loadOptions, ErrorHandler h = nullptr); + Callback endCallback, LoadOptions loadOptions, + std::optional<DomType> fileType = std::optional<DomType>(), + ErrorHandler h = nullptr); void loadModuleDependency(DomItem &self, QString uri, Version v, Callback loadCallback = nullptr, Callback endCallback = nullptr, ErrorHandler = nullptr); |