/* This file is part of KDevelop Copyright 2002-2005 Roberto Raggi This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ //krazy:excludeall=cpp #include "name_compiler.h" #include "type_compiler.h" #include "lexer.h" #include "symbol.h" #include "parsesession.h" #include "tokens.h" #include ///@todo this is very expensive QString decode(ParseSession* session, AST* ast, bool without_spaces = false) { QString ret; if( without_spaces ) { //Decode operator-names without spaces for now, since we rely on it in other places. ///@todo change this, here and in all the places that rely on it. Operators should then by written like "operator [ ]"(space between each token) for( size_t a = ast->start_token; a < ast->end_token; a++ ) { ret += session->token_stream->token(a).symbolString(); } } else { for( size_t a = ast->start_token; a < ast->end_token; a++ ) { ret += session->token_stream->token(a).symbolString() + ' '; } } return ret; } /*uint parseConstVolatile(ParseSession* session, const ListNode *cv) { uint ret = AbstractType::NoModifiers; if (cv) { const ListNode *it = cv->toFront(); const ListNode *end = it; do { int kind = session->token_stream->kind(it->element); if (kind == Token_const) ret |= AbstractType::ConstModifier; else if (kind == Token_volatile) ret |= AbstractType::VolatileModifier; it = it->next; } while (it != end); } return ret; }*/ /*IndexedTypeIdentifier typeIdentifierFromTemplateArgument(ParseSession* session, TemplateArgumentAST *node) { IndexedTypeIdentifier id; if(node->expression) { id = IndexedTypeIdentifier(decode(session, node), true); }else if(node->type_id) { //Parse the pointer operators TypeCompiler tc(session); tc.run(node->type_id->type_specifier); id = IndexedTypeIdentifier(tc.identifier()); //node->type_id->type_specifier->cv if(node->type_id->type_specifier) id.setIsConstant(parseConstVolatile(session, node->type_id->type_specifier->cv) & AbstractType::ConstModifier); if(node->type_id->declarator && node->type_id->declarator->ptr_ops) { const ListNode *it = node->type_id->declarator->ptr_ops->toFront(); const ListNode *end = it; ///@todo check ordering, eventually walk the list in reversed order do { if(it->element && it->element->op) { ///@todo What about ptr-to-member? static IndexedString ref('&'); if( session->token_stream->token(it->element->op).symbol() == ref) { //We're handling a 'reference' id.setIsReference(true); } else { //We're handling a real pointer id.setPointerDepth(id.pointerDepth()+1); if(it->element->cv) { id.setIsConstPointer(id.pointerDepth()-1, parseConstVolatile(session, it->element->cv) & AbstractType::ConstModifier); } } } it = it->next; } while (it != end); } } return id; }*/ NameCompiler::NameCompiler(ParseSession* session) : m_session(session) { } void NameCompiler::internal_run(AST *node) { m_name.clear(); visit(node); } void NameCompiler::visitUnqualifiedName(UnqualifiedNameAST *node) { IndexedString tmp_name; if (node->id) tmp_name = m_session->token_stream->token(node->id).symbol(); if (node->tilde) tmp_name = IndexedString('~' + tmp_name.byteArray()); if (OperatorFunctionIdAST *op_id = node->operator_id) { #if defined(__GNUC__) #warning "NameCompiler::visitUnqualifiedName() -- implement me" #endif static QString operatorString("operator"); QString tmp = operatorString; if (op_id->op && op_id->op->op) tmp += decode(m_session, op_id->op, true); else tmp += QLatin1String("{...cast...}"); tmp_name = IndexedString(tmp); m_typeSpecifier = op_id->type_specifier; } m_currentIdentifier = tmp_name.str(); m_name.push_back(m_currentIdentifier); if (node->template_arguments) { visitNodes(this, node->template_arguments); }/*else if(node->end_token == node->start_token + 3 && node->id == node->start_token && m_session->token_stream->token(node->id+1).symbol() == KDevelop::IndexedString('<')) { ///@todo Represent this nicer in the AST ///It's probably a type-specifier with instantiation of the default-parameter, like "Bla<>". m_currentIdentifier.appendTemplateIdentifier( IndexedTypeIdentifier() ); }*/ } TypeSpecifierAST* NameCompiler::lastTypeSpecifier() const { return m_typeSpecifier; } void NameCompiler::visitTemplateArgument(TemplateArgumentAST *node) { TypeCompiler tc(m_session); tc.run(node->type_id->type_specifier); if (tc.isIntegral()) m_templateArgs << tc.qualifiedName().join(" "); else m_templateArgs << tc.qualifiedName().join("::"); // m_currentIdentifier.appendTemplateIdentifier( typeIdentifierFromTemplateArgument(m_session, node) ); } /*const QualifiedIdentifier& NameCompiler::identifier() const { return *_M_name; }*/ void NameCompiler::run(NameAST *node/*, QualifiedIdentifier* target*/) { // if(target) // _M_name = target; // else // _M_name = &m_localName; m_typeSpecifier = 0; internal_run(node); /*if(node && node->global) _M_name->setExplicitlyGlobal( node->global );*/ }