##// END OF EJS Templates
added error handling for virtual method overloads, added more global functions (qsrand etc.), added support for exec_ etc (python keyword overlap resolution), change virtual method handling, this will require code regeneration (I will do that tomorrow)...
added error handling for virtual method overloads, added more global functions (qsrand etc.), added support for exec_ etc (python keyword overlap resolution), change virtual method handling, this will require code regeneration (I will do that tomorrow) git-svn-id: svn://svn.code.sf.net/p/pythonqt/code/trunk@103 ea8d5007-eb21-0410-b261-ccb3ea6e24a9

File last commit:

r10:21d959e02207
r67:57d78f859ef3
Show More
binder.cpp
906 lines | 27.9 KiB | text/x-c | CppLexer
/****************************************************************************
**
** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
**
** This file is part of the Qt Script Generator project on Trolltech Labs.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#include "binder.h"
#include "lexer.h"
#include "control.h"
#include "symbol.h"
#include "codemodel_finder.h"
#include "class_compiler.h"
#include "compiler_utils.h"
#include "tokens.h"
#include "dumptree.h"
#include <iostream>
#include <qdebug.h>
Binder::Binder(CodeModel *__model, LocationManager &__location, Control *__control)
: _M_model(__model),
_M_location(__location),
_M_token_stream(&_M_location.token_stream),
_M_control(__control),
_M_current_function_type(CodeModel::Normal),
type_cc(this),
name_cc(this),
decl_cc(this)
{
_M_qualified_types["char"] = QString();
_M_qualified_types["double"] = QString();
_M_qualified_types["float"] = QString();
_M_qualified_types["int"] = QString();
_M_qualified_types["long"] = QString();
_M_qualified_types["short"] = QString();
_M_qualified_types["void"] = QString();
}
Binder::~Binder()
{
}
FileModelItem Binder::run(AST *node)
{
FileModelItem old = _M_current_file;
_M_current_access = CodeModel::Public;
_M_current_file = model()->create<FileModelItem>();
updateItemPosition (_M_current_file->toItem(), node);
visit(node);
FileModelItem result = _M_current_file;
_M_current_file = old; // restore
return result;
}
ScopeModelItem Binder::currentScope()
{
if (_M_current_class)
return model_static_cast<ScopeModelItem>(_M_current_class);
else if (_M_current_namespace)
return model_static_cast<ScopeModelItem>(_M_current_namespace);
return model_static_cast<ScopeModelItem>(_M_current_file);
}
TemplateParameterList Binder::changeTemplateParameters(TemplateParameterList templateParameters)
{
TemplateParameterList old = _M_current_template_parameters;
_M_current_template_parameters = templateParameters;
return old;
}
CodeModel::FunctionType Binder::changeCurrentFunctionType(CodeModel::FunctionType functionType)
{
CodeModel::FunctionType old = _M_current_function_type;
_M_current_function_type = functionType;
return old;
}
CodeModel::AccessPolicy Binder::changeCurrentAccess(CodeModel::AccessPolicy accessPolicy)
{
CodeModel::AccessPolicy old = _M_current_access;
_M_current_access = accessPolicy;
return old;
}
NamespaceModelItem Binder::changeCurrentNamespace(NamespaceModelItem item)
{
NamespaceModelItem old = _M_current_namespace;
_M_current_namespace = item;
return old;
}
ClassModelItem Binder::changeCurrentClass(ClassModelItem item)
{
ClassModelItem old = _M_current_class;
_M_current_class = item;
return old;
}
FunctionDefinitionModelItem Binder::changeCurrentFunction(FunctionDefinitionModelItem item)
{
FunctionDefinitionModelItem old = _M_current_function;
_M_current_function = item;
return old;
}
int Binder::decode_token(std::size_t index) const
{
return _M_token_stream->kind(index);
}
CodeModel::AccessPolicy Binder::decode_access_policy(std::size_t index) const
{
switch (decode_token(index))
{
case Token_class:
return CodeModel::Private;
case Token_struct:
case Token_union:
return CodeModel::Public;
default:
return CodeModel::Public;
}
}
CodeModel::ClassType Binder::decode_class_type(std::size_t index) const
{
switch (decode_token(index))
{
case Token_class:
return CodeModel::Class;
case Token_struct:
return CodeModel::Struct;
case Token_union:
return CodeModel::Union;
default:
std::cerr << "** WARNING unrecognized class type" << std::endl;
}
return CodeModel::Class;
}
const NameSymbol *Binder::decode_symbol(std::size_t index) const
{
return _M_token_stream->symbol(index);
}
void Binder::visitAccessSpecifier(AccessSpecifierAST *node)
{
const ListNode<std::size_t> *it = node->specs;
if (it == 0)
return;
it = it->toFront();
const ListNode<std::size_t> *end = it;
do
{
switch (decode_token(it->element))
{
default:
break;
case Token_public:
changeCurrentAccess(CodeModel::Public);
changeCurrentFunctionType(CodeModel::Normal);
break;
case Token_protected:
changeCurrentAccess(CodeModel::Protected);
changeCurrentFunctionType(CodeModel::Normal);
break;
case Token_private:
changeCurrentAccess(CodeModel::Private);
changeCurrentFunctionType(CodeModel::Normal);
break;
case Token_signals:
changeCurrentAccess(CodeModel::Protected);
changeCurrentFunctionType(CodeModel::Signal);
break;
case Token_slots:
changeCurrentFunctionType(CodeModel::Slot);
break;
}
it = it->next;
}
while (it != end);
}
void Binder::visitSimpleDeclaration(SimpleDeclarationAST *node)
{
visit(node->type_specifier);
if (const ListNode<InitDeclaratorAST*> *it = node->init_declarators)
{
it = it->toFront();
const ListNode<InitDeclaratorAST*> *end = it;
do
{
InitDeclaratorAST *init_declarator = it->element;
declare_symbol(node, init_declarator);
it = it->next;
}
while (it != end);
}
}
void Binder::declare_symbol(SimpleDeclarationAST *node, InitDeclaratorAST *init_declarator)
{
DeclaratorAST *declarator = init_declarator->declarator;
while (declarator && declarator->sub_declarator)
declarator = declarator->sub_declarator;
NameAST *id = declarator->id;
if (! declarator->id)
{
std::cerr << "** WARNING expected a declarator id" << std::endl;
return;
}
CodeModelFinder finder(model(), this);
ScopeModelItem symbolScope = finder.resolveScope(id, currentScope());
if (! symbolScope)
{
name_cc.run(id);
std::cerr << "** WARNING scope not found for symbol:"
<< qPrintable(name_cc.name()) << std::endl;
return;
}
decl_cc.run(declarator);
if (decl_cc.isFunction())
{
name_cc.run(id->unqualified_name);
FunctionModelItem fun = model()->create<FunctionModelItem>();
updateItemPosition (fun->toItem(), node);
fun->setAccessPolicy(_M_current_access);
fun->setFunctionType(_M_current_function_type);
fun->setName(name_cc.name());
fun->setAbstract(init_declarator->initializer != 0);
fun->setConstant(declarator->fun_cv != 0);
fun->setTemplateParameters(_M_current_template_parameters);
applyStorageSpecifiers(node->storage_specifiers, model_static_cast<MemberModelItem>(fun));
applyFunctionSpecifiers(node->function_specifiers, fun);
// build the type
TypeInfo typeInfo = CompilerUtils::typeDescription(node->type_specifier,
declarator,
this);
fun->setType(qualifyType(typeInfo, symbolScope->qualifiedName()));
fun->setVariadics (decl_cc.isVariadics ());
// ... and the signature
foreach (DeclaratorCompiler::Parameter p, decl_cc.parameters())
{
ArgumentModelItem arg = model()->create<ArgumentModelItem>();
arg->setType(qualifyType(p.type, _M_context));
arg->setName(p.name);
arg->setDefaultValue(p.defaultValue);
if (p.defaultValue)
arg->setDefaultValueExpression(p.defaultValueExpression);
fun->addArgument(arg);
}
fun->setScope(symbolScope->qualifiedName());
symbolScope->addFunction(fun);
}
else
{
VariableModelItem var = model()->create<VariableModelItem>();
updateItemPosition (var->toItem(), node);
var->setTemplateParameters(_M_current_template_parameters);
var->setAccessPolicy(_M_current_access);
name_cc.run(id->unqualified_name);
var->setName(name_cc.name());
TypeInfo typeInfo = CompilerUtils::typeDescription(node->type_specifier,
declarator,
this);
if (declarator != init_declarator->declarator
&& init_declarator->declarator->parameter_declaration_clause != 0)
{
typeInfo.setFunctionPointer (true);
decl_cc.run (init_declarator->declarator);
foreach (DeclaratorCompiler::Parameter p, decl_cc.parameters())
typeInfo.addArgument(p.type);
}
var->setType(qualifyType(typeInfo, _M_context));
applyStorageSpecifiers(node->storage_specifiers, model_static_cast<MemberModelItem>(var));
var->setScope(symbolScope->qualifiedName());
symbolScope->addVariable(var);
}
}
void Binder::visitFunctionDefinition(FunctionDefinitionAST *node)
{
Q_ASSERT(node->init_declarator != 0);
ScopeModelItem scope = currentScope();
InitDeclaratorAST *init_declarator = node->init_declarator;
DeclaratorAST *declarator = init_declarator->declarator;
// in the case of "void (func)()" or "void ((func))()" we need to
// skip to the inner most. This is in line with how the declarator
// node is generated in 'parser.cpp'
while (declarator && declarator->sub_declarator)
declarator = declarator->sub_declarator;
Q_ASSERT(declarator->id);
CodeModelFinder finder(model(), this);
ScopeModelItem functionScope = finder.resolveScope(declarator->id, scope);
if (! functionScope)
{
name_cc.run(declarator->id);
std::cerr << "** WARNING scope not found for function definition:"
<< qPrintable(name_cc.name()) << std::endl
<< "\tdefinition *ignored*"
<< std::endl;
return;
}
decl_cc.run(declarator);
Q_ASSERT(! decl_cc.id().isEmpty());
FunctionDefinitionModelItem
old = changeCurrentFunction(_M_model->create<FunctionDefinitionModelItem>());
_M_current_function->setScope(functionScope->qualifiedName());
updateItemPosition (_M_current_function->toItem(), node);
Q_ASSERT(declarator->id->unqualified_name != 0);
name_cc.run(declarator->id->unqualified_name);
QString unqualified_name = name_cc.name();
_M_current_function->setName(unqualified_name);
TypeInfo tmp_type = CompilerUtils::typeDescription(node->type_specifier,
declarator, this);
_M_current_function->setType(qualifyType(tmp_type, _M_context));
_M_current_function->setAccessPolicy(_M_current_access);
_M_current_function->setFunctionType(_M_current_function_type);
_M_current_function->setConstant(declarator->fun_cv != 0);
_M_current_function->setTemplateParameters(_M_current_template_parameters);
applyStorageSpecifiers(node->storage_specifiers,
model_static_cast<MemberModelItem>(_M_current_function));
applyFunctionSpecifiers(node->function_specifiers,
model_static_cast<FunctionModelItem>(_M_current_function));
_M_current_function->setVariadics (decl_cc.isVariadics ());
foreach (DeclaratorCompiler::Parameter p, decl_cc.parameters())
{
ArgumentModelItem arg = model()->create<ArgumentModelItem>();
arg->setType(qualifyType(p.type, functionScope->qualifiedName()));
arg->setName(p.name);
arg->setDefaultValue(p.defaultValue);
if (p.defaultValue)
arg->setDefaultValueExpression(p.defaultValueExpression);
_M_current_function->addArgument(arg);
}
functionScope->addFunctionDefinition(_M_current_function);
FunctionModelItem prototype = model_static_cast<FunctionModelItem>(_M_current_function);
FunctionModelItem declared = functionScope->declaredFunction(prototype);
// try to find a function declaration for this definition..
if (! declared)
{
functionScope->addFunction(prototype);
}
else
{
applyFunctionSpecifiers(node->function_specifiers, declared);
// fix the function type and the access policy
_M_current_function->setAccessPolicy(declared->accessPolicy());
_M_current_function->setFunctionType(declared->functionType());
}
changeCurrentFunction(old);
}
void Binder::visitTemplateDeclaration(TemplateDeclarationAST *node)
{
const ListNode<TemplateParameterAST*> *it = node->template_parameters;
if (it == 0) {
// QtScript: we want to visit the declaration still, so that
// e.g. QMetaTypeId<Foo> is added to the code model
visit(node->declaration);
return;
}
TemplateParameterList savedTemplateParameters = changeTemplateParameters(TemplateParameterList());
it = it->toFront();
const ListNode<TemplateParameterAST*> *end = it;
TemplateParameterList templateParameters;
do {
TemplateParameterAST *parameter = it->element;
TypeParameterAST *type_parameter = parameter->type_parameter;
NameAST *name;
if (!type_parameter) {
// A hacky hack to work around missing support for parameter declarations in
// templates. We just need the to get the name of the variable, since we
// aren't actually compiling these anyway. We are still not supporting much
// more, but we are refusing to fail for a few more declarations
if (parameter->parameter_declaration == 0 ||
parameter->parameter_declaration->declarator == 0 ||
parameter->parameter_declaration->declarator->id == 0) {
/*std::cerr << "** WARNING template declaration not supported ``";
Token const &tk = _M_token_stream->token ((int) node->start_token);
Token const &end_tk = _M_token_stream->token ((int) node->declaration->start_token);
std::cerr << std::string (&tk.text[tk.position], (end_tk.position) - tk.position) << "''"
<< std::endl << std::endl;*/
changeTemplateParameters(savedTemplateParameters);
return;
}
name = parameter->parameter_declaration->declarator->id;
} else {
int tk = decode_token(type_parameter->type);
if (tk != Token_typename && tk != Token_class)
{
/*std::cerr << "** WARNING template declaration not supported ``";
Token const &tk = _M_token_stream->token ((int) node->start_token);
Token const &end_tk = _M_token_stream->token ((int) node->declaration->start_token);
std::cerr << std::string (&tk.text[tk.position], (end_tk.position) - tk.position) << "''"
<< std::endl << std::endl;*/
changeTemplateParameters(savedTemplateParameters);
return;
}
assert(tk == Token_typename || tk == Token_class);
name = type_parameter->name;
}
TemplateParameterModelItem p = model()->create<TemplateParameterModelItem>();
name_cc.run(name);
p->setName(name_cc.name());
_M_current_template_parameters.append(p);
it = it->next;
} while (it != end);
visit(node->declaration);
changeTemplateParameters(savedTemplateParameters);
}
void Binder::visitTypedef(TypedefAST *node)
{
const ListNode<InitDeclaratorAST*> *it = node->init_declarators;
if (it == 0)
return;
it = it->toFront();
const ListNode<InitDeclaratorAST*> *end = it;
do
{
InitDeclaratorAST *init_declarator = it->element;
it = it->next;
Q_ASSERT(init_declarator->declarator != 0);
// the name
decl_cc.run (init_declarator->declarator);
QString alias_name = decl_cc.id ();
if (alias_name.isEmpty ())
{
std::cerr << "** WARNING anonymous typedef not supported! ``";
Token const &tk = _M_token_stream->token ((int) node->start_token);
Token const &end_tk = _M_token_stream->token ((int) node->end_token);
std::cerr << std::string (&tk.text[tk.position], end_tk.position - tk.position) << "''"
<< std::endl << std::endl;
continue;
}
// build the type
TypeInfo typeInfo = CompilerUtils::typeDescription (node->type_specifier,
init_declarator->declarator,
this);
DeclaratorAST *decl = init_declarator->declarator;
while (decl && decl->sub_declarator)
decl = decl->sub_declarator;
if (decl != init_declarator->declarator
&& init_declarator->declarator->parameter_declaration_clause != 0)
{
typeInfo.setFunctionPointer (true);
decl_cc.run (init_declarator->declarator);
foreach (DeclaratorCompiler::Parameter p, decl_cc.parameters())
typeInfo.addArgument(p.type);
}
ScopeModelItem scope = currentScope();
DeclaratorAST *declarator = init_declarator->declarator;
CodeModelFinder finder(model(), this);
ScopeModelItem typedefScope = finder.resolveScope(declarator->id, scope);
TypeAliasModelItem typeAlias = model ()->create<TypeAliasModelItem> ();
updateItemPosition (typeAlias->toItem (), node);
typeAlias->setName (alias_name);
typeAlias->setType (qualifyType (typeInfo, currentScope ()->qualifiedName ()));
typeAlias->setScope (typedefScope->qualifiedName());
_M_qualified_types[typeAlias->qualifiedName().join(".")] = QString();
currentScope ()->addTypeAlias (typeAlias);
}
while (it != end);
}
void Binder::visitNamespace(NamespaceAST *node)
{
bool anonymous = (node->namespace_name == 0);
ScopeModelItem scope = currentScope();
NamespaceModelItem old;
if (! anonymous)
{
QString name = decode_symbol(node->namespace_name)->as_string();
QStringList qualified_name = scope->qualifiedName();
qualified_name += name;
NamespaceModelItem ns =
model_safe_cast<NamespaceModelItem>(_M_model->findItem(qualified_name,
_M_current_file->toItem()));
if (!ns)
{
ns = _M_model->create<NamespaceModelItem>();
updateItemPosition (ns->toItem(), node);
ns->setName(name);
ns->setScope(scope->qualifiedName());
}
old = changeCurrentNamespace(ns);
_M_context.append(name);
}
DefaultVisitor::visitNamespace(node);
if (! anonymous)
{
Q_ASSERT(scope->kind() == _CodeModelItem::Kind_Namespace
|| scope->kind() == _CodeModelItem::Kind_File);
_M_context.removeLast();
if (NamespaceModelItem ns = model_static_cast<NamespaceModelItem>(scope))
{
ns->addNamespace(_M_current_namespace);
}
changeCurrentNamespace(old);
}
}
void Binder::visitForwardDeclarationSpecifier(ForwardDeclarationSpecifierAST *node)
{
name_cc.run(node->name);
if (name_cc.name().isEmpty())
return;
ScopeModelItem scope = currentScope();
_M_qualified_types[(scope->qualifiedName() + name_cc.qualifiedName()).join(".") ] = QString();
}
void Binder::visitClassSpecifier(ClassSpecifierAST *node)
{
ClassCompiler class_cc(this);
class_cc.run(node);
if (class_cc.name().isEmpty())
{
// anonymous not supported
return;
}
Q_ASSERT(node->name != 0 && node->name->unqualified_name != 0);
ScopeModelItem scope = currentScope();
ClassModelItem old = changeCurrentClass(_M_model->create<ClassModelItem>());
updateItemPosition (_M_current_class->toItem(), node);
_M_current_class->setName(class_cc.name());
QStringList baseClasses = class_cc.baseClasses(); TypeInfo info;
for (int i=0; i<baseClasses.size(); ++i)
{
info.setQualifiedName(baseClasses.at(i).split("::"));
baseClasses[i] = qualifyType(info, scope->qualifiedName()).qualifiedName().join("::");
}
_M_current_class->setBaseClasses(baseClasses);
_M_current_class->setClassType(decode_class_type(node->class_key));
_M_current_class->setTemplateParameters(_M_current_template_parameters);
if (! _M_current_template_parameters.isEmpty())
{
QString name = _M_current_class->name();
name += "<";
for (int i = 0; i<_M_current_template_parameters.size(); ++i)
{
if (i != 0)
name += ",";
name += _M_current_template_parameters.at(i)->name();
}
name += ">";
_M_current_class->setName(name);
}
CodeModel::AccessPolicy oldAccessPolicy = changeCurrentAccess(decode_access_policy(node->class_key));
CodeModel::FunctionType oldFunctionType = changeCurrentFunctionType(CodeModel::Normal);
_M_current_class->setScope(scope->qualifiedName());
_M_qualified_types[_M_current_class->qualifiedName().join(".")] = QString();
scope->addClass(_M_current_class);
name_cc.run(node->name->unqualified_name);
_M_context.append(name_cc.name());
visitNodes(this, node->member_specs);
_M_context.removeLast();
changeCurrentClass(old);
changeCurrentAccess(oldAccessPolicy);
changeCurrentFunctionType(oldFunctionType);
}
void Binder::visitLinkageSpecification(LinkageSpecificationAST *node)
{
DefaultVisitor::visitLinkageSpecification(node);
}
void Binder::visitUsing(UsingAST *node)
{
DefaultVisitor::visitUsing(node);
}
void Binder::visitEnumSpecifier(EnumSpecifierAST *node)
{
CodeModelFinder finder(model(), this);
ScopeModelItem scope = currentScope();
ScopeModelItem enumScope = finder.resolveScope(node->name, scope);
name_cc.run(node->name);
QString name = name_cc.name();
if (name.isEmpty())
{
// anonymous enum
QString key = _M_context.join("::");
int current = ++_M_anonymous_enums[key];
name += QLatin1String("enum_");
name += QString::number(current);
}
_M_current_enum = model()->create<EnumModelItem>();
_M_current_enum->setAccessPolicy(_M_current_access);
updateItemPosition (_M_current_enum->toItem(), node);
_M_current_enum->setName(name);
_M_current_enum->setScope(enumScope->qualifiedName());
_M_qualified_types[_M_current_enum->qualifiedName().join(".")] = QString();
enumScope->addEnum(_M_current_enum);
DefaultVisitor::visitEnumSpecifier(node);
_M_current_enum = 0;
}
static QString strip_preprocessor_lines(const QString &name)
{
QStringList lst = name.split("\n");
QString s;
for (int i=0; i<lst.size(); ++i) {
if (!lst.at(i).startsWith('#'))
s += lst.at(i);
}
return s.trimmed();
}
void Binder::visitEnumerator(EnumeratorAST *node)
{
Q_ASSERT(_M_current_enum != 0);
EnumeratorModelItem e = model()->create<EnumeratorModelItem>();
updateItemPosition (e->toItem(), node);
e->setName(decode_symbol(node->id)->as_string());
if (ExpressionAST *expr = node->expression)
{
const Token &start_token = _M_token_stream->token((int) expr->start_token);
const Token &end_token = _M_token_stream->token((int) expr->end_token);
e->setValue(strip_preprocessor_lines(QString::fromUtf8(&start_token.text[start_token.position],
(int) (end_token.position - start_token.position)).trimmed()).remove(' '));
}
_M_current_enum->addEnumerator(e);
}
void Binder::visitUsingDirective(UsingDirectiveAST *node)
{
DefaultVisitor::visitUsingDirective(node);
}
void Binder::visitQEnums(QEnumsAST *node)
{
const Token &start = _M_token_stream->token((int) node->start_token);
const Token &end = _M_token_stream->token((int) node->end_token);
QStringList enum_list = QString::fromLatin1(start.text + start.position,
end.position - start.position).split(' ');
ScopeModelItem scope = currentScope();
for (int i=0; i<enum_list.size(); ++i)
scope->addEnumsDeclaration(enum_list.at(i));
}
void Binder::visitQProperty(QPropertyAST *node)
{
const Token &start = _M_token_stream->token((int) node->start_token);
const Token &end = _M_token_stream->token((int) node->end_token);
QString property = QString::fromLatin1(start.text + start.position,
end.position - start.position);
_M_current_class->addPropertyDeclaration(property);
}
void Binder::applyStorageSpecifiers(const ListNode<std::size_t> *it, MemberModelItem item)
{
if (it == 0)
return;
it = it->toFront();
const ListNode<std::size_t> *end = it;
do
{
switch (decode_token(it->element))
{
default:
break;
case Token_friend:
item->setFriend(true);
break;
case Token_auto:
item->setAuto(true);
break;
case Token_register:
item->setRegister(true);
break;
case Token_static:
item->setStatic(true);
break;
case Token_extern:
item->setExtern(true);
break;
case Token_mutable:
item->setMutable(true);
break;
}
it = it->next;
}
while (it != end);
}
void Binder::applyFunctionSpecifiers(const ListNode<std::size_t> *it, FunctionModelItem item)
{
if (it == 0)
return;
it = it->toFront();
const ListNode<std::size_t> *end = it;
do
{
switch (decode_token(it->element))
{
default:
break;
case Token_inline:
item->setInline(true);
break;
case Token_virtual:
item->setVirtual(true);
break;
case Token_explicit:
item->setExplicit(true);
break;
case Token_Q_INVOKABLE:
item->setInvokable(true);
break;
}
it = it->next;
}
while (it != end);
}
TypeInfo Binder::qualifyType(const TypeInfo &type, const QStringList &context) const
{
// ### Potentially improve to use string list in the name table to
if (context.size() == 0)
{
// ### We can assume that this means global namespace for now...
return type;
}
else if (_M_qualified_types.contains(type.qualifiedName().join(".")))
{
return type;
}
else
{
QStringList expanded = context;
expanded << type.qualifiedName();
if (_M_qualified_types.contains(expanded.join(".")))
{
TypeInfo modified_type = type;
modified_type.setQualifiedName(expanded);
return modified_type;
}
else
{
CodeModelItem scope = model ()->findItem (context, _M_current_file->toItem ());
if (ClassModelItem klass = model_dynamic_cast<ClassModelItem> (scope))
{
foreach (QString base, klass->baseClasses ())
{
QStringList ctx = context;
ctx.removeLast();
ctx.append (base);
TypeInfo qualified = qualifyType (type, ctx);
if (qualified != type)
return qualified;
}
}
QStringList copy = context;
copy.removeLast();
return qualifyType(type, copy);
}
}
}
void Binder::updateItemPosition(CodeModelItem item, AST *node)
{
QString filename;
int line, column;
assert (node != 0);
_M_location.positionAt (_M_token_stream->position(node->start_token), &line, &column, &filename);
item->setFileName (filename);
}
// kate: space-indent on; indent-width 2; replace-tabs on;