~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to tools/porting/src/semantic.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2004-2005 Trolltech AS. All rights reserved.
 
4
** Copyright (C) 2001-2004 Roberto Raggi
 
5
**
 
6
** This file is part of the porting application of the Qt Toolkit.
 
7
**
 
8
** This file may be distributed under the terms of the Q Public License
 
9
** as defined by Trolltech AS of Norway and appearing in the file
 
10
** LICENSE.QPL included in the packaging of this file.
 
11
**
 
12
** This file may be distributed and/or modified under the terms of the
 
13
** GNU General Public License version 2 as published by the Free Software
 
14
** Foundation and appearing in the file LICENSE.GPL included in the
 
15
** packaging of this file.
 
16
**
 
17
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
18
**   information about Qt Commercial License Agreements.
 
19
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
20
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
21
**
 
22
** Contact info@trolltech.com if any conditions of this licensing are
 
23
** not clear to you.
 
24
**
 
25
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
26
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
27
**
 
28
****************************************************************************/
 
29
#include "semantic.h"
 
30
#include <QDebug>
 
31
#include <QString>
 
32
#include <QRegExp>
 
33
 
 
34
#include "smallobject.h"
 
35
#include "tokenengine.h"
 
36
 
 
37
using namespace TokenStreamAdapter;
 
38
using namespace TokenEngine;
 
39
using namespace CodeModel;
 
40
using namespace std;
 
41
 
 
42
Semantic::Semantic(CodeModel::NamespaceScope *globalScope,
 
43
                   TokenStreamAdapter::TokenStream *tokenStream,
 
44
                   TypedPool<CodeModel::Item> *storage)
 
45
{
 
46
    m_storage = storage;
 
47
    m_tokenStream = tokenStream;
 
48
 
 
49
    m_currentAccess = CodeModel::Member::Public;
 
50
    m_inSlots = false;
 
51
    m_inSignals = false;
 
52
    m_inStorageSpec = false;
 
53
    m_inTypedef = false;
 
54
 
 
55
    globalScope->setName("::");
 
56
    currentScope.push(globalScope);
 
57
 
 
58
    //create global UnknownType and UnknownTypeMember
 
59
    UnknownType *type = Create<UnknownType>(m_storage);
 
60
    type->setName("__UnknownType");
 
61
    globalScope->addType(type);
 
62
    type->setParent(globalScope);
 
63
 
 
64
    m_sharedUnknownMember = Create<TypeMember>(m_storage);
 
65
    m_sharedUnknownMember->setNameToken(TokenRef());
 
66
    m_sharedUnknownMember->setName("Unknown");
 
67
    m_sharedUnknownMember->setType(type);
 
68
    globalScope->addMember(m_sharedUnknownMember);
 
69
    m_sharedUnknownMember->setParent(globalScope);
 
70
 
 
71
}
 
72
 
 
73
void Semantic::parseAST(TranslationUnitAST *node)
 
74
{
 
75
    TreeWalker::parseTranslationUnit(node);
 
76
}
 
77
 
 
78
 
 
79
void Semantic::parseLinkageSpecification(LinkageSpecificationAST *ast)
 
80
{
 
81
    if(!ast)
 
82
        return;
 
83
    int inStorageSpec = m_inStorageSpec;
 
84
    m_inStorageSpec = true;
 
85
    TreeWalker::parseLinkageSpecification(ast);
 
86
    m_inStorageSpec = inStorageSpec;
 
87
}
 
88
 
 
89
void Semantic::parseNamespace(NamespaceAST *ast)
 
90
{
 
91
    CodeModel::NamespaceScope *parent = currentScope.top()->toNamespaceScope();
 
92
    if(!parent->toNamespaceScope()) {
 
93
        emit error("Error in Semantic::parseNamespace: parent scope was not a namespace");
 
94
        return;
 
95
    }
 
96
 
 
97
    QByteArray nsName;
 
98
    if (!ast->namespaceName() || textOf(ast->namespaceName()).isEmpty()){
 
99
        nsName = "(__QT_ANON_NAMESPACE)";
 
100
    } else {
 
101
        nsName = textOf(ast->namespaceName());
 
102
    }
 
103
 
 
104
    CodeModel::NamespaceScope *namespaceScope = 0;
 
105
 
 
106
    // Look up namespace scope in case it is already defined.
 
107
    // (Unlike classes, C++ namespaces are "open" and can be added to.)
 
108
    CodeModel::Scope *scope = parent->scopes().value(nsName);
 
109
    if (scope)
 
110
        namespaceScope = scope->toNamespaceScope();
 
111
 
 
112
    // Create new namespace if not found.
 
113
    if (!namespaceScope) {
 
114
        namespaceScope = CodeModel::Create<CodeModel::NamespaceScope>(m_storage);
 
115
        namespaceScope->setName(nsName);
 
116
        parent->addScope(namespaceScope);
 
117
 
 
118
        NamespaceMember *namespaceMember = Create<NamespaceMember>(m_storage);
 
119
        namespaceMember->setNameToken(tokenRefFromAST(ast->namespaceName()));
 
120
        namespaceMember->setName(nsName);
 
121
        namespaceMember->setNamespaceScope(namespaceScope);
 
122
        currentScope.top()->addMember(namespaceMember);
 
123
        namespaceMember->setParent(currentScope.top());
 
124
    }
 
125
 
 
126
    currentScope.push(namespaceScope);
 
127
    TreeWalker::parseNamespace(ast);
 
128
    currentScope.pop();
 
129
}
 
130
 
 
131
void Semantic::parseClassSpecifier(ClassSpecifierAST *ast)
 
132
{
 
133
    if (!ast->name()){
 
134
        return;
 
135
    }
 
136
 
 
137
    QByteArray kind = textOf(ast->classKey());
 
138
    if (kind == "class")
 
139
        m_currentAccess = CodeModel::Member::Private;
 
140
    else // kind =="struct"
 
141
        m_currentAccess = CodeModel::Member::Public;
 
142
 
 
143
    QByteArray className = textOf(ast->name()->unqualifiedName());
 
144
 
 
145
    //create ClassScope
 
146
    CodeModel::ClassScope *klass = CodeModel::Create<CodeModel::ClassScope>(m_storage);
 
147
    klass->setName(className);
 
148
    currentScope.top()->addScope(klass);
 
149
 
 
150
    //create ClassType
 
151
    CodeModel::ClassType *type = CodeModel::Create<CodeModel::ClassType>(m_storage);
 
152
    type->setScope(klass);
 
153
    currentScope.top()->addType(type);
 
154
    type->setParent(currentScope.top());
 
155
 
 
156
    //create TypeMember
 
157
    CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
 
158
    typeMember->setNameToken(tokenRefFromAST(ast->name()->unqualifiedName()));
 
159
    typeMember->setName(className);
 
160
    typeMember->setType(type);
 
161
    currentScope.top()->addMember(typeMember);
 
162
    typeMember->setParent(currentScope.top());
 
163
 
 
164
    currentScope.push(klass);
 
165
    if (ast->baseClause())
 
166
        parseBaseClause(ast->baseClause(), klass);
 
167
 
 
168
    //TreeWalker::parseClassSpecifier(ast);
 
169
    parseNode(ast->winDeclSpec());
 
170
    parseNode(ast->classKey());
 
171
    parseNode(ast->baseClause());
 
172
 
 
173
    // Here's the trick for parsing c++ classes:
 
174
    // All inline function definitions must be interpreted as if they were
 
175
    // written after any other declarations in the class.
 
176
    QList<DeclarationAST *> functionDefinitions;
 
177
    if (ast->declarationList())
 
178
        foreach(DeclarationAST *decl, *ast->declarationList()) {
 
179
            if(decl->nodeType() == NodeType_FunctionDefinition)
 
180
                functionDefinitions.append(decl);
 
181
            else
 
182
            parseNode(decl);
 
183
        }
 
184
    foreach(DeclarationAST *decl, functionDefinitions)
 
185
        parseNode(decl);
 
186
 
 
187
    currentScope.pop();
 
188
}
 
189
/*
 
190
    Parse a class, struct or enum forward decalration.
 
191
*/
 
192
void Semantic::parseElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node)
 
193
{
 
194
    if (!node)
 
195
        return;
 
196
    AST *kind = node->kind();
 
197
    if (!kind)
 
198
        return;
 
199
 
 
200
    const QByteArray kindText = textOf(kind);
 
201
    const QByteArray nameText = textOf(node->name());
 
202
 
 
203
    if (kindText == "class" || kindText == "struct") {
 
204
        // Create ClassType.
 
205
        CodeModel::ClassType *type = CodeModel::Create<CodeModel::ClassType>(m_storage);
 
206
        type->setScope(0);
 
207
        currentScope.top()->addType(type);
 
208
        type->setParent(currentScope.top());
 
209
 
 
210
        // Create TypeMember.
 
211
        CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
 
212
        typeMember->setNameToken(tokenRefFromAST(node->name()->unqualifiedName()));
 
213
        typeMember->setName(nameText);
 
214
        typeMember->setType(type);
 
215
        currentScope.top()->addMember(typeMember);
 
216
        typeMember->setParent(currentScope.top());
 
217
    } else if (kindText == "enum") {
 
218
        //create a Type
 
219
        CodeModel::EnumType *enumType = CodeModel::Create<CodeModel::EnumType>(m_storage);
 
220
        enumType->setName(nameText);
 
221
        currentScope.top()->addType(enumType);
 
222
        enumType->setParent(currentScope.top());
 
223
 
 
224
        //create a TypeMember
 
225
        CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
 
226
        if(node->name())
 
227
            typeMember->setNameToken(tokenRefFromAST(node->name()->unqualifiedName()));
 
228
        typeMember->setName(nameText);
 
229
        typeMember->setType(enumType);
 
230
        currentScope.top()->addMember(typeMember);
 
231
        typeMember->setParent(currentScope.top());
 
232
    }
 
233
}
 
234
 
 
235
void Semantic::parseSimpleDeclaration(SimpleDeclarationAST *ast)
 
236
{
 
237
    TypeSpecifierAST *typeSpec = ast->typeSpec();
 
238
    InitDeclaratorListAST *declarators = ast->initDeclaratorList();
 
239
 
 
240
    if (typeSpec)
 
241
        parseTypeSpecifier(typeSpec);
 
242
 
 
243
    if (declarators){
 
244
        List<InitDeclaratorAST*> l = *declarators->initDeclaratorList();
 
245
 
 
246
        foreach (InitDeclaratorAST *current, l) {
 
247
            parseDeclaration(ast->functionSpecifier(), ast->storageSpecifier(), typeSpec, current);
 
248
        }
 
249
    }
 
250
}
 
251
 
 
252
void Semantic::parseDeclaration(AST *funSpec, AST *storageSpec, TypeSpecifierAST *typeSpec, InitDeclaratorAST *decl)
 
253
{
 
254
    if (m_inStorageSpec)
 
255
            return;
 
256
 
 
257
    if(!decl)
 
258
        return;
 
259
 
 
260
    DeclaratorAST *d = decl->declarator();
 
261
    if (!d)
 
262
        return;
 
263
 
 
264
    if (!d->subDeclarator() && d->parameterDeclarationClause()) {
 
265
        parseFunctionDeclaration(funSpec, storageSpec, typeSpec, decl);
 
266
                return;
 
267
        }
 
268
    if(!typeSpec || !typeSpec->name())
 
269
        return;
 
270
 
 
271
    DeclaratorAST *t = d;
 
272
    while (t && t->subDeclarator())
 
273
        t = t->subDeclarator();
 
274
 
 
275
    QByteArray id;
 
276
    if (t && t->declaratorId() && t->declaratorId()->unqualifiedName())
 
277
        id = textOf(t->declaratorId()->unqualifiedName());
 
278
 
 
279
    if (!t || !t->declaratorId() || !t->declaratorId()->unqualifiedName())
 
280
        return;
 
281
    AST *nameAST = t->declaratorId()->unqualifiedName();
 
282
    QByteArray name = textOf(nameAST);
 
283
 
 
284
 
 
285
    if (!scopeOfDeclarator(d, QList<QByteArray>()).isEmpty()){
 
286
        return;
 
287
    }
 
288
 
 
289
    //create VariableMember
 
290
    CodeModel::VariableMember *variableMember = CodeModel::Create<CodeModel::VariableMember>(m_storage);
 
291
    variableMember->setNameToken(tokenRefFromAST(nameAST));
 
292
    variableMember->setName(name);
 
293
    variableMember->setAccess(m_currentAccess);
 
294
    variableMember->setParent(currentScope.top());
 
295
    currentScope.top()->addMember(variableMember);
 
296
 
 
297
    //look up type of variableMember,
 
298
 
 
299
    TypeMember *typeMember = typeLookup(currentScope.top(), typeSpec->name());
 
300
    if(typeMember) {
 
301
        variableMember->setType(typeMember->type());
 
302
    } else {
 
303
        QByteArray text = typeOfDeclaration(typeSpec, d);
 
304
        CodeModel::UnknownType *type = CodeModel::Create<CodeModel::UnknownType>(m_storage);
 
305
        type->setName(text);
 
306
        variableMember->setType(type);
 
307
    }
 
308
 
 
309
    if (decl)
 
310
        parseNode(decl->initializer());
 
311
 
 
312
}
 
313
 
 
314
void Semantic::parseFunctionDeclaration(AST *funSpec, AST *storageSpec,
 
315
                                        TypeSpecifierAST * typeSpec, InitDeclaratorAST * initDeclarator)
 
316
{
 
317
    bool isFriend = false;
 
318
    bool isVirtual = false;
 
319
    bool isStatic = false;
 
320
    bool isInline = false;
 
321
    bool isPure = initDeclarator->initializer() != 0;
 
322
 
 
323
    if (funSpec){
 
324
        List<AST*> l = *funSpec->children();
 
325
        foreach (AST *current, l) {
 
326
            QByteArray text = textOf(current);
 
327
            if (text == "virtual") isVirtual = true;
 
328
            else if (text == "inline") isInline = true;
 
329
        }
 
330
    }
 
331
 
 
332
    if (storageSpec){
 
333
        List<AST*> l = *storageSpec->children();
 
334
        foreach (AST *current, l) {
 
335
            QByteArray text = textOf(current);
 
336
            if (text == "friend") isFriend = true;
 
337
            else if (text == "static") isStatic = true;
 
338
        }
 
339
    }
 
340
    DeclaratorAST *declarator = initDeclarator->declarator();
 
341
    if(!declarator || !declarator->declaratorId())
 
342
        return;
 
343
    AST *nameAST = declarator->declaratorId()->unqualifiedName();
 
344
    QByteArray name = textOf(nameAST);
 
345
 
 
346
    CodeModel::FunctionMember *method = CodeModel::Create<CodeModel::FunctionMember>(m_storage);
 
347
    method->setNameToken(tokenRefFromAST(nameAST));
 
348
    method->setName(name);
 
349
    method->setAccess(m_currentAccess);
 
350
    method->setStatic(isStatic);
 
351
    method->setVirtual(isVirtual);
 
352
    method->setAbstract(isPure);
 
353
 
 
354
    parseFunctionArguments(declarator, method);
 
355
 
 
356
    if (m_inSignals)
 
357
        method->setSignal(true);
 
358
 
 
359
    if (m_inSlots)
 
360
        method->setSlot(true);
 
361
 
 
362
    method->setConstant(declarator->constant() != 0);
 
363
 
 
364
    QByteArray text = typeOfDeclaration(typeSpec, declarator);
 
365
    if (!text.isEmpty()) {
 
366
        CodeModel::UnknownType *type = CodeModel::Create<CodeModel::UnknownType>(m_storage);
 
367
        type->setName(text);
 
368
        method->setReturnType(type);
 
369
    }
 
370
 
 
371
    method->setParent(currentScope.top());
 
372
    currentScope.top()->addMember(method);
 
373
}
 
374
 
 
375
 
 
376
void Semantic::parseBaseClause(BaseClauseAST * baseClause, CodeModel::ClassScope *klass)
 
377
{
 
378
    if(!baseClause)
 
379
        return;
 
380
    if(!klass)
 
381
        return;
 
382
    List<BaseSpecifierAST*> *l = baseClause->baseSpecifierList();
 
383
    if (!l)
 
384
        return;
 
385
    foreach (BaseSpecifierAST *baseSpecifier, *l) {
 
386
        QByteArray baseName;
 
387
        if (!baseSpecifier->name())
 
388
            continue;
 
389
 
 
390
        // Look up a class with the correct name.
 
391
        QList<Member *> candidates = nameLookup(klass, baseSpecifier->name());
 
392
        if (candidates.count() == 1 ) {
 
393
            Member *member = candidates.at(0);
 
394
            Q_ASSERT(member);
 
395
            TypeMember *typeMember = member->toTypeMember();
 
396
            if (typeMember) {
 
397
                Q_ASSERT(typeMember->type());
 
398
                ClassType *classType = typeMember->type()->toClassType();
 
399
                if (classType) {
 
400
                    klass->addBaseClass(classType);
 
401
                }
 
402
            }
 
403
        }
 
404
    }
 
405
}
 
406
void Semantic::parseFunctionArguments(const DeclaratorAST *declarator, CodeModel::FunctionMember *method)
 
407
{
 
408
    if(!declarator || !method)
 
409
        return;
 
410
 
 
411
    ParameterDeclarationClauseAST *clause = declarator->parameterDeclarationClause();
 
412
 
 
413
    if (clause && clause->parameterDeclarationList()){
 
414
        ParameterDeclarationListAST *params = clause->parameterDeclarationList();
 
415
        List<ParameterDeclarationAST*> *l = params->parameterList();
 
416
        if (!l)
 
417
            return;
 
418
        foreach (ParameterDeclarationAST *param, *l) {
 
419
            CodeModel::Argument *arg = CodeModel::Create<CodeModel::Argument>(m_storage);
 
420
            arg->setParent(method);
 
421
 
 
422
            if (param->declarator()){
 
423
                QByteArray text = declaratorToString(param->declarator(), QByteArray(), true);
 
424
                if(param->declarator()->declaratorId())
 
425
                    arg->setNameToken(tokenRefFromAST(param->declarator()->declaratorId()->unqualifiedName()));
 
426
                if (!text.isEmpty())
 
427
                    arg->setName(text);
 
428
            }
 
429
 
 
430
            QByteArray tp = typeOfDeclaration(param->typeSpec(), param->declarator());
 
431
            if (!tp.isEmpty()) {
 
432
                CodeModel::UnknownType *type = CodeModel::Create<CodeModel::UnknownType>(m_storage);
 
433
                type->setName(tp);
 
434
                arg->setType(type);
 
435
            }
 
436
 
 
437
            method->addArgument(arg);
 
438
        }
 
439
    }
 
440
}
 
441
 
 
442
// using directive (using namespace A)
 
443
void Semantic::parseUsingDirective(UsingDirectiveAST *ast)
 
444
{
 
445
    QByteArray qualifiedname = textOf(ast->name());
 
446
    QByteArray name = textOf(ast->name()->unqualifiedName());
 
447
 
 
448
    //look up target namespace name
 
449
    QList<Member *> memberList = nameLookup(currentScope.top(), ast->name());
 
450
 
 
451
    NamespaceScope *targetNamespace = 0;
 
452
 
 
453
    // search for namespace in member list.
 
454
    QList<Member *>::ConstIterator it = memberList.constBegin();
 
455
    while(it != memberList.constEnd()) {
 
456
        if (NamespaceMember *namespaceMember = (*it)->toNamespaceMember()) {
 
457
            targetNamespace = namespaceMember->namespaceScope();
 
458
            break;
 
459
        }
 
460
        ++it;
 
461
    }
 
462
 
 
463
    if (targetNamespace == 0)
 
464
        return;
 
465
 
 
466
    // Find the insertion namespace, wich is the first common
 
467
    // ancesotor namespace for the current sope and the insertion namespace
 
468
 
 
469
    // currentScope might be a block scope, find the first namespace parent
 
470
    CodeModel::Scope *currentParent = currentScope.top();
 
471
    while (currentParent->toNamespaceScope() == 0) {
 
472
        currentParent = currentParent->parent();
 
473
    }
 
474
 
 
475
    CodeModel::Scope *namespaceA = currentParent;
 
476
    while (namespaceA != 0) {
 
477
        CodeModel::Scope *namespaceB = targetNamespace;
 
478
        while (namespaceB != 0) {
 
479
            if (namespaceB == namespaceA)
 
480
                break;
 
481
            namespaceB = namespaceB->parent();
 
482
        }
 
483
        if (namespaceB == namespaceA)
 
484
            break;
 
485
        namespaceA = namespaceA->parent();
 
486
    }
 
487
 
 
488
    if (namespaceA == 0 || namespaceA->toNamespaceScope() == 0)
 
489
        return;
 
490
 
 
491
    NamespaceScope *insertionNamespace = namespaceA->toNamespaceScope();
 
492
 
 
493
    // Create using directive link
 
494
    UsingDirectiveLink *usingDirectiveLink = Create<UsingDirectiveLink>(m_storage);
 
495
    usingDirectiveLink->setParent(currentScope.top());
 
496
    usingDirectiveLink->setTargetNamespace(targetNamespace);
 
497
    usingDirectiveLink->setInsertionNamespace(insertionNamespace);
 
498
 
 
499
    // add it to current namespace
 
500
    if (NamespaceScope *namespaceScope = currentScope.top()->toNamespaceScope())
 
501
        namespaceScope->addUsingDirectiveLink(usingDirectiveLink);
 
502
    else if (BlockScope *blockScope = currentScope.top()->toBlockScope())
 
503
        blockScope->addUsingDirectiveLink(usingDirectiveLink);
 
504
}
 
505
 
 
506
void Semantic::parseFunctionDefinition(FunctionDefinitionAST *ast)
 
507
{
 
508
    AST *funSpec = ast->functionSpecifier();
 
509
    AST *storageSpec = ast->storageSpecifier();
 
510
    TypeSpecifierAST *typeSpec = ast->typeSpec();
 
511
    InitDeclaratorAST *initDeclarator = ast->initDeclarator();
 
512
    if (!ast->initDeclarator())
 
513
        return;
 
514
 
 
515
    DeclaratorAST *d = initDeclarator->declarator();
 
516
 
 
517
    if (!d->declaratorId())
 
518
        return;
 
519
 
 
520
 
 
521
    // Check if function already has been declared, if not then this is also a declaration.
 
522
    CodeModel::FunctionMember *method = functionLookup(currentScope.top(), d);
 
523
    if (!method)
 
524
        parseFunctionDeclaration(funSpec, storageSpec, typeSpec, initDeclarator);
 
525
    method = functionLookup(currentScope.top(), d);
 
526
 
 
527
    if(!method) {
 
528
        emit error("Error in Semantic::parseFunctionDefinition: Could not find declaration for function definition");
 
529
        return;
 
530
    }
 
531
 
 
532
    CodeModel::Scope *parent = method->parent();
 
533
 
 
534
    if(!ast->functionBody()) {
 
535
        emit error("Error in Semantic::parseFunctionDefinition: no function body in function definition");
 
536
        return;
 
537
    }
 
538
 
 
539
    //create child function scope
 
540
    QByteArray id = textOf(d->declaratorId()->unqualifiedName());
 
541
    CodeModel::BlockScope *functionScope = CodeModel::Create<CodeModel::BlockScope>(m_storage);
 
542
    functionScope->setName(QByteArray("__QT_ANON_BLOCK_SCOPE(Function: ") + id + QByteArray(")"));
 
543
    functionScope->setParent(parent);
 
544
    method->setFunctionBodyScope(functionScope);
 
545
 
 
546
    //add arguments to child scope
 
547
     ArgumentCollection arguments = method->arguments();
 
548
     ArgumentCollection::ConstIterator it = arguments.constBegin();
 
549
     while(it != arguments.constEnd()) {
 
550
         CodeModel::Argument *argument = *it;
 
551
         CodeModel::VariableMember *variableMember = CodeModel::Create<CodeModel::VariableMember>(m_storage);
 
552
         variableMember->setNameToken(argument->nameToken());
 
553
         variableMember->setType(argument->type());
 
554
         variableMember->setName(argument->name());
 
555
         variableMember->setParent(functionScope);
 
556
         functionScope->addMember(variableMember);
 
557
         ++it;
 
558
     }
 
559
 
 
560
    //push function scope and parse function body
 
561
    currentScope.push(functionScope);
 
562
    parseStatementList(ast->functionBody());
 
563
    currentScope.pop();
 
564
}
 
565
 
 
566
void Semantic::parseStatementList(StatementListAST *statemenList)
 
567
{
 
568
    if(!statemenList)
 
569
        return;
 
570
    CodeModel::BlockScope *blockScope = CodeModel::Create<CodeModel::BlockScope>(m_storage);
 
571
    blockScope->setName("__QT_ANON_BLOCK_SCOPE");
 
572
    blockScope->setParent(currentScope.top());
 
573
    currentScope.top()->addScope(blockScope);
 
574
 
 
575
    currentScope.push(blockScope);
 
576
    TreeWalker::parseStatementList(statemenList);
 
577
    currentScope.pop();
 
578
}
 
579
 
 
580
void Semantic::parseExpression(AbstractExpressionAST* node)
 
581
{
 
582
    if(!node)
 
583
        return;
 
584
    if(node->nodeType() == NodeType_ClassMemberAccess)
 
585
        parseClassMemberAccess(static_cast<ClassMemberAccessAST *>(node));
 
586
    else
 
587
        TreeWalker::parseExpression(node);
 
588
}
 
589
 
 
590
/*
 
591
    Pretty hardwired code for handling class member access of the types:
 
592
    object.member and objectPtr->member.
 
593
 
 
594
    This function creates a name use for object to its declaration, and a
 
595
    name use from member to its declaration in the class.
 
596
*/
 
597
void Semantic::parseClassMemberAccess(ClassMemberAccessAST *node)
 
598
{
 
599
    if(!node)
 
600
        return;
 
601
    parseExpression(node->expression());
 
602
    // Get a name use for the 'object' name.
 
603
    NameUse *nameUse = findNameUse(node->expression());
 
604
    // Since the NameUse refers to an object, its decalaration must be
 
605
    // a ClassType. Get the scope of this class type.
 
606
    if(    nameUse
 
607
        && nameUse->declaration()
 
608
        && nameUse->declaration()->toVariableMember()
 
609
        && nameUse->declaration()->toVariableMember()->type()
 
610
        && nameUse->declaration()->toVariableMember()->type()->toClassType()
 
611
        && nameUse->declaration()->toVariableMember()->type()->toClassType()->scope())   {
 
612
 
 
613
        CodeModel::Scope *scope = nameUse->declaration()->toVariableMember()->type()->toClassType()->scope();
 
614
        QList<CodeModel::Member *> members = lookupNameInScope(scope, node->name());
 
615
            if(members.count() != 0) {
 
616
                createNameUse(members.at(0), node->name());
 
617
                return;
 
618
            }
 
619
    }
 
620
    // Create a NameUse that refers to the global shared unknown type.
 
621
    createNameUse(m_sharedUnknownMember, node->name());
 
622
}
 
623
 
 
624
void Semantic::parseExpressionStatement(ExpressionStatementAST *node)
 
625
{
 
626
    TreeWalker::parseExpressionStatement(node);
 
627
}
 
628
 
 
629
// using declaration (using A::b)
 
630
void Semantic::parseUsing(UsingAST *ast)
 
631
{
 
632
    //CodeModel::Scope *s = lookUpScope(currentScope.top(), ast->name());
 
633
    QList<CodeModel::Member *> members = nameLookup(currentScope.top(), ast->name());
 
634
    if(members.isEmpty()) {
 
635
        emit error("Error in Semantic::parseUsing: could not look up using target");
 
636
        return;
 
637
    }
 
638
    //TODO: handle multiple members (when nameLookup returns a set of overloded functions)
 
639
    CodeModel::Member *member = members[0];
 
640
    CodeModel::Scope *targetScope = member->parent();
 
641
    if(!targetScope) {
 
642
        emit error("Error in Semantic::parseUsing: target has no parent scope");
 
643
        return;
 
644
    }
 
645
 
 
646
    if(!ast->name())
 
647
        return;
 
648
    AST *nameAST = ast->name()->unqualifiedName();
 
649
    if(!nameAST)
 
650
        return;
 
651
    QByteArray name = textOf(nameAST);
 
652
}
 
653
 
 
654
void Semantic::parseEnumSpecifier(EnumSpecifierAST *ast)
 
655
{
 
656
    if (!ast->name())
 
657
         return;
 
658
 
 
659
    QByteArray name = textOf(ast->name());
 
660
 
 
661
    //create a Type
 
662
    CodeModel::EnumType *enumType = CodeModel::Create<CodeModel::EnumType>(m_storage);
 
663
    enumType->setName(name);
 
664
    currentScope.top()->addType(enumType);
 
665
    enumType->setParent(currentScope.top());
 
666
 
 
667
    //create a TypeMember
 
668
    CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
 
669
    if(ast->name())
 
670
        typeMember->setNameToken(tokenRefFromAST(ast->name()->unqualifiedName()));
 
671
    typeMember->setName(name);
 
672
    typeMember->setType(enumType);
 
673
    currentScope.top()->addMember(typeMember);
 
674
    typeMember->setParent(currentScope.top());
 
675
 
 
676
    //parse the eneumerators
 
677
    List<EnumeratorAST*> *list = ast->enumeratorList();
 
678
    if (!list)
 
679
        return;
 
680
    foreach (EnumeratorAST *current, *list) {
 
681
        CodeModel::VariableMember *enumerator = CodeModel::Create<CodeModel::VariableMember>(m_storage);
 
682
        enumerator->setNameToken(tokenRefFromAST(current->id()));
 
683
        enumerator->setName(textOf(current->id()));
 
684
        enumerator->setAccess(m_currentAccess);
 
685
        enumerator->setStatic(true);
 
686
        enumerator->setType(enumType);
 
687
        currentScope.top()->addMember(enumerator);
 
688
        enumerator->setParent(currentScope.top());
 
689
    }
 
690
 
 
691
}
 
692
 
 
693
void Semantic::parseTypedef(TypedefAST *ast)
 
694
{
 
695
    TypeSpecifierAST *typeSpec = ast->typeSpec();
 
696
    InitDeclaratorListAST *declarators = ast->initDeclaratorList();
 
697
 
 
698
    if (typeSpec && declarators){
 
699
        QByteArray typeId;
 
700
 
 
701
        if (typeSpec->name())
 
702
            typeId = textOf(typeSpec->name());
 
703
 
 
704
        List<InitDeclaratorAST*> *l = declarators->initDeclaratorList();
 
705
        if (!l)
 
706
            return;
 
707
        foreach (InitDeclaratorAST *initDecl, *l) {
 
708
            QByteArray type, id;
 
709
            if (initDecl->declarator()){
 
710
               type = typeOfDeclaration(typeSpec, initDecl->declarator());
 
711
 
 
712
               DeclaratorAST *d = initDecl->declarator();
 
713
               while (d->subDeclarator()){
 
714
                   d = d->subDeclarator();
 
715
               }
 
716
 
 
717
               if (d->declaratorId())
 
718
                  id = textOf(d->declaratorId());
 
719
            }
 
720
 
 
721
            //create a type
 
722
            CodeModel::Scope *scope = currentScope.top();
 
723
            CodeModel::AliasType *typeAlias = CodeModel::Create<CodeModel::AliasType>(m_storage);
 
724
            //typeAlias->setName(id);
 
725
            //typeAlias->setParent(scope);
 
726
            scope->addType(typeAlias);
 
727
 
 
728
            //create a TypeMember
 
729
            CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
 
730
            if(typeSpec->name())
 
731
                typeMember->setNameToken(tokenRefFromAST(typeSpec->name()->unqualifiedName()));
 
732
            typeMember->setName(id);
 
733
            typeMember->setType(typeAlias);
 
734
            currentScope.top()->addMember(typeMember);
 
735
            typeMember->setParent(currentScope.top());
 
736
 
 
737
        }
 
738
 
 
739
    }
 
740
}
 
741
 
 
742
void Semantic::parseTypeSpecifier(TypeSpecifierAST *ast)
 
743
{
 
744
    // If this is a classSpecifier or a EnumSpecifier we skip the name lookup,
 
745
    // becuase looking up the name "E" in a class definition like
 
746
    // "class E { ..." makes no sense. (There might be a variable named E
 
747
    // already declared, but that variable is now shadowed by the class type.)
 
748
    if(   ast->nodeType() != NodeType_EnumSpecifier
 
749
       && ast->nodeType() != NodeType_ClassSpecifier
 
750
       && ast->nodeType() != NodeType_ElaboratedTypeSpecifier )
 
751
        parseNameUse(ast->name());
 
752
    TreeWalker::parseTypeSpecifier(ast);
 
753
}
 
754
 
 
755
/*
 
756
    Parses a name: looks up name, creates name use.
 
757
*/
 
758
void Semantic::parseNameUse(NameAST* name)
 
759
{
 
760
    if(!name)
 
761
        return;
 
762
 
 
763
    // Look up name
 
764
    QList<CodeModel::Member *> members = nameLookup(currentScope.top(), name);
 
765
    if(members.isEmpty()) {
 
766
        //cout << "no declaration found for " << textOf(name).constData() << endl;
 
767
        // Create NameUse that refer to a shared UnknownMember
 
768
        createNameUse(m_sharedUnknownMember, name);
 
769
        return;
 
770
    }
 
771
 
 
772
    //TODO: handle multiple members (when nameLookup returns a set of overloaded functions)
 
773
    CodeModel::Member *member = members[0];
 
774
    if(!member->parent()) {
 
775
        emit error("Error in Semantic::parseUsing: target has no parent scope");
 
776
        return;
 
777
    }
 
778
 
 
779
    createNameUse(member, name);
 
780
}
 
781
 
 
782
/*
 
783
    looks up name used in basescope. If name->isGlobal() is true or if classOrNamespaceList()
 
784
    returns a non-emty list, the C++ qualified name lookup rules are used. Otherwise the
 
785
    unquialified name lookup rules are used.  Returns the a list of members that was found,
 
786
    In most cases this list will contain zero or one element, exept in the case of overloaded functions.
 
787
    TODO: Argument-dependent name lookup
 
788
*/
 
789
QList<CodeModel::Member *> Semantic::nameLookup(CodeModel::Scope *baseScope, const NameAST* name)
 
790
{
 
791
    if (name->isGlobal() || (name->classOrNamespaceNameList()
 
792
                              && name->classOrNamespaceNameList()->size()>0 )) {
 
793
        return qualifiedNameLookup(baseScope, name);
 
794
    } else {
 
795
        return unqualifiedNameLookup(baseScope, name);
 
796
    }
 
797
}
 
798
 
 
799
//look up an unqualified name
 
800
QList<CodeModel::Member *> Semantic::unqualifiedNameLookup(CodeModel::Scope *baseScope, const NameAST* name)
 
801
{
 
802
    QList<UsingDirectiveLink *> usingDirectiveLinks;
 
803
    CodeModel::Scope *currentScope = baseScope;
 
804
    QList<CodeModel::Member *>  entities;
 
805
 
 
806
    while (currentScope != 0) {
 
807
        // Add any "using namespace" directive links for the current scope to
 
808
        // usingDirectiveLinks
 
809
        if (NamespaceScope *namespaceScope = currentScope->toNamespaceScope())
 
810
            usingDirectiveLinks += namespaceScope->usingDirectiveLinks();
 
811
        if (BlockScope *blockScope = currentScope->toBlockScope())
 
812
            usingDirectiveLinks += blockScope->usingDirectiveLinks();
 
813
 
 
814
        // Search usingDirectiveLinks for a link where currentScope is the
 
815
        // insertion namespace. If found look up name in the target namespace
 
816
        // for that link.
 
817
        if (NamespaceScope *namespaceScope = currentScope->toNamespaceScope()) {
 
818
            QList<UsingDirectiveLink *>::ConstIterator it = usingDirectiveLinks.constBegin();
 
819
            while (it != usingDirectiveLinks.constEnd()) {
 
820
                if ((*it)->insertionNamespace() == namespaceScope)
 
821
                    entities = lookupNameInScope((*it)->targetNamespace(), name);
 
822
                ++it;
 
823
            }
 
824
        }
 
825
 
 
826
        // Look up names in this scope.
 
827
        entities += lookupNameInScope(currentScope, name);
 
828
        if (!entities.isEmpty())
 
829
            break;
 
830
        currentScope = currentScope->parent();
 
831
    }
 
832
    return entities;
 
833
}
 
834
 
 
835
//look up a qualified name
 
836
QList<CodeModel::Member *> Semantic::qualifiedNameLookup(CodeModel::Scope *baseScope, const NameAST* name)
 
837
{
 
838
    QList<CodeModel::Member *> entities;
 
839
    CodeModel::Scope *currentScope = baseScope;
 
840
 
 
841
    // Check if the global ("::") scope has been specified.
 
842
    if(name->isGlobal()) {
 
843
        while (currentScope->parent())
 
844
            currentScope = currentScope->parent();
 
845
    }
 
846
 
 
847
    while (entities.isEmpty() && currentScope != 0) {
 
848
        CodeModel::Scope *targetScope = scopeLookup(currentScope, name);
 
849
        entities = lookupNameInScope(targetScope, name);
 
850
        currentScope = currentScope->parent();
 
851
    }
 
852
 
 
853
    return entities;
 
854
}
 
855
 
 
856
//looks up a name in a scope, includes base classes if scope is a class scope
 
857
QList<CodeModel::Member *> Semantic::lookupNameInScope(CodeModel::Scope *scope, const NameAST* name)
 
858
{
 
859
    QList<CodeModel::Member *> entities;
 
860
 
 
861
    if(!scope || !name)
 
862
        return entities;
 
863
 
 
864
    QByteArray nameText = textOf(name->unqualifiedName()->name());
 
865
    //look up name in members of current scope
 
866
    const CodeModel::MemberCollection members = scope->members();
 
867
    if (members.contains(nameText))
 
868
        entities.append(members.value(nameText));
 
869
 
 
870
    // if not found, look up name in  base classes (if any)
 
871
    CodeModel::ClassScope *classScope = scope->toClassScope();
 
872
    if (entities.isEmpty() && classScope) {
 
873
        const TypeCollection baseClasses = classScope->baseClasses();
 
874
        TypeCollection::ConstIterator it = baseClasses.constBegin();
 
875
        while (it != baseClasses.constEnd()) {
 
876
            CodeModel::Scope *baseClass = it.value()->toClassType()->scope();
 
877
            if (scope != baseClass)
 
878
                entities += lookupNameInScope(baseClass, name);
 
879
            ++it;
 
880
        }
 
881
 
 
882
        if (entities.count() > 1)
 
883
            emit error("Error in Semantic::lookupNameInScope: name "
 
884
            + nameText + " is ambigous");
 
885
    }
 
886
    return entities;
 
887
}
 
888
 
 
889
/*
 
890
    Resolves the classOrNamespaceNameList part of a NameAST against a base scope.
 
891
*/
 
892
CodeModel::Scope *Semantic::scopeLookup(CodeModel::Scope *baseScope, const NameAST* name)
 
893
{
 
894
    CodeModel::Scope *currentScope = baseScope;
 
895
    const List<ClassOrNamespaceNameAST *> *scopeList = name->classOrNamespaceNameList();
 
896
    // if there is no scope list, then the scope we are looking for is baseScope
 
897
    if (!scopeList)
 
898
        return baseScope;
 
899
 
 
900
    // Check if the global ("::") scope has been specified.
 
901
    if(name->isGlobal()) {
 
902
        while (currentScope->parent())
 
903
            currentScope = currentScope->parent();
 
904
    }
 
905
 
 
906
    while(currentScope != 0) {
 
907
        int nestingCounter = 0;
 
908
        CodeModel::Scope *nestedScope = currentScope;
 
909
        while (nestingCounter < scopeList->count()) {
 
910
            const QByteArray nameText = textOf((*scopeList)[nestingCounter]->name());
 
911
            nestedScope = nestedScope->scopes().value(nameText);
 
912
            if (!nestedScope)
 
913
                break;
 
914
            ++nestingCounter;
 
915
        }
 
916
        if(nestedScope) // found target scope?
 
917
            return nestedScope;
 
918
 
 
919
        currentScope = currentScope->parent(); //look in parent scope
 
920
    }
 
921
 
 
922
    return 0;
 
923
}
 
924
 
 
925
TypeMember *Semantic::typeLookup(CodeModel::Scope *baseScope, const NameAST* name)
 
926
{
 
927
    QList<CodeModel::Member *> memberList = nameLookup(baseScope, name);
 
928
 
 
929
    foreach(Member *member, memberList) {
 
930
        if(TypeMember *typeMember = member->toTypeMember())
 
931
            return typeMember;
 
932
    }
 
933
    return 0;
 
934
}
 
935
 
 
936
FunctionMember *Semantic::functionLookup(CodeModel::Scope *baseScope,
 
937
                                          const DeclaratorAST *functionDeclarator)
 
938
{
 
939
 
 
940
    QList<CodeModel::Member*> candidateList =
 
941
                nameLookup(baseScope, functionDeclarator->declaratorId());
 
942
    return selectFunction(candidateList, functionDeclarator);
 
943
}
 
944
 
 
945
/*
 
946
    This is a simplified function lookup routine, for matching member function
 
947
    definitions with member function declarations. It does not implement
 
948
    the general C++ function overload resolution rules.
 
949
*/
 
950
FunctionMember *Semantic::selectFunction(QList<CodeModel::Member*> candidatateList, const DeclaratorAST *functionDeclarator)
 
951
{
 
952
    // get arguments for funciton we are looking for
 
953
    FunctionMember testFunction;
 
954
    parseFunctionArguments(functionDeclarator, &testFunction);
 
955
    const ArgumentCollection testArgumentCollection = testFunction.arguments();
 
956
 
 
957
    //test againts functions in overload list.
 
958
    foreach(Member* member, candidatateList) {
 
959
        FunctionMember *function = member->toFunctionMember();
 
960
        if (!function)
 
961
            continue;
 
962
        const ArgumentCollection argumentCollection = function->arguments();
 
963
 
 
964
        //test argument types and number of arguments
 
965
        ArgumentCollection::ConstIterator arg1 = argumentCollection.constBegin();
 
966
        ArgumentCollection::ConstIterator arg2 = testArgumentCollection.constBegin();
 
967
        bool match = true;
 
968
        while(arg1 != argumentCollection.constEnd() && arg2 != testArgumentCollection.constEnd()) {
 
969
            if( arg1.value()->type()->name() != arg2.value()->type()->name() ) {
 
970
                match = false;
 
971
                break;
 
972
            }
 
973
            ++arg1;
 
974
            ++arg2;
 
975
        }
 
976
        if(match)
 
977
            return function;
 
978
    }
 
979
    return 0;
 
980
}
 
981
 
 
982
QByteArray Semantic::typeOfDeclaration(TypeSpecifierAST *typeSpec, DeclaratorAST *declarator)
 
983
{
 
984
    if (!typeSpec)
 
985
        return QByteArray();
 
986
 
 
987
    QByteArray text;
 
988
 
 
989
    if (typeSpec->cvQualify()) {
 
990
        List<AST*> cv = *typeSpec->cvQualify()->children();
 
991
        foreach (AST *current, cv) {
 
992
            text += " " + textOf(current);
 
993
        }
 
994
        text += " ";
 
995
    }
 
996
 
 
997
 
 
998
    text += textOf(typeSpec);
 
999
 
 
1000
    if (typeSpec->cv2Qualify()) {
 
1001
        List<AST*> cv = *typeSpec->cv2Qualify()->children();
 
1002
        foreach (AST *current, cv) {
 
1003
            text += textOf(current) + " ";
 
1004
        }
 
1005
    }
 
1006
 
 
1007
    if (declarator && declarator->ptrOpList()) {
 
1008
        List<AST*> ptrOpList = *declarator->ptrOpList();
 
1009
        foreach (AST *current, ptrOpList) {
 
1010
            text += " " + textOf(current);
 
1011
        }
 
1012
        text += " ";
 
1013
    }
 
1014
 
 
1015
    return text.trimmed().simplified();
 
1016
}
 
1017
 
 
1018
 
 
1019
 
 
1020
QList<QByteArray> Semantic::scopeOfName(NameAST *id, const QList<QByteArray>& startScope)
 
1021
{
 
1022
    QList<QByteArray> scope = startScope;
 
1023
    if (id && id->classOrNamespaceNameList()){
 
1024
        if (id->isGlobal())
 
1025
            scope.clear();
 
1026
 
 
1027
        List<ClassOrNamespaceNameAST*> l = *id->classOrNamespaceNameList();
 
1028
        foreach (ClassOrNamespaceNameAST *current, l) {
 
1029
            if (current->name())
 
1030
               scope << textOf(current->name());
 
1031
        }
 
1032
    }
 
1033
 
 
1034
    return scope;
 
1035
}
 
1036
 
 
1037
QList<QByteArray> Semantic::scopeOfDeclarator(DeclaratorAST *d, const QList<QByteArray>& startScope)
 
1038
{
 
1039
    if(!d)
 
1040
        return QList<QByteArray>();
 
1041
    return scopeOfName(d->declaratorId(), startScope);
 
1042
}
 
1043
 
 
1044
QByteArray Semantic::typeSpecToString(TypeSpecifierAST* typeSpec)
 
1045
{
 
1046
    if (!typeSpec)
 
1047
        return QByteArray();
 
1048
 
 
1049
    QByteArray tp;
 
1050
    if (typeSpec->cvQualify()) {
 
1051
        tp += "const ";
 
1052
    }
 
1053
 
 
1054
    tp += (QString(textOf(typeSpec)).replace(QRegExp(" :: "), QString::fromUtf8("::"))).toLatin1();
 
1055
    return tp;
 
1056
}
 
1057
 
 
1058
QByteArray Semantic::declaratorToString(DeclaratorAST* declarator, const QByteArray& scope, bool skipPtrOp)
 
1059
{
 
1060
    if (!declarator)
 
1061
        return QByteArray();
 
1062
 
 
1063
    QByteArray text;
 
1064
 
 
1065
    if (!skipPtrOp && declarator->ptrOpList()){
 
1066
        List<AST*> ptrOpList = *declarator->ptrOpList();
 
1067
        foreach (AST *current, ptrOpList) {
 
1068
            text += textOf(current);
 
1069
        }
 
1070
        text += " ";
 
1071
    }
 
1072
 
 
1073
    text += scope;
 
1074
 
 
1075
    if (declarator->subDeclarator())
 
1076
        text += "(" + declaratorToString(declarator->subDeclarator()) + ")";
 
1077
 
 
1078
    if (declarator->declaratorId())
 
1079
        text += textOf(declarator->declaratorId());
 
1080
 
 
1081
    if (declarator->arrayDimensionList()) {
 
1082
        List<AST*> arrays = *declarator->arrayDimensionList();
 
1083
        foreach (AST *current, arrays) {
 
1084
            current=current;    //silence unused symbol warning
 
1085
            text += "[]";
 
1086
        }
 
1087
    }
 
1088
 
 
1089
    if (declarator->parameterDeclarationClause()){
 
1090
        text += "(";
 
1091
 
 
1092
        ParameterDeclarationListAST* l = declarator->parameterDeclarationClause()->parameterDeclarationList();
 
1093
        if (l != 0){
 
1094
            List<ParameterDeclarationAST*> params = *l->parameterList();
 
1095
            foreach (ParameterDeclarationAST *current, params) {
 
1096
                QByteArray type = typeSpecToString(current->typeSpec());
 
1097
                text += type;
 
1098
                if (!type.isEmpty())
 
1099
                    text += " ";
 
1100
                text += declaratorToString(current->declarator());
 
1101
 
 
1102
                // ### FIXME if (it.current())
 
1103
                    text += ", ";
 
1104
            }
 
1105
        }
 
1106
 
 
1107
        text += ")";
 
1108
 
 
1109
        if (declarator->constant() != 0)
 
1110
            text += " const";
 
1111
    }
 
1112
 
 
1113
    return QString(text).replace(QRegExp(" :: "), "::").simplified().toLatin1();
 
1114
}
 
1115
 
 
1116
QByteArray Semantic::textOf(const AST *node) const
 
1117
{
 
1118
    if (!node)
 
1119
        return QByteArray();
 
1120
    QByteArray text;
 
1121
    for (int i = node->startToken(); i < node->endToken(); ++i) {
 
1122
        if (!m_tokenStream->isHidden(i)) {
 
1123
            if (i != node->startToken())
 
1124
                text += " ";
 
1125
            text += m_tokenStream->tokenText(i);
 
1126
        }
 
1127
    }
 
1128
    return text;
 
1129
}
 
1130
 
 
1131
void Semantic::createNameUse(Member *member, NameAST *name)
 
1132
{
 
1133
    AST *unqualifedName = name->unqualifiedName()->name();
 
1134
 
 
1135
    if(!unqualifedName || !member || !name)
 
1136
        return;
 
1137
 
 
1138
    CodeModel::NameUse *nameUse = CodeModel::Create<CodeModel::NameUse>(m_storage);
 
1139
    nameUse->setParent(currentScope.top());
 
1140
    nameUse->setNameToken(tokenRefFromAST(unqualifedName));
 
1141
    nameUse->setName(textOf(unqualifedName));
 
1142
    nameUse->setDeclaration(member);
 
1143
 
 
1144
    currentScope.top()->addNameUse(nameUse);
 
1145
    addNameUse(unqualifedName, nameUse);
 
1146
}
 
1147
 
 
1148
void Semantic::addNameUse(AST *node, NameUse *nameUse)
 
1149
{
 
1150
    const int tokenIndex = node->startToken();
 
1151
    m_nameUses.insert(tokenIndex, nameUse);
 
1152
}
 
1153
 
 
1154
/*
 
1155
    Searches a AST node and all its children for a nameUse. The name use is
 
1156
    found by looking up each node's tokens in the m_nameUses map. A depth-first
 
1157
    search is used.
 
1158
*/
 
1159
NameUse *Semantic::findNameUse(AST *node)
 
1160
{
 
1161
    if(!node)
 
1162
        return 0;
 
1163
 
 
1164
    List<AST*> *children = node->children();
 
1165
    if(children) {
 
1166
        NameUse *nameUse = 0;
 
1167
        foreach(AST* child , *children) {
 
1168
            nameUse = findNameUse(child);
 
1169
            if(nameUse)
 
1170
                break;
 
1171
        }
 
1172
        if (nameUse)
 
1173
            return nameUse;
 
1174
    }
 
1175
 
 
1176
    for (int t = node->startToken(); t < node->endToken(); ++t) {
 
1177
 //       cout << t <<" |" <<m_tokenStream->tokenText(t).constData() << "|" << endl;
 
1178
        if (m_nameUses.contains(t))
 
1179
            return m_nameUses.value(t);
 
1180
    }
 
1181
    return 0;
 
1182
}
 
1183
 
 
1184
/*
 
1185
    Gets a TokenRef from an AST node.
 
1186
    Assumes that the node only covers one token, which means that
 
1187
    node->statToken() == node->endToken(). If this is not the case
 
1188
    then the TokenRef will reference the token at startToken.
 
1189
*/
 
1190
TokenEngine::TokenRef Semantic::tokenRefFromAST(AST *node)
 
1191
{
 
1192
    const int startTokenIndex = node->startToken();
 
1193
    const TokenEngine::TokenContainer tokenContainer = m_tokenStream->tokenContainer(startTokenIndex);
 
1194
    const int containerIndex = m_tokenStream->containerIndex(startTokenIndex);
 
1195
    return TokenEngine::TokenRef(tokenContainer, containerIndex);
 
1196
}