File indexing completed on 2024-05-12 04:37:48

0001 /*
0002     SPDX-FileCopyrightText: 2009 Ramón Zarazúa <killerfox512+kde@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-only
0005 */
0006 
0007 #include "utilities.h"
0008 #include <debug.h>
0009 
0010 #include <serialization/indexedstring.h>
0011 #include <duchain/identifier.h>
0012 #include <duchain/duchainlock.h>
0013 #include <duchain/duchain.h>
0014 #include <duchain/declaration.h>
0015 #include <duchain/forwarddeclaration.h>
0016 #include <duchain/functiondefinition.h>
0017 #include <duchain/classfunctiondeclaration.h>
0018 #include <duchain/types/functiontype.h>
0019 
0020 namespace KDevelop {
0021 namespace CodeGenUtils {
0022 IdentifierValidator::IdentifierValidator(DUContext* context) : QValidator(nullptr)
0023     , m_context(context)
0024 {
0025 }
0026 
0027 IdentifierValidator::~IdentifierValidator()
0028 {
0029 }
0030 
0031 QValidator::State IdentifierValidator::validate(QString& input, int&) const
0032 {
0033     //I can't figure out why it wouldn't compile when I tried to use Identifier identifier();
0034     Identifier identifier = Identifier(IndexedString(input));
0035 
0036     if (identifier.isUnique())
0037         return Acceptable;
0038 
0039     DUChainReadLocker lock(DUChain::lock(), 10);
0040     return m_context->findLocalDeclarations(identifier, CursorInRevision::invalid(), nullptr,
0041                                             AbstractType::Ptr(), DUContext::NoFiltering).empty() ? Acceptable : Invalid;
0042 }
0043 
0044 IndexedString fetchImplementationFileForClass(const Declaration& targetClass)
0045 {
0046     DUChainReadLocker lock(DUChain::lock());
0047     qCDebug(LANGUAGE) << "Looking for implementation file for class:" << targetClass.identifier().toString();
0048 
0049     DUContext* context = targetClass.internalContext();
0050 
0051     //If this declaration is not a user defined type, then ignore and return empty file
0052     if (targetClass.kind() != Declaration::Type)
0053         return IndexedString();
0054 
0055     //If this is a forward declaration attempt to resolve it.
0056     const Declaration* realClass = &targetClass;
0057     if (const auto* forward = dynamic_cast<const ForwardDeclaration*>(realClass)) {
0058         if (!(realClass = forward->resolve(context->topContext())))
0059             return IndexedString();
0060         context = realClass->internalContext();
0061     }
0062 
0063     const QVector<Declaration*> declarations = context->localDeclarations();
0064 
0065     QMap<IndexedString, unsigned int> implementationsInFile;
0066 
0067     for (Declaration* decl : declarations) {
0068         ///@todo check for static variable instantiation as well
0069         if (auto* classFun = dynamic_cast<ClassFunctionDeclaration*>(decl))
0070             if (auto* def = FunctionDefinition::definition(classFun)) {
0071                 qCDebug(LANGUAGE) << "Definition For declaration in:" << def->url().toUrl();
0072                 ++implementationsInFile[def->url()];
0073             }
0074     }
0075 
0076     QMultiMap<unsigned int, IndexedString> sorter;
0077     for (auto it = implementationsInFile.constBegin(), end = implementationsInFile.constEnd(); it != end; ++it) {
0078         const IndexedString& file = it.key();
0079         unsigned int count = it.value();
0080         sorter.insert(count, file);
0081     }
0082     QList<IndexedString> sortedFiles = sorter.values();
0083 
0084     //If there are no methods, then just return the file the declaration is in
0085     if (sortedFiles.empty())
0086         return context->url();
0087 
0088     if (sortedFiles.size() == 1)
0089         return sortedFiles[0];
0090 
0091     const QList<IndexedString> tiedFiles = sorter.values(sorter.end().key());
0092     if (tiedFiles.size() > 1) {
0093         //Return the file that has the most uses
0094         const auto uses = realClass->uses();
0095 
0096         IndexedString mostUsesFile;
0097         unsigned int mostUses = 0;
0098         for (const IndexedString& currentFile : tiedFiles) {
0099             if (static_cast<unsigned int>(uses[currentFile].size()) > mostUses) {
0100                 mostUses = uses[currentFile].size();
0101                 mostUsesFile = currentFile;
0102             }
0103         }
0104 
0105         return mostUsesFile;
0106     } else
0107         return sortedFiles.back();
0108 }
0109 }
0110 }
0111 
0112 #include "moc_utilities.cpp"