LookupContext.cpp 26.3 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
/**************************************************************************
**
** 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"
33
#include "DeprecatedGenTemplateInstance.h"
34
35
36
37
38
39
40
41
42
43

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

#include <QtDebug>

Roberto Raggi's avatar
Roberto Raggi committed
44
45
46
47
namespace {
    const bool debug = ! qgetenv("CPLUSPLUS_LOOKUPCONTEXT_DEBUG").isEmpty();
}

48
49
using namespace CPlusPlus;

50
static void fullyQualifiedName_helper(Symbol *symbol, QList<const Name *> *names)
51
52
53
54
{
    if (! symbol)
        return;

55
    fullyQualifiedName_helper(symbol->enclosingSymbol(), names);
56

57
58
59
60
61
62
63
64
65
    if (symbol->name()) {
        if (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
        } else if (symbol->isObjCClass() || symbol->isObjCBaseClass() || symbol->isObjCProtocol()
                || symbol->isObjCForwardClassDeclaration() || symbol->isObjCForwardProtocolDeclaration()) {
            if (symbol->name())
                names->append(symbol->name());
70
71
72
73
74
        } else if (symbol->isFunction()) {
            if (const QualifiedNameId *q = symbol->name()->asQualifiedNameId()) {
                for (unsigned i = 0; i < q->nameCount() - 1; ++i)
                    names->append(q->nameAt(i));
            }
75
76
77
78
        }
    }
}

79
80
81
82
bool ClassOrNamespace::CompareName::operator()(const Name *name, const Name *other) const
{
    Q_ASSERT(name != 0);
    Q_ASSERT(other != 0);
83

84
85
    const Identifier *id = name->identifier();
    const Identifier *otherId = other->identifier();
86
    return strcmp(id->chars(), otherId->chars()) < 0;
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
/////////////////////////////////////////////////////////////////////
// LookupContext
/////////////////////////////////////////////////////////////////////
LookupContext::LookupContext()
{ }

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

LookupContext::LookupContext(Document::Ptr expressionDocument,
                             Document::Ptr thisDocument,
                             const Snapshot &snapshot)
    : _expressionDocument(expressionDocument),
      _thisDocument(thisDocument),
      _snapshot(snapshot)
{
}

LookupContext::LookupContext(const LookupContext &other)
113
    : _expressionDocument(other._expressionDocument),
114
115
116
117
118
119
120
121
122
123
124
125
126
127
      _thisDocument(other._thisDocument),
      _snapshot(other._snapshot),
      _bindings(other._bindings)
{ }

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

128
129
130
131
132
133
134
QList<const Name *> LookupContext::fullyQualifiedName(Symbol *symbol)
{
    QList<const Name *> names;
    fullyQualifiedName_helper(symbol, &names);
    return names;
}

135
136
137
138
139
140
141
142
143
144
145
146
147
148
QSharedPointer<CreateBindings> LookupContext::bindings() const
{
    if (! _bindings)
        _bindings = QSharedPointer<CreateBindings>(new CreateBindings(_thisDocument, _snapshot));

    return _bindings;
}

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

Control *LookupContext::control() const
149
{ return bindings()->control(); }
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

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();
}

168
ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope) const
169
{
Roberto Raggi's avatar
Roberto Raggi committed
170
    if (ClassOrNamespace *b = bindings()->lookupType(scope->owner()))
171
        return b->lookupType(name);
172
173
174
175

    return 0;
}

176
ClassOrNamespace *LookupContext::lookupType(Symbol *symbol) const
177
{
Roberto Raggi's avatar
Roberto Raggi committed
178
    return bindings()->lookupType(symbol);
179
180
181
182
183
184
185
186
187
188
}

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

    if (! name)
        return candidates;

    for (; scope; scope = scope->enclosingScope()) {
Roberto Raggi's avatar
Roberto Raggi committed
189
        if ((name->isNameId() || name->isTemplateNameId()) && scope->isBlockScope()) {
Roberto Raggi's avatar
Roberto Raggi committed
190
            bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0);
191
192
193
194
195
196
197
198

            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()) {
199
                    if (Namespace *enclosingNamespace = u->enclosingNamespaceScope()->owner()->asNamespace()) {
Roberto Raggi's avatar
Roberto Raggi committed
200
                        if (ClassOrNamespace *b = bindings()->lookupType(enclosingNamespace)) {
201
                            if (ClassOrNamespace *uu = b->lookupType(u->name())) {
202
203
204
205
206
207
                                candidates = uu->lookup(name);

                                if (! candidates.isEmpty())
                                    return candidates;
                            }
                        }
208
209
210
211
212
213
                    }
                }
            }

        } else if (scope->isFunctionScope()) {
            Function *fun = scope->owner()->asFunction();
Roberto Raggi's avatar
Roberto Raggi committed
214
            bindings()->lookupInScope(name, fun->arguments(), &candidates, /*templateId = */ 0);
215
216
217
218

            for (TemplateParameters *it = fun->templateParameters(); it && candidates.isEmpty(); it = it->previous())
                bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0);

219
            if (! candidates.isEmpty())
220
                break; // it's an argument or a template parameter.
221
222

            if (fun->name() && fun->name()->isQualifiedNameId()) {
223
224
225
226
227
228
                if (ClassOrNamespace *binding = bindings()->lookupType(fun)) {
                    candidates = binding->lookup(name);

                    if (! candidates.isEmpty())
                        return candidates;
                }
229
230
            }

231
232
            // contunue, and look at the enclosing scope.

233
234
        } else if (scope->isObjCMethodScope()) {
            ObjCMethod *method = scope->owner()->asObjCMethod();
Roberto Raggi's avatar
Roberto Raggi committed
235
            bindings()->lookupInScope(name, method->arguments(), &candidates, /*templateId = */ 0);
236

237
238
239
            if (! candidates.isEmpty())
                break; // it's a formal argument.

240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
        } else if (scope->isClassScope()) {
            Class *klass = scope->owner()->asClass();

            for (TemplateParameters *it = klass->templateParameters(); it && candidates.isEmpty(); it = it->previous())
                bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0);

            if (! candidates.isEmpty())
                break; // it's an argument or a template parameter.

            if (ClassOrNamespace *binding = bindings()->lookupType(klass)) {
                candidates = binding->lookup(name);

                if (! candidates.isEmpty())
                    return candidates;
            }

        } else if (scope->isNamespaceScope() || scope->isObjCClassScope() || scope->isObjCProtocolScope()) {
Roberto Raggi's avatar
Roberto Raggi committed
257
            if (ClassOrNamespace *binding = bindings()->lookupType(scope->owner()))
258
259
260
261
262
263
264
265
266
267
                return binding->lookup(name);

            break;
        }
    }

    return candidates;
}

ClassOrNamespace::ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent)
268
    : _factory(factory), _parent(parent), _templateId(0)
269
270
271
{
}

272
273
274
275
276
const TemplateNameId *ClassOrNamespace::templateId() const
{
    return _templateId;
}

277
278
279
280
281
ClassOrNamespace *ClassOrNamespace::parent() const
{
    return _parent;
}

282
283
284
285
286
287
288
289
290
291
292
293
294
295
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
{
296
297
298
    if (_templateId && ! _usings.isEmpty())
        return _usings.first()->symbols(); // ask to the base implementation

299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
    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;
}

317
318
319
320
321
QList<Symbol *> ClassOrNamespace::find(const Name *name)
{
    return lookup_helper(name, false);
}

322
QList<Symbol *> ClassOrNamespace::lookup(const Name *name)
323
324
325
326
327
{
    return lookup_helper(name, true);
}

QList<Symbol *> ClassOrNamespace::lookup_helper(const Name *name, bool searchInEnclosingScope)
328
329
330
{
    QList<Symbol *> result;

331
332
333
    if (name) {
        if (const QualifiedNameId *q = name->asQualifiedNameId()) {
            ClassOrNamespace *binding = this;
334

335
336
            if (q->isGlobal())
                binding = globalNamespace();
337

338
339
            if (q->nameCount() == 1)
                return binding->find(q->unqualifiedNameId());
Roberto Raggi's avatar
Roberto Raggi committed
340

341
            binding = binding->lookupType(q->nameAt(0));
342

343
            for (unsigned index = 1; binding && index < q->nameCount() - 1; ++index)
344
                binding = binding->findType(q->nameAt(index));
345

346
347
            if (binding)
                result = binding->find(q->unqualifiedNameId());
348

349
350
            return result;
        }
351

352
353
354
355
356
357
358
        QSet<ClassOrNamespace *> processed;
        ClassOrNamespace *binding = this;
        do {
            lookup_helper(name, binding, &result, &processed, /*templateId = */ 0);
            binding = binding->_parent;
        } while (searchInEnclosingScope && binding);
    }
359
360
361
362
363
364

    return result;
}

void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding,
                                     QList<Symbol *> *result,
365
366
                                     QSet<ClassOrNamespace *> *processed,
                                     const TemplateNameId *templateId)
367
{
Roberto Raggi's avatar
Roberto Raggi committed
368
    if (binding && ! processed->contains(binding)) {
369
370
371
372
        processed->insert(binding);

        foreach (Symbol *s, binding->symbols()) {
            if (ScopedSymbol *scoped = s->asScopedSymbol())
Roberto Raggi's avatar
Roberto Raggi committed
373
                _factory->lookupInScope(name, scoped->members(), result, templateId);
374
375
376
        }

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

        foreach (ClassOrNamespace *u, binding->usings())
380
            lookup_helper(name, u, result, processed, binding->_templateId);
381
382
383
    }
}

Roberto Raggi's avatar
Roberto Raggi committed
384
void CreateBindings::lookupInScope(const Name *name, Scope *scope,
385
386
                                   QList<Symbol *> *result,
                                   const TemplateNameId *templateId)
387
{
388
389
    Q_UNUSED(templateId);

390
391
392
393
394
395
396
397
398
    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;
399

400
401
402
403
404
            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
405
            if (! id->isEqualTo(s->identifier()))
406
                continue;
Roberto Raggi's avatar
Roberto Raggi committed
407
408
            else if (s->name()->isQualifiedNameId())
                continue; // skip qualified ids.
409

410
#if 0
411
            if (templateId && (s->isDeclaration() || s->isFunction())) {
412

413
                FullySpecifiedType ty = GenTemplateInstance::instantiate(templateId, s, _control);
414

415
                if (debug) {
Roberto Raggi's avatar
Roberto Raggi committed
416
417
418
                    Overview oo;
                    oo.setShowFunctionSignatures(true);
                    oo.setShowReturnTypes(true);
419
420
                    qDebug() << "instantiate:" << oo(s->type(), s->name()) << "using:" << oo(templateId) << oo(ty);
                }
421

422
423
424
425
426
427
428
429
430
431
432
                if (Declaration *decl = s->asDeclaration()) {
                    Declaration *d = _control->newDeclaration(0, 0);
                    d->copy(decl);
                    d->setType(ty);
                    result->append(d);
                    continue;
                } else if (Function *fun = s->asFunction()) {
                    Function *d = ty->asFunctionType();
                    d->copy(fun);
                    result->append(d);
                    continue;
Roberto Raggi's avatar
Roberto Raggi committed
433
                }
434
            }
435
#endif
436

437
438
439
440
441
442
            result->append(s);
        }

    }
}

443
ClassOrNamespace *ClassOrNamespace::lookupType(const Name *name)
444
445
446
447
448
{
    if (! name)
        return 0;

    QSet<ClassOrNamespace *> processed;
449
    return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ true);
450
451
}

452
ClassOrNamespace *ClassOrNamespace::findType(const Name *name)
453
454
{
    QSet<ClassOrNamespace *> processed;
455
    return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ false);
456
457
}

Roberto Raggi's avatar
Roberto Raggi committed
458
ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
459
460
                                                      QSet<ClassOrNamespace *> *processed,
                                                      bool searchInEnclosingScope)
461
{
462
463
    if (const QualifiedNameId *q = name->asQualifiedNameId()) {
        ClassOrNamespace *e = this;
464

465
466
        if (q->isGlobal())
            e = globalNamespace();
467

468
        e = e->lookupType(q->nameAt(0));
469

470
471
        for (unsigned index = 1; e && index < q->nameCount(); ++index)
            e = e->findType(q->nameAt(index));
472

473
        return e;
474

475
476
    } else if (! processed->contains(this)) {
        processed->insert(this);
477

478
479
        if (name->isNameId() || name->isTemplateNameId()) {
            flush();
480

Roberto Raggi's avatar
Roberto Raggi committed
481
            if (ClassOrNamespace *e = nestedType(name))
482
483
                return e;

484
            else if (_templateId) {
485
486
487
488
489
490
491
492
493
                if (_usings.size() == 1) {
                    ClassOrNamespace *delegate = _usings.first();

                    if (ClassOrNamespace *r = delegate->lookupType_helper(name, processed, /*searchInEnclosingScope = */ true))
                        return r;
                } else {
                    if (debug)
                        qWarning() << "expected one using declaration. Number of using declarations is:" << _usings.size();
                }
494
495
            }

496
            foreach (ClassOrNamespace *u, usings()) {
497
                if (ClassOrNamespace *r = u->lookupType_helper(name, processed, /*searchInEnclosingScope =*/ false))
498
499
500
501
                    return r;
            }
        }

502
503
        if (_parent && searchInEnclosingScope)
            return _parent->lookupType_helper(name, processed, searchInEnclosingScope);
504
505
506
507
508
    }

    return 0;
}

Roberto Raggi's avatar
Roberto Raggi committed
509
ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name) const
510
{
511
512
    Q_ASSERT(name != 0);
    Q_ASSERT(name->isNameId() || name->isTemplateNameId());
513

514
    const_cast<ClassOrNamespace *>(this)->flush();
515

516
    Table::const_iterator it = _classOrNamespaces.find(name);
517

518
519
    if (it == _classOrNamespaces.end())
        return 0;
520

521
522
523
524
    ClassOrNamespace *c = it->second;

    if (const TemplateNameId *templId = name->asTemplateNameId()) {
        foreach (ClassOrNamespace *i, c->_instantiations) {
525
            if (i->_templateId && templId->isEqualTo(i->_templateId))
526
527
528
529
530
531
532
533
534
535
536
                return i;
        }

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

    return c;
537
538
539
540
}

void ClassOrNamespace::flush()
{
Roberto Raggi's avatar
Roberto Raggi committed
541
542
543
    if (! _todo.isEmpty()) {
        const QList<Symbol *> todo = _todo;
        _todo.clear();
544

Roberto Raggi's avatar
Roberto Raggi committed
545
        foreach (Symbol *member, todo)
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
            _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);
}

Roberto Raggi's avatar
Roberto Raggi committed
570
void ClassOrNamespace::addNestedType(const Name *alias, ClassOrNamespace *e)
571
{
572
    _classOrNamespaces[alias] = e;
573
574
}

575
ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name)
576
577
578
579
580
581
582
583
{
    if (! name)
        return this;

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

        for (unsigned i = 0; e && i < q->nameCount(); ++i)
584
            e = e->findOrCreateType(q->nameAt(i));
585
586
587

        return e;

588
    } else if (name->isNameId() || name->isTemplateNameId()) {
Roberto Raggi's avatar
Roberto Raggi committed
589
        ClassOrNamespace *e = nestedType(name);
590
591
592

        if (! e) {
            e = _factory->allocClassOrNamespace(this);
593
            _classOrNamespaces[name] = e;
594
595
596
597
598
599
600
601
602
603
604
        }

        return e;
    }

    return 0;
}

CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot)
    : _snapshot(snapshot)
{
605
    _control = new Control();
606
607
608
609
610
611
612
613
614
    _globalNamespace = allocClassOrNamespace(/*parent = */ 0);
    _currentClassOrNamespace = _globalNamespace;

    process(thisDocument);
}

CreateBindings::~CreateBindings()
{
    qDeleteAll(_entities);
615
    delete _control;
616
617
}

Roberto Raggi's avatar
Roberto Raggi committed
618
ClassOrNamespace *CreateBindings::switchCurrentClassOrNamespace(ClassOrNamespace *classOrNamespace)
619
620
621
622
623
624
625
626
627
628
629
{
    ClassOrNamespace *previous = _currentClassOrNamespace;
    _currentClassOrNamespace = classOrNamespace;
    return previous;
}

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

Roberto Raggi's avatar
Roberto Raggi committed
630
ClassOrNamespace *CreateBindings::lookupType(Symbol *symbol)
631
{
632
    const QList<const Name *> names = LookupContext::fullyQualifiedName(symbol);
633

634
635
    if (names.isEmpty())
        return _globalNamespace;
636

637
    ClassOrNamespace *b = _globalNamespace->lookupType(names.at(0));
638
639

    for (int i = 1; b && i < names.size(); ++i)
640
        b = b->findType(names.at(i));
641
642

    return b;
643
644
645
646
}

void CreateBindings::process(Symbol *s, ClassOrNamespace *classOrNamespace)
{
Roberto Raggi's avatar
Roberto Raggi committed
647
    ClassOrNamespace *previous = switchCurrentClassOrNamespace(classOrNamespace);
648
    accept(s);
Roberto Raggi's avatar
Roberto Raggi committed
649
    (void) switchCurrentClassOrNamespace(previous);
650
651
652
653
654
655
656
}

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

657
658
659
660
661
Control *CreateBindings::control() const
{
    return _control;
}

662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
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);
        }
    }
}

688
ClassOrNamespace *CreateBindings::enterClassOrNamespaceBinding(Symbol *symbol)
689
{
690
    ClassOrNamespace *entity = _currentClassOrNamespace->findOrCreateType(symbol->name());
691
692
    entity->addSymbol(symbol);

Roberto Raggi's avatar
Roberto Raggi committed
693
    return switchCurrentClassOrNamespace(entity);
694
695
}

696
ClassOrNamespace *CreateBindings::enterGlobalClassOrNamespace(Symbol *symbol)
697
{
698
    ClassOrNamespace *entity = _globalNamespace->findOrCreateType(symbol->name());
699
700
    entity->addSymbol(symbol);

Roberto Raggi's avatar
Roberto Raggi committed
701
    return switchCurrentClassOrNamespace(entity);
702
703
704
705
}

bool CreateBindings::visit(Namespace *ns)
{
706
    ClassOrNamespace *previous = enterClassOrNamespaceBinding(ns);
707
708
709
710
711
712
713
714
715
716

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

    _currentClassOrNamespace = previous;
    return false;
}

bool CreateBindings::visit(Class *klass)
{
717
718
719
720
    ClassOrNamespace *previous = _currentClassOrNamespace;
    ClassOrNamespace *binding = 0;

    if (klass->name() && klass->name()->isQualifiedNameId())
721
        binding = _currentClassOrNamespace->lookupType(klass->name());
722
723

    if (! binding)
724
        binding = _currentClassOrNamespace->findOrCreateType(klass->name());
725
726
727

    _currentClassOrNamespace = binding;
    _currentClassOrNamespace->addSymbol(klass);
728
729
730
731
732
733
734
735
736
737
738
739
740

    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)
{
741
    if (! klass->isFriend()) {
742
        ClassOrNamespace *previous = enterClassOrNamespaceBinding(klass);
743
744
745
        _currentClassOrNamespace = previous;
    }

746
747
748
749
750
751
752
753
754
755
756
757
    return false;
}

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

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

        if (typedefId && ! (ty.isConst() || ty.isVolatile())) {
            if (const NamedType *namedTy = ty->asNamedType()) {
763
                if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(namedTy->name())) {
Roberto Raggi's avatar
Roberto Raggi committed
764
                    _currentClassOrNamespace->addNestedType(decl->name(), e);
765
766
767
768
                } else if (false) {
                    Overview oo;
                    qDebug() << "found entity not found for" << oo(namedTy->name());
                }
769
770
771
772
773
            } else if (Class *klass = ty->asClassType()) {
                if (const NameId *nameId = decl->name()->asNameId()) {
                    ClassOrNamespace *binding = _currentClassOrNamespace->findOrCreateType(nameId);
                    binding->addSymbol(klass);
                }
774
775
776
777
778
779
780
781
782
783
784
785
786
787
            }
        }
    }

    return false;
}

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

bool CreateBindings::visit(BaseClass *b)
{
788
    if (ClassOrNamespace *base = _currentClassOrNamespace->lookupType(b->name())) {
789
790
791
792
793
794
795
796
        _currentClassOrNamespace->addUsing(base);
    } else if (false) {
        Overview oo;
        qDebug() << "no entity for:" << oo(b->name());
    }
    return false;
}

Roberto Raggi's avatar
Roberto Raggi committed
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
bool CreateBindings::visit(UsingDeclaration *u)
{
    if (u->name()) {
        if (const QualifiedNameId *q = u->name()->asQualifiedNameId()) {
            if (const NameId *unqualifiedId = q->unqualifiedNameId()->asNameId()) {
                if (ClassOrNamespace *delegate = _currentClassOrNamespace->lookupType(q)) {
                    ClassOrNamespace *b = _currentClassOrNamespace->findOrCreateType(unqualifiedId);
                    b->addUsing(delegate);
                }
            }
        }
    }
    return false;
}

812
813
bool CreateBindings::visit(UsingNamespaceDirective *u)
{
814
    if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(u->name())) {
815
816
817
818
819
820
821
822
823
824
825
826
827
        _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;

828
    } else if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(a->namespaceName())) {
829
        if (a->name()->isNameId() || a->name()->isTemplateNameId())
Roberto Raggi's avatar
Roberto Raggi committed
830
            _currentClassOrNamespace->addNestedType(a->name(), e);
831
832
833
834
835
836
837
838
839
840
841

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

    return false;
}

bool CreateBindings::visit(ObjCClass *klass)
{
842
    ClassOrNamespace *previous = enterGlobalClassOrNamespace(klass);
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857

    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)
{
858
    if (ClassOrNamespace *base = _globalNamespace->lookupType(b->name())) {
859
860
861
862
863
864
865
866
867
868
        _currentClassOrNamespace->addUsing(base);
    } else if (false) {
        Overview oo;
        qDebug() << "no entity for:" << oo(b->name());
    }
    return false;
}

bool CreateBindings::visit(ObjCForwardClassDeclaration *klass)
{
869
    ClassOrNamespace *previous = enterGlobalClassOrNamespace(klass);
870
871
872
873
874
875
    _currentClassOrNamespace = previous;
    return false;
}

bool CreateBindings::visit(ObjCProtocol *proto)
{
876
    ClassOrNamespace *previous = enterGlobalClassOrNamespace(proto);
877
878
879
880
881
882
883
884
885
886
887
888
889

    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)
{
890
    if (ClassOrNamespace *base = _globalNamespace->lookupType(b->name())) {
891
892
893
894
895
896
897
898
899
900
        _currentClassOrNamespace->addUsing(base);
    } else if (false) {
        Overview oo;
        qDebug() << "no entity for:" << oo(b->name());
    }
    return false;
}

bool CreateBindings::visit(ObjCForwardProtocolDeclaration *proto)
{
901
    ClassOrNamespace *previous = enterGlobalClassOrNamespace(proto);
902
903
904
905
906
907
908
909
    _currentClassOrNamespace = previous;
    return false;
}

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