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);
}
Esempio n. 2
0
void TestDUChain::testNamespace()
{
    TestFile file("namespace foo { struct bar { int baz; }; }\n"
                  "int main() { foo::bar myBar; }\n", "cpp");
    QVERIFY(file.parseAndWait());

    DUChainReadLocker lock;
    QVERIFY(file.topContext());
    QCOMPARE(file.topContext()->localDeclarations().size(), 2);
    auto fooDecl = file.topContext()->localDeclarations().first();
    QVERIFY(fooDecl->internalContext());
    QCOMPARE(fooDecl->internalContext()->localDeclarations().size(), 1);

    DUContext* top = file.topContext().data();
    DUContext* mainCtx = file.topContext()->childContexts().last();

    auto foo = top->localDeclarations().first();
    QCOMPARE(foo->qualifiedIdentifier().toString(), QString("foo"));

    DUContext* fooCtx = file.topContext()->childContexts().first();
    QCOMPARE(fooCtx->localScopeIdentifier().toString(), QString("foo"));
    QCOMPARE(fooCtx->scopeIdentifier(true).toString(), QString("foo"));
    QCOMPARE(fooCtx->localDeclarations().size(), 1);
    auto bar = fooCtx->localDeclarations().first();
    QCOMPARE(bar->qualifiedIdentifier().toString(), QString("foo::bar"));
    QCOMPARE(fooCtx->childContexts().size(), 1);

    DUContext* barCtx = fooCtx->childContexts().first();
    QCOMPARE(barCtx->localScopeIdentifier().toString(), QString("bar"));
    QCOMPARE(barCtx->scopeIdentifier(true).toString(), QString("foo::bar"));
    QCOMPARE(barCtx->localDeclarations().size(), 1);
    auto baz = barCtx->localDeclarations().first();
    QCOMPARE(baz->qualifiedIdentifier().toString(), QString("foo::bar::baz"));

    for (auto ctx : {top, mainCtx}) {
        QCOMPARE(ctx->findDeclarations(QualifiedIdentifier("foo")).size(), 1);
        QCOMPARE(ctx->findDeclarations(QualifiedIdentifier("foo::bar")).size(), 1);
        QCOMPARE(ctx->findDeclarations(QualifiedIdentifier("foo::bar::baz")).size(), 1);
    }
}
Esempio n. 3
0
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());
}