File indexing completed on 2024-05-05 16:42:26
0001 /* 0002 SPDX-FileCopyrightText: 2013 Sven Brauch <svenbrauch@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "correctionhelper.h" 0008 #include "helpers.h" 0009 #include "declarationbuilder.h" 0010 0011 #include <language/duchain/duchain.h> 0012 #include <language/duchain/duchainlock.h> 0013 #include <language/duchain/declaration.h> 0014 0015 #include <QDebug> 0016 #include "duchaindebug.h" 0017 0018 0019 #include <QFile> 0020 0021 using namespace KDevelop; 0022 0023 namespace Python { 0024 0025 CorrectionHelper::CorrectionHelper(const IndexedString& _url, DeclarationBuilder* builder) 0026 { 0027 m_contextStack.push(nullptr); 0028 auto absolutePath = Helper::getCorrectionFile(_url.toUrl()); 0029 0030 if ( !absolutePath.isValid() || absolutePath.isEmpty() || ! QFile::exists(absolutePath.path()) ) { 0031 return; 0032 } 0033 qCDebug(KDEV_PYTHON_DUCHAIN) << "Found correction file for " << _url.str() << ": " << absolutePath.path(); 0034 0035 const IndexedString indexedPath(absolutePath); 0036 DUChainReadLocker lock; 0037 m_hintTopContext = DUChain::self()->chainForDocument(indexedPath); 0038 qCDebug(KDEV_PYTHON_DUCHAIN) << "got top context for" << absolutePath << m_hintTopContext; 0039 m_contextStack.top() = m_hintTopContext.data(); 0040 if ( ! m_hintTopContext ) { 0041 // The file exists, but was not parsed yet. Schedule it, and re-schedule the current one too. 0042 Helper::scheduleDependency(indexedPath, builder->jobPriority()); 0043 builder->addUnresolvedImport(indexedPath); 0044 } 0045 } 0046 0047 CorrectionHelper::~CorrectionHelper() 0048 { 0049 Q_ASSERT(m_contextStack.size() == 1); 0050 Q_ASSERT(m_contextStack.top() == m_hintTopContext.data()); 0051 } 0052 0053 void CorrectionHelper::enter(const KDevelop::Identifier& identifier) 0054 { 0055 DUContext* current = m_contextStack.top(); 0056 if ( ! current ) { 0057 // no hints for the parent object, so no hints for its children either 0058 m_contextStack.push(nullptr); 0059 return; 0060 } 0061 0062 DUChainReadLocker lock; 0063 const QList<Declaration*> decls = current->findDeclarations(identifier); 0064 if ( decls.isEmpty() ) { 0065 // no hints for the current object 0066 m_contextStack.push(nullptr); 0067 return; 0068 } 0069 0070 qCDebug(KDEV_PYTHON_DUCHAIN) << "Looking in " << identifier.toString(); 0071 // there's a hint declaration for this object, put it on the stack 0072 DUContext* internal = decls.first()->internalContext(); 0073 m_contextStack.push(internal); 0074 return; 0075 } 0076 0077 AbstractType::Ptr CorrectionHelper::hintForLocal(const QString &local) const 0078 { 0079 return hintFor(KDevelop::Identifier(QLatin1String("l_") + local)); 0080 } 0081 0082 AbstractType::Ptr CorrectionHelper::returnTypeHint() const 0083 { 0084 return hintFor(KDevelop::Identifier(QLatin1String("returns"))); 0085 } 0086 0087 AbstractType::Ptr CorrectionHelper::hintFor(const KDevelop::Identifier &identifier) const 0088 { 0089 DUContext* current = m_contextStack.top(); 0090 AbstractType::Ptr hint; 0091 if ( ! current ) { 0092 return hint; 0093 } 0094 const QList<Declaration*> decls = current->findDeclarations(identifier); 0095 if ( decls.isEmpty() ) { 0096 return hint; 0097 } 0098 0099 qCDebug(KDEV_PYTHON_DUCHAIN) << "Found specified correct type for " << identifier.toString() << decls.first()->abstractType()->toString(); 0100 return decls.first()->abstractType(); 0101 } 0102 0103 0104 CorrectionHelper::Recursion CorrectionHelper::enterClass(const QString& identifier) 0105 { 0106 enter(KDevelop::Identifier(QLatin1String("class_") + identifier)); 0107 return CorrectionHelper::Recursion(this); 0108 } 0109 0110 CorrectionHelper::Recursion CorrectionHelper::enterFunction(const QString &identifier) 0111 { 0112 enter(KDevelop::Identifier(QLatin1String("function_") + identifier)); 0113 return CorrectionHelper::Recursion(this); 0114 } 0115 0116 void CorrectionHelper::leave() 0117 { 0118 m_contextStack.pop(); 0119 } 0120 0121 }