Esempio n. 1
0
void CppTree2Uml::parseFunctionDeclaration(GroupAST* funSpec, GroupAST* storageSpec,
                                             TypeSpecifierAST * typeSpec, InitDeclaratorAST * decl)
{
    bool isFriend = false;
//:unused:    bool isVirtual = false;
    bool isStatic = false;
//:unused:    bool isInline = false;
    bool isPure = decl->initializer() != 0;
    bool isConstructor = false;

    if (funSpec){
//:unused:        QList<AST*> l = funSpec->nodeList();
//:unused:        for (int i = 0; i < l.size(); ++i) {
//:unused:            QString text = l.at(i)->text();
//:unused:            if (text == QLatin1String("virtual")) isVirtual = true;
//:unused:            else if (text == QLatin1String("inline")) isInline = true;
//:unused:        }
    }

    if (storageSpec){
        QList<AST*> l = storageSpec->nodeList();
        for (int i = 0; i < l.size(); ++i) {
            QString text = l.at(i)->text();
            if (text == QLatin1String("friend")) isFriend = true;
            else if (text == QLatin1String("static")) isStatic = true;
        }
    }

    DeclaratorAST* d = decl->declarator();
    QString id = d->declaratorId()->unqualifiedName()->text();

    UMLClassifier *c = m_currentClass[m_clsCnt];
    if (c == NULL) {
        uDebug() << id << ": need a surrounding class.";
        return;
    }

    QString returnType = typeOfDeclaration(typeSpec, d);
    UMLOperation *m = Import_Utils::makeOperation(c, id);
    // if a class has no return type, it could de a constructor or
    // a destructor
    if (d && returnType.isEmpty() && id.indexOf(QLatin1Char('~')) == -1)
        isConstructor = true;

    parseFunctionArguments(d, m);
    Import_Utils::insertMethod(c, m, m_currentAccess, returnType,
                               isStatic, isPure, isFriend, isConstructor, m_comment);
    m_comment = QString();
}
Esempio n. 2
0
void scopeOfNode( AST* ast, QStringList& scope )
{
    if( !ast )
        return;

    if( ast->parent() )
        scopeOfNode( ast->parent(), scope );

    QString s;
    switch( ast->nodeType() )
    {
    case NodeType_ClassSpecifier:
        if( ((ClassSpecifierAST*)ast)->name() ){
            s = ((ClassSpecifierAST*)ast)->name()->text();
            s = s.isEmpty() ? QString::fromLatin1("<unnamed>") : s;
            scope.push_back( s );
        }
        break;

    case NodeType_Namespace:
    {
        AST* namespaceName = ((NamespaceAST*)ast)->namespaceName();
        s = namespaceName ? namespaceName->text() : QString::fromLatin1("<unnamed>");
        scope.push_back( s );
    }
    break;

    case NodeType_FunctionDefinition:
    {
        FunctionDefinitionAST* funDef = static_cast<FunctionDefinitionAST*>( ast );
        DeclaratorAST* d = funDef->initDeclarator()->declarator();

        // hotfix for bug #68726
        if ( !d->declaratorId() )
            break;

        QList<ClassOrNamespaceNameAST*> l = d->declaratorId()->classOrNamespaceNameList();
        for( int i = 0; i < l.size(); ++i ) {
            AST* name = l.at(i)->name();
            scope.push_back( name->text() );
        }
    }
    break;

    default:
        break;
    }
}
Esempio n. 3
0
void CppTree2Uml::parseTemplateDeclaration(TemplateDeclarationAST* ast)
{
    TemplateParameterListAST* parmListAST = ast->templateParameterList();
    if (parmListAST == NULL)
        return;
    QList<TemplateParameterAST*> parmList = parmListAST->templateParameterList();
    for (int i = 0; i < parmList.size(); ++i) {
        // The template is either a typeParameter or a typeValueParameter.
        TemplateParameterAST* tmplParmNode = parmList.at(i);
        TypeParameterAST* typeParmNode = tmplParmNode->typeParameter();
        if (typeParmNode) {
            NameAST* nameNode = typeParmNode->name();
            if (nameNode) {
                QString typeName = nameNode->unqualifiedName()->text();
                Model_Utils::NameAndType nt(typeName, NULL);
                m_templateParams.append(nt);
            } else {
                uError() << "nameNode is NULL";
            }
        }

        ParameterDeclarationAST* valueNode = tmplParmNode->typeValueParameter();
        if (valueNode) {
            TypeSpecifierAST* typeSpec = valueNode->typeSpec();
            if (typeSpec == NULL) {
                uError() << "typeSpec is NULL";
                continue;
            }
            QString typeName = typeSpec->name()->text();
            UMLObject *t = Import_Utils::createUMLObject(UMLObject::ot_UMLObject, typeName,
                                                          m_currentNamespace[m_nsCnt]);
            DeclaratorAST* declNode = valueNode->declarator();
            NameAST* nameNode = declNode->declaratorId();
            if (nameNode == NULL) {
                uError() << "CppTree2Uml::parseTemplateDeclaration(value):"
                         << " nameNode is NULL";
                continue;
            }
            QString paramName = nameNode->unqualifiedName()->text();
            Model_Utils::NameAndType nt(paramName, t);
            m_templateParams.append(nt);
        }
    }

    if (ast->declaration())
        TreeParser::parseDeclaration(ast->declaration());
}
Esempio n. 4
0
void CppTree2Uml::parseDeclaration2(GroupAST* funSpec, GroupAST* storageSpec,
                                    TypeSpecifierAST* typeSpec, InitDeclaratorAST* decl)
{
    if (m_inStorageSpec)
            return;

    DeclaratorAST* d = decl->declarator();

    if (!d)
        return;

    if (!d->subDeclarator() && d->parameterDeclarationClause())
        return parseFunctionDeclaration(funSpec, storageSpec, typeSpec, decl);

    DeclaratorAST* t = d;
    while (t && t->subDeclarator())
        t = t->subDeclarator();

    QString id;
    if (t && t->declaratorId() && t->declaratorId()->unqualifiedName())
        id = t->declaratorId()->unqualifiedName()->text();

    if (!scopeOfDeclarator(d, QStringList()).isEmpty()){
        uDebug() << id << ": skipping.";
        return;
    }

    UMLClassifier *c = m_currentClass[m_clsCnt];
    if (c == NULL) {
        uDebug() << id << ": need a surrounding class.";
        return;
    }

    QString typeName = typeOfDeclaration(typeSpec, d);
//:unused:    bool isFriend = false;
    bool isStatic = false;
//:unused:    bool isInitialized = decl->initializer() != 0;

    if (storageSpec){
        QList<AST*> l = storageSpec->nodeList();
        for (int i = 0; i < l.size(); ++i) {
            QString text = l.at(i)->text();
            if (text == QLatin1String("static")) isStatic = true;
//:unused:            else if (text == QLatin1String("friend")) isFriend = true;
        }
    }

    Import_Utils::insertAttribute(c, m_currentAccess, id, typeName,
                                  m_comment, isStatic);
    m_comment = QString();
}
/*! Handle declaration in foreach statement */
bool PointerDeclarationFormatter::visit(ForeachStatementAST *ast)
{
    CHECK_RV(ast, "Invalid AST", true);
    printCandidate(ast);

    DeclaratorAST *declarator = ast->declarator;
    CHECK_RV(declarator, "No declarator", true);
    CHECK_RV(declarator->ptr_operator_list, "No Pointer or references", true);
    CHECK_RV(ast->type_specifier_list, "No type specifier", true);
    SpecifierAST *firstSpecifier = ast->type_specifier_list->value;
    CHECK_RV(firstSpecifier, "No first type specifier", true);
    CHECK_RV(ast->symbol, "No symbol", true);
    Symbol *symbol = ast->symbol->memberAt(0);

    // Specify activation range
    const int lastActivationToken = declarator->equal_token
        ? declarator->equal_token - 1
        : declarator->lastToken() - 1;
    TokenRange range(firstSpecifier->firstToken(), lastActivationToken);

    checkAndRewrite(declarator, symbol, range);
    return true;
}
/*!
    Handle
      (1) Simple declarations like in "char *s, *t, *int foo();"
      (2) Return types of function declarations.
 */
bool PointerDeclarationFormatter::visit(SimpleDeclarationAST *ast)
{
    CHECK_RV(ast, "Invalid AST", true);
    printCandidate(ast);

    const unsigned tokenKind = tokenAt(ast->firstToken()).kind();
    const bool astIsOk = tokenKind != T_CLASS && tokenKind != T_STRUCT && tokenKind != T_ENUM;
    CHECK_RV(astIsOk, "Nothing to do for class/struct/enum", true);

    DeclaratorListAST *declaratorList = ast->declarator_list;
    CHECK_RV(declaratorList, "No declarator list", true);
    DeclaratorAST *firstDeclarator = declaratorList->value;
    CHECK_RV(firstDeclarator, "No declarator", true);
    CHECK_RV(ast->symbols, "No Symbols", true);
    CHECK_RV(ast->symbols->value, "No Symbol", true);

    List<Symbol *> *sit = ast->symbols;
    DeclaratorListAST *dit = declaratorList;
    for (; sit && dit; sit = sit->next, dit = dit->next) {
        DeclaratorAST *declarator = dit->value;
        Symbol *symbol = sit->value;

        const bool isFirstDeclarator = declarator == firstDeclarator;

        // If were not handling the first declarator, we need to remove
        // characters from the beginning since our rewritten declaration
        // will contain all type specifiers.
        int charactersToRemove = 0;
        if (!isFirstDeclarator) {
            const int startAST = m_cppRefactoringFile->startOf(ast);
            const int startFirstDeclarator = m_cppRefactoringFile->startOf(firstDeclarator);
            CHECK_RV(startAST < startFirstDeclarator, "No specifier", true);
            charactersToRemove = startFirstDeclarator - startAST;
        }

        // Specify activation range
        int lastActivationToken = 0;
        TokenRange range;
        // (2) Handle function declaration's return type
        if (symbol->type()->asFunctionType()) {
            PostfixDeclaratorListAST *pfDeclaratorList = declarator->postfix_declarator_list;
            CHECK_RV(pfDeclaratorList, "No postfix declarator list", true);
            PostfixDeclaratorAST *pfDeclarator = pfDeclaratorList->value;
            CHECK_RV(pfDeclarator, "No postfix declarator", true);
            FunctionDeclaratorAST *functionDeclarator = pfDeclarator->asFunctionDeclarator();
            CHECK_RV(functionDeclarator, "No function declarator", true);
            // End the activation range before the '(' token.
            lastActivationToken = functionDeclarator->lparen_token - 1;

            SpecifierListAST *specifierList = isFirstDeclarator
                ? ast->decl_specifier_list
                : declarator->attribute_list;

            unsigned firstActivationToken = 0;
            bool foundBegin = false;
            firstActivationToken = firstTypeSpecifierWithoutFollowingAttribute(
                        specifierList,
                        m_cppRefactoringFile->cppDocument()->translationUnit(),
                        lastActivationToken,
                        &foundBegin);
            if (!foundBegin) {
                CHECK_RV(!isFirstDeclarator, "Declaration without attributes not supported", true);
                firstActivationToken = declarator->firstToken();
            }

            range.start = firstActivationToken;

        // (1) Handle 'normal' declarations.
        } else {
            if (isFirstDeclarator) {
                bool foundBegin = false;
                unsigned firstActivationToken = firstTypeSpecifierWithoutFollowingAttribute(
                            ast->decl_specifier_list,
                            m_cppRefactoringFile->cppDocument()->translationUnit(),
                            declarator->firstToken(),
                            &foundBegin);
                CHECK_RV(foundBegin, "Declaration without attributes not supported", true);
                range.start = firstActivationToken;
            } else {
                range.start = declarator->firstToken();
            }
            lastActivationToken = declarator->equal_token
                ? declarator->equal_token - 1
                : declarator->lastToken() - 1;
        }

        range.end = lastActivationToken;

        checkAndRewrite(declarator, symbol, range, charactersToRemove);
    }
    return true;
}
Esempio n. 7
0
void CppTree2Uml::parseFunctionDefinition(FunctionDefinitionAST* ast)
{
    TypeSpecifierAST* typeSpec = ast->typeSpec();
    GroupAST* funSpec = ast->functionSpecifier();
    GroupAST* storageSpec = ast->storageSpecifier();

    if (!ast->initDeclarator())
        return;

    DeclaratorAST* d = ast->initDeclarator()->declarator();

    if (!d->declaratorId())
        return;

    bool isFriend = false;
//:unused:    bool isVirtual = false;
    bool isStatic = false;
//:unused:    bool isInline = false;
    bool isConstructor = false;

    if (funSpec){
//:unused:        QList<AST*> l = funSpec->nodeList();
//:unused:        for (int i = 0; i < l.size(); ++i) {
//:unused:            QString text = l.at(i)->text();
//:unused:            if (text == "virtual") isVirtual = true;
//:unused:            else if (text == "inline") isInline = true;
//:unused:        }
    }

    if (storageSpec){
        QList<AST*> l = storageSpec->nodeList();
        for (int i = 0; i < l.size(); ++i) {
            QString text = l.at(i)->text();
            if (text == QLatin1String("friend")) isFriend = true;
            else if (text == QLatin1String("static")) isStatic = true;
        }
    }

    QString id = d->declaratorId()->unqualifiedName()->text().trimmed();
    if (m_thread) {
        m_thread->emitMessageToLog(QString(), QLatin1String("method ") + id);
    }
    uDebug() << id;

    UMLClassifier *c = m_currentClass[m_clsCnt];
    if (c == NULL) {
        uDebug() << id << ": need a surrounding class.";
        return;
    }

    QString returnType = typeOfDeclaration(typeSpec, d);
    UMLOperation *m = Import_Utils::makeOperation(c, id);
    // if a class has no return type, it could be a constructor or
    // a destructor
    if (d && returnType.isEmpty() && id.indexOf(QLatin1Char('~')) == -1)
        isConstructor = true;

    parseFunctionArguments(d, m);
    Import_Utils::insertMethod(c, m, m_currentAccess, returnType,
                              isStatic, false /*isAbstract*/, isFriend, isConstructor, m_comment);
    m_comment = QString();

/* For reference, Kdevelop does some more:
    method->setFileName(m_fileName);
    if (m_inSignals)
        method->setSignal(true);
    if (m_inSlots)
        method->setSlot(true);
 */
}
Esempio n. 8
0
void CppTree2Uml::parseTypedef(TypedefAST* ast)
{
    TypeSpecifierAST* typeSpec = ast->typeSpec();
    InitDeclaratorListAST* declarators = ast->initDeclaratorList();

    if (typeSpec && declarators){
        QString typeId;

        if (typeSpec->name())
            typeId = typeSpec->name()->text();

        QList<InitDeclaratorAST*> l(declarators->initDeclaratorList());
        InitDeclaratorAST* initDecl = 0;
        for (int i = 0; i < l.size(); ++i) {
            initDecl = l.at(i);
            if (initDecl==0) break;
            QString type, id;
            if (initDecl->declarator()){
               type = typeOfDeclaration(typeSpec, initDecl->declarator());

               DeclaratorAST* d = initDecl->declarator();
               while (d->subDeclarator()){
                   d = d->subDeclarator();
               }

               if (d->declaratorId())
                  id = d->declaratorId()->text();
            }
            /* @todo Trace typedefs back to their root type for deciding
                     whether to build a Datatype (for pointers.)  */
            /* check out if the ID type is a Datatype
               ex: typedef unsigned int uint;
               where unsigned int is a known datatype
               I'm not sure if setIsReference() should be run
             */
            bool isDatatype = Import_Utils::isDatatype(typeId, m_currentNamespace[m_nsCnt]);

            if (type.contains(QLatin1Char('*')) || isDatatype) {
                UMLObject *inner = 0;
                if (m_currentNamespace[m_nsCnt] &&
                        m_currentNamespace[m_nsCnt]->baseType() == UMLObject::ot_Class &&
                        typeId == m_currentNamespace[m_nsCnt]->name())
                    inner = m_currentNamespace[m_nsCnt];
                else
                    inner = Import_Utils::createUMLObject(UMLObject::ot_Class, typeId,
                                                          m_currentNamespace[m_nsCnt]);
                UMLObject *typedefObj =
                 Import_Utils::createUMLObject(UMLObject::ot_Datatype, id,
                                               m_currentNamespace[m_nsCnt]);
                UMLClassifier *dt = static_cast<UMLClassifier*>(typedefObj);
                dt->setIsReference();
                dt->setOriginType(static_cast<UMLClassifier*>(inner));
            } else {
                Import_Utils::createUMLObject(UMLObject::ot_Class, id,
                                               m_currentNamespace[m_nsCnt],
                                               QString() /* doc */,
                                               QLatin1String("typedef") /* stereotype */);
            }
        }

    }
}