File indexing completed on 2024-05-12 04:39:26

0001 /*
0002     SPDX-FileCopyrightText: 2014 Aleix Pol <aleixpol@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "cmakeparsejob.h"
0008 #include "declarationbuilder.h"
0009 #include "usebuilder.h"
0010 #include <debug.h>
0011 #include <cmakelistsparser.h>
0012 #include <cmakemanager.h>
0013 #include <language/backgroundparser/urlparselock.h>
0014 #include <language/duchain/duchain.h>
0015 #include <language/duchain/duchainlock.h>
0016 #include <language/duchain/duchainutils.h>
0017 #include <interfaces/icore.h>
0018 #include <language/duchain/problem.h>
0019 
0020 #include <KIO/Global>
0021 
0022 #include <QReadWriteLock>
0023 
0024 using namespace KDevelop;
0025 
0026 CMakeParseJob::CMakeParseJob(const KDevelop::IndexedString& url, KDevelop::ILanguageSupport* languageSupport)
0027     : ParseJob(url, languageSupport)
0028 {
0029 }
0030 
0031 IndexedString parentCMakeFile(const IndexedString& doc)
0032 {
0033     return IndexedString(QUrl(KIO::upUrl(doc.toUrl().adjusted(QUrl::RemoveFilename)).toString()+QLatin1String("CMakeLists.txt")));
0034 }
0035 
0036 void CMakeParseJob::run(ThreadWeaver::JobPointer /*self*/, ThreadWeaver::Thread* /*thread*/)
0037 {
0038     const IndexedString languageName(CMakeManager::languageName());
0039 
0040     UrlParseLock urlLock(document());
0041     if (abortRequested() || !isUpdateRequired(languageName)) {
0042         return;
0043     }
0044 
0045     ProblemPointer p = readContents();
0046     if (p) {
0047         //TODO: associate problem with topducontext
0048         return;
0049     }
0050 
0051     ReferencedTopDUContext parentCtx;
0052     if (document().str().endsWith(QLatin1String("CMakeLists.txt"))) {
0053         IndexedString parentFile = parentCMakeFile(document());
0054         if (QFile::exists(parentFile.toUrl().toLocalFile())) {
0055 
0056 //         TODO: figure out includes import
0057             {
0058                 DUChainReadLocker lock;
0059                 parentCtx = DUChain::self()->chainForDocument(parentFile);
0060             }
0061 
0062             if (!parentCtx) {
0063                 qCDebug(CMAKE) << "waiting for..." << parentFile << document();
0064                 //FIXME: Currently dead-locks
0065                 //parentCtx = DUChain::self()->waitForUpdate(parentFile, TopDUContext::AllDeclarationsAndContexts);
0066             }
0067             //Q_ASSERT(parentCtx);
0068         }
0069     }
0070 
0071     ReferencedTopDUContext context;
0072     {
0073         DUChainReadLocker lock;
0074         context = DUChainUtils::standardContextForUrl(document().toUrl());
0075     }
0076     if (context) {
0077         translateDUChainToRevision(context);
0078 
0079         DUChainWriteLocker lock;
0080         context->setRange(RangeInRevision(0, 0, INT_MAX, INT_MAX));
0081         context->addImportedParentContext(parentCtx);
0082     }
0083 
0084     CMakeFileContent package = CMakeListsParser::readCMakeFile(document().toUrl().toLocalFile());
0085     if (!package.isEmpty()) {
0086         if (abortRequested()) {
0087             abortJob();
0088             return;
0089         }
0090 
0091         QReadLocker parseLock(languageSupport()->parseLock());
0092         CMakeContentIterator it(package);
0093         DeclarationBuilder builder;
0094         context = builder.build(document(), &it, context);
0095 
0096         if (abortRequested()) {
0097             abortJob();
0098             return;
0099         }
0100 
0101 //         session.reparseImporters(context);
0102 
0103         if ( context && (minimumFeatures() & TopDUContext::AllDeclarationsContextsAndUses) ) {
0104             UseBuilder useBuilder(context);
0105             CMakeContentIterator it(package);
0106             useBuilder.startVisiting(&it);
0107         }
0108     }
0109 
0110     if (abortRequested()) {
0111         abortJob();
0112         return;
0113     }
0114 
0115     if (!context) {
0116         DUChainWriteLocker lock;
0117         auto* file = new ParsingEnvironmentFile(document());
0118         file->setLanguage(languageName);
0119         context = new TopDUContext(document(), RangeInRevision(0, 0, INT_MAX, INT_MAX), file);
0120         DUChain::self()->addDocumentChain(context);
0121     }
0122 
0123     setDuChain(context);
0124     {
0125         DUChainWriteLocker lock;
0126 //         context->setProblems(session.problems());
0127 
0128         context->setFeatures(minimumFeatures());
0129         ParsingEnvironmentFilePointer file = context->parsingEnvironmentFile();
0130         Q_ASSERT(file);
0131         file->setModificationRevision(contents().modification);
0132         DUChain::self()->updateContextEnvironment( context->topContext(), file.data() );
0133     }
0134     highlightDUChain();
0135 
0136     DUChain::self()->emitUpdateReady(document(), duChain());
0137 }
0138 
0139 #include "moc_cmakeparsejob.cpp"