Example #1
0
void DeclarationBuilder::visitForStatement(Ast *node)
{
    Node *aux = node->tree;
    node->tree = node->tree->cond;

    ExpressionVisitor ev(currentContext(), m_editor);
    ev.visitNode(node);
    AbstractType::Ptr type = ev.lastType();

    DUChainReadLocker rlock;
    if (type) {
        ClassType::Ptr ctype = type.cast<ClassType>();
        if (ctype && ctype->contentType()) {
            type = ctype->contentType().abstractType();
        } else {
            type = getBuiltinsType(QStringLiteral("Object"), currentContext());
        }
    } else {
        type = getBuiltinsType(QStringLiteral("Object"), currentContext());
    }

    node->tree = aux->r;
    for (Node *n = node->tree; n != nullptr; n = n->next) {
        node->tree = n;
        QualifiedIdentifier id = getIdentifier(node);
        rlock.unlock();
        declareVariable(id, type, node);
        rlock.lock();
    }
    node->tree = aux;
}
Example #2
0
void DeclarationBuilder::visitBlockVariables(Ast *node)
{
    DUChainReadLocker rlock;
    MethodDeclaration *last = dynamic_cast<MethodDeclaration *>(m_lastMethodCall);
    Node *n = node->tree;
    if (!n) {
        return;
    }

    uint max = 0, i = 0;
    const YieldType *yieldList = nullptr;
    if (last) {
        yieldList = last->yieldTypes();
        max = last->yieldTypesSize();
    }

    AbstractType::Ptr type;
    for (Node *aux = n; aux != nullptr; aux = aux->next, i++) {
        node->tree = aux;
        if (yieldList && i < max) {
            type = yieldList[i].type.abstractType();
        } else {
            type = getBuiltinsType(QStringLiteral("Object"), currentContext());
        }
        rlock.unlock();
        declareVariable(getIdentifier(node), type, node, DUContext::DontSearchInParent);
        rlock.lock();
    }
}
Example #3
0
void AdaptSignatureAction::execute()
{
    DUChainReadLocker lock;
    IndexedString url = m_otherSideTopContext->url();
    lock.unlock();
    m_otherSideTopContext = DUChain::self()->waitForUpdate(url, TopDUContext::AllDeclarationsContextsAndUses);
    if (!m_otherSideTopContext) {
        clangDebug() << "failed to update" << url.str();
        return;
    }

    lock.lock();

    Declaration* otherSide = m_otherSideId.getDeclaration(m_otherSideTopContext.data());
    if (!otherSide) {
        clangDebug() << "could not find definition";
        return;
    }
    DUContext* functionContext = DUChainUtils::getFunctionContext(otherSide);
    if (!functionContext) {
        clangDebug() << "no function context";
        return;
    }
    if (!functionContext || functionContext->type() != DUContext::Function) {
        clangDebug() << "no correct function context";
        return;
    }

    DocumentChangeSet changes;
    KTextEditor::Range parameterRange = ClangIntegration::DUChainUtils::functionSignatureRange(otherSide);
    QString newText = CodegenHelper::makeSignatureString(otherSide, m_newSignature, !m_editingDefinition);
    if (!m_editingDefinition) {
        // append a newline after the method signature in case the method definition follows
        newText += QLatin1Char('\n');
    }

    DocumentChange changeParameters(functionContext->url(), parameterRange, QString(), newText);
    changeParameters.m_ignoreOldText = true;
    changes.addChange(changeParameters);
    changes.setReplacementPolicy(DocumentChangeSet::WarnOnFailedChange);
    DocumentChangeSet::ChangeResult result = changes.applyAllChanges();
    if (!result) {
        KMessageBox::error(0, i18n("Failed to apply changes: %1", result.m_failureReason));
    }
    emit executed(this);

    foreach(RenameAction * renAct, m_renameActions) {
        renAct->execute();
    }
}
Example #4
0
AbstractType::Ptr CodeCompletionContext::getExpressionType(const QString &token)
{
    AbstractType::Ptr res;
    QString expr = m_text.left(m_text.lastIndexOf(token));
    EditorIntegrator e;
    ExpressionVisitor ev(m_duContext.data(), &e);

    DUChainReadLocker lock;
    Parser parser(IndexedString(), expr.toUtf8());
    Ast *ast = parser.parse();
    if (!ast || !ast->tree) {
        return AbstractType::Ptr(nullptr);
    }
    lock.unlock();
    ev.visitCode(ast);
    res = ev.lastType();
    lock.lock();

    return res;
}
Example #5
0
void TestCppCodegen::testSimplifiedUpdating()
{
  {
    InsertIntoDUChain code1("duchaintest_1.h", "template <typename T> struct test{};"
                                               "template <> struct test<int> {};");
    code1.parse(TopDUContext::SimplifiedVisibleDeclarationsAndContexts | TopDUContext::AST);

    DUChainReadLocker lock;
    //No specializations are handled in simplified parsing
    Cpp::TemplateDeclaration *specClassDecl = dynamic_cast<Cpp::TemplateDeclaration*>(code1->localDeclarations()[1]);
    QVERIFY(!specClassDecl->specializedFrom().data());
  }
  {
    InsertIntoDUChain code1("duchaintest_1.h", "struct A { struct Member2; struct Member1; };");
    InsertIntoDUChain code3("duchaintest_3.h", "#include <duchaintest_1.h>\n struct C : public A { Member1 m1; Member2 m2; };");
    qWarning() << "********************* Parsing step 1";
    code3.parse(TopDUContext::AllDeclarationsContextsUsesAndAST);

    DUChainReadLocker lock;

    QCOMPARE(code3->localDeclarations().size(), 1);
    QCOMPARE(code3->childContexts().size(), 1);
    QCOMPARE(code3->childContexts()[0]->localDeclarations().size(), 2);
    QVERIFY(code3->childContexts()[0]->localDeclarations()[0]->abstractType().cast<StructureType>());
    QVERIFY(code3->childContexts()[0]->localDeclarations()[1]->abstractType().cast<StructureType>());
    QCOMPARE(code3->childContexts()[0]->importedParentContexts().size(), 1);
    QCOMPARE(code1->childContexts().size(), 1);
  }
  {
    InsertIntoDUChain code1("duchaintest_1.h", "struct A { struct Member1; };");
    InsertIntoDUChain code2("duchaintest_2.h", "template<class T> struct B : public T{ struct Member2; };");
    InsertIntoDUChain code3("duchaintest_3.h", "#include <duchaintest_2.h>\n #include <duchaintest_1.h>\n struct C : public B<A> { Member1 m1; Member2 m2; };");
    qWarning() << "********************* Parsing step 1";
    code3.parse(TopDUContext::AllDeclarationsContextsUsesAndAST);

    DUChainReadLocker lock;

    QCOMPARE(code3->localDeclarations().size(), 1);
    QCOMPARE(code3->childContexts().size(), 1);
    QCOMPARE(code3->childContexts()[0]->localDeclarations().size(), 2);
    QVERIFY(code3->childContexts()[0]->localDeclarations()[0]->abstractType().cast<StructureType>());
    QVERIFY(code3->childContexts()[0]->localDeclarations()[1]->abstractType().cast<StructureType>());
    QCOMPARE(code3->childContexts()[0]->importedParentContexts().size(), 1);
    QCOMPARE(code1->childContexts().size(), 1);

    QCOMPARE(code2->localDeclarations().size(), 1);
    ClassDeclaration* BClass = dynamic_cast<ClassDeclaration*>(code2->localDeclarations()[0]);
    QVERIFY(BClass);
    QCOMPARE(BClass->baseClassesSize(), 1u);
    QCOMPARE(BClass->baseClasses()[0].baseClass.abstractType()->toString(), QString("T"));

    QCOMPARE(code3->childContexts()[0]->importedParentContexts().size(), 1);

    DUContext* BAContext = code3->childContexts()[0]->importedParentContexts()[0].context(code3.topContext());
    QVERIFY(BAContext);
    QVERIFY(!BAContext->inSymbolTable());

    //2 contexts are imported: The template-context and the parent-class context
    QCOMPARE(BAContext->importedParentContexts().size(), 2);
    QCOMPARE(BAContext->importedParentContexts()[1].context(code3.topContext()), code1->childContexts()[0]);
    ClassDeclaration* classDecl = dynamic_cast<ClassDeclaration*>(BAContext->owner());
    QVERIFY(classDecl);
    QCOMPARE(classDecl->baseClassesSize(), 1u);
    QCOMPARE(classDecl->baseClasses()[0].baseClass.index(), code1->localDeclarations()[0]->indexedType().index());

    lock.unlock();
    qWarning() << "********************* Parsing step 2";
    code3.parse(TopDUContext::AllDeclarationsContextsUsesAndAST | TopDUContext::ForceUpdateRecursive, true);

    lock.lock();
    QCOMPARE(code3->localDeclarations().size(), 1);
    QCOMPARE(code3->childContexts().size(), 1);
    QCOMPARE(code3->childContexts()[0]->localDeclarations().size(), 2);
    QCOMPARE(code1->childContexts().size(), 1);

    QVERIFY(code3->childContexts()[0]->localDeclarations()[0]->abstractType().cast<StructureType>());
    QVERIFY(code3->childContexts()[0]->localDeclarations()[1]->abstractType().cast<StructureType>());

    //BClass should have been updated, not deleted
    QVERIFY(BClass == dynamic_cast<ClassDeclaration*>(code2->localDeclarations()[0]));
    QCOMPARE(BClass->baseClassesSize(), 1u);
    QCOMPARE(BClass->baseClasses()[0].baseClass.abstractType()->toString(), QString("T"));

    //The template-instantiation context "B<A>" should have been deleted
    DUContext* BAContext2 = code3->childContexts()[0]->importedParentContexts()[0].context(code3.topContext());
//     qDebug() << "BAContexts" << BAContext << BAContext2;
//     QVERIFY(BAContext != BAContext2);
    QCOMPARE(BAContext2->importedParentContexts().size(), 2);
    QCOMPARE(BAContext2->importedParentContexts()[1].context(code3.topContext()), code1->childContexts()[0]);

    classDecl = dynamic_cast<ClassDeclaration*>(BAContext2->owner());
    QVERIFY(classDecl);
    QCOMPARE(classDecl->baseClassesSize(), 1u);
    QCOMPARE(classDecl->baseClasses()[0].baseClass.index(), code1->localDeclarations()[0]->indexedType().index());
  }
  {
    InsertIntoDUChain code1("duchaintest_1.h", "struct A { struct Member1; };");
    InsertIntoDUChain code2("duchaintest_2.h", "template<class T> struct B : public T{ struct Member2; };");
    InsertIntoDUChain code3("duchaintest_3.h", "#include <duchaintest_2.h>\n #include <duchaintest_1.h>\n typedef B<A> Parent; struct C : public Parent { Member1 m1; Member2 m2; };");

    code3.parse(TopDUContext::AllDeclarationsContextsUsesAndAST);

    DUChainReadLocker lock;

    QCOMPARE(code3->localDeclarations().size(), 2);
    QCOMPARE(code3->childContexts().size(), 1);
    QCOMPARE(code3->childContexts()[0]->localDeclarations().size(), 2);
    QVERIFY(code3->childContexts()[0]->localDeclarations()[0]->abstractType().cast<StructureType>());
    QVERIFY(code3->childContexts()[0]->localDeclarations()[1]->abstractType().cast<StructureType>());

    lock.unlock();
    code3.parse(TopDUContext::AllDeclarationsContextsUsesAndAST | TopDUContext::ForceUpdateRecursive, true);

    lock.lock();
    QCOMPARE(code3->localDeclarations().size(), 2);
    QCOMPARE(code3->childContexts().size(), 1);
    QCOMPARE(code3->childContexts()[0]->localDeclarations().size(), 2);
    QVERIFY(code3->childContexts()[0]->localDeclarations()[0]->abstractType().cast<StructureType>());
    QVERIFY(code3->childContexts()[0]->localDeclarations()[1]->abstractType().cast<StructureType>());
  }

  {
    QString text = "class C { class D d; };";

    InsertIntoDUChain code("testsimplified.cpp", text);

    code.parse(TopDUContext::AllDeclarationsContextsUsesAndAST);

    DUChainReadLocker lock;

    dumpAST(code);

    //The forward-declaration of 'D' is forwarded into the top-context
    QCOMPARE(code->localDeclarations().size(), 2);
    Declaration* classDecl = code->localDeclarations()[0];
    QCOMPARE(code->childContexts().size(), 1);
    QCOMPARE(code->childContexts()[0]->localDeclarations().size(), 1);
    QVERIFY(code->childContexts()[0]->localDeclarations()[0]->abstractType().cast<StructureType>());
    QCOMPARE(code->childContexts()[0]->localDeclarations()[0]->abstractType()->toString(), QString("D"));

    lock.unlock();

    code.parse(TopDUContext::AllDeclarationsContextsUsesAndAST | TopDUContext::ForceUpdate, true);
    lock.lock();

    QCOMPARE(code->localDeclarations().size(), 2);

    //Verify that an update has happened, rather than recreating everything
    QCOMPARE(code->localDeclarations()[0], classDecl);

    QCOMPARE(code->childContexts().size(), 1);
    QCOMPARE(code->childContexts()[0]->localDeclarations().size(), 1);
    QVERIFY(code->childContexts()[0]->localDeclarations()[0]->abstractType().cast<StructureType>());
    QCOMPARE(code->childContexts()[0]->localDeclarations()[0]->abstractType()->toString(), QString("D"));
  }

  {
    QString text = "class C {int test(); int mem; }; void test(int a); int i;";

    InsertIntoDUChain code("testsimplified.cpp", text);

    code.parse(TopDUContext::SimplifiedVisibleDeclarationsAndContexts | TopDUContext::AST);

    DUChainReadLocker lock;

    dumpAST(code);

    QCOMPARE(code->localDeclarations().size(), 3);
    QCOMPARE(code->childContexts().size(), 1);
    QCOMPARE(code->childContexts()[0]->localDeclarations().size(), 2);
    QVERIFY(!code->childContexts()[0]->localDeclarations()[0]->abstractType());
    QVERIFY(!code->childContexts()[0]->localDeclarations()[1]->abstractType());
    //In simplified parsing mode, the type should not have been built
    QVERIFY(!code->localDeclarations()[0]->abstractType());
    QVERIFY(code->localDeclarations()[0]->kind() == Declaration::Type);
    QVERIFY(!code->localDeclarations()[1]->abstractType());
    QVERIFY(code->localDeclarations()[1]->kind() == Declaration::Instance);
    QVERIFY(!code->localDeclarations()[2]->abstractType());
    QVERIFY(code->localDeclarations()[2]->kind() == Declaration::Instance);

    {
      uint count;
      const KDevelop::CodeModelItem* items;

      KDevelop::CodeModel::self().items(code->url(), count, items);
      for(uint a = 0; a < count; ++a) {
        if(items[a].id == code->localDeclarations()[0]->qualifiedIdentifier()) {
          QVERIFY(items[a].kind & KDevelop::CodeModelItem::Class);
        }
      }
    }
  }

  {
    InsertIntoDUChain codeA("A.h", "#ifndef A_H\n #define A_H\n class A{}; \n#endif");
    InsertIntoDUChain codeB("B.h", "#include <A.h>\n class B{};");

    codeB.parse(TopDUContext::SimplifiedVisibleDeclarationsAndContexts | TopDUContext::AST | TopDUContext::Recursive);

    DUChainReadLocker lock;

    //This is not only for debug-output, but also verifies that the AST is there as requesed
    dumpAST(codeA);

    QCOMPARE(codeB->importedParentContexts().size(), 1);
    QCOMPARE(codeA->localDeclarations().size(), 1);
    QVERIFY(codeA->parsingEnvironmentFile()->featuresSatisfied((TopDUContext::Features)(TopDUContext::SimplifiedVisibleDeclarationsAndContexts | TopDUContext::AST | TopDUContext::Recursive)));
    QVERIFY(codeB->parsingEnvironmentFile()->featuresSatisfied((TopDUContext::Features)(TopDUContext::SimplifiedVisibleDeclarationsAndContexts | TopDUContext::AST | TopDUContext::Recursive)));

    lock.unlock();

    //Update with more features
    codeB.parse(TopDUContext::AllDeclarationsContextsUsesAndAST | TopDUContext::Recursive, true);

    lock.lock();
    QCOMPARE(codeB->importedParentContexts().size(), 1);
    QCOMPARE(codeA->localDeclarations().size(), 1);
    QVERIFY(codeA->parsingEnvironmentFile()->featuresSatisfied((TopDUContext::Features)(TopDUContext::AllDeclarationsContextsUsesAndAST | TopDUContext::Recursive)));
    QVERIFY(codeB->parsingEnvironmentFile()->featuresSatisfied((TopDUContext::Features)(TopDUContext::AllDeclarationsContextsUsesAndAST | TopDUContext::Recursive)));
  }
  {
    ///Test whether "empty" files work
    InsertIntoDUChain codeA("Q.h", "");
    InsertIntoDUChain codeB("B.h", "#include <Q.h>\n class B{};");

    codeB.parse(TopDUContext::SimplifiedVisibleDeclarationsAndContexts | TopDUContext::AST | TopDUContext::Recursive);

    DUChainReadLocker lock;

    QCOMPARE(codeB->importedParentContexts().size(), 1);
    QVERIFY(codeA->localDeclarations().isEmpty());
    QVERIFY(!codeA->parsingEnvironmentFile()->isProxyContext());
  }
  {
    ///Test the 'ignoring' of header-guards
    InsertIntoDUChain codeA("A.h", "#ifndef A_H\n #define A_H\n class A{};\n #ifdef HONK\n class Honk {};\n #endif\n \n#endif \n");
    InsertIntoDUChain codeB("B.h", "#define A_H\n \n #include <A.h>\n class B{};");

    QVERIFY(!codeA.tryGet());

    codeB.parse(TopDUContext::SimplifiedVisibleDeclarationsAndContexts | TopDUContext::AST | TopDUContext::Recursive);

    DUChainReadLocker lock;

    //This is not only for debug-output, but also verifies that the AST is there as requesed
    dumpAST(codeA);

    QCOMPARE(codeA->localDeclarations().size(), 1);
    QCOMPARE(codeB->importedParentContexts().size(), 1);

    lock.unlock();

    codeB.parse(TopDUContext::SimplifiedVisibleDeclarationsAndContexts | TopDUContext::AST | TopDUContext::ForceUpdateRecursive | TopDUContext::Recursive);

    lock.lock();

    QCOMPARE(codeA->localDeclarations().size(), 1);
    QCOMPARE(codeB->importedParentContexts().size(), 1);
  }
}
Example #6
0
void TestCppCodegen::testUpdateIndices()
{
  /// @todo Extend this test to make sure t hat all kinds of declarations retain their indices when they are updated
  {
    InsertIntoDUChain code1("duchaintest_1.h", "class QW{}; struct A { struct Member2; struct Member1; }; class Oq{};");
    InsertIntoDUChain code3("duchaintest_3.h", "#include <duchaintest_1.h>\n struct C : public A { Member1 m1; Member2 m2; A test(int arg) { int v1; \n{}\n { int v2, *v3; }} int test(); };");
    qWarning() << "********************* Parsing step 1";
    code3.parse(TopDUContext::AllDeclarationsContextsUsesAndAST);

    DUChainReadLocker lock;

    IndexedDeclaration CDecl = code3.getDeclaration("C");
    QVERIFY(CDecl.isValid());
    IndexedDeclaration ADecl = code3.getDeclaration("A");
    QVERIFY(ADecl.isValid());

    IndexedDeclaration C_m1 = code3.getDeclaration("C::m1");
    QVERIFY(C_m1.isValid());
    IndexedDeclaration C_m2 = code3.getDeclaration("C::m2");
    QVERIFY(C_m2.isValid());

    QVERIFY(CDecl.declaration()->internalContext());
    QCOMPARE(CDecl.declaration()->internalContext()->localDeclarations().size(), 4);

    IndexedDeclaration C_test = CDecl.declaration()->internalContext()->localDeclarations()[2];
    QVERIFY(C_test.isValid());
    DUContext* testCtx = C_test.data()->internalContext();
    QVERIFY(testCtx);
    QCOMPARE(testCtx->localDeclarations().size(), 1);

    IndexedDeclaration C_test_v1 = testCtx->localDeclarations()[0];

    QCOMPARE(testCtx->childContexts().size(), 2);
    DUContext* child = testCtx->childContexts()[1];

    QCOMPARE(child->localDeclarations().size(), 2);

    IndexedDeclaration C_test_v2 = child->localDeclarations()[0];
    IndexedDeclaration C_test_v3 = child->localDeclarations()[1];

    QCOMPARE(C_test_v1.declaration()->identifier(), Identifier("v1"));
    QCOMPARE(C_test_v2.declaration()->identifier(), Identifier("v2"));
    QCOMPARE(C_test_v3.declaration()->identifier(), Identifier("v3"));
    QCOMPARE(C_m1.declaration()->identifier(), Identifier("m1"));
    QCOMPARE(C_m2.declaration()->identifier(), Identifier("m2"));
    QCOMPARE(C_test.declaration()->identifier(), Identifier("test"));
    QCOMPARE(CDecl.declaration()->identifier(), Identifier("C"));
    QCOMPARE(ADecl.declaration()->identifier(), Identifier("A"));

    lock.unlock();
    code1.m_insertedCode.setText("struct A { struct Member2; struct Member1; };");
    code3.m_insertedCode.setText("#include <duchaintest_1.h>\n class Q{}; struct C : public A { Member2 m2; int c; A test(int arg) { int w1; int v1;\n\n { int     *v3; }} int test(); };");
    code3.parse(TopDUContext::AllDeclarationsContextsAndUses | TopDUContext::ForceUpdateRecursive, true);

    lock.lock();
    QVERIFY(ADecl.declaration());
    QCOMPARE(ADecl.declaration()->identifier(), Identifier("A"));
    QVERIFY(CDecl.declaration());
    QCOMPARE(CDecl.declaration()->identifier(), Identifier("C"));
    QVERIFY(!C_m1.declaration());
    QVERIFY(C_m2.declaration());
    QCOMPARE(C_m2.declaration()->identifier(), Identifier("m2"));
    QVERIFY(C_test.declaration());
    QCOMPARE(C_test.declaration()->identifier(), Identifier("test"));
    QVERIFY(C_test_v1.declaration());
    QCOMPARE(C_test_v1.declaration()->identifier(), Identifier("v1"));
    QVERIFY(!C_test_v2.declaration());
    QVERIFY(C_test_v3.declaration());
    QCOMPARE(C_test_v3.declaration()->identifier(), Identifier("v3"));
  }
}
Example #7
0
void DeclarationBuilder::visitAssignmentStatement(Ast *node)
{
    QList<AbstractType::Ptr> values;
    QList<DeclarationPointer> declarations;
    QList<bool> alias;
    DUChainReadLocker lock;

    /* First of all, fetch the types and declaration on the right side */
    Ast *aux = new Ast(node->tree->r, node->context);
    for (Node *n = aux->tree; n != nullptr; n = n->next) {
        ExpressionVisitor v(currentContext(), m_editor);
        aux->tree = n;
        lock.unlock();
        // TODO: improve this
        DeclarationBuilderBase::visitNode(aux);
        v.visitNode(aux);
        lock.lock();
        values << v.lastType();
        alias << v.lastAlias();
        declarations << v.lastDeclaration();
    }
    lock.unlock();

    /*
     * Check if we can unpack. If it's possible, do it and get out! We can
     * unpack if the following conditions are satisfied:
     *  - More than 1 expressions on the left side.
     *  - Just one expression on the right side, which has Array as its type.
     */
    int rsize = values.length();
    if (rsize == 1) {
        int rest = nodeListSize(node->tree->l);
        ClassType::Ptr ct = values.first().cast<ClassType>();
        if (rest > 1 && ct && ct->contentType()) {
            lock.lock();
            QualifiedIdentifier qi = ct.data()->declaration(topContext())->qualifiedIdentifier();
            lock.unlock();
            if (qi == QualifiedIdentifier("Array")) {
                for (Node *n = node->tree->l; n != nullptr; n = n->next) {
                    aux->tree = n;
                    QualifiedIdentifier id = getIdentifier(aux);
                    declareVariable(id, ct->contentType().abstractType(), aux);
                }
                delete aux;
                return;
            }
        }
    }

    /*
     * We cannot unpack, so iterate over the left side expressions
     * and assign types.
     */
    int i = 0;
    AbstractType::Ptr type;
    for (Node *n = node->tree->l; n != nullptr; n = n->next, i++) {
        if (n->kind == token_method_call)
            continue;
        aux->tree = n;
        if (has_star(n)) {
            int rest = nodeListSize(n) - 1;
            int pack = rsize - i - rest;
            ClassType::Ptr newType = getBuiltinsType(QStringLiteral("Array"), currentContext()).cast<ClassType>();
            DUChainWriteLocker wlock;
            for (int j = pack; j > 0; j--, i++) {
                newType->addContentType(values.at(i));
            }
            wlock.unlock();
            i--;
            if (!is_just_a_star(n)) {
                QualifiedIdentifier id = getIdentifier(aux);
                declareVariable(id, newType.cast<AbstractType>(), aux);
            }
        } else if (i < rsize) {
            if (alias.at(i)) {
                DUChainWriteLocker wlock;
                RangeInRevision range = getNameRange(aux);
                QualifiedIdentifier id = getIdentifier(aux);
                AliasDeclaration *d = openDeclaration<AliasDeclaration>(id, range);
                d->setAliasedDeclaration(declarations.at(i).data());
                closeDeclaration();
            } else {
                type = values.at(i);
                if (!type) { // HACK: provisional fix, should be removed in the future
                    type = getBuiltinsType(QStringLiteral("Object"), currentContext());
                }
                QualifiedIdentifier id = getIdentifier(aux);
                declareVariable(id, type, aux);
            }
        } else {
            lock.lock();
            type = getBuiltinsType(QStringLiteral("NilClass"), currentContext());
            lock.unlock();
            QualifiedIdentifier id = getIdentifier(aux);
            declareVariable(id, type, aux);
        }
    }
    delete aux;
}