QVariant CompletionItem::data(const QModelIndex& index, int role, const KDevelop::CodeCompletionModel* model) const { switch(role) { case Qt::DisplayRole: { if (index.column() == CodeCompletionModel::Prefix && m_prefix != "") { return m_prefix; } break; } case CodeCompletionModel::BestMatchesCount: return 5; case CodeCompletionModel::MatchQuality: { if(!declaration()) return QVariant(); //type aliases are actually different types if(declaration()->isTypeAlias()) return QVariant(); AbstractType::Ptr typeToMatch = static_cast<go::CodeCompletionContext*>(model->completionContext().data())->typeToMatch(); if(!typeToMatch) return QVariant(); AbstractType::Ptr declType = declaration()->abstractType(); if (!declType) return QVariant(); //ignore constants typeToMatch->setModifiers(AbstractType::NoModifiers); declType->setModifiers(AbstractType::NoModifiers); if(declType->equals(typeToMatch.constData())) { return QVariant(10); } else if(declType->whichType() == AbstractType::TypeFunction) { GoFunctionType* function = fastCast<GoFunctionType*>(declType.constData()); auto args = function->returnArguments(); if(args.size() != 0) { AbstractType::Ptr first = args.first(); first->setModifiers(AbstractType::NoModifiers); if(first->equals(typeToMatch.constData())) return QVariant(10); } }else { return QVariant(); } } } return NormalDeclarationCompletionItem::data(index, role, model); }
uint TypeRepository::indexForType(const AbstractType::Ptr input) { if(!input) return 0; uint i = typeRepository()->index(AbstractTypeDataRequest(*input)); #ifdef DEBUG_TYPE_REPOSITORY AbstractType::Ptr t = typeForIndex(i); if(!t->equals(input.data())) { qCWarning(LANGUAGE) << "found type in repository does not equal source type:" << input->toString() << t->toString(); t->equals(input.data()); } #ifdef ASSERT_ON_PROBLEM Q_ASSERT(t->equals(input.data())); Q_ASSERT(input->equals(t.data())); #endif #endif return i; }
void ImplementationItem::execute(KTextEditor::View* view, const KTextEditor::Range& word) { DUChainReadLocker lock(DUChain::lock()); KTextEditor::Document *document = view->document(); QString replText; if (m_declaration) { //TODO:respect custom code styles // get existing modifiers so we can respect the user's choice of public/protected and final QStringList modifiers = getMethodTokens(document->text(KTextEditor::Range(KTextEditor::Cursor::start(), word.start()))); // get range to replace KTextEditor::Range replaceRange(word); if (!modifiers.isEmpty()) { // TODO: is there no easy API to map QString Index to a KTextEditor::Cursor ?! QString methodText = document->text(KTextEditor::Range(KTextEditor::Cursor::start(), word.start())); methodText = methodText.left(methodText.lastIndexOf(modifiers.last(), -1, Qt::CaseInsensitive)); replaceRange.start() = KTextEditor::Cursor(methodText.count('\n'), methodText.length() - methodText.lastIndexOf('\n') - 1); } // get indendation QString indendation; { QString currentLine = document->line(replaceRange.start().line()); indendation = getIndendation(currentLine); if ( !currentLine.isEmpty() && currentLine != indendation ) { // since theres some non-whitespace in this line, skip to the enxt one replText += '\n' + indendation; } if (indendation.isEmpty()) { // use a minimal indendation // TODO: respect code style indendation = QStringLiteral(" "); replText += indendation; } } #if 0 //Disabled, because not everyone writes phpdoc for every function //TODO: move to a phpdoc helper // build phpdoc comment { QualifiedIdentifier parentClassIdentifier; if (DUContext* pctx = m_declaration->context()) { parentClassIdentifier = pctx->localScopeIdentifier(); } else { qCDebug(COMPLETION) << "completion item for implementation has no parent context!"; } replText += "/**\n" + indendation + " * "; // insert old comment: const QString indentationWithExtra = "\n" + indendation + " *"; replText += m_declaration->comment().replace('\n', indentationWithExtra.toAscii().constData()); replText += "\n" + indendation + " * @overload " + m_declaration->internalContext()->scopeIdentifier(true).toString(); replText += "\n" + indendation + " **/\n" + indendation; } #endif // write function signature // copy existing modifiers if (!modifiers.isEmpty()) { // the tokens are in a bad order and there's no reverse method or similar, so we can't simply join the tokens QStringList::const_iterator i = modifiers.constEnd() - 1; while (true) { replText += (*i) + ' '; if (i == modifiers.constBegin()) { break; } else { --i; } } } QString functionName; bool isConstructorOrDestructor = false; bool isInterface = false; if (ClassMemberDeclaration* member = dynamic_cast<ClassMemberDeclaration*>(m_declaration.data())) { // NOTE: it should _never_ be private - but that's the completionmodel / context / worker's job if (!modifiers.contains(QStringLiteral("public")) && !modifiers.contains(QStringLiteral("protected"))) { if (member->accessPolicy() == Declaration::Protected) { replText += QLatin1String("protected "); } else { replText += QLatin1String("public "); } } if (!modifiers.contains(QStringLiteral("static")) && member->isStatic()) { replText += QLatin1String("static "); } functionName = member->identifier().toString(); ClassMethodDeclaration* method = dynamic_cast<ClassMethodDeclaration*>(m_declaration.data()); if (method) { functionName = method->prettyName().str(); isConstructorOrDestructor = method->isConstructor() || method->isDestructor(); } if (member->context() && member->context()->owner()) { ClassDeclaration* classDec = dynamic_cast<ClassDeclaration*>(member->context()->owner()); if (classDec) { isInterface = (classDec->classType() == ClassDeclarationData::Interface); } } } else { qCDebug(COMPLETION) << "completion item for implementation was not a classfunction declaration!"; functionName = m_declaration->identifier().toString(); } if (m_type == ImplementationItem::OverrideVar) { replText += "$" + functionName + " = "; } else { if (!modifiers.contains(QStringLiteral("function"))) { replText += QLatin1String("function "); } replText += functionName; { // get argument list QString arguments; createArgumentList(*this, arguments, 0, true); replText += arguments; } QString arguments; QVector<Declaration*> parameters; if (DUChainUtils::getArgumentContext(m_declaration.data())) parameters = DUChainUtils::getArgumentContext(m_declaration.data())->localDeclarations(); arguments = '('; bool first = true; foreach(Declaration* dec, parameters) { if (first) first = false; else arguments += QLatin1String(", "); arguments += '$' + dec->identifier().toString(); } arguments += ')'; bool voidReturnType = false; if (FunctionType::Ptr::dynamicCast(m_declaration->abstractType())) { AbstractType::Ptr retType = FunctionType::Ptr::staticCast(m_declaration->abstractType())->returnType(); if (retType->equals(new IntegralType(IntegralType::TypeVoid))) { voidReturnType = true; } } replText += QStringLiteral("\n%1{\n%1 ").arg(indendation); if (isInterface || m_type == ImplementationItem::Implement) { } else if (!isConstructorOrDestructor && !voidReturnType) { replText += QStringLiteral("$ret = parent::%2%3;\n%1 return $ret;").arg(indendation, functionName, arguments); } else { replText += QStringLiteral("parent::%1%2;").arg(functionName, arguments); } replText += QStringLiteral("\n%1}\n%1") .arg(indendation); } //TODO: properly place the cursor inside the {} part document->replaceText(replaceRange, replText); } else {