QString AbstractNavigationContext::declarationKind(DeclarationPointer decl)
{
  const AbstractFunctionDeclaration* function = dynamic_cast<const AbstractFunctionDeclaration*>(decl.data());

  QString kind;

  if( decl->isTypeAlias() )
    kind = i18n("Typedef");
  else if( decl->kind() == Declaration::Type ) {
    if( decl->type<StructureType>() )
      kind = i18n("Class");
  } else if( decl->kind() == Declaration::Instance ) {
    kind = i18n("Variable");
  } else if ( decl->kind() == Declaration::Namespace ) {
    kind = i18n("Namespace");
  }

  if( NamespaceAliasDeclaration* alias = dynamic_cast<NamespaceAliasDeclaration*>(decl.data()) ) {
    if( alias->identifier().isEmpty() )
      kind = i18n("Namespace import");
    else
      kind = i18n("Namespace alias");
  }

  if(function)
    kind = i18n("Function");

  if( decl->isForwardDeclaration() )
    kind = i18n("Forward Declaration");

  return kind;
}
Ejemplo n.º 2
0
void DeclarationBuilder::visitMethodCall(Ast *node)
{
    Node *aux = node->tree;

    /*
     * Handle chained method calls. Take a look at the implementation of
     * AstVisitor::visitMethodCall() for more details.
     */
    node->tree = aux->l;
    if (node->tree->kind == token_method_call)
        visitMethodCall(node);
    node->tree = aux;

    ExpressionVisitor v(currentContext(), m_editor);
    v.visitNode(node);
    DeclarationPointer lastMethod = v.lastDeclaration();

    /* Let's take a look at the method arguments */
    visitMethodCallArgs(node, lastMethod);

    /* And last but not least, go for the block */
    node->tree = aux->cond;
    m_lastMethodCall = lastMethod.data();
    visitBlock(node);
    m_lastMethodCall = nullptr;
    node->tree = aux;
}
Ejemplo n.º 3
0
void DeclarationBuilder::visitAliasStatement(Ast *node)
{
    Ast *right = new Ast(node->tree->r, node->context);
    QualifiedIdentifier id = QualifiedIdentifier(QString(right->tree->name));
    const RangeInRevision &range = editorFindRange(right, right);
    DeclarationPointer decl = getDeclaration(id, range, DUContextPointer(currentContext()));

    if (is_global_var(node->tree->l) && is_global_var(right->tree)) {
        DUChainWriteLocker wlock;
        // If the global variable on the right is not declared, declare it as nil
        if (!decl) {
            AbstractType::Ptr type = topContext()->findDeclarations(QualifiedIdentifier("NilClass")).first()->abstractType();
            VariableDeclaration *vDecl = openDefinition<VariableDeclaration>(id, range);
            vDecl->setVariableKind(right->tree);
            vDecl->setKind(Declaration::Instance);
            vDecl->setType(type);
            eventuallyAssignInternalContext();
            DeclarationBuilderBase::closeDeclaration();
            decl = vDecl;
        }
        node->tree = node->tree->l;
        QualifiedIdentifier aid = getIdentifier(node);
        AbstractType::Ptr type = decl->abstractType();
        declareVariable(aid, type, node);
    } else if (decl && decl->isFunctionDeclaration()) {
        DUChainWriteLocker wlock;
        MethodDeclaration *md = dynamic_cast<MethodDeclaration *>(decl.data());
        node->tree = node->tree->l;
        const RangeInRevision & arange = editorFindRange(node, node);
        QualifiedIdentifier aid = getIdentifier(node);
        aliasMethodDeclaration(aid, arange, md);
    } else
        appendProblem(node->tree, i18n("undefined method `%1'", id.toString()));
}
Ejemplo n.º 4
0
void UseBuilder::visitTraitAliasStatement(TraitAliasStatementAst *node)
{
    if (node->conflictIdentifierSequence) {
        const KDevPG::ListNode< NamespacedIdentifierAst* >* it = node->conflictIdentifierSequence->front();
        forever {
            buildNamespaceUses(it->element, ClassDeclarationType);

            if ( it->hasNext() ) {
                it = it->next;
            } else {
                break;
            }
        }
    }

    DUChainWriteLocker lock;
    DeclarationPointer dec = findDeclarationImport(ClassDeclarationType, identifierForNamespace(node->importIdentifier->identifier, m_editor));

    if (dec) {
        QualifiedIdentifier original = identifierPairForNode(node->importIdentifier->methodIdentifier).second;
        QList <Declaration*> list = dec.data()->internalContext()->findLocalDeclarations(original.last(), dec.data()->internalContext()->range().start);

        if (!list.isEmpty()) {
            UseBuilderBase::newUse(node->importIdentifier->methodIdentifier, DeclarationPointer(list.first()));
        }
    }

    lock.unlock();

    visitTraitAliasIdentifier(node->importIdentifier);
}
NavigationContextPointer AbstractNavigationContext::registerChild(DeclarationPointer declaration) {
  //We create a navigation-widget here, and steal its context.. evil ;)
  QWidget* navigationWidget = declaration->context()->createNavigationWidget(declaration.data());
  NavigationContextPointer ret;
  AbstractNavigationWidget* abstractNavigationWidget = dynamic_cast<AbstractNavigationWidget*>(navigationWidget);
  if(abstractNavigationWidget)
    ret = abstractNavigationWidget->context();
  delete navigationWidget;
  ret->setPreviousContext(this);
  m_children << ret;
  return ret;
}
Ejemplo n.º 6
0
void TestDUChain::testReparse()
{
    TestFile file("int main() { int i = 42; return i; }", "cpp");
    file.parse(TopDUContext::AllDeclarationsContextsAndUses);

    DeclarationPointer mainDecl;
    DeclarationPointer iDecl;
    for (int i = 0; i < 3; ++i) {
        QVERIFY(file.waitForParsed(500));
        DUChainReadLocker lock;
        QVERIFY(file.topContext());
        QCOMPARE(file.topContext()->childContexts().size(), 1);
        QCOMPARE(file.topContext()->localDeclarations().size(), 1);
        DUContext *exprContext = file.topContext()->childContexts().first()->childContexts().first();
        QCOMPARE(exprContext->localDeclarations().size(), 1);

        if (i) {
            QVERIFY(mainDecl);
            QCOMPARE(mainDecl.data(), file.topContext()->localDeclarations().first());

            QVERIFY(iDecl);
            QCOMPARE(iDecl.data(), exprContext->localDeclarations().first());
        }
        mainDecl = file.topContext()->localDeclarations().first();
        iDecl = exprContext->localDeclarations().first();

        QVERIFY(mainDecl->uses().isEmpty());
        QCOMPARE(iDecl->uses().size(), 1);
        QCOMPARE(iDecl->uses().begin()->size(), 1);

        if (i == 1) {
            file.setFileContents("int main()\n{\nfloat i = 13; return i - 5;\n}\n");
        }

        file.parse(TopDUContext::Features(TopDUContext::AllDeclarationsContextsAndUses | TopDUContext::ForceUpdateRecursive));
    }
}
Ejemplo n.º 7
0
void ExpressionVisitor::instantiateCurrentDeclaration()
{
    StructureType::Ptr type = StructureType::Ptr(new StructureType);
    DeclarationPointer decl = lastDeclaration();

    {
        DUChainReadLocker lock;
        auto funcType = QmlJS::FunctionType::Ptr::dynamicCast(decl->abstractType());

        if (funcType) {
            decl = funcType->declaration(topContext());
        }

        type->setDeclaration(decl.data());
    }

    encounter(AbstractType::Ptr::staticCast(type), decl);
}
void AbstractNavigationContext::makeLink( const QString& name, DeclarationPointer declaration, NavigationAction::Type actionType )
{
  NavigationAction action( declaration, actionType );
  QString targetId = QString::number((quint64)declaration.data() * actionType);
  makeLink(name, targetId, action);
}
Ejemplo n.º 9
0
void DeclarationBuilder::visitClassStatement(Ast *node)
{
    ModuleDeclaration *baseClass = nullptr;
    RangeInRevision range = getNameRange(node);
    const QByteArray comment = getComment(node);
    QualifiedIdentifier id = getIdentifier(node);
    DUContext *ctx = getContainedNameContext(node);

    /* First of all, open the declaration. */
    ModuleDeclaration *decl = reopenDeclaration<ModuleDeclaration>(id, range, ctx, DeclarationKind::Class);
    if (!decl) {
        node->foundProblems = true;
        return;
    }

    // Initialize the declaration.
    DUChainWriteLocker lock;
    if (!comment.isEmpty()) {
        decl->setComment(comment);
    }
    decl->setIsModule(false);
    decl->clearBaseClass();
    decl->clearModuleMixins();
    decl->setKind(KDevelop::Declaration::Type);
    m_accessPolicy.push(Declaration::Public);
    m_classDeclarations.push(DeclarationPointer(decl));

    /*
     * Now let's check for the base class. Ruby does not support multiple
     * inheritance, and the access is always public.
     */
    Node *aux = node->tree;
    node->tree = node->tree->cond;
    if (node->tree) {
        ExpressionVisitor ev(ctx, m_editor);
        lock.unlock();
        ev.visitNode(node);
        DeclarationPointer baseDecl = ev.lastDeclaration();
        lock.lock();
        if (baseDecl) {
            baseClass = dynamic_cast<ModuleDeclaration *>(baseDecl.data());
            if (!baseClass || baseClass->isModule()) {
                appendProblem(
                    node->tree,
                    i18n("TypeError: wrong argument type (expected Class)")
                );
            } else if (baseClass->internalContext()) {
                decl->setBaseClass(baseClass->indexedType());
            }
        }
    }
    node->tree = aux;

    /*  Setup types and go for the class body */
    ClassType::Ptr type(new ClassType());
    type->setDeclaration(decl);
    decl->setType(type);
    openType(type);

    openContextForClassDefinition(decl, node);
    if (baseClass && baseClass->internalContext()) {
        currentContext()->addImportedParentContext(baseClass->internalContext());
    }
    decl->setInternalContext(currentContext());
    lock.unlock();
    DeclarationBuilderBase::visitClassStatement(node);
    lock.lock();
    closeContext();

    closeType();
    closeDeclaration();
    m_classDeclarations.pop();
    m_accessPolicy.pop();
}
DeclarationNavigationContext::DeclarationNavigationContext(DeclarationPointer decl, KDevelop::TopDUContextPointer topContext, AbstractNavigationContext* previousContext)
        : AbstractDeclarationNavigationContext(decl, topContext, previousContext)
{
    kDebug() << "Generating declaration widget";
    importedModuleDeclaration* import_decl = dynamic_cast<importedModuleDeclaration*>(decl.data());
    if ( import_decl ) {
        kDebug() << " >> Module declaration found! Building documentation";
        kDebug() << " >> Identifier: " << import_decl->m_moduleIdentifier;
        m_fullyQualifiedModuleIdentifier = import_decl->m_moduleIdentifier;
    }
    else {
        kDebug() << "Could not find declaration for this module!" << decl->identifier().identifier().str();
    }
}
Ejemplo n.º 11
0
DeclarationPointer getDeclarationOrSignal(const QualifiedIdentifier& id, const DUContext* context, bool searchInParent)
{
    QString identifier = id.last().toString();

    if (identifier.startsWith(QLatin1String("on")) && identifier.size() > 2) {
        // The use may have typed the name of a QML slot (onFoo), try to get
        // the declaration of its corresponding signal (foo)
        identifier = identifier.at(2).toLower() + identifier.mid(3);
        DeclarationPointer decl = getDeclaration(QualifiedIdentifier(identifier), context, searchInParent);

        if (decl) {
            ClassFunctionDeclaration* classFuncDecl = dynamic_cast<ClassFunctionDeclaration *>(decl.data());

            if (classFuncDecl && classFuncDecl->isSignal()) {
                // Removing "on" has given the identifier of a QML signal, return
                // it instead of the name of its slot
                return decl;
            }
        }
    }

    // No signal found, fall back to normal behavior
    return getDeclaration(id, context, searchInParent);
}