QPair<DUContext*, QualifiedIdentifier> ContextBuilder::findPrefixContext(const QualifiedIdentifier& id, KDevelop::SimpleCursor pos) { if(id.count() < 2) return qMakePair((DUContext*)0, QualifiedIdentifier()); QualifiedIdentifier prefixId(id); prefixId.pop(); DUContext* import = 0; { DUChainReadLocker lock(DUChain::lock()); QualifiedIdentifier currentScopeId = currentContext()->scopeIdentifier(true); QList<Declaration*> decls = currentContext()->findDeclarations(prefixId, pos); if(!decls.isEmpty()) { DUContext* classContext = decls.first()->logicalInternalContext(0); if(classContext && classContext->type() == DUContext::Class) { import = classContext; //Change the prefix-id so it respects namespace-imports prefixId = classContext->scopeIdentifier(true); if(prefixId.count() >= currentScopeId.count() && prefixId.left(currentScopeId.count()) == currentScopeId) prefixId = prefixId.mid(currentScopeId.count()); else kDebug() << "resolved bad prefix context. Should start with" << currentScopeId.toString() << "but is" << prefixId.toString(); } } } return qMakePair(import, prefixId); }
QualifiedIdentifier InstantiationInformation::applyToIdentifier(const QualifiedIdentifier& id) const { QualifiedIdentifier ret; if(id.count() > 1) { ret = id; ret.pop(); if(previousInstantiationInformation.index()) ret = previousInstantiationInformation.information().applyToIdentifier(ret); } Identifier lastId(id.last()); KDevVarLengthArray<IndexedTypeIdentifier> oldTemplateIdentifiers; for(uint a = 0; a < lastId.templateIdentifiersCount(); ++a) oldTemplateIdentifiers.append(lastId.templateIdentifier(a)); lastId.clearTemplateIdentifiers(); for(uint a = 0; a < templateParametersSize(); ++a) { if(templateParameters()[a].abstractType()) { lastId.appendTemplateIdentifier(IndexedTypeIdentifier(templateParameters()[a].abstractType()->toString(), true)); }else{ lastId.appendTemplateIdentifier((uint) oldTemplateIdentifiers.size() > a ? oldTemplateIdentifiers[a] : IndexedTypeIdentifier()); } } for(int a = templateParametersSize(); a < oldTemplateIdentifiers.size(); ++a) lastId.appendTemplateIdentifier(oldTemplateIdentifiers[a]); ret.push(lastId); return ret; }
void ContextBuilder::openPrefixContext(AST* ast, const QualifiedIdentifier& id, const SimpleCursor& pos) { if(id.count() < 2) return; //When creating a prefix-context that is there to embed a class within another class, import the enclosing class into that context. //That way items from the base class can be found. QPair<DUContext*, QualifiedIdentifier> prefix = findPrefixContext(id, pos); openContext(ast, DUContext::Helper, prefix.second); DUContext* import = prefix.first; if(import) { DUChainWriteLocker lock(DUChain::lock()); addImportedParentContextSafely(currentContext(), import); } }
QString DeclarationNavigationContext::html(bool shorten) { clear(); m_shorten = shorten; modifyHtml() += "<html><body><p>" + fontSizePrefix(shorten); addExternalHtml(m_prefix); if(!m_declaration.data()) { modifyHtml() += i18n("<br /> lost declaration <br />"); return currentHtml(); } if( m_previousContext ) { QString link = createLink( m_previousContext->name(), m_previousContext->name(), NavigationAction(m_previousContext) ); modifyHtml() += navigationHighlight(i18n("Back to %1<br />", link)); } QExplicitlySharedDataPointer<IDocumentation> doc; if( !shorten ) { doc = ICore::self()->documentationController()->documentationForDeclaration(m_declaration.data()); const AbstractFunctionDeclaration* function = dynamic_cast<const AbstractFunctionDeclaration*>(m_declaration.data()); if( function ) { htmlFunction(); } else if( m_declaration->isTypeAlias() || m_declaration->kind() == Declaration::Instance ) { if( m_declaration->isTypeAlias() ) modifyHtml() += importantHighlight("type "); if(m_declaration->type<EnumeratorType>()) modifyHtml() += i18n("enumerator "); if( !m_declaration->isTypeAlias()) modifyHtml() += ' ' + identifierHighlight(declarationName(m_declaration).toHtmlEscaped(), m_declaration) + " "; AbstractType::Ptr useType = m_declaration->abstractType(); if(m_declaration->isTypeAlias()) { //Do not show the own name as type of typedefs if(useType.cast<TypeAliasType>()) useType = useType.cast<TypeAliasType>()->type(); } eventuallyMakeTypeLinks( useType ); modifyHtml() += "<br>"; }else{ if( m_declaration->kind() == Declaration::Type && m_declaration->abstractType().cast<StructureType>()) { htmlClass(); } if ( m_declaration->kind() == Declaration::Namespace ) { modifyHtml() += i18n("namespace %1 ", identifierHighlight(m_declaration->qualifiedIdentifier().toString().toHtmlEscaped(), m_declaration)); } if(m_declaration->type<EnumerationType>()) { EnumerationType::Ptr enumeration = m_declaration->type<EnumerationType>(); modifyHtml() += i18n("enumeration %1 ", identifierHighlight(m_declaration->identifier().toString().toHtmlEscaped(), m_declaration)); } if(m_declaration->isForwardDeclaration()) { ForwardDeclaration* forwardDec = static_cast<ForwardDeclaration*>(m_declaration.data()); Declaration* resolved = forwardDec->resolve(m_topContext.data()); if(resolved) { modifyHtml() += i18n("( resolved forward-declaration: "); makeLink(resolved->identifier().toString(), KDevelop::DeclarationPointer(resolved), NavigationAction::NavigateDeclaration ); modifyHtml() += i18n(") "); }else{ modifyHtml() += i18n("(unresolved forward-declaration) "); QualifiedIdentifier id = forwardDec->qualifiedIdentifier(); uint count; const IndexedDeclaration* decls; PersistentSymbolTable::self().declarations(id, count, decls); for(uint a = 0; a < count; ++a) { if(decls[a].isValid() && !decls[a].data()->isForwardDeclaration()) { modifyHtml() += "<br />"; makeLink(i18n("possible resolution from"), KDevelop::DeclarationPointer(decls[a].data()), NavigationAction::NavigateDeclaration); modifyHtml() += ' ' + decls[a].data()->url().str(); } } } } modifyHtml() += "<br />"; } }else{ AbstractType::Ptr showType = m_declaration->abstractType(); if(showType && showType.cast<FunctionType>()) { showType = showType.cast<FunctionType>()->returnType(); if(showType) modifyHtml() += labelHighlight(i18n("Returns: ")); }else if(showType) { modifyHtml() += labelHighlight(i18n("Type: ")); } if(showType) { eventuallyMakeTypeLinks(showType); modifyHtml() += " "; } } QualifiedIdentifier identifier = m_declaration->qualifiedIdentifier(); if( identifier.count() > 1 ) { if( m_declaration->context() && m_declaration->context()->owner() ) { Declaration* decl = m_declaration->context()->owner(); FunctionDefinition* definition = dynamic_cast<FunctionDefinition*>(decl); if(definition && definition->declaration()) decl = definition->declaration(); if(decl->abstractType().cast<EnumerationType>()) modifyHtml() += labelHighlight(i18n("Enum: ")); else modifyHtml() += labelHighlight(i18n("Container: ")); makeLink( declarationName(DeclarationPointer(decl)), DeclarationPointer(decl), NavigationAction::NavigateDeclaration ); modifyHtml() += " "; } else { QualifiedIdentifier parent = identifier; parent.pop(); modifyHtml() += labelHighlight(i18n("Scope: %1 ", typeHighlight(parent.toString().toHtmlEscaped()))); } } if( shorten && !m_declaration->comment().isEmpty() ) { QString comment = QString::fromUtf8(m_declaration->comment()); if( comment.length() > 60 ) { comment.truncate(60); comment += "..."; } comment.replace('\n', " "); comment.replace("<br />", " "); comment.replace("<br/>", " "); modifyHtml() += commentHighlight(comment.toHtmlEscaped()) + " "; } QString access = stringFromAccess(m_declaration); if( !access.isEmpty() ) modifyHtml() += labelHighlight(i18n("Access: %1 ", propertyHighlight(access.toHtmlEscaped()))); ///@todo Enumerations QString detailsHtml; QStringList details = declarationDetails(m_declaration); if( !details.isEmpty() ) { bool first = true; foreach( const QString &str, details ) { if( !first ) detailsHtml += ", "; first = false; detailsHtml += propertyHighlight(str); } }
void TestIdentifier::testQualifiedIdentifier() { QFETCH(QString, stringId); const QStringList list = stringId.split(QStringLiteral("::"), QString::SkipEmptyParts); QualifiedIdentifier id(stringId); QCOMPARE(id.isEmpty(), stringId.isEmpty()); QCOMPARE(id, QualifiedIdentifier(stringId)); QVERIFY(!(id != QualifiedIdentifier(stringId))); QCOMPARE(id, QualifiedIdentifier(stringId)); if (list.size() == 1) { QCOMPARE(id, QualifiedIdentifier(Identifier(list.last()))); } else if (list.isEmpty()) { QualifiedIdentifier empty{Identifier()}; QCOMPARE(id, empty); QVERIFY(empty.isEmpty()); QVERIFY(empty.inRepository()); } QCOMPARE(id.toString(), stringId); QCOMPARE(id.toStringList(), list); QCOMPARE(id.top(), Identifier(list.isEmpty() ? QString() : list.last())); if (stringId.isEmpty()) { QVERIFY(id.inRepository()); QVERIFY(QualifiedIdentifier(id).inRepository()); } QualifiedIdentifier copy = id; QCOMPARE(copy, id); copy = copy; QCOMPARE(copy, id); copy = QualifiedIdentifier(); QVERIFY(copy.isEmpty()); copy = id; QCOMPARE(copy, id); IndexedQualifiedIdentifier indexedId(id); QVERIFY(indexedId == id); QCOMPARE(indexedId, IndexedQualifiedIdentifier(id)); QCOMPARE(indexedId.isValid(), !stringId.isEmpty()); QCOMPARE(indexedId.identifier(), id); IndexedQualifiedIdentifier indexedCopy = indexedId; QCOMPARE(indexedCopy, indexedId); indexedCopy = indexedCopy; QCOMPARE(indexedCopy, indexedId); indexedCopy = IndexedQualifiedIdentifier(); QVERIFY(!indexedCopy.isValid()); indexedCopy = indexedId; QCOMPARE(indexedCopy, indexedId); QualifiedIdentifier moved = std::move(id); QVERIFY(id.isEmpty()); QCOMPARE(moved, copy); IndexedQualifiedIdentifier movedIndexed = std::move(indexedId); QVERIFY(indexedId.isEmpty()); QCOMPARE(movedIndexed, indexedCopy); copy.clear(); QVERIFY(copy.isEmpty()); copy.push(moved); QCOMPARE(copy, moved); copy.push(Identifier(QStringLiteral("lalala"))); QCOMPARE(copy.count(), moved.count() + 1); }
void ContextBuilder::closePrefixContext(const QualifiedIdentifier& id) { if(id.count() < 2) return; closeContext(); }