diff --git a/phpparsejob.cpp b/phpparsejob.cpp index 5b39308..cf740c4 100644 --- a/phpparsejob.cpp +++ b/phpparsejob.cpp @@ -1,250 +1,250 @@ /***************************************************************************** * Copyright (c) 2007 Piyush verma * * Copyright (c) 2008 Niko Sams * * Copyright (c) 2010 Milian Wolff * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * *****************************************************************************/ #include "phpparsejob.h" #include #include #include #include #include #include #include #include #include #include #include #include "editorintegrator.h" #include "parsesession.h" #include "phplanguagesupport.h" #include "phpdebugvisitor.h" #include "duchain/builders/declarationbuilder.h" #include "duchain/builders/usebuilder.h" #include "duchain/helper.h" #include "phpducontext.h" #include "phpdebug.h" #include #include #include #include using namespace KDevelop; namespace Php { ParseJob::ParseJob(const IndexedString& url, ILanguageSupport* languageSupport) : KDevelop::ParseJob(url, languageSupport) , m_parentJob(nullptr) { } ParseJob::~ParseJob() { } LanguageSupport* ParseJob::php() const { return dynamic_cast(languageSupport()); } void ParseJob::run(ThreadWeaver::JobPointer /*self*/, ThreadWeaver::Thread * /*thread*/) { if (document() != internalFunctionFile()) { // make sure we loaded the internal file already const auto &phpSupport = languageSupport(); static std::once_flag once; std::call_once(once, [phpSupport] { qCDebug(PHP) << "Initializing internal function file" << internalFunctionFile(); ParseJob internalJob(internalFunctionFile(), phpSupport); internalJob.setMinimumFeatures(TopDUContext::AllDeclarationsAndContexts); internalJob.run({}, nullptr); Q_ASSERT(internalJob.success()); }); } UrlParseLock urlLock(document()); - if (!(minimumFeatures() & Resheduled) && !isUpdateRequired(phpLanguageString())) { + if (!(minimumFeatures() & Rescheduled) && !isUpdateRequired(phpLanguageString())) { return; } qCDebug(PHP) << "parsing" << document().str(); KDevelop::ProblemPointer p = readContents(); if (p) { //TODO: associate problem with topducontext return abortJob();; } ParseSession session; //TODO: support different charsets session.setContents(QString::fromUtf8(contents().contents)); session.setCurrentDocument(document()); // 2) parse StartAst* ast = nullptr; bool matched = session.parse(&ast); if (abortRequested() || ICore::self()->shuttingDown()) { return abortJob(); } KDevelop::ReferencedTopDUContext toUpdate; { KDevelop::DUChainReadLocker duchainlock(KDevelop::DUChain::lock()); toUpdate = KDevelop::DUChainUtils::standardContextForUrl(document().toUrl()); } KDevelop::TopDUContext::Features newFeatures = minimumFeatures(); if (toUpdate) newFeatures = (KDevelop::TopDUContext::Features)(newFeatures | toUpdate->features()); //Remove update-flags like 'Recursive' or 'ForceUpdate' newFeatures = static_cast(newFeatures & KDevelop::TopDUContext::AllDeclarationsContextsUsesAndAST); if (matched) { if (abortRequested()) { return abortJob(); } EditorIntegrator editor(&session); QReadLocker parseLock(php()->parseLock()); DeclarationBuilder builder(&editor); KDevelop::ReferencedTopDUContext chain = builder.build(document(), ast, toUpdate); if (abortRequested()) { return abortJob(); } setDuChain(chain); bool hadUnresolvedIdentifiers = builder.hadUnresolvedIdentifiers(); if ( newFeatures & TopDUContext::AllDeclarationsContextsAndUses && document() != internalFunctionFile() ) { UseBuilder useBuilder(&editor); useBuilder.buildUses(ast); if (useBuilder.hadUnresolvedIdentifiers()) hadUnresolvedIdentifiers = true; } if (hadUnresolvedIdentifiers) { - if (!(minimumFeatures() & Resheduled)) { + if (!(minimumFeatures() & Rescheduled)) { // Need to create new parse job with lower priority qCDebug(PHP) << "Reschedule file " << document().str() << "for parsing"; KDevelop::TopDUContext::Features feat = static_cast( - minimumFeatures() | KDevelop::TopDUContext::VisibleDeclarationsAndContexts | Resheduled + minimumFeatures() | KDevelop::TopDUContext::VisibleDeclarationsAndContexts | Rescheduled ); int priority = qMin(parsePriority()+100, (int)KDevelop::BackgroundParser::WorstPriority); KDevelop::ICore::self()->languageController()->backgroundParser() ->addDocument(document(), feat, priority); } else { // We haven't resolved all identifiers, but by now, we don't expect to qCDebug(PHP) << "Builder found unresolved identifiers when they should have been resolved! (if there was no coding error)"; } } if (abortRequested()) { return abortJob(); } if (abortRequested()) { return abortJob(); } { DUChainWriteLocker lock(DUChain::lock()); foreach(const ProblemPointer &p, session.problems()) { chain->addProblem(p); } chain->setFeatures(newFeatures); ParsingEnvironmentFilePointer file = chain->parsingEnvironmentFile(); file->setModificationRevision(contents().modification); DUChain::self()->updateContextEnvironment( chain->topContext(), file.data() ); } highlightDUChain(); } else { ReferencedTopDUContext top; DUChainWriteLocker lock; { top = DUChain::self()->chainForDocument(document()); } if (top) { ///NOTE: if we clear the imported parent contexts, autocompletion of built-in PHP stuff won't work! //top->clearImportedParentContexts(); top->parsingEnvironmentFile()->clearModificationRevisions(); top->clearProblems(); } else { ParsingEnvironmentFile *file = new ParsingEnvironmentFile(document()); file->setLanguage(phpLanguageString()); top = new TopDUContext(document(), RangeInRevision(0, 0, INT_MAX, INT_MAX), file); DUChain::self()->addDocumentChain(top); } foreach(const ProblemPointer &p, session.problems()) { top->addProblem(p); } setDuChain(top); qCDebug(PHP) << "===Failed===" << document().str(); } DUChain::self()->emitUpdateReady(document(), duChain()); } void ParseJob::setParentJob(ParseJob *job) { m_parentJob = job; } bool ParseJob::hasParentDocument(const IndexedString &doc) { if (document() == doc) return true; if (!m_parentJob) return false; if (m_parentJob->document() == doc) return true; return m_parentJob->hasParentDocument(doc); } ProblemPointer ParseJob::createProblem(const QString &description, AstNode* node, EditorIntegrator * editor, IProblem::Source source, IProblem::Severity severity) { ProblemPointer p(new Problem()); p->setSource(source); p->setSeverity(severity); p->setDescription(description); p->setFinalLocation(DocumentRange(document(), editor->findRange(node).castToSimpleRange())); qCDebug(PHP) << p->description(); return p; } } // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/phpparsejob.h b/phpparsejob.h index 009c20a..bc48bd7 100644 --- a/phpparsejob.h +++ b/phpparsejob.h @@ -1,75 +1,75 @@ /***************************************************************************** * Copyright (c) 2007 Piyush verma * * Copyright (c) 2009 Niko Sams * * Copyright (c) 2010 Milian Wolff * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * *****************************************************************************/ #ifndef PHP_PARSEJOB_H #define PHP_PARSEJOB_H #include #include #include #include #include namespace Php { struct AstNode; class LanguageSupport; class EditorIntegrator; class ParseJob : public KDevelop::ParseJob { Q_OBJECT public: enum { - Resheduled = KDevelop::TopDUContext::LastFeature + Rescheduled = KDevelop::TopDUContext::LastFeature }; explicit ParseJob(const KDevelop::IndexedString& url, KDevelop::ILanguageSupport* LanguageSupport); ~ParseJob() override; void setParentJob(ParseJob *job); protected: LanguageSupport* php() const; void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread *thread) override; private: ParseJob *m_parentJob; ///< parent job if this one is an include /** * Checks if a parent job parses already \p document. Used to prevent * endless recursions in include statements */ bool hasParentDocument(const KDevelop::IndexedString &document); /// create a problem pointer for the current document KDevelop::ProblemPointer createProblem(const QString &description, AstNode* node, EditorIntegrator * editor, KDevelop::IProblem::Source source, KDevelop::IProblem::Severity severity = KDevelop::IProblem::Error); }; } #endif // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on; auto-insert-doxygen on