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"