diff --git a/rustparsejob.cpp b/rustparsejob.cpp index 1b55cc2..dbc78e9 100644 --- a/rustparsejob.cpp +++ b/rustparsejob.cpp @@ -1,144 +1,172 @@ #include "rustparsejob.h" #include #include +#include #include +#include #include #include #include +#include #include #include "duchain/parsesession.h" #include "duchain/astredux.h" #include "duchain/declarationbuilder.h" #include "duchain/usebuilder.h" #include "rustlanguagesupport.h" #include "rustdebug.h" using namespace KDevelop; namespace Rust { ParseJob::ParseJob(const IndexedString &url, ILanguageSupport *languageSupport) : KDevelop::ParseJob(url, languageSupport) { } LanguageSupport *ParseJob::rust() const { return static_cast(languageSupport()); } ParseSessionData::Ptr ParseJob::findParseSessionData(const IndexedString &url) { DUChainReadLocker lock; auto context = KDevelop::DUChainUtils::standardContextForUrl(url.toUrl()); if (context) { return ParseSessionData::Ptr(dynamic_cast(context->ast().data())); } return {}; } void ParseJob::run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread *thread) { if (abortRequested() || ICore::self()->shuttingDown()) { return abortJob(); } qCDebug(KDEV_RUST) << "Parse job starting for: " << document().toUrl(); QReadLocker parseLock(languageSupport()->parseLock()); { UrlParseLock urlLock(document()); readContents(); } if (abortRequested()) { return; } + if (!(minimumFeatures() & TopDUContext::ForceUpdate || minimumFeatures() & Rescheduled)) { + DUChainReadLocker lock; + static const IndexedString langString(rust()->name()); + for (const ParsingEnvironmentFilePointer &file : DUChain::self()->allEnvironmentFiles(document())) { + if (file->language() != langString) { + continue; + } + + if (!file->needsUpdate() && file->featuresSatisfied(minimumFeatures()) && file->topContext()) { + qCDebug(KDEV_RUST) << "Already up to date, skipping:" << document().str(); + setDuChain(file->topContext()); + if (ICore::self()->languageController()->backgroundParser()->trackerForUrl(document())) { + lock.unlock(); + highlightDUChain(); + } + return; + } + break; + } + } + + if (abortRequested()) { + return; + } + ParseSession session(findParseSessionData(document())); if (!session.data()) { session.setData(ParseSessionData::Ptr(new ParseSessionData(document(), contents().contents))); } if (abortRequested()) { return; } ReferencedTopDUContext toUpdate = nullptr; { DUChainReadLocker lock; toUpdate = DUChainUtils::standardContextForUrl(document().toUrl()); } if (toUpdate) { translateDUChainToRevision(toUpdate); toUpdate->setRange(RangeInRevision(0, 0, INT_MAX, INT_MAX)); toUpdate->clearProblems(); } session.parse(); RustOwnedNode crateNode = RustOwnedNode(node_from_crate(session.crate())); ReferencedTopDUContext context; if (crateNode.data() != nullptr) { RustNode node(crateNode); qCDebug(KDEV_RUST) << "Parsing succeeded for: " << document().toUrl(); DeclarationBuilder builder; builder.setParseSession(&session); context = builder.build(document(), &node, toUpdate); setDuChain(context); UseBuilder uses(document()); uses.setParseSession(&session); uses.buildUses(&node); if (abortRequested()) { return; } highlightDUChain(); } else { qCDebug(KDEV_RUST) << "Parsing failed for: " << document().toUrl(); DUChainWriteLocker lock; context = toUpdate.data(); if (context) { ParsingEnvironmentFilePointer parsingEnvironmentFile = context->parsingEnvironmentFile(); parsingEnvironmentFile->setModificationRevision(contents().modification); context->clearProblems(); } else { ParsingEnvironmentFile *file = new ParsingEnvironmentFile(document()); file->setLanguage(IndexedString("Rust")); context = new TopDUContext(document(), RangeInRevision(0, 0, INT_MAX, INT_MAX), file); DUChain::self()->addDocumentChain(context); } setDuChain(context); } // TODO: add problems exposed by libsyntax if (minimumFeatures() & TopDUContext::AST) { DUChainWriteLocker lock; context->setAst(IAstContainer::Ptr(session.data())); } DUChain::self()->emitUpdateReady(document(), duChain()); qCDebug(KDEV_RUST) << "Parse job finished for: " << document().toUrl(); } } diff --git a/rustparsejob.h b/rustparsejob.h index bd8f3f3..2af01d3 100644 --- a/rustparsejob.h +++ b/rustparsejob.h @@ -1,34 +1,37 @@ #ifndef RUSTPARSEJOB_H #define RUSTPARSEJOB_H #include #include #include #include #include #include "duchain/parsesession.h" namespace Rust { class LanguageSupport; class ParseJob : public KDevelop::ParseJob { Q_OBJECT - public: + enum { + Rescheduled = (KDevelop::TopDUContext::LastFeature << 1), + }; + ParseJob(const KDevelop::IndexedString &url, KDevelop::ILanguageSupport *languageSupport); protected: void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread *thread) override; private: LanguageSupport *rust() const; ParseSessionData::Ptr findParseSessionData(const KDevelop::IndexedString &url); }; } #endif // RUSTPARSEJOB_H