void DeclarationBuilder::visitFuncDeclaration(IFunctionDeclaration *node) { TypeBuilder::visitFuncDeclaration(node); DUChainWriteLocker lock; if(inClassScope) { ClassFunctionDeclaration *newMethod = openDefinition<ClassFunctionDeclaration>(node->getName(), node); if(node->getComment()) newMethod->setComment(QString::fromUtf8(node->getComment())); newMethod->setKind(KDevelop::Declaration::Type); lock.unlock(); ContextBuilder::visitFuncDeclaration(node); lock.lock(); closeDeclaration(); newMethod->setInternalContext(lastContext()); newMethod->setType(currentFunctionType); } else { FunctionDeclaration *newMethod = openDefinition<FunctionDeclaration>(node->getName(), node); if(node->getComment()) newMethod->setComment(QString::fromUtf8(node->getComment())); newMethod->setKind(KDevelop::Declaration::Type); lock.unlock(); ContextBuilder::visitFuncDeclaration(node); lock.lock(); closeDeclaration(); newMethod->setInternalContext(lastContext()); newMethod->setType(currentFunctionType); } }
void UsesCollector::startCollecting() { DUChainReadLocker lock(DUChain::lock()); if(Declaration* decl = m_declaration.data()) { if(m_collectDefinitions) { if(FunctionDefinition* def = dynamic_cast<FunctionDefinition*>(decl)) { //Jump from definition to declaration Declaration* declaration = def->declaration(); if(declaration) decl = declaration; } } ///Collect all overloads into "decls" QList<Declaration*> decls; if(m_collectOverloads && decl->context()->owner() && decl->context()->type() == DUContext::Class) { //First find the overridden base, and then all overriders of that base. while(Declaration* overridden = DUChainUtils::getOverridden(decl)) decl = overridden; uint maxAllowedSteps = 10000; decls += DUChainUtils::getOverriders( decl->context()->owner(), decl, maxAllowedSteps ); if(maxAllowedSteps == 10000) { ///@todo Fail! } } decls << decl; ///Collect all "parsed versions" or forward-declarations etc. here, into allDeclarations QSet<IndexedDeclaration> allDeclarations; foreach(Declaration* overload, decls) { m_declarations = DUChainUtils::collectAllVersions(overload); foreach(const IndexedDeclaration &d, m_declarations) { if(!d.data() || d.data()->id() != overload->id()) continue; allDeclarations.insert(d); if(m_collectConstructors && d.data() && d.data()->internalContext() && d.data()->internalContext()->type() == DUContext::Class) { QList<Declaration*> constructors = d.data()->internalContext()->findLocalDeclarations(d.data()->identifier(), CursorInRevision::invalid(), nullptr, AbstractType::Ptr(), DUContext::OnlyFunctions); foreach(Declaration* constructor, constructors) { ClassFunctionDeclaration* classFun = dynamic_cast<ClassFunctionDeclaration*>(constructor); if(classFun && classFun->isConstructor()) allDeclarations.insert(IndexedDeclaration(constructor)); } Identifier destructorId = destructorForName(d.data()->identifier()); QList<Declaration*> destructors = d.data()->internalContext()->findLocalDeclarations(destructorId, CursorInRevision::invalid(), nullptr, AbstractType::Ptr(), DUContext::OnlyFunctions); foreach(Declaration* destructor, destructors) { ClassFunctionDeclaration* classFun = dynamic_cast<ClassFunctionDeclaration*>(destructor); if(classFun && classFun->isDestructor()) allDeclarations.insert(IndexedDeclaration(destructor)); } }
void DeclarationBuilder::visitDestructor(IDestructor *node) { TypeBuilder::visitDestructor(node); DUChainWriteLocker lock; ClassFunctionDeclaration *newMethod = openDefinition<ClassFunctionDeclaration>(QualifiedIdentifier("~this"), editorFindRange(node, node)); if(node->getComment()) newMethod->setComment(QString::fromUtf8(node->getComment())); newMethod->setKind(KDevelop::Declaration::Type); lock.unlock(); ContextBuilder::visitDestructor(node); lock.lock(); closeDeclaration(); newMethod->setInternalContext(lastContext()); newMethod->setType(currentFunctionType); }
DeclarationPointer getDeclarationOrSignal(const QualifiedIdentifier& id, const DUContext* context, bool searchInParent) { QString identifier = id.last().toString(); if (identifier.startsWith(QLatin1String("on")) && identifier.size() > 2) { // The use may have typed the name of a QML slot (onFoo), try to get // the declaration of its corresponding signal (foo) identifier = identifier.at(2).toLower() + identifier.mid(3); DeclarationPointer decl = getDeclaration(QualifiedIdentifier(identifier), context, searchInParent); if (decl) { ClassFunctionDeclaration* classFuncDecl = dynamic_cast<ClassFunctionDeclaration *>(decl.data()); if (classFuncDecl && classFuncDecl->isSignal()) { // Removing "on" has given the identifier of a QML signal, return // it instead of the name of its slot return decl; } } } // No signal found, fall back to normal behavior return getDeclaration(id, context, searchInParent); }
QVariant NormalDeclarationCompletionItem::data(const QModelIndex& index, int role, const KDevelop::CodeCompletionModel* model) const { DUChainReadLocker lock(DUChain::lock(), 500); if(!lock.locked()) { kDebug(9007) << "Failed to lock the du-chain in time"; return QVariant(); } switch (role) { case Qt::DisplayRole: if (index.column() == CodeCompletionModel::Name) { return declarationName(); } else if(index.column() == CodeCompletionModel::Postfix) { if (FunctionType::Ptr functionType = m_declaration->type<FunctionType>()) { // Retrieve const/volatile string return functionType->AbstractType::toString(); } } else if(index.column() == CodeCompletionModel::Prefix) { if (m_declaration->abstractType()) { if(EnumeratorType::Ptr enumerator = m_declaration->type<EnumeratorType>()) { if(m_declaration->context()->owner() && m_declaration->context()->owner()->abstractType()) { if(!m_declaration->context()->owner()->identifier().isEmpty()) return shortenedTypeString(DeclarationPointer(m_declaration->context()->owner()), desiredTypeLength); else return "enum"; } } if (FunctionType::Ptr functionType = m_declaration->type<FunctionType>()) { ClassFunctionDeclaration* funDecl = dynamic_cast<ClassFunctionDeclaration*>(m_declaration.data()); if (functionType->returnType()) { QString ret = shortenedTypeString(m_declaration, desiredTypeLength); if(shortenArgumentHintReturnValues && argumentHintDepth() && ret.length() > maximumArgumentHintReturnValueLength) return QString("..."); else return ret; }else if(argumentHintDepth()) { return QString();//Don't show useless prefixes in the argument-hints }else if(funDecl && funDecl->isConstructor() ) return "<constructor>"; else if(funDecl && funDecl->isDestructor() ) return "<destructor>"; else return "<incomplete type>"; } else { return shortenedTypeString(m_declaration, desiredTypeLength); } } else { return "<incomplete type>"; } } break; case CodeCompletionModel::BestMatchesCount: return QVariant(normalBestMatchesCount); break; case CodeCompletionModel::IsExpandable: return QVariant(createsExpandingWidget()); case CodeCompletionModel::ExpandingWidget: { QWidget* nav = createExpandingWidget(model); Q_ASSERT(nav); model->addNavigationWidget(this, nav); QVariant v; v.setValue<QWidget*>(nav); return v; } case CodeCompletionModel::ScopeIndex: return static_cast<int>(reinterpret_cast<long>(m_declaration->context())); case CodeCompletionModel::CompletionRole: return (int)completionProperties(); case Qt::DecorationRole: { if( index.column() == CodeCompletionModel::Icon ) { CodeCompletionModel::CompletionProperties p = completionProperties(); lock.unlock(); return DUChainUtils::iconForProperties(p); } break; } } return QVariant(); }