//Returns only the name, no template-parameters or scope QString cursorItemText() { KDevelop::DUChainReadLocker lock( DUChain::lock() ); Declaration* decl = cursorDeclaration(); if(!decl) return QString(); IDocument* doc = ICore::self()->documentController()->activeDocument(); if(!doc) return QString(); TopDUContext* context = DUChainUtils::standardContextForUrl( doc->url() ); if( !context ) { qCDebug(PLUGIN_QUICKOPEN) << "Got no standard context"; return QString(); } AbstractType::Ptr t = decl->abstractType(); IdentifiedType* idType = dynamic_cast<IdentifiedType*>(t.data()); if( idType && idType->declaration(context) ) decl = idType->declaration(context); if(!decl->qualifiedIdentifier().isEmpty()) return decl->qualifiedIdentifier().last().identifier().str(); return QString(); }
void ContextBuilder::addBaseType( KDevelop::BaseClassInstance base, BaseSpecifierAST *node ) { DUChainWriteLocker lock(DUChain::lock()); addImportedContexts(); //Make sure the template-contexts are imported first, before any parent-class contexts. Q_ASSERT(currentContext()->type() == DUContext::Class); AbstractType::Ptr baseClass = base.baseClass.abstractType(); IdentifiedType* idType = dynamic_cast<IdentifiedType*>(baseClass.unsafeData()); Declaration* idDecl = 0; if( idType && (idDecl = idType->declaration(currentContext()->topContext())) ) { DUContext* ctx = idDecl->logicalInternalContext(currentContext()->topContext()); if(ctx) { currentContext()->addImportedParentContext( ctx ); }else{ currentContext()->addIndirectImport( DUContext::Import(idType->declarationId()) ); QString text = i18n("Could not resolve base class, adding it indirectly: %1", (base.baseClass ? base.baseClass.abstractType()->toString() : QString())); lock.unlock(); createUserProblem(node, text); } } else if( !baseClass.cast<DelayedType>() ) { QString text = i18n("Invalid base class: %1", (base.baseClass ? base.baseClass.abstractType()->toString() : QString())); lock.unlock(); createUserProblem(node, text); } }
AbstractType::Ptr TypeRepository::registerType(AbstractType::Ptr input) { if (!input) { kWarning(9007) << "Asked to register a null type." ; return input; } switch (input->whichType()) { case AbstractType::TypeAbstract: return input; case AbstractType::TypeIntegral: return input; case AbstractType::TypePointer: return registerPointer(CppPointerType::Ptr::dynamicCast(input)); case AbstractType::TypeReference: return registerReference(CppReferenceType::Ptr::dynamicCast(input)); case AbstractType::TypeFunction: return registerFunction(CppFunctionType::Ptr::dynamicCast(input)); case AbstractType::TypeStructure: return input; case AbstractType::TypeArray: return registerArray(ArrayType::Ptr::dynamicCast(input)); case AbstractType::TypeDelayed: return registerDelayedType(DelayedType::Ptr::dynamicCast(input)); default: return input; } }
QList< TypePtr< StructureType > > ExpressionVisitor::possibleStructureTypes(AbstractType::Ptr type) { QList< TypePtr< StructureType > > result; type = Helper::resolveType(type); if ( ! type ) { return result; } if ( type->whichType() == KDevelop::AbstractType::TypeUnsure ) { AbstractType::Ptr current; UnsureType::Ptr possible = type.cast<UnsureType>(); int amount = possible->typesSize(); for ( int i = 0; i < amount; i++ ) { StructureType::Ptr current = Helper::resolveType(possible->types()[i].abstractType()).cast<StructureType>(); if ( current ) { result << current; } } } else { StructureType::Ptr c = type.cast<StructureType>(); if ( c ) { result << c; } } return result; }
AbstractType::Ptr mergeTypes(AbstractType::Ptr type, const AbstractType::Ptr newType) { if (newType && newType->whichType() == AbstractType::TypeFunction) { return newType; } else { return TypeUtils::mergeTypes(type, newType); } }
AbstractType::Ptr binaryOperatorReturnType(AbstractType::Ptr left, AbstractType::Ptr right, int tokenKind) { if(!left || !right) return AbstractType::Ptr(); IntegralType* leftIntegral = dynamic_cast<IntegralType*>(left.unsafeData()); IntegralType* rightIntegral = dynamic_cast<IntegralType*>(right.unsafeData()); PointerType* leftPointer = dynamic_cast<PointerType*>(right.unsafeData()); AbstractType::Ptr ret; //Constantly evaluate integral expressions ConstantIntegralType* leftConstantIntegral = dynamic_cast<ConstantIntegralType*>(left.unsafeData()); ConstantIntegralType* rightConstantIntegral = dynamic_cast<ConstantIntegralType*>(right.unsafeData()); if(leftIntegral && rightIntegral) { if(tokenKind == '+' || tokenKind == '-' || tokenKind == '*' || tokenKind == '/' || tokenKind == '%' || tokenKind == '^' || tokenKind == '&' || tokenKind == '|' || tokenKind == '~' || tokenKind == Token_shift) { if(moreExpressiveThan(leftIntegral, rightIntegral)) ret = left; else ret = right; } if(tokenKind == '<' || tokenKind == '>' || tokenKind == Token_eq || tokenKind == Token_not_eq || tokenKind == Token_leq || tokenKind == Token_geq || tokenKind == Token_not_eq || tokenKind == Token_and || tokenKind == Token_or) ret = AbstractType::Ptr(new IntegralType(IntegralType::TypeBoolean)); } if(leftPointer && rightIntegral && (tokenKind == '+' || tokenKind == '-')) ret = left; IntegralType* retIntegral = dynamic_cast<IntegralType*>(ret.unsafeData()); ///We have determined the resulting type now. If both sides are constant, also evaluate the resulting value. if(ret && retIntegral && leftConstantIntegral && rightConstantIntegral) { switch( retIntegral->dataType() ) { case IntegralType::TypeFloat: { ConstantBinaryExpressionEvaluator<float> evaluator( retIntegral->dataType(), retIntegral->modifiers(), tokenKind, leftConstantIntegral, rightConstantIntegral ); return evaluator.createType(); } case IntegralType::TypeDouble: { ConstantBinaryExpressionEvaluator<double> evaluator( retIntegral->dataType(), retIntegral->modifiers(), tokenKind, leftConstantIntegral, rightConstantIntegral ); return evaluator.createType(); } default: if( leftConstantIntegral->modifiers() & AbstractType::UnsignedModifier ) { ConstantBinaryExpressionEvaluator<quint64> evaluator( retIntegral->dataType(), retIntegral->modifiers(), tokenKind, leftConstantIntegral, rightConstantIntegral); return evaluator.createType(); } else { ConstantBinaryExpressionEvaluator<qint64> evaluator( retIntegral->dataType(), retIntegral->modifiers(), tokenKind, leftConstantIntegral, rightConstantIntegral); return evaluator.createType(); } break; } } return ret; }
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; }
QList<CompletionTreeItemPointer> CodeCompletionContext::getCompletionItemsFromType(AbstractType::Ptr type, bool scoped) { QList<CompletionTreeItemPointer> res; if (type->whichType() == AbstractType::TypeUnsure) { UnsureType::Ptr unsure = type.cast<UnsureType>(); int count = unsure->typesSize(); for (int i = 0; i < count; i++) { res.append(getCompletionItemsForOneType(unsure->types()[i].abstractType(), scoped)); } } else { res = getCompletionItemsForOneType(type, scoped); } return res; }
void ADLHelper::addArgumentType(const AbstractType::Ptr typePtr) { if(m_alreadyProcessed.contains(typePtr.data())) return; if (typePtr) { #ifdef DEBUG_ADL qCDebug(CPPDUCHAIN) << " added argument type " << typePtr->toString() << " to ADL lookup"; #endif // the enumeration and enumerator types are not part of the TypeVisitor interface switch (typePtr->whichType()) { case AbstractType::TypeEnumeration: { EnumerationType* specificType = fastCast<EnumerationType*>(typePtr.data()); if (specificType) { Declaration * enumDecl = specificType->declaration(m_topContext.data()); addDeclarationScopeIdentifier(enumDecl); } break; } case AbstractType::TypeEnumerator: { if (m_templateArgsDepth == 0) { EnumeratorType* specificType = fastCast<EnumeratorType*>(typePtr.data()); if (specificType) { // use the enumeration context for the enumerator value declaration to find out the namespace Declaration * enumeratorDecl = specificType->declaration(m_topContext.data()); if (enumeratorDecl) { DUContext * enumContext = enumeratorDecl->context(); if (enumContext) { addAssociatedNamespace(enumContext->scopeIdentifier(false)); } } } } break; } default: typePtr->accept(&m_typeVisitor); } } m_alreadyProcessed.insert(typePtr.data()); }
void ExpressionVisitor::encounter(AbstractType::Ptr type, EncounterFlags flags) { if ( type ) kDebug() << "type encountered: " << type->toString(); else kDebug() << "unknown type encountered"; if ( flags & AutomaticallyDetermineDeclaration ) { StructureType::Ptr t = type.cast<StructureType>(); if ( t ) { encounterDeclaration(t->declaration(m_ctx->topContext())); } else { encounterDeclaration(0); } } m_lastType.push(encounterPreprocess(type, flags & MergeTypes)); }
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 {
void FunctionType::setReturnType(AbstractType::Ptr returnType) { d_func_dynamic()->m_returnType = returnType->indexed(); }
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); }
void PointerType::setBaseType(AbstractType::Ptr type) { d_func_dynamic()->m_baseType = type->indexed(); }
void GoChanType::setValueType(AbstractType::Ptr type) { d_func_dynamic()->valueType = type->indexed(); }