LookupContext.cpp 26 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "LookupContext.h"
#include "ResolveExpression.h"
#include "Overview.h"
#include "CppBindings.h"
34
#include "GenTemplateInstance.h"
35
36
37
38
39
40
41
42
43
44
45
46

#include <CoreTypes.h>
#include <Symbols.h>
#include <Literals.h>
#include <Names.h>
#include <Scope.h>
#include <Control.h>

#include <QtDebug>

using namespace CPlusPlus;

47
static void fullyQualifiedName_helper(Symbol *symbol, QList<const Name *> *names)
48
49
50
51
{
    if (! symbol)
        return;

52
    fullyQualifiedName_helper(symbol->enclosingSymbol(), names);
53
54
55
56
57
58
59
60
61
62
63
64
65

    if (symbol->name() && (symbol->isClass() || symbol->isNamespace())) {
        if (const QualifiedNameId *q = symbol->name()->asQualifiedNameId()) {
            for (unsigned i = 0; i < q->nameCount(); ++i)
                names->append(q->nameAt(i));

        } else if (symbol->name()->isNameId() || symbol->name()->isTemplateNameId()) {
            names->append(symbol->name());

        }
    }
}

66
67
68
69
bool ClassOrNamespace::CompareName::operator()(const Name *name, const Name *other) const
{
    Q_ASSERT(name != 0);
    Q_ASSERT(other != 0);
70

71
72
    const Identifier *id = name->identifier();
    const Identifier *otherId = other->identifier();
73
    return strcmp(id->chars(), otherId->chars()) < 0;
74
75
}

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/////////////////////////////////////////////////////////////////////
// LookupContext
/////////////////////////////////////////////////////////////////////
LookupContext::LookupContext()
    : _control(0)
{ }

LookupContext::LookupContext(Document::Ptr thisDocument,
                             const Snapshot &snapshot)
    : _expressionDocument(Document::create("<LookupContext>")),
      _thisDocument(thisDocument),
      _snapshot(snapshot)
{
    _control = _expressionDocument->control();
}

LookupContext::LookupContext(Document::Ptr expressionDocument,
                             Document::Ptr thisDocument,
                             const Snapshot &snapshot)
    : _expressionDocument(expressionDocument),
      _thisDocument(thisDocument),
      _snapshot(snapshot)
{
    _control = _expressionDocument->control();
}

LookupContext::LookupContext(const LookupContext &other)
    : _control(other._control),
      _expressionDocument(other._expressionDocument),
      _thisDocument(other._thisDocument),
      _snapshot(other._snapshot),
      _bindings(other._bindings)
{ }

LookupContext &LookupContext::operator = (const LookupContext &other)
{
    _control = other._control;
    _expressionDocument = other._expressionDocument;
    _thisDocument = other._thisDocument;
    _snapshot = other._snapshot;
    _bindings = other._bindings;
    return *this;
}

120
121
122
123
124
125
126
QList<const Name *> LookupContext::fullyQualifiedName(Symbol *symbol)
{
    QList<const Name *> names;
    fullyQualifiedName_helper(symbol, &names);
    return names;
}

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
QSharedPointer<CreateBindings> LookupContext::bindings() const
{
    if (! _bindings)
        _bindings = QSharedPointer<CreateBindings>(new CreateBindings(_thisDocument, _snapshot));

    return _bindings;
}

void LookupContext::setBindings(QSharedPointer<CreateBindings> bindings)
{
    _bindings = bindings;
}

bool LookupContext::isValid() const
{ return _control != 0; }

Control *LookupContext::control() const
{ return _control; }

Document::Ptr LookupContext::expressionDocument() const
{ return _expressionDocument; }

Document::Ptr LookupContext::thisDocument() const
{ return _thisDocument; }

Document::Ptr LookupContext::document(const QString &fileName) const
{ return _snapshot.document(fileName); }

Snapshot LookupContext::snapshot() const
{ return _snapshot; }

ClassOrNamespace *LookupContext::globalNamespace() const
{
    return bindings()->globalNamespace();
}

163
ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope) const
164
165
{
    if (ClassOrNamespace *b = bindings()->findClassOrNamespace(scope->owner()))
166
        return b->lookupType(name);
167
168
169
170

    return 0;
}

171
ClassOrNamespace *LookupContext::lookupType(Symbol *symbol) const
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
{
    return bindings()->findClassOrNamespace(symbol);
}

QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
{
    QList<Symbol *> candidates;

    if (! name)
        return candidates;

    const Identifier *id = name->identifier();

    for (; scope; scope = scope->enclosingScope()) {
        if (id && scope->isBlockScope()) {
Roberto Raggi's avatar
Roberto Raggi committed
187
            bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0);
188
189
190
191
192
193
194
195

            if (! candidates.isEmpty())
                break; // it's a local.

            for (unsigned index = 0; index < scope->symbolCount(); ++index) {
                Symbol *member = scope->symbolAt(index);

                if (UsingNamespaceDirective *u = member->asUsingNamespaceDirective()) {
196
197
                    if (Namespace *enclosingNamespace = u->enclosingNamespaceScope()->owner()->asNamespace()) {
                        if (ClassOrNamespace *b = bindings()->findClassOrNamespace(enclosingNamespace)) {
198
                            if (ClassOrNamespace *uu = b->lookupType(u->name())) {
199
200
201
202
203
204
                                candidates = uu->lookup(name);

                                if (! candidates.isEmpty())
                                    return candidates;
                            }
                        }
205
206
207
208
209
210
                    }
                }
            }

        } else if (scope->isFunctionScope()) {
            Function *fun = scope->owner()->asFunction();
Roberto Raggi's avatar
Roberto Raggi committed
211
            bindings()->lookupInScope(name, fun->arguments(), &candidates, /*templateId = */ 0);
212
213
214
215
216
217
            if (! candidates.isEmpty())
                break; // it's a formal argument.

            if (fun->name() && fun->name()->isQualifiedNameId()) {
                const QualifiedNameId *q = fun->name()->asQualifiedNameId();

218
                QList<const Name *> path = fullyQualifiedName(scope->owner());
219
220
221

                for (unsigned index = 0; index < q->nameCount() - 1; ++index) { // ### TODO remove me.
                    const Name *name = q->nameAt(index);
222

223
224
                    if (name->isNameId() || name->isTemplateNameId())
                        path.append(name);
225
226
227
228
229
230
231
232
                }

                if (ClassOrNamespace *binding = bindings()->findClassOrNamespace(path))
                    return binding->lookup(name);
            }

        } else if (scope->isObjCMethodScope()) {
            ObjCMethod *method = scope->owner()->asObjCMethod();
Roberto Raggi's avatar
Roberto Raggi committed
233
            bindings()->lookupInScope(name, method->arguments(), &candidates, /*templateId = */ 0);
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
            if (! candidates.isEmpty())
                break; // it's a formal argument.

        } else if (scope->isClassScope() || scope->isNamespaceScope()
                    || scope->isObjCClassScope() || scope->isObjCProtocolScope()) {
            if (ClassOrNamespace *binding = bindings()->findClassOrNamespace(scope->owner()))
                return binding->lookup(name);

            break;
        }
    }

    return candidates;
}

ClassOrNamespace::ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent)
250
    : _factory(factory), _parent(parent), _templateId(0)
251
252
253
{
}

254
255
256
257
258
const TemplateNameId *ClassOrNamespace::templateId() const
{
    return _templateId;
}

259
260
261
262
263
ClassOrNamespace *ClassOrNamespace::parent() const
{
    return _parent;
}

264
265
266
267
268
269
270
271
272
273
274
275
276
277
QList<ClassOrNamespace *> ClassOrNamespace::usings() const
{
    const_cast<ClassOrNamespace *>(this)->flush();
    return _usings;
}

QList<Enum *> ClassOrNamespace::enums() const
{
    const_cast<ClassOrNamespace *>(this)->flush();
    return _enums;
}

QList<Symbol *> ClassOrNamespace::symbols() const
{
278
279
280
    if (_templateId && ! _usings.isEmpty())
        return _usings.first()->symbols(); // ask to the base implementation

281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
    const_cast<ClassOrNamespace *>(this)->flush();
    return _symbols;
}

ClassOrNamespace *ClassOrNamespace::globalNamespace() const
{
    ClassOrNamespace *e = const_cast<ClassOrNamespace *>(this);

    do {
        if (! e->_parent)
            break;

        e = e->_parent;
    } while (e);

    return e;
}

299
300
301
302
303
QList<Symbol *> ClassOrNamespace::find(const Name *name)
{
    return lookup_helper(name, false);
}

304
QList<Symbol *> ClassOrNamespace::lookup(const Name *name)
305
306
307
308
309
{
    return lookup_helper(name, true);
}

QList<Symbol *> ClassOrNamespace::lookup_helper(const Name *name, bool searchInEnclosingScope)
310
311
312
{
    QList<Symbol *> result;

313
314
315
    if (name) {
        if (const QualifiedNameId *q = name->asQualifiedNameId()) {
            ClassOrNamespace *binding = this;
316

317
318
            if (q->isGlobal())
                binding = globalNamespace();
319

320
321
            if (q->nameCount() == 1)
                return binding->find(q->unqualifiedNameId());
Roberto Raggi's avatar
Roberto Raggi committed
322

323
            binding = binding->lookupType(q->nameAt(0));
324

325
            for (unsigned index = 1; binding && index < q->nameCount() - 1; ++index)
326
                binding = binding->findType(q->nameAt(index));
327

328
329
            if (binding)
                result = binding->find(q->unqualifiedNameId());
330

331
332
            return result;
        }
333

334
335
336
337
338
339
340
        QSet<ClassOrNamespace *> processed;
        ClassOrNamespace *binding = this;
        do {
            lookup_helper(name, binding, &result, &processed, /*templateId = */ 0);
            binding = binding->_parent;
        } while (searchInEnclosingScope && binding);
    }
341
342
343
344
345
346

    return result;
}

void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding,
                                     QList<Symbol *> *result,
347
348
                                     QSet<ClassOrNamespace *> *processed,
                                     const TemplateNameId *templateId)
349
350
351
352
353
354
355
{
    if (! binding)
        return;

    else if (! processed->contains(binding)) {
        processed->insert(binding);

356
357
358
        //Overview oo;
        //qDebug() << "search for:" << oo(name) << "template:" << oo(templateId) << "b:" << oo(binding->_templateId);

359
360
        foreach (Symbol *s, binding->symbols()) {
            if (ScopedSymbol *scoped = s->asScopedSymbol())
Roberto Raggi's avatar
Roberto Raggi committed
361
                _factory->lookupInScope(name, scoped->members(), result, templateId);
362
363
364
        }

        foreach (Enum *e, binding->enums())
Roberto Raggi's avatar
Roberto Raggi committed
365
            _factory->lookupInScope(name, e->members(), result, templateId);
366
367

        foreach (ClassOrNamespace *u, binding->usings())
368
369
370
            lookup_helper(name, u, result, processed, binding->_templateId);

        //qDebug() << "=======" << oo(name) << "template:" << oo(binding->_templateId);
371
372
373
    }
}

Roberto Raggi's avatar
Roberto Raggi committed
374
void CreateBindings::lookupInScope(const Name *name, Scope *scope,
375
376
                                   QList<Symbol *> *result,
                                   const TemplateNameId *templateId)
377
{
378
379
    Q_UNUSED(templateId);

380
381
382
383
384
385
386
387
388
    if (! name) {
        return;

    } else if (const OperatorNameId *op = name->asOperatorNameId()) {
        for (Symbol *s = scope->lookat(op->kind()); s; s = s->next()) {
            if (! s->name())
                continue;
            else if (! s->name()->isEqualTo(op))
                continue;
389

390
391
392
393
394
            result->append(s);
        }

    } else if (const Identifier *id = name->identifier()) {
        for (Symbol *s = scope->lookat(id); s; s = s->next()) {
Roberto Raggi's avatar
Roberto Raggi committed
395
            if (! id->isEqualTo(s->identifier()))
396
                continue;
Roberto Raggi's avatar
Roberto Raggi committed
397
398
            else if (s->name()->isQualifiedNameId())
                continue; // skip qualified ids.
399

400
#if 1
401
402
            if (templateId && (s->isDeclaration() || s->isFunction())) {

403
                FullySpecifiedType ty = GenTemplateInstance::instantiate(templateId, s, _control);
404
405
406
407
408
409
410
411

                Overview oo;
                oo.setShowFunctionSignatures(true);
                oo.setShowReturnTypes(true);

                qDebug() << "TODO: instantiate:" << oo(s->type(), s->name()) << "using:" << oo(templateId)
                        << oo(ty);

412
#if 0
413
414
                if (Declaration *decl = s->asDeclaration()) {
                    qDebug() << "instantiate declaration";
415
416
                    Declaration *d = _control->newDeclaration(0, 0);
                    d->copy(decl);
417
418
419
420
421
422
                    d->setType(ty);
                    result->append(d);
                    continue;
                } else if (Function *fun = s->asFunction()) {
                    qDebug() << "instantiate function";
                    Function *d = ty->asFunctionType();
423
                    d->copy(fun);
424
425
426
                    result->append(d);
                    continue;
                }
427
428
#endif

429
            }
Roberto Raggi's avatar
Roberto Raggi committed
430
#endif
431

432
433
434
435
436
437
            result->append(s);
        }

    }
}

438
ClassOrNamespace *ClassOrNamespace::lookupType(const Name *name)
439
440
441
442
443
444
445
446
{
    if (! name)
        return 0;

    QSet<ClassOrNamespace *> processed;
    return lookupClassOrNamespace_helper(name, &processed);
}

447
ClassOrNamespace *ClassOrNamespace::findType(const Name *name)
448
449
450
451
452
{
    QSet<ClassOrNamespace *> processed;
    return findClassOrNamespace_helper(name, &processed);
}

453
ClassOrNamespace *ClassOrNamespace::findType(const QList<const Name *> &path)
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
{
    if (path.isEmpty())
        return globalNamespace();

    ClassOrNamespace *e = this;

    for (int i = 0; e && i < path.size(); ++i) {
        QSet<ClassOrNamespace *> processed;
        e = e->findClassOrNamespace_helper(path.at(i), &processed);
    }

    return e;
}

ClassOrNamespace *ClassOrNamespace::lookupClassOrNamespace_helper(const Name *name,
                                                                  QSet<ClassOrNamespace *> *processed)
{
    Q_ASSERT(name != 0);

    if (! processed->contains(this)) {
        processed->insert(this);

        if (const QualifiedNameId *q = name->asQualifiedNameId()) {
            ClassOrNamespace *e = this;

            if (q->isGlobal())
                e = globalNamespace();

482
            e = e->lookupType(q->nameAt(0));
483
484
485
486
487
488
489
490

            for (unsigned index = 1; e && index < q->nameCount(); ++index) {
                QSet<ClassOrNamespace *> processed;
                e = e->findClassOrNamespace_helper(q->nameAt(index), &processed);
            }

            return e;

491
492
        } else if (name->isNameId() || name->isTemplateNameId()) {
            if (ClassOrNamespace *e = nestedClassOrNamespace(name))
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
                return e;

            foreach (ClassOrNamespace *u, usings()) {
                if (ClassOrNamespace *r = u->lookupClassOrNamespace_helper(name, processed))
                    return r;
            }
        }

        if (_parent)
            return _parent->lookupClassOrNamespace_helper(name, processed);
    }

    return 0;
}

ClassOrNamespace *ClassOrNamespace::findClassOrNamespace_helper(const Name *name,
                                                                QSet<ClassOrNamespace *> *processed)
{
    if (! name) {
        return 0;

    } else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
        ClassOrNamespace *e = this;

        if (q->isGlobal())
            e = globalNamespace();

        for (unsigned i = 0; e && i < q->nameCount(); ++i) {
            QSet<ClassOrNamespace *> processed;
            e = e->findClassOrNamespace_helper(q->nameAt(i), &processed);
        }

        return e;

527
528
529
530
531
532
533
534
535
536
537
538
    } else if (name->isNameId() || name->isTemplateNameId()) {
        if (ClassOrNamespace *e = nestedClassOrNamespace(name))
            return e;

        else if (! processed->contains(this)) {
            processed->insert(this);

            foreach (ClassOrNamespace *u, usings()) {
                if (ClassOrNamespace *e = u->findClassOrNamespace_helper(name, processed))
                    return e;
            }
        }
539
540
541
542
543
544

    }

    return 0;
}

545
ClassOrNamespace *ClassOrNamespace::nestedClassOrNamespace(const Name *name) const
546
{
547
548
    Q_ASSERT(name != 0);
    Q_ASSERT(name->isNameId() || name->isTemplateNameId());
549

550
    const_cast<ClassOrNamespace *>(this)->flush();
551

552
    Table::const_iterator it = _classOrNamespaces.find(name);
553

554
555
    if (it == _classOrNamespaces.end())
        return 0;
556

557
558
559
560
    ClassOrNamespace *c = it->second;

    if (const TemplateNameId *templId = name->asTemplateNameId()) {
        foreach (ClassOrNamespace *i, c->_instantiations) {
561
            if (templId->isEqualTo(i->_templateId))
562
563
564
565
566
567
568
569
570
571
572
                return i;
        }

        ClassOrNamespace *i = _factory->allocClassOrNamespace(c);
        i->_templateId = templId;
        i->_usings.append(c);
        c->_instantiations.append(i);
        return i;
    }

    return c;
573
574
575
576
}

void ClassOrNamespace::flush()
{
Roberto Raggi's avatar
Roberto Raggi committed
577
578
579
    if (! _todo.isEmpty()) {
        const QList<Symbol *> todo = _todo;
        _todo.clear();
580

Roberto Raggi's avatar
Roberto Raggi committed
581
        foreach (Symbol *member, todo)
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
            _factory->process(member, this);
    }
}

void ClassOrNamespace::addSymbol(Symbol *symbol)
{
    _symbols.append(symbol);
}

void ClassOrNamespace::addTodo(Symbol *symbol)
{
    _todo.append(symbol);
}

void ClassOrNamespace::addEnum(Enum *e)
{
    _enums.append(e);
}

void ClassOrNamespace::addUsing(ClassOrNamespace *u)
{
    _usings.append(u);
}

606
void ClassOrNamespace::addNestedClassOrNamespace(const Name *alias, ClassOrNamespace *e)
607
{
608
    _classOrNamespaces[alias] = e;
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
}

ClassOrNamespace *ClassOrNamespace::findOrCreate(const Name *name)
{
    if (! name)
        return this;

    if (const QualifiedNameId *q = name->asQualifiedNameId()) {
        ClassOrNamespace *e = this;

        for (unsigned i = 0; e && i < q->nameCount(); ++i)
            e = e->findOrCreate(q->nameAt(i));

        return e;

624
    } else if (name->isNameId() || name->isTemplateNameId()) {
625
626
627
628
        ClassOrNamespace *e = nestedClassOrNamespace(name);

        if (! e) {
            e = _factory->allocClassOrNamespace(this);
629
            _classOrNamespaces[name] = e;
630
631
632
633
634
635
636
637
638
639
640
        }

        return e;
    }

    return 0;
}

CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot)
    : _snapshot(snapshot)
{
641
    _control = new Control();
642
643
644
645
646
647
648
649
650
    _globalNamespace = allocClassOrNamespace(/*parent = */ 0);
    _currentClassOrNamespace = _globalNamespace;

    process(thisDocument);
}

CreateBindings::~CreateBindings()
{
    qDeleteAll(_entities);
651
    delete _control;
652
653
}

Roberto Raggi's avatar
Roberto Raggi committed
654
ClassOrNamespace *CreateBindings::switchCurrentClassOrNamespace(ClassOrNamespace *classOrNamespace)
655
656
657
658
659
660
661
662
663
664
665
{
    ClassOrNamespace *previous = _currentClassOrNamespace;
    _currentClassOrNamespace = classOrNamespace;
    return previous;
}

ClassOrNamespace *CreateBindings::globalNamespace() const
{
    return _globalNamespace;
}

666
ClassOrNamespace *CreateBindings::findClassOrNamespace(Symbol *symbol)
667
{
668
    const QList<const Name *> names = LookupContext::fullyQualifiedName(symbol);
669

670
671
    if (names.isEmpty())
        return _globalNamespace;
672

673
    ClassOrNamespace *b = _globalNamespace->lookupType(names.at(0));
674
675

    for (int i = 1; b && i < names.size(); ++i)
676
        b = b->findType(names.at(i));
677
678

    return b;
679
680
}

681
ClassOrNamespace *CreateBindings::findClassOrNamespace(const QList<const Name *> &path)
682
{
683
    ClassOrNamespace *e = _globalNamespace->findType(path);
684
685
686
687
688
    return e;
}

void CreateBindings::process(Symbol *s, ClassOrNamespace *classOrNamespace)
{
Roberto Raggi's avatar
Roberto Raggi committed
689
    ClassOrNamespace *previous = switchCurrentClassOrNamespace(classOrNamespace);
690
    accept(s);
Roberto Raggi's avatar
Roberto Raggi committed
691
    (void) switchCurrentClassOrNamespace(previous);
692
693
694
695
696
697
698
}

void CreateBindings::process(Symbol *symbol)
{
    _currentClassOrNamespace->addTodo(symbol);
}

699
700
701
702
703
Control *CreateBindings::control() const
{
    return _control;
}

704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
ClassOrNamespace *CreateBindings::allocClassOrNamespace(ClassOrNamespace *parent)
{
    ClassOrNamespace *e = new ClassOrNamespace(this, parent);
    _entities.append(e);
    return e;
}

void CreateBindings::process(Document::Ptr doc)
{
    if (! doc)
        return;

    else if (Namespace *globalNamespace = doc->globalNamespace()) {
        if (! _processed.contains(globalNamespace)) {
            _processed.insert(globalNamespace);

            foreach (const Document::Include &i, doc->includes()) {
                if (Document::Ptr incl = _snapshot.document(i.fileName()))
                    process(incl);
            }

            accept(globalNamespace);
        }
    }
}

730
ClassOrNamespace *CreateBindings::enterClassOrNamespaceBinding(Symbol *symbol)
731
732
733
734
{
    ClassOrNamespace *entity = _currentClassOrNamespace->findOrCreate(symbol->name());
    entity->addSymbol(symbol);

Roberto Raggi's avatar
Roberto Raggi committed
735
    return switchCurrentClassOrNamespace(entity);
736
737
}

738
ClassOrNamespace *CreateBindings::enterGlobalClassOrNamespace(Symbol *symbol)
739
740
741
742
{
    ClassOrNamespace *entity = _globalNamespace->findOrCreate(symbol->name());
    entity->addSymbol(symbol);

Roberto Raggi's avatar
Roberto Raggi committed
743
    return switchCurrentClassOrNamespace(entity);
744
745
746
747
}

bool CreateBindings::visit(Namespace *ns)
{
748
    ClassOrNamespace *previous = enterClassOrNamespaceBinding(ns);
749
750
751
752
753
754
755
756
757
758

    for (unsigned i = 0; i < ns->memberCount(); ++i)
        process(ns->memberAt(i));

    _currentClassOrNamespace = previous;
    return false;
}

bool CreateBindings::visit(Class *klass)
{
759
760
761
762
    ClassOrNamespace *previous = _currentClassOrNamespace;
    ClassOrNamespace *binding = 0;

    if (klass->name() && klass->name()->isQualifiedNameId())
763
        binding = _currentClassOrNamespace->lookupType(klass->name());
764
765
766
767
768
769

    if (! binding)
        binding = _currentClassOrNamespace->findOrCreate(klass->name());

    _currentClassOrNamespace = binding;
    _currentClassOrNamespace->addSymbol(klass);
770
771
772
773
774
775
776
777
778
779
780
781
782

    for (unsigned i = 0; i < klass->baseClassCount(); ++i)
        process(klass->baseClassAt(i));

    for (unsigned i = 0; i < klass->memberCount(); ++i)
        process(klass->memberAt(i));

    _currentClassOrNamespace = previous;
    return false;
}

bool CreateBindings::visit(ForwardClassDeclaration *klass)
{
783
    if (! klass->isFriend()) {
784
        ClassOrNamespace *previous = enterClassOrNamespaceBinding(klass);
785
786
787
        _currentClassOrNamespace = previous;
    }

788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
    return false;
}

bool CreateBindings::visit(Enum *e)
{
    _currentClassOrNamespace->addEnum(e);
    return false;
}

bool CreateBindings::visit(Declaration *decl)
{
    if (decl->isTypedef()) {
        const FullySpecifiedType ty = decl->type();
        const Identifier *typedefId = decl->identifier();

        if (typedefId && ! (ty.isConst() || ty.isVolatile())) {
            if (const NamedType *namedTy = ty->asNamedType()) {
805
                if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(namedTy->name())) {
806
                    _currentClassOrNamespace->addNestedClassOrNamespace(decl->name(), e);
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
                } else if (false) {
                    Overview oo;
                    qDebug() << "found entity not found for" << oo(namedTy->name());
                }
            }
        }
    }

    return false;
}

bool CreateBindings::visit(Function *)
{
    return false;
}

bool CreateBindings::visit(BaseClass *b)
{
825
    if (ClassOrNamespace *base = _currentClassOrNamespace->lookupType(b->name())) {
826
827
828
829
830
831
832
833
834
835
        _currentClassOrNamespace->addUsing(base);
    } else if (false) {
        Overview oo;
        qDebug() << "no entity for:" << oo(b->name());
    }
    return false;
}

bool CreateBindings::visit(UsingNamespaceDirective *u)
{
836
    if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(u->name())) {
837
838
839
840
841
842
843
844
845
846
847
848
849
        _currentClassOrNamespace->addUsing(e);
    } else if (false) {
        Overview oo;
        qDebug() << "no entity for namespace:" << oo(u->name());
    }
    return false;
}

bool CreateBindings::visit(NamespaceAlias *a)
{
    if (! a->identifier()) {
        return false;

850
    } else if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(a->namespaceName())) {
851
852
        if (a->name()->isNameId() || a->name()->isTemplateNameId())
            _currentClassOrNamespace->addNestedClassOrNamespace(a->name(), e);
853
854
855
856
857
858
859
860
861
862
863

    } else if (false) {
        Overview oo;
        qDebug() << "no entity for namespace:" << oo(a->namespaceName());
    }

    return false;
}

bool CreateBindings::visit(ObjCClass *klass)
{
864
    ClassOrNamespace *previous = enterGlobalClassOrNamespace(klass);
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879

    process(klass->baseClass());

    for (unsigned i = 0; i < klass->protocolCount(); ++i)
        process(klass->protocolAt(i));

    for (unsigned i = 0; i < klass->memberCount(); ++i)
        process(klass->memberAt(i));

    _currentClassOrNamespace = previous;
    return false;
}

bool CreateBindings::visit(ObjCBaseClass *b)
{
880
    if (ClassOrNamespace *base = _globalNamespace->lookupType(b->name())) {
881
882
883
884
885
886
887
888
889
890
        _currentClassOrNamespace->addUsing(base);
    } else if (false) {
        Overview oo;
        qDebug() << "no entity for:" << oo(b->name());
    }
    return false;
}

bool CreateBindings::visit(ObjCForwardClassDeclaration *klass)
{
891
    ClassOrNamespace *previous = enterGlobalClassOrNamespace(klass);
892
893
894
895
896
897
    _currentClassOrNamespace = previous;
    return false;
}

bool CreateBindings::visit(ObjCProtocol *proto)
{
898
    ClassOrNamespace *previous = enterGlobalClassOrNamespace(proto);
899
900
901
902
903
904
905
906
907
908
909
910
911

    for (unsigned i = 0; i < proto->protocolCount(); ++i)
        process(proto->protocolAt(i));

    for (unsigned i = 0; i < proto->memberCount(); ++i)
        process(proto->memberAt(i));

    _currentClassOrNamespace = previous;
    return false;
}

bool CreateBindings::visit(ObjCBaseProtocol *b)
{
912
    if (ClassOrNamespace *base = _globalNamespace->lookupType(b->name())) {
913
914
915
916
917
918
919
920
921
922
        _currentClassOrNamespace->addUsing(base);
    } else if (false) {
        Overview oo;
        qDebug() << "no entity for:" << oo(b->name());
    }
    return false;
}

bool CreateBindings::visit(ObjCForwardProtocolDeclaration *proto)
{
923
    ClassOrNamespace *previous = enterGlobalClassOrNamespace(proto);
924
925
926
927
928
929
930
931
    _currentClassOrNamespace = previous;
    return false;
}

bool CreateBindings::visit(ObjCMethod *)
{
    return false;
}