fix compile, sorry I didn't do that yesterday :-S
[kdevelop:cmohs-kdevelop.git] / languages / cpp / cppduchain / tests / test_duchain.cpp
1 /* This file is part of KDevelop
2     Copyright 2006 Hamish Rodda <rodda@kde.org>
3     Copyright 2007-2009 David Nolden <david.nolden.kdevelop@art-master.de>
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public
7    License version 2 as published by the Free Software Foundation.
8
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public License
15    along with this library; see the file COPYING.LIB.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17    Boston, MA 02110-1301, USA.
18 */
19
20 #include "test_duchain.h"
21
22 #include <QtTest/QtTest>
23
24 #include <language/duchain/duchain.h>
25 #include <language/duchain/duchainlock.h>
26 #include <language/duchain/topducontext.h>
27 #include <language/duchain/forwarddeclaration.h>
28 #include <language/duchain/functiondefinition.h>
29 #include "declarationbuilder.h"
30 #include "usebuilder.h"
31 #include <language/duchain/declarationid.h>
32 #include <language/duchain/declaration.h>
33 #include <language/duchain/dumpdotgraph.h>
34 #include <typeinfo>
35 #include <time.h>
36 #include <set>
37 #include <algorithm>
38 #include <iterator>
39 #include <time.h>
40 #include "cpptypes.h"
41 #include "templateparameterdeclaration.h"
42 #include "cppeditorintegrator.h"
43 #include "dumptypes.h"
44 #include "environmentmanager.h"
45 #include <language/util/setrepository.h>
46
47 #include <language/editor/hashedstring.h>
48 #include <language/editor/documentrange.h>
49
50 #include "typeutils.h"
51 #include "templatedeclaration.h"
52 #include "rpp/chartools.h"
53 #include "rpp/pp-engine.h"
54 #include "rpp/preprocessor.h"
55
56 #include <language/duchain/indexedstring.h>
57 #include <language/duchain/classdeclaration.h>
58 #include <language/duchain/types/alltypes.h>
59 #include <language/duchain/persistentsymboltable.h>
60 #include <language/duchain/codemodel.h>
61 #include <language/codegen/coderepresentation.h>
62
63 #include <tests/testcore.h>
64 #include <tests/autotestshell.h>
65
66 #include "tokens.h"
67 #include "parsesession.h"
68 #include "astutilities.h"
69
70 //Extremely slow
71 // #define TEST_NORMAL_IMPORTS
72
73 #include <typeinfo>
74 #include <language/duchain/duchainutils.h>
75 #include <qtfunctiondeclaration.h>
76 #include <qwidget.h>
77 #include <language/duchain/navigation/abstractnavigationwidget.h>
78 #include <sourcemanipulation.h>
79
80 //Uncomment the following line to get additional output from the string-repository test
81 //#define DEBUG_STRINGREPOSITORY
82
83 using namespace KTextEditor;
84 using namespace TypeUtils;
85 using namespace KDevelop;
86 using namespace Cpp;
87 using namespace Utils;
88
89 QTEST_MAIN(TestDUChain)
90
91 void release(TopDUContext* top)
92 {
93   //KDevelop::EditorIntegrator::releaseTopRange(top->textRangePtr());
94
95   TopDUContextPointer tp(top);
96   DUChain::self()->removeDocumentChain(static_cast<TopDUContext*>(top));
97   Q_ASSERT(!tp);
98 }
99
100 /// Object that locks the duchain for writing and destroys its TopDUContext on destruction
101 struct LockedTopDUContext
102 {
103   LockedTopDUContext(TopDUContext* top) : m_top(top)
104   {
105   }
106   
107   ~LockedTopDUContext() {
108     DUChainWriteLocker lock(DUChain::lock());
109     release(m_top);
110   }
111   LockedTopDUContext& operator=(TopDUContext* ctx) {
112     m_top = ctx;
113     return *this;
114   }
115   TopDUContext* operator->() {
116     return m_top;
117   }
118   operator TopDUContext*() {
119     return m_top;
120   }
121   TopDUContext* m_top;
122   DUChainWriteLocker m_writeLock;
123 };
124
125 namespace QTest {
126   template<>
127   char* toString(const Cursor& cursor)
128   {
129     QByteArray ba = "Cursor(";
130     ba += QByteArray::number(cursor.line()) + ", " + QByteArray::number(cursor.column());
131     ba += ')';
132     return qstrdup(ba.data());
133   }
134   template<>
135   char *toString(const SimpleRange &range)
136   {
137       QByteArray ba = "[ (";
138       ba += QByteArray::number(range.start.line) + ", " + QByteArray::number(range.start.column);
139       ba += ") -> (";
140       ba += QByteArray::number(range.end.line) + ", " + QByteArray::number(range.end.column);
141       ba += ") ]";
142       return qstrdup(ba.data());
143   }
144   template<>
145   char* toString(const QualifiedIdentifier& id)
146   {
147     QByteArray arr = id.toString().toLatin1();
148     return qstrdup(arr.data());
149   }
150   template<>
151   char* toString(const Identifier& id)
152   {
153     QByteArray arr = id.toString().toLatin1();
154     return qstrdup(arr.data());
155   }
156   /*template<>
157   char* toString(QualifiedIdentifier::MatchTypes t)
158   {
159     QString ret;
160     switch (t) {
161       case QualifiedIdentifier::NoMatch:
162         ret = "No Match";
163         break;
164       case QualifiedIdentifier::Contains:
165         ret = "Contains";
166         break;
167       case QualifiedIdentifier::ContainedBy:
168         ret = "Contained By";
169         break;
170       case QualifiedIdentifier::ExactMatch:
171         ret = "Exact Match";
172         break;
173     }
174     QByteArray arr = ret.toString().toLatin1();
175     return qstrdup(arr.data());
176   }*/
177   template<>
178   char* toString(const Declaration& def)
179   {
180     QString s = QString("Declaration %1 (%2): %3").arg(def.identifier().toString()).arg(def.qualifiedIdentifier().toString()).arg(reinterpret_cast<long>(&def));
181     return qstrdup(s.toLatin1().constData());
182   }
183   template<>
184   char* toString(const TypePtr<AbstractType>& type)
185   {
186     QString s = QString("Type: %1 (%2 %3)").arg(type ? type->toString() : QString("<null>")).arg(typeid(*type).name()).arg((size_t)type.unsafeData());
187     return qstrdup(s.toLatin1().constData());
188   }
189 }
190
191 Declaration* getDeclaration( AbstractType::Ptr base, TopDUContext* top ) {
192   if( !base ) return 0;
193
194   IdentifiedType* idType = dynamic_cast<IdentifiedType*>(base.unsafeData());
195   if( idType ) {
196     return idType->declaration(top);
197   } else {
198     return 0;
199   }
200 }
201
202
203 #define TEST_FILE_PARSE_ONLY if (testFileParseOnly) QSKIP("Skip", SkipSingle);
204 TestDUChain::TestDUChain()
205 {
206   testFileParseOnly = false;
207 }
208
209 void TestDUChain::initTestCase()
210 {
211   noDef = 0;
212
213   AutoTestShell::init();
214   TestCore* core = new TestCore();
215   core->initialize(KDevelop::Core::NoUi);
216   EnvironmentManager::init();
217
218   DUChain::self()->disablePersistentStorage();
219   KDevelop::CodeRepresentation::setDiskChangesForbidden(true);
220
221   file1 = "file:///media/data/kdedev/4.0/kdevelop/languages/cpp/parser/duchain.cpp";
222   file2 = "file:///media/data/kdedev/4.0/kdevelop/languages/cpp/parser/dubuilder.cpp";
223
224   topContext = new TopDUContext(IndexedString(file1.pathOrUrl()), SimpleRange(SimpleCursor(0,0),SimpleCursor(25,0)));
225   DUChainWriteLocker lock(DUChain::lock());
226
227   DUChain::self()->addDocumentChain(topContext);
228
229   typeVoid = AbstractType::Ptr(new IntegralType(IntegralType::TypeVoid))->indexed();
230   typeInt = AbstractType::Ptr(new IntegralType(IntegralType::TypeInt))->indexed();
231   AbstractType::Ptr s(new IntegralType(IntegralType::TypeInt));
232   s->setModifiers(AbstractType::ShortModifier);
233   typeShort = s->indexed();
234 }
235
236 void TestDUChain::cleanupTestCase()
237 {
238   //Just a few tests so there is always something cleared away
239   QualifiedIdentifier id("test_bla12310915205342");
240   IndexedQualifiedIdentifier indexedId(id);
241   DelayedType::Ptr delayed(new DelayedType);
242   delayed->setIdentifier(IndexedTypeIdentifier("frokkoflasdasotest_bla12310915205342"));
243   IndexedType indexed = delayed->indexed();
244   DUChain::self()->finalCleanup();
245
246   /*delete type1;
247   delete type2;
248   delete type3;*/
249
250   {
251   DUChainWriteLocker lock(DUChain::lock());
252
253   //EditorIntegrator::releaseTopRange(topContext->textRangePtr());
254   topContext->deleteSelf();
255   }
256 }
257
258 Declaration* TestDUChain::findDeclaration(DUContext* context, const Identifier& id, const SimpleCursor& position)
259 {
260   QList<Declaration*> ret = context->findDeclarations(id, position);
261   if (ret.count())
262     return ret.first();
263   return 0;
264 }
265
266 Declaration* TestDUChain::findDeclaration(DUContext* context, const QualifiedIdentifier& id, const SimpleCursor& position)
267 {
268   QList<Declaration*> ret = context->findDeclarations(id, position);
269   if (ret.count())
270     return ret.first();
271   return 0;
272 }
273
274 void TestDUChain::testIdentifiers()
275 {
276   TEST_FILE_PARSE_ONLY
277
278   QualifiedIdentifier aj("::Area::jump");
279   QCOMPARE(aj.count(), 2);
280   QCOMPARE(aj.explicitlyGlobal(), true);
281   QCOMPARE(aj.at(0), Identifier("Area"));
282   QCOMPARE(aj.at(1), Identifier("jump"));
283
284   QualifiedIdentifier aj2 = QualifiedIdentifier("Area::jump");
285   QCOMPARE(aj2.count(), 2);
286   QCOMPARE(aj2.explicitlyGlobal(), false);
287   QCOMPARE(aj2.at(0), Identifier("Area"));
288   QCOMPARE(aj2.at(1), Identifier("jump"));
289 kDebug() << aj.toString() << aj2.toString();
290 kDebug() << aj.index() << aj2.index();
291   QCOMPARE(aj == aj2, true);
292
293   QVERIFY(QualifiedIdentifier("") == QualifiedIdentifier());
294   QVERIFY(QualifiedIdentifier("").index() == QualifiedIdentifier().index());
295   
296 //   QCOMPARE(aj.match(aj2), QualifiedIdentifier::ExactMatch);
297
298   QualifiedIdentifier ajt("Area::jump::test");
299   QualifiedIdentifier jt("jump::test");
300   QualifiedIdentifier ajt2("Area::jump::tes");
301
302 //   QCOMPARE(aj2.match(ajt), QualifiedIdentifier::NoMatch);
303 //   QCOMPARE(ajt.match(aj2), QualifiedIdentifier::NoMatch);
304 //   //QCOMPARE(jt.match(aj2), QualifiedIdentifier::ContainedBy); ///@todo reenable this(but it fails)
305 //   QCOMPARE(ajt.match(jt), QualifiedIdentifier::EndsWith);
306
307 /*  QCOMPARE(aj2.match(ajt2), QualifiedIdentifier::NoMatch);
308   QCOMPARE(ajt2.match(aj2), QualifiedIdentifier::NoMatch);*/
309   QualifiedIdentifier t(" Area<A,B>::jump <F> ::tes<C>");
310   QCOMPARE(t.count(), 3);
311   QCOMPARE(t.at(0).templateIdentifiersCount(), 2u);
312   QCOMPARE(t.at(1).templateIdentifiersCount(), 1u);
313   QCOMPARE(t.at(2).templateIdentifiersCount(), 1u);
314   QCOMPARE(t.at(0).identifier().str(), QString("Area"));
315   QCOMPARE(t.at(1).identifier().str(), QString("jump"));
316   QCOMPARE(t.at(2).identifier().str(), QString("tes"));
317
318   QualifiedIdentifier op1("operator<");
319   QualifiedIdentifier op2("operator<=");
320   QualifiedIdentifier op3("operator>");
321   QualifiedIdentifier op4("operator>=");
322   QualifiedIdentifier op5("operator()");
323   QualifiedIdentifier op6("operator( )");
324   QCOMPARE(op1.count(), 1);
325   QCOMPARE(op2.count(), 1);
326   QCOMPARE(op3.count(), 1);
327   QCOMPARE(op4.count(), 1);
328   QCOMPARE(op5.count(), 1);
329   QCOMPARE(op6.count(), 1);
330   QCOMPARE(op4.toString(), QString("operator>="));
331   QCOMPARE(op3.toString(), QString("operator>"));
332   QCOMPARE(op1.toString(), QString("operator<"));
333   QCOMPARE(op2.toString(), QString("operator<="));
334   QCOMPARE(op5.toString(), QString("operator()"));
335   QCOMPARE(op6.toString(), QString("operator( )"));
336   QCOMPARE(QualifiedIdentifier("Area<A,B>::jump <F> ::tes<C>").index(), t.index());
337   QCOMPARE(op4.index(), QualifiedIdentifier("operator>=").index());
338   ///@todo create a big randomized test for the identifier repository(check that indices are the same)
339 }
340
341 void TestDUChain::testContextRelationships()
342 {
343   TEST_FILE_PARSE_ONLY
344
345   DUChainWriteLocker lock(DUChain::lock());
346
347   QCOMPARE(DUChain::self()->chainForDocument(file1), topContext);
348
349   DUContext* firstChild = new DUContext(SimpleRange(SimpleCursor(4,4), SimpleCursor(10,3)), topContext);
350
351   QCOMPARE(firstChild->parentContext(), topContext);
352   QCOMPARE(firstChild->childContexts().count(), 0);
353   QCOMPARE(topContext->childContexts().count(), 1);
354   QCOMPARE(topContext->childContexts().last(), firstChild);
355
356   DUContext* secondChild = new DUContext(SimpleRange(SimpleCursor(14,4), SimpleCursor(19,3)), topContext);
357
358   QCOMPARE(topContext->childContexts().count(), 2);
359   QCOMPARE(topContext->childContexts()[1], secondChild);
360
361   DUContext* thirdChild = new DUContext(SimpleRange(SimpleCursor(10,4), SimpleCursor(14,3)), topContext);
362
363   QCOMPARE(topContext->childContexts().count(), 3);
364   QCOMPARE(topContext->childContexts()[1], thirdChild);
365
366   topContext->deleteChildContextsRecursively();
367   QVERIFY(topContext->childContexts().isEmpty());
368 }
369
370 void TestDUChain::testDeclareInt()
371 {
372   TEST_FILE_PARSE_ONLY
373
374   QByteArray method("int i;");
375
376   LockedTopDUContext top = parse(method, DumpNone);
377
378   QVERIFY(!top->parentContext());
379   QCOMPARE(top->childContexts().count(), 0);
380   QCOMPARE(top->localDeclarations().count(), 1);
381   QVERIFY(top->localScopeIdentifier().isEmpty());
382
383   Declaration* def = top->localDeclarations().first();
384   QCOMPARE(def->identifier(), Identifier("i"));
385   QCOMPARE(findDeclaration(top, def->identifier()), def);
386 }
387
388 void TestDUChain::testMultiByteCStrings()
389 {
390   ///@todo This currently does not work, the range has an offset of 1 to the right
391 #if 0
392   int c;
393   QByteArray method("char* c=\"รค\";void test() { c = 1; }");
394   LockedTopDUContext top = parse(method, DumpNone);
395   Declaration* cDec = top->localDeclarations().first();
396   QCOMPARE(cDec->uses().size(), 1);
397   QCOMPARE(cDec->uses().begin()->size(), 1);
398   kDebug() << cDec->uses().begin()->first().textRange();
399   
400 //   QVERIFY(cDec->uses().begin()->first() == SimpleRange(0, 28, 0, 29));
401 #endif
402 }
403
404 void TestDUChain::testEllipsis()
405 {
406   QByteArray method("void infinity(int i, ...) { }");
407   LockedTopDUContext top = parse(method, DumpNone);
408   Declaration* defInfinity = top->localDeclarations().first();
409   QCOMPARE(defInfinity->type<FunctionType>()->arguments().count(), 2);
410   QCOMPARE(defInfinity->type<FunctionType>()->arguments()[1]->toString(), QString("..."));
411 }
412
413 void TestDUChain::testContextSearch() {
414   {
415     QByteArray method("int t; struct C { }; void test() { C c; c.t = 3;}");
416     
417     LockedTopDUContext top = parse(method, DumpNone);
418     QCOMPARE(top->localDeclarations().count(), 3);
419     QVERIFY(top->localDeclarations()[0]->uses().isEmpty());
420   }
421   {
422     QByteArray method("typedef union { char __size[2]; long int __align; } pthread_attr_t; struct Stru {};");
423     
424     LockedTopDUContext top = parse(method, DumpNone);
425   }
426 }
427
428 void TestDUChain::testSeparateVariableDefinition() {
429   {
430     QByteArray method("struct S {static int testValue; enum { A = 5 }; class C {}; int test(C); }; int S::testValue(A); int S::test(C) {}; ");
431     
432     /**
433     * A prefix-context is created that surrounds S::testValue to represent the "S" part of the scope.
434     */
435     
436     LockedTopDUContext top = parse(method, DumpNone);
437     QCOMPARE(top->localDeclarations().count(), 2);
438     QCOMPARE(top->localDeclarations()[0]->qualifiedIdentifier(), QualifiedIdentifier("S"));
439     QCOMPARE(top->childContexts().count(), 5); ///There is one 'garbage' context 
440     QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 4);
441     QCOMPARE(top->childContexts()[0]->childContexts().count(), 3);
442     QCOMPARE(top->childContexts()[0]->childContexts()[0]->localDeclarations().count(), 1);
443     ClassMemberDeclaration* staticDeclaration = dynamic_cast<ClassMemberDeclaration*>(top->childContexts()[0]->localDeclarations()[0]);
444     QVERIFY(staticDeclaration);
445     QCOMPARE(staticDeclaration->qualifiedIdentifier(), QualifiedIdentifier("S::testValue"));
446     QVERIFY(staticDeclaration->isStatic());
447     
448     QCOMPARE(top->childContexts()[2]->localDeclarations().count(), 1);
449     Declaration* actualDeclaration = top->childContexts()[2]->localDeclarations()[0];
450     QVERIFY(!dynamic_cast<AbstractFunctionDeclaration*>(actualDeclaration));
451     QCOMPARE(actualDeclaration->qualifiedIdentifier(), QualifiedIdentifier("S::testValue"));
452
453     QCOMPARE(top->childContexts()[0]->childContexts()[0]->localDeclarations()[0]->uses().count(), 1);
454     
455     ///@todo declaration/definition relationship
456
457     
458     QVERIFY(dynamic_cast<AbstractFunctionDeclaration*>(top->localDeclarations()[1]));
459
460   }
461   
462   {
463     //Declaration + definition
464     QByteArray method("extern int x; int x;");
465     
466     LockedTopDUContext top = parse(method, DumpNone);
467     QCOMPARE(top->localDeclarations().count(), 2);
468     ///@todo declaration/definition relationship
469   }
470 }
471
472 void TestDUChain::testIntegralTypes()
473 {
474   TEST_FILE_PARSE_ONLY
475
476   QByteArray method("const unsigned int i, k; volatile long double j; int* l; double * const * m; const int& n = l;");
477
478   LockedTopDUContext top = parse(method, DumpNone);
479
480   QVERIFY(!top->parentContext());
481   QCOMPARE(top->childContexts().count(), 0);
482   QCOMPARE(top->localDeclarations().count(), 6);
483   QVERIFY(top->localScopeIdentifier().isEmpty());
484
485   Declaration* defI = top->localDeclarations().first();
486   QCOMPARE(defI->identifier(), Identifier("i"));
487   QCOMPARE(findDeclaration(top, defI->identifier()), defI);
488   QVERIFY(defI->type<IntegralType>());
489   QCOMPARE(defI->type<IntegralType>()->dataType(), (uint)IntegralType::TypeInt);
490   QCOMPARE(defI->type<IntegralType>()->modifiers(), (unsigned long long)(AbstractType::UnsignedModifier | AbstractType::ConstModifier));
491
492   Declaration* defK = top->localDeclarations()[1];
493   QCOMPARE(defK->identifier(), Identifier("k"));
494   QCOMPARE(defK->type<IntegralType>()->indexed(), defI->type<IntegralType>()->indexed());
495
496   Declaration* defJ = top->localDeclarations()[2];
497   QCOMPARE(defJ->identifier(), Identifier("j"));
498   QCOMPARE(findDeclaration(top, defJ->identifier()), defJ);
499   QVERIFY(defJ->type<IntegralType>());
500   QCOMPARE(defJ->type<IntegralType>()->dataType(), (uint)IntegralType::TypeDouble);
501   QCOMPARE(defJ->type<IntegralType>()->modifiers(), (unsigned long long)AbstractType::LongModifier | (unsigned long long)AbstractType::VolatileModifier);
502
503   Declaration* defL = top->localDeclarations()[3];
504   QCOMPARE(defL->identifier(), Identifier("l"));
505   QVERIFY(defL->type<PointerType>());
506   QCOMPARE(defL->type<PointerType>()->baseType()->indexed(), typeInt);
507   QCOMPARE(defL->type<PointerType>()->modifiers(), (unsigned long long)AbstractType::NoModifiers);
508
509   Declaration* defM = top->localDeclarations()[4];
510   QCOMPARE(defM->identifier(), Identifier("m"));
511   PointerType::Ptr firstpointer = defM->type<PointerType>();
512   QVERIFY(firstpointer);
513   QCOMPARE(firstpointer->modifiers(), (unsigned long long)AbstractType::NoModifiers);
514   PointerType::Ptr secondpointer = PointerType::Ptr::dynamicCast(firstpointer->baseType());
515   QVERIFY(secondpointer);
516   QCOMPARE(secondpointer->modifiers(), (unsigned long long)AbstractType::ConstModifier);
517   IntegralType::Ptr base = IntegralType::Ptr::dynamicCast(secondpointer->baseType());
518   QVERIFY(base);
519   QCOMPARE(base->dataType(), (uint)IntegralType::TypeDouble);
520   QCOMPARE(base->modifiers(), (unsigned long long)AbstractType::NoModifiers);
521
522   Declaration* defN = top->localDeclarations()[5];
523   QCOMPARE(defN->identifier(), Identifier("n"));
524   QVERIFY(defN->type<ReferenceType>());
525   base = IntegralType::Ptr::dynamicCast(defN->type<ReferenceType>()->baseType());
526   QVERIFY(base);
527   QCOMPARE(base->dataType(), (uint)IntegralType::TypeInt);
528   QCOMPARE(base->modifiers(), (unsigned long long)AbstractType::ConstModifier);
529
530   //Even if reference/pointer types have an invalid target, they should still preserve the pointer
531   QVERIFY(AbstractType::Ptr(new ReferenceType)->toString().endsWith("&"));
532   QVERIFY(AbstractType::Ptr(new PointerType)->toString().endsWith("*"));
533   
534 }
535
536 void TestDUChain::testConversionReturn() {
537   TEST_FILE_PARSE_ONLY
538
539   QByteArray method("class A {}; class B{ operator A*() const ; };");
540
541   LockedTopDUContext top = parse(method, DumpNone);
542
543   QVERIFY(!top->parentContext());
544   QCOMPARE(top->childContexts().count(), 2);
545   QCOMPARE(top->localDeclarations().count(), 2);
546
547   QCOMPARE(top->childContexts()[1]->localDeclarations().count(), 1);
548   FunctionType::Ptr funType = top->childContexts()[1]->localDeclarations()[0]->type<KDevelop::FunctionType>();
549   QVERIFY(funType);
550   QVERIFY(funType->returnType().cast<PointerType>());
551
552 }
553
554 void TestDUChain::testTypeof() {
555   TEST_FILE_PARSE_ONLY
556   
557   {
558     QByteArray method("__typeof__(wchar_t) x; typedef typeof(++x) x_t;");
559
560     LockedTopDUContext top = parse(method, DumpNone);
561
562     QCOMPARE(top->localDeclarations().count(), 2);
563     QCOMPARE(unAliasedType(top->localDeclarations()[1]->abstractType())->toString(), QString("wchar_t"));
564   }
565 }
566
567 void TestDUChain::testArrayType()
568 {
569   TEST_FILE_PARSE_ONLY
570
571   QByteArray method("const unsigned int ArraySize = 3; int i[ArraySize];");
572
573   LockedTopDUContext top = parse(method, DumpNone);
574
575   QVERIFY(!top->parentContext());
576   QCOMPARE(top->childContexts().count(), 0);
577   QCOMPARE(top->localDeclarations().count(), 2);
578   QVERIFY(top->localScopeIdentifier().isEmpty());
579
580   kDebug() << top->localDeclarations()[0]->abstractType()->toString();
581   QVERIFY(top->localDeclarations()[0]->uses().size());
582   QVERIFY(top->localDeclarations()[0]->type<ConstantIntegralType>());
583
584   Declaration* defI = top->localDeclarations().last();
585   QCOMPARE(defI->identifier(), Identifier("i"));
586   QCOMPARE(findDeclaration(top, defI->identifier()), defI);
587
588   ArrayType::Ptr array = defI->type<ArrayType>();
589   QVERIFY(array);
590   IntegralType::Ptr element = IntegralType::Ptr::dynamicCast(array->elementType());
591   QVERIFY(element);
592   QCOMPARE(element->dataType(), (uint)IntegralType::TypeInt);
593   QCOMPARE(array->dimension(), 3);
594
595 }
596
597 void TestDUChain::testProblematicUses()
598 {
599   TEST_FILE_PARSE_ONLY
600   
601   {
602     QByteArray method("struct S { int a; }; int c; int q; int a; S* s; void test() { if(s->a < q && a > c) { } if(s->a < q && a > c) { } }");
603
604     LockedTopDUContext top = parse(method, DumpNone);
605
606     QCOMPARE(top->childContexts().count(), 3);
607     QCOMPARE(top->localDeclarations().count(), 6);
608     QCOMPARE(top->localDeclarations()[1]->uses().size(), 1);
609     QCOMPARE(top->localDeclarations()[1]->uses().begin()->size(), 2); //c uses
610     QCOMPARE(top->localDeclarations()[2]->uses().size(), 1);
611     QCOMPARE(top->localDeclarations()[2]->uses().begin()->size(), 2); //q uses
612     QCOMPARE(top->localDeclarations()[3]->uses().size(), 1);
613     QCOMPARE(top->localDeclarations()[3]->uses().begin()->size(), 2); //a uses
614     QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().begin()->size(), 2); //a uses
615
616   }
617
618 {
619     //                 0         1         2         3         4         5
620     //                 012345678901234567890123456789012345678901234567890123456789
621     QByteArray method("enum { b = 5 }; template<bool b> struct A { enum { Mem }; }; void test(int a) { if(a < 0 && a > -1) { } if(a < 0 && a < -1) { } if(A<(b < 10 && b < 0)>::Mem) { } if(A<(b < 10 && b > 0)>::Mem) { } }");
622
623 ///@todo This works in g++, but not in kdevelops parser. Although it's butt ugly.
624 //     if(A<b < 10 && b < 0>::Mem) {}
625     
626     LockedTopDUContext top = parse(method, DumpNone);
627
628     QCOMPARE(top->childContexts().count(), 5);
629     QCOMPARE(top->childContexts()[3]->localDeclarations().count(), 1);
630     QCOMPARE(top->childContexts()[3]->localDeclarations()[0]->uses().size(), 1);
631     QCOMPARE(top->childContexts()[3]->localDeclarations()[0]->uses().begin()->size(), 4); //a uses
632     
633     QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 1);
634     QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().begin()->size(), 4); //b uses
635
636   }
637 }
638
639 void TestDUChain::testBaseUses()
640 {
641   TEST_FILE_PARSE_ONLY
642
643 {
644     //                 0         1         2         3         4         5         6         7         8
645     //                 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
646     QByteArray method("namespace N { struct A { A(int); int m; }; }; struct B : public N::A { B() : N::A(5) { this->N::A::m = 5; } };");
647
648     LockedTopDUContext top = parse(method, DumpNone);
649
650     QVERIFY(top->problems().isEmpty()); //N::A must be found in the constructor
651     QCOMPARE(top->childContexts().count(), 2);
652     QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 1);
653     QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().size(), 1);
654     QCOMPARE(top->childContexts()[0]->childContexts().count(), 1);
655     QCOMPARE(top->childContexts()[0]->childContexts()[0]->localDeclarations().count(), 2);
656     QVERIFY(!top->childContexts()[0]->childContexts()[0]->localDeclarations()[1]->uses().isEmpty());
657     QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().begin()->size(), 3);
658     // the ctor usage
659     QCOMPARE(top->childContexts()[0]->childContexts()[0]->localDeclarations()[0]->uses().count(), 1);
660     QCOMPARE(top->childContexts()[0]->childContexts()[0]->localDeclarations()[0]->uses().values().first().count(), 1);
661     QCOMPARE(top->childContexts()[0]->childContexts()[0]->localDeclarations()[0]->uses().values().first().first(), SimpleRange(0, 81, 0, 82));
662   }
663
664   {
665     //                 0         1         2         3         4         5
666     //                 012345678901234567890123456789012345678901234567890123456789
667     QByteArray method("class A{ class B {}; }; class C : public A::B { C() : A::B() {} };");
668
669     LockedTopDUContext top = parse(method, DumpNone);
670
671     QCOMPARE(top->localDeclarations().count(), 2);
672     QCOMPARE(top->childContexts().count(), 2);
673     QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 1);
674     QCOMPARE(top->childContexts()[1]->usesCount(), 2);
675
676     QCOMPARE(top->childContexts()[1]->uses()[0].m_range, SimpleRange(0, 41, 0, 42));
677     QCOMPARE(top->childContexts()[1]->uses()[1].m_range, SimpleRange(0, 44, 0, 45));
678
679     QCOMPARE(top->localDeclarations()[0]->uses().count(), 1);
680     QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().count(), 1);
681
682     QCOMPARE(top->childContexts()[1]->childContexts().count(), 2);
683     QCOMPARE(top->childContexts()[1]->childContexts()[1]->usesCount(), 2);
684
685   }
686   {
687     //                 0         1         2         3         4         5
688     //                 012345678901234567890123456789012345678901234567890123456789
689     QByteArray method("template<typename T> class A{ A(){} };\n"
690                       "template<typename T> class B : public A<T> { B() : A<T>() {} };");
691
692     LockedTopDUContext top = parse(method, DumpNone);
693
694     QCOMPARE(top->localDeclarations().count(), 2);
695
696     // uses of class A
697     QEXPECT_FAIL("", "Cookie for the one fixing that!", Abort);
698     QCOMPARE(top->localDeclarations().first()->uses().size(), 1);
699     QCOMPARE(top->localDeclarations().first()->uses().begin()->size(), 2);
700     // use in class B : public A<T>
701     QCOMPARE(top->localDeclarations().first()->uses().begin()->at(0), SimpleRange(1, 38, 1, 39));
702     // use in B() : A<T>()
703     QCOMPARE(top->localDeclarations().first()->uses().begin()->at(1), SimpleRange(1, 51, 1, 52));
704
705     // use of A's ctor
706     QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 1);
707     QCOMPARE(top->childContexts()[1]->localDeclarations().first()->uses().size(), 1);
708     QCOMPARE(top->childContexts()[1]->localDeclarations().first()->uses().begin()->size(), 1);
709     QCOMPARE(top->childContexts()[1]->localDeclarations().first()->uses().begin()->first(), SimpleRange(1, 55, 1, 56));
710
711   }
712 }
713
714
715 void TestDUChain::testTypedefUses()
716 {
717   {
718
719     //                 0         1         2         3         4         5
720     //                 012345678901234567890123456789012345678901234567890123456789
721     QByteArray method("namespace Search { typedef int StateHypothesisIndexwqeqrqwe; StateHypothesisIndexwqeqrqwe i; }");
722
723     LockedTopDUContext top = parse(method, DumpNone);
724
725     QCOMPARE(top->localDeclarations().count(), 1);
726     QCOMPARE(top->childContexts().count(), 1);
727     QCOMPARE(top->childContexts()[0]->usesCount(), 1);
728     QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 2);
729     QVERIFY(top->childContexts()[0]->localDeclarations()[0]->inSymbolTable());
730     QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().size(), 1);
731     QCOMPARE(unAliasedType(top->childContexts()[0]->localDeclarations()[1]->abstractType())->toString(), QString("int"));
732     
733   }
734   {
735     //                 0         1         2         3         4         5
736     //                 012345678901234567890123456789012345678901234567890123456789
737     QByteArray method("class A{}; typedef A B; A c; B d;");
738
739     LockedTopDUContext top = parse(method, DumpNone);
740
741     QCOMPARE(top->localDeclarations().count(), 4);
742     QCOMPARE(top->usesCount(), 3);
743     QCOMPARE(top->localDeclarations()[0]->uses().count(), 1); //1 File
744     QCOMPARE(top->localDeclarations()[1]->uses().count(), 1); //1 File
745
746     QCOMPARE(top->localDeclarations()[0]->uses().begin()->count(), 2); //Typedef and "A c;"
747     QCOMPARE(top->localDeclarations()[1]->uses().begin()->count(), 1); //"B d;"
748
749   }
750 }
751
752 void TestDUChain::testConstructorOperatorUses()
753 {
754   TEST_FILE_PARSE_ONLY
755
756   //                 0         1         2         3         4         5         6         7         8
757   //                 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
758   QByteArray method("class A{A(int); int operator()( ) {}; }; void test() { A a(1); A b = A(2); b(); }");
759
760   LockedTopDUContext top = parse(method, DumpNone);
761
762   QCOMPARE(top->localDeclarations().count(), 2);
763 //   QCOMPARE(top->usesCount(), 3);
764   QCOMPARE(top->childContexts().count(), 3);
765   QCOMPARE(top->childContexts()[2]->localDeclarations().count(), 2);
766
767   QCOMPARE(top->childContexts()[2]->localDeclarations()[1]->uses().count(), 1);
768   
769   QCOMPARE(top->localDeclarations()[0]->uses().count(), 1);
770   QCOMPARE(top->localDeclarations()[0]->uses().begin()->count(), 3);
771   QCOMPARE(top->localDeclarations()[0]->uses().begin()->at(0), SimpleRange(0, 55, 0, 56));
772   QCOMPARE(top->localDeclarations()[0]->uses().begin()->at(1), SimpleRange(0, 63, 0, 64));
773   QCOMPARE(top->localDeclarations()[0]->uses().begin()->at(2), SimpleRange(0, 69, 0, 70));
774
775   QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 2);
776   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().count(), 1);
777   
778   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().begin()->count(), 2);
779   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().begin()->at(0), SimpleRange(0, 58, 0, 59));
780   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().begin()->at(1), SimpleRange(0, 70, 0, 71));
781   
782   QCOMPARE(top->childContexts()[0]->localDeclarations()[1]->uses().count(), 1);
783   QCOMPARE(top->childContexts()[0]->localDeclarations()[1]->uses().begin()->count(), 1);
784   QCOMPARE(top->childContexts()[0]->localDeclarations()[1]->uses().begin()->at(0), SimpleRange(0, 76, 0, 77));
785   
786 }
787 void TestDUChain::testDeclareFor()
788 {
789   TEST_FILE_PARSE_ONLY
790
791   //                 0         1         2         3         4         5
792   //                 012345678901234567890123456789012345678901234567890123456789
793   QByteArray method("int main() { for (int i = 0; i < 10; i++) { if (i == 4) return; int i5[5]; i5[i] = 1; } }");
794
795   LockedTopDUContext top = parse(method, DumpNone);
796
797   QVERIFY(!top->parentContext());
798   QCOMPARE(top->childContexts().count(), 2);
799   QCOMPARE(top->localDeclarations().count(), 1);
800   QVERIFY(top->localScopeIdentifier().isEmpty());
801
802   Declaration* defMain = top->localDeclarations().first();
803   QCOMPARE(defMain->identifier(), Identifier("main"));
804   QCOMPARE(findDeclaration(top, defMain->identifier()), defMain);
805   QVERIFY(defMain->type<FunctionType>());
806   QCOMPARE(defMain->type<FunctionType>()->returnType()->indexed(), typeInt);
807   QCOMPARE(defMain->type<FunctionType>()->arguments().count(), 0);
808   QCOMPARE(defMain->type<FunctionType>()->modifiers(), (unsigned long long)AbstractType::NoModifiers);
809
810   QCOMPARE(findDeclaration(top, Identifier("i")), noDef);
811
812   DUContext* main = top->childContexts()[1];
813   QVERIFY(main->parentContext());
814   QCOMPARE(main->importedParentContexts().count(), 1);
815   QCOMPARE(main->childContexts().count(), 2);
816   QCOMPARE(main->localDeclarations().count(), 0);
817   QCOMPARE(main->localScopeIdentifier(), QualifiedIdentifier("main"));
818
819   QCOMPARE(findDeclaration(main, Identifier("i")), noDef);
820
821   DUContext* forCtx = main->childContexts()[1];
822   QVERIFY(forCtx->parentContext());
823   QCOMPARE(forCtx->importedParentContexts().count(), 1);
824   QCOMPARE(forCtx->childContexts().count(), 2);
825   QCOMPARE(forCtx->localDeclarations().count(), 1);
826   QVERIFY(forCtx->localScopeIdentifier().isEmpty());
827
828   DUContext* forParamCtx = forCtx->importedParentContexts().first().context(0);
829   QVERIFY(forParamCtx->parentContext());
830   QCOMPARE(forParamCtx->importedParentContexts().count(), 0);
831   QCOMPARE(forParamCtx->childContexts().count(), 0);
832   QCOMPARE(forParamCtx->localDeclarations().count(), 1);
833   QVERIFY(forParamCtx->localScopeIdentifier().isEmpty());
834
835   Declaration* defI = forParamCtx->localDeclarations().first();
836   QCOMPARE(defI->identifier(), Identifier("i"));
837   QCOMPARE(defI->uses().count(), 1);
838   QCOMPARE(defI->uses().begin()->count(), 4);
839
840   QCOMPARE(findDeclaration(forCtx, defI->identifier()), defI);
841
842   DUContext* ifCtx = forCtx->childContexts()[1];
843   QVERIFY(ifCtx->parentContext());
844   QCOMPARE(ifCtx->importedParentContexts().count(), 1);
845   QCOMPARE(ifCtx->childContexts().count(), 0);
846   QCOMPARE(ifCtx->localDeclarations().count(), 0);
847   QVERIFY(ifCtx->localScopeIdentifier().isEmpty());
848
849   QCOMPARE(findDeclaration(ifCtx,  defI->identifier()), defI);
850
851 }
852
853
854 void TestDUChain::testEnum()
855 {
856   TEST_FILE_PARSE_ONLY
857
858 /*                   0         1         2         3         4         5         6         7
859                      01234567890123456789012345678901234567890123456789012345678901234567890123456789*/
860   QByteArray method("enum Enum { Value1 = 5 //Comment\n, value2 //Comment1\n }; enum Enum2 { Value21, value22 = 0x02 }; union { int u1; float u2; };");
861
862   LockedTopDUContext top = parse(method, DumpNone);
863 /*  {
864     Declaration* decl = findDeclaration(top, QualifiedIdentifier("Value1"));
865     QVERIFY(decl);
866     AbstractType::Ptr t = decl->abstractType();
867     QVERIFY(t);
868     IdentifiedType* id = dynamic_cast<IdentifiedType*>(t.unsafeData());
869     QVERIFY(id);
870     QCOMPARE(id->declaration(top), decl);
871   }*/
872
873   QCOMPARE(top->localDeclarations().count(), 3);
874   QCOMPARE(top->childContexts().count(), 3);
875
876   QVERIFY(top->childContexts()[2]->inSymbolTable());
877   
878   ///@todo Test for the enum ranges and fix them, they overlap
879   kDebug() << top->childContexts()[0]->range().textRange();
880   kDebug() << top->localDeclarations()[0]->range().textRange();
881
882   Declaration* decl = findDeclaration(top, Identifier("Enum"));
883   Declaration* enumDecl = decl;
884   QVERIFY(decl);
885   QVERIFY(decl->internalContext());
886   AbstractType::Ptr t = decl->abstractType();
887   QVERIFY(dynamic_cast<EnumerationType*>(t.unsafeData()));
888   EnumerationType* en = static_cast<EnumerationType*>(t.unsafeData());
889   QVERIFY(en->declaration(top));
890   QCOMPARE(en->qualifiedIdentifier(), QualifiedIdentifier("Enum"));
891   Declaration* EnumDecl = decl;
892
893   {
894     QVERIFY(!top->findLocalDeclarations(Identifier("Value1")).isEmpty());
895
896     decl = findDeclaration(top, QualifiedIdentifier("Value1"));
897     QVERIFY(decl);
898
899     QCOMPARE(decl->context()->owner(), enumDecl);
900 //     QCOMPARE(decl->context()->scopeIdentifier(), QualifiedIdentifier("Enum"));
901
902
903     t = decl->abstractType();
904     QVERIFY(dynamic_cast<EnumeratorType*>(t.unsafeData()));
905     EnumeratorType* en = static_cast<EnumeratorType*>(t.unsafeData());
906     QCOMPARE((int)en->value<qint64>(), 5);
907     kDebug() << decl->qualifiedIdentifier().toString();
908     kDebug() << en->toString();
909     QCOMPARE(en->declaration(top), top->childContexts()[0]->localDeclarations()[0]);
910
911     decl = findDeclaration(top, Identifier("value2"));
912     QVERIFY(decl);
913     t = decl->abstractType();
914     QVERIFY(dynamic_cast<EnumeratorType*>(t.unsafeData()));
915     en = static_cast<EnumeratorType*>(t.unsafeData());
916     QCOMPARE((int)en->value<qint64>(), 6);
917     QCOMPARE(en->declaration(top), top->childContexts()[0]->localDeclarations()[1]);
918     QCOMPARE(en->declaration(top)->context()->owner(), EnumDecl);
919   }
920   decl = findDeclaration(top, Identifier("Enum2"));
921   QVERIFY(decl);
922   t = decl->abstractType();
923   QVERIFY(dynamic_cast<EnumerationType*>(t.unsafeData()));
924   en = static_cast<EnumerationType*>(t.unsafeData());
925   QVERIFY(en->declaration(top));
926   QCOMPARE(en->qualifiedIdentifier(), QualifiedIdentifier("Enum2"));
927   Declaration* Enum2Decl = decl;
928
929   {
930     decl = findDeclaration(top, Identifier("Value21"));
931     QVERIFY(decl);
932     t = decl->abstractType();
933     QVERIFY(dynamic_cast<EnumeratorType*>(t.unsafeData()));
934     EnumeratorType* en = static_cast<EnumeratorType*>(t.unsafeData());
935     QCOMPARE((int)en->value<qint64>(), 0);
936     QCOMPARE(en->declaration(top)->context()->owner(), Enum2Decl);
937
938     decl = findDeclaration(top, Identifier("value22"));
939     QVERIFY(decl);
940     t = decl->abstractType();
941     QVERIFY(dynamic_cast<EnumeratorType*>(t.unsafeData()));
942     en = static_cast<EnumeratorType*>(t.unsafeData());
943     QCOMPARE((int)en->value<qint64>(), 2);
944     QCOMPARE(en->declaration(top)->context()->owner(), Enum2Decl);
945   }
946   {
947     //Verify that the union members were propagated up
948     decl = findDeclaration(top, Identifier("u1"));
949     QVERIFY(decl);
950
951     decl = findDeclaration(top, Identifier("u2"));
952     QVERIFY(decl);
953   }
954 }
955
956 /*! Custom assertion which verifies that @p topcontext contains a
957  *  single class with a single memberfunction declaration in it.
958  *  @p memberFun is an output parameter and should have type
959  *  pointer to ClassFunctionDeclaration */
960 #define ASSERT_SINGLE_MEMBER_FUNCTION_IN(topcontext, memberFun) \
961 { \
962     QVERIFY(top);\
963     QCOMPARE(1, top->childContexts().count());\
964     QCOMPARE(1, top->localDeclarations().count()); \
965     DUContext* clazzCtx = top->childContexts()[0]; \
966     QCOMPARE(1, clazzCtx->localDeclarations().count()); \
967     Declaration* member = clazzCtx->localDeclarations()[0]; \
968     memberFun = dynamic_cast<ClassFunctionDeclaration*>(member); \
969     QVERIFY(memberFun); \
970 } (void)(0)
971
972 /*! Custom assertion which verifies that @p topcontext contains a
973  *  single class with two memberfunction declarations in it.
974  *  @p memberFun1 and @p memberFUn2 are output parameter and should
975  *  have type pointer to ClassFunctionDeclaration */
976 #define ASSERT_TWO_MEMBER_FUNCTIONS_IN(topcontext, memberFun1, memberFun2) \
977 { \
978     QVERIFY(top);\
979     QCOMPARE(1, top->childContexts().count());\
980     QCOMPARE(1, top->localDeclarations().count()); \
981     DUContext* clazzCtx = top->childContexts()[0]; \
982     QCOMPARE(2, clazzCtx->localDeclarations().count()); \
983     Declaration* member = clazzCtx->localDeclarations()[0]; \
984     memberFun1 = dynamic_cast<ClassFunctionDeclaration*>(member); \
985     QVERIFY(memberFun1); \
986     member = clazzCtx->localDeclarations()[1]; \
987     memberFun2 = dynamic_cast<ClassFunctionDeclaration*>(member); \
988     QVERIFY(memberFun2); \
989 } (void)(0)
990
991 void TestDUChain::testVirtualMemberFunction()
992 {
993   {
994     QByteArray text("class Foo { public: virtual void bar(const float i, const int i) = 0; }; \n");
995     LockedTopDUContext top = parse(text, DumpAll);
996
997     ClassFunctionDeclaration* memberFun; // filled by assert macro below
998     ASSERT_SINGLE_MEMBER_FUNCTION_IN(top, memberFun);
999     QVERIFY(memberFun->isVirtual());
1000     QVERIFY(memberFun->isAbstract());
1001     FunctionType::Ptr funType = memberFun->abstractType().cast<FunctionType>();
1002     QVERIFY(funType);
1003     QCOMPARE(funType->arguments().size(), 2);
1004     QCOMPARE(funType->arguments()[0]->toString(), QString("const float"));
1005     QCOMPARE(funType->arguments()[1]->toString(), QString("const int"));
1006   }
1007   {
1008     QByteArray text("class Foo { public: virtual void bar(); }; \n");
1009     LockedTopDUContext top = parse(text, DumpNone);
1010
1011     ClassFunctionDeclaration* memberFun; // filled by assert macro below
1012     ASSERT_SINGLE_MEMBER_FUNCTION_IN(top, memberFun);
1013     QVERIFY(memberFun->isVirtual());
1014     QVERIFY(!memberFun->isAbstract());
1015   }
1016   {
1017     //Forward-declarations with "struct" or "class" are considered equal, so make sure the override is detected correctly.
1018     QByteArray text("class S; struct A { virtual S* ret(); }; struct S { }; struct B : public A { virtual S* ret(); };");
1019     LockedTopDUContext top = parse(text, DumpNone);
1020
1021     QCOMPARE(top->childContexts().count(), 3);
1022     QCOMPARE(top->localDeclarations().count(), 4);
1023     QCOMPARE(top->localDeclarations()[0]->indexedType(), top->localDeclarations()[2]->indexedType());
1024     QCOMPARE(top->childContexts()[2]->localDeclarations().count(), 1);
1025     QVERIFY(DUChainUtils::getOverridden(top->childContexts()[2]->localDeclarations()[0]));
1026
1027   }
1028 }
1029
1030 void TestDUChain::testMultipleVirtual()
1031 {
1032     QByteArray text("class Foo { public: virtual void bar(); virtual void baz(); }; \n");
1033     LockedTopDUContext top = parse(text, DumpNone);
1034
1035     ClassFunctionDeclaration *bar, *baz; // filled by assert macro below
1036     ASSERT_TWO_MEMBER_FUNCTIONS_IN(top, bar, baz);
1037     QVERIFY(bar->isVirtual());
1038     QVERIFY(baz->isVirtual());
1039     QVERIFY(!baz->isAbstract());
1040 }
1041
1042 void TestDUChain::testMixedVirtualNormal()
1043 {
1044   {
1045     QByteArray text("class Foo { public: virtual void bar(); void baz(); }; \n");
1046     LockedTopDUContext top = parse(text, DumpNone);
1047
1048     ClassFunctionDeclaration *bar, *baz; // filled by assert macro below
1049     ASSERT_TWO_MEMBER_FUNCTIONS_IN(top, bar, baz);
1050     QVERIFY(bar->isVirtual());
1051     QVERIFY(!baz->isVirtual());
1052     QVERIFY(!baz->isAbstract());
1053   }
1054 }
1055
1056 void TestDUChain::testNonVirtualMemberFunction()
1057 {
1058   {
1059     QByteArray text("class Foo \n { public: void bar(); };\n");
1060     LockedTopDUContext top = parse(text, DumpNone);
1061
1062     ClassFunctionDeclaration* memberFun; // filled by assert macro below
1063     ASSERT_SINGLE_MEMBER_FUNCTION_IN(top, memberFun);
1064     QVERIFY(!memberFun->isVirtual());
1065     QVERIFY(!memberFun->isAbstract());
1066   }
1067 }
1068
1069 /*! Extract memberfunction from @p topcontext in the @p nrofClass 'th class
1070  *  declaration. Assert that it is named @p expectedName. Fill the outputparameter
1071  *  @p memberFun */
1072 #define FETCH_MEMBER_FUNCTION(nrofClass, topcontext, expectedName, memberFun) \
1073 { \
1074     QVERIFY(top);\
1075     DUContext* clazzCtx = top->childContexts()[nrofClass]; \
1076     QCOMPARE(1, clazzCtx->localDeclarations().count()); \
1077     Declaration* member = clazzCtx->localDeclarations()[0]; \
1078     memberFun = dynamic_cast<ClassFunctionDeclaration*>(member); \
1079     QVERIFY(memberFun); \
1080     QCOMPARE(QString(expectedName), memberFun->toString()); \
1081 } (void)(0)
1082
1083 void TestDUChain::testMemberFunctionModifiers()
1084 {
1085   // NOTE this only verifies
1086   //      {no member function modifiers in code} => {no modifiers in duchain}
1087   // it does not check that (but probably should, with all permutations ;))
1088   //      {member function modifiers in code} => {exactly the same modifiers in duchain}
1089   //      {illegal combinations, eg explicit not on a constructor} => {error/warning}
1090   {
1091       QByteArray text("class FuBarr { void foo(); };\n"
1092                       "class ZooLoo { void bar(); };\n\n"
1093                       "class MooFoo \n { public: void loo(); };\n"
1094                       "class GooRoo { void baz(); };\n"
1095                       "class PooYoo { \n void zoo(); };\n");
1096       // at one point extra '\n' characters would affect these modifiers.
1097       LockedTopDUContext top = parse(text, DumpNone);
1098
1099       ClassFunctionDeclaration *foo, *bar, *loo, *baz, *zoo; // filled below
1100       FETCH_MEMBER_FUNCTION(0, top, "void foo ()", foo);
1101       FETCH_MEMBER_FUNCTION(1, top, "void bar ()", bar);
1102       FETCH_MEMBER_FUNCTION(2, top, "void loo ()", loo);
1103       FETCH_MEMBER_FUNCTION(3, top, "void baz ()", baz);
1104       FETCH_MEMBER_FUNCTION(4, top, "void zoo ()", zoo);
1105
1106       assertNoMemberFunctionModifiers(foo);
1107       assertNoMemberFunctionModifiers(bar);
1108       assertNoMemberFunctionModifiers(loo);
1109       assertNoMemberFunctionModifiers(baz);
1110       assertNoMemberFunctionModifiers(zoo);
1111
1112   }
1113
1114 }
1115
1116 void TestDUChain::assertNoMemberFunctionModifiers(ClassFunctionDeclaration* memberFun)
1117 {
1118     AbstractType::Ptr t(memberFun->abstractType());
1119     Q_ASSERT(t);
1120     bool isConstant = t->modifiers() & AbstractType::ConstModifier;
1121     bool isVolatile = t->modifiers() & AbstractType::VolatileModifier;
1122
1123     kDebug() << memberFun->toString() << "virtual?"  << memberFun->isVirtual()
1124                                       << "explicit?" << memberFun->isExplicit()
1125                                       << "inline?"   << memberFun->isInline()
1126                                       << "constant?" << isConstant
1127                                       << "volatile?" << isVolatile
1128                                       << "static?"   << memberFun->isStatic();
1129     QVERIFY(!memberFun->isVirtual());
1130     QVERIFY(!memberFun->isExplicit());
1131     QVERIFY(!memberFun->isInline());
1132     QVERIFY(!isConstant);
1133     QVERIFY(!isVolatile);
1134     QVERIFY(!memberFun->isStatic());
1135 }
1136
1137
1138 void TestDUChain::testAssignedContexts()
1139 {
1140   {
1141     QByteArray method("void test() { int i; if(i) { int q; }  int c; while(c) { char q; } int w; { float q;  } }");
1142
1143     LockedTopDUContext top = parse(method, DumpNone);
1144
1145     QCOMPARE(top->childContexts().count(), 2);
1146     QCOMPARE(top->childContexts()[1]->type(), DUContext::Other);
1147     QCOMPARE(top->childContexts()[1]->childContexts().count(), 4);
1148     QCOMPARE(top->childContexts()[1]->localDeclarations().count(), 3);
1149     QVERIFY(!top->childContexts()[1]->childContexts()[0]->owner());
1150     QVERIFY(!top->childContexts()[1]->childContexts()[1]->owner());
1151     QVERIFY(!top->childContexts()[1]->childContexts()[2]->owner());
1152     QVERIFY(!top->childContexts()[1]->childContexts()[3]->owner());
1153   }
1154 }
1155
1156 void TestDUChain::testTryCatch() {
1157   TEST_FILE_PARSE_ONLY
1158   {
1159     QByteArray method("void test() { try{ int o = 3; o += 3; } catch (...) { } }");
1160
1161     LockedTopDUContext top = parse(method, DumpNone);
1162
1163     QCOMPARE(top->childContexts().count(), 2);
1164     QCOMPARE(top->childContexts()[1]->type(), DUContext::Other);
1165     QCOMPARE(top->childContexts()[1]->childContexts().count(), 2);
1166     QCOMPARE(top->childContexts()[1]->childContexts()[0]->usesCount(), 1);
1167   }
1168 }
1169
1170 void TestDUChain::testDeclareStruct()
1171 {
1172   TEST_FILE_PARSE_ONLY
1173 //   {
1174 //     QByteArray method("struct { short i; } instance;");
1175 // 
1176 //     LockedTopDUContext top = parse(method, DumpNone);
1177 // 
1178 //     QVERIFY(!top->parentContext());
1179 //     QCOMPARE(top->childContexts().count(), 1);
1180 //     QCOMPARE(top->localDeclarations().count(), 2);
1181 //     QVERIFY(top->localScopeIdentifier().isEmpty());
1182 // 
1183 //     AbstractType::Ptr t = top->localDeclarations()[0]->abstractType();
1184 //     IdentifiedType* idType = dynamic_cast<IdentifiedType*>(t.unsafeData());
1185 //     QVERIFY(idType);
1186 //     QVERIFY(idType->qualifiedIdentifier().count() == 1);
1187 //     QVERIFY(idType->qualifiedIdentifier().at(0).uniqueToken());
1188 // 
1189 //     Declaration* defStructA = top->localDeclarations().first();
1190 // 
1191 //     QCOMPARE(top->localDeclarations()[1]->abstractType()->indexed(), top->localDeclarations()[0]->abstractType()->indexed());
1192 // 
1193 //     QCOMPARE(idType->declaration(top), defStructA);
1194 //     QVERIFY(defStructA->type<CppClassType>());
1195 //     QVERIFY(defStructA->internalContext());
1196 //     QCOMPARE(defStructA->internalContext()->localDeclarations().count(), 1);
1197 //     Cpp::ClassDeclaration* classDecl = dynamic_cast<Cpp::ClassDeclaration*>(top->localDeclarations()[0]);
1198 //     QVERIFY(classDecl);
1199 // 
1200 //     QCOMPARE(classDecl->classType(), Cpp::ClassDeclarationData::Struct);
1201 // 
1202 //   }
1203     //                 0         1         2         3         4         5         6         7
1204     //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1205   {
1206     QByteArray method("class A { public: union { struct { int x; }; int p; }; struct { int b; }; struct { int c; } cc; }; A test; void test() { test.x = 1; test.b = 1; test.p = 1; test.cc.c = 1; }");
1207
1208     LockedTopDUContext top = parse(method, DumpNone);
1209
1210     QCOMPARE(top->childContexts().count(), 3);
1211     QCOMPARE(top->childContexts()[0]->childContexts().count(), 3);
1212     QCOMPARE(top->childContexts()[0]->childContexts()[2]->localDeclarations().count(), 1);
1213     QVERIFY(!top->childContexts()[0]->childContexts()[2]->localDeclarations()[0]->uses().isEmpty());
1214     QCOMPARE(top->childContexts()[0]->childContexts()[1]->localDeclarations().count(), 1);
1215     QVERIFY(top->childContexts()[0]->childContexts()[1]->isPropagateDeclarations());
1216     QVERIFY(top->childContexts()[0]->childContexts()[0]->isPropagateDeclarations());
1217     QVERIFY(top->childContexts()[0]->childContexts()[0]->inSymbolTable());
1218     QVERIFY(top->childContexts()[0]->childContexts()[1]->inSymbolTable());
1219     QVERIFY(top->childContexts()[0]->childContexts()[0]->localScopeIdentifier().isEmpty());
1220     QVERIFY(top->childContexts()[0]->childContexts()[1]->localScopeIdentifier().isEmpty());
1221     QVERIFY(!top->childContexts()[0]->childContexts()[1]->localDeclarations()[0]->uses().isEmpty());
1222     QCOMPARE(top->childContexts()[0]->childContexts()[0]->childContexts().count(), 1);
1223     QCOMPARE(top->childContexts()[0]->childContexts()[0]->childContexts()[0]->localDeclarations().count(), 1);
1224     QVERIFY(top->childContexts()[0]->childContexts()[0]->isPropagateDeclarations());
1225     QVERIFY(top->childContexts()[0]->childContexts()[0]->childContexts()[0]->isPropagateDeclarations());
1226     QVERIFY(!top->childContexts()[0]->childContexts()[0]->childContexts()[0]->localDeclarations()[0]->uses().isEmpty());
1227     QCOMPARE(top->childContexts()[2]->usesCount(), 9);
1228              
1229   }
1230
1231   {
1232     //                 0         1         2         3         4         5         6         7
1233     //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1234     QByteArray method("typedef struct { short i; } A; A instance;");
1235
1236     LockedTopDUContext top = parse(method, DumpNone);
1237
1238     QVERIFY(!top->parentContext());
1239     QCOMPARE(top->childContexts().count(), 1);
1240     QCOMPARE(top->localDeclarations().count(), 3);
1241     QVERIFY(top->localScopeIdentifier().isEmpty());
1242
1243     AbstractType::Ptr t = top->localDeclarations()[0]->abstractType();
1244     IdentifiedType* idType = dynamic_cast<IdentifiedType*>(t.unsafeData());
1245     QVERIFY(idType);
1246     QVERIFY(idType->qualifiedIdentifier().count() == 1);
1247     QVERIFY(idType->qualifiedIdentifier().at(0).uniqueToken());
1248
1249     QVERIFY(top->localDeclarations()[1]->isTypeAlias());
1250     QCOMPARE(top->localDeclarations()[1]->identifier(), Identifier("A"));
1251     QCOMPARE(top->localDeclarations()[2]->abstractType()->indexed(), top->localDeclarations()[1]->abstractType()->indexed());
1252
1253     QCOMPARE(top->localDeclarations()[1]->uses().count(), 1);
1254     QCOMPARE(top->localDeclarations()[1]->uses().begin()->count(), 1);
1255
1256     Declaration* defStructA = top->localDeclarations().first();
1257     QVERIFY(!defStructA->isTypeAlias());
1258     QVERIFY(defStructA->identifier().uniqueToken());
1259
1260     QCOMPARE(idType->declaration(top), defStructA);
1261     QVERIFY(defStructA->type<CppClassType>());
1262     QVERIFY(defStructA->internalContext());
1263     QCOMPARE(defStructA->internalContext()->localDeclarations().count(), 1);
1264     ClassDeclaration* classDecl = dynamic_cast<ClassDeclaration*>(defStructA);
1265     QVERIFY(classDecl);
1266     QCOMPARE(classDecl->classType(), ClassDeclarationData::Struct);
1267
1268     QVERIFY(!findDeclaration(top, Identifier("i")));
1269     QVERIFY(findDeclaration(top, QualifiedIdentifier("A::i")));
1270     
1271   }
1272   {
1273     //                 0         1         2         3         4         5         6         7
1274     //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1275     QByteArray method("typedef struct B A; A instance;");
1276
1277     LockedTopDUContext top = parse(method, DumpNone);
1278
1279     QVERIFY(!top->parentContext());
1280     QCOMPARE(top->localDeclarations().count(), 3);
1281     QVERIFY(top->localScopeIdentifier().isEmpty());
1282
1283     AbstractType::Ptr t = top->localDeclarations()[0]->abstractType();
1284     IdentifiedType* idType = dynamic_cast<IdentifiedType*>(t.unsafeData());
1285     QVERIFY(idType);
1286     QVERIFY(idType->qualifiedIdentifier().count() == 1);
1287
1288     QVERIFY(top->localDeclarations()[1]->isTypeAlias());
1289     QCOMPARE(top->localDeclarations()[1]->identifier(), Identifier("A"));
1290     QCOMPARE(top->localDeclarations()[2]->abstractType()->indexed(), top->localDeclarations()[1]->abstractType()->indexed());
1291
1292     QCOMPARE(top->localDeclarations()[1]->uses().count(), 1);
1293     QCOMPARE(top->localDeclarations()[1]->uses().begin()->count(), 1);
1294
1295     Declaration* defStructA = top->localDeclarations().first();
1296     QVERIFY(!defStructA->isTypeAlias());
1297     QVERIFY(defStructA->isForwardDeclaration());
1298     
1299   }  
1300   {
1301     //                 0         1         2         3         4         5         6         7
1302     //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1303     QByteArray method("struct A { short i; A(int b, int c) : i(c) { } virtual void test(int j) = 0; }; A instance;");
1304
1305     LockedTopDUContext top = parse(method, DumpNone);
1306
1307     QVERIFY(!top->parentContext());
1308     QCOMPARE(top->childContexts().count(), 1);
1309     QCOMPARE(top->localDeclarations().count(), 2);
1310     QVERIFY(top->localScopeIdentifier().isEmpty());
1311
1312     AbstractType::Ptr t = top->localDeclarations()[1]->abstractType();
1313     IdentifiedType* idType = dynamic_cast<IdentifiedType*>(t.unsafeData());
1314     QVERIFY(idType);
1315     QCOMPARE( idType->qualifiedIdentifier(), QualifiedIdentifier("A") );
1316
1317     Declaration* defStructA = top->localDeclarations().first();
1318     QCOMPARE(defStructA->identifier(), Identifier("A"));
1319     QCOMPARE(defStructA->uses().count(), 1);
1320     QCOMPARE(defStructA->uses().begin()->count(), 1);
1321     QVERIFY(defStructA->type<CppClassType>());
1322     ClassDeclaration* classDecl = dynamic_cast<ClassDeclaration*>(defStructA);
1323     QVERIFY(classDecl);
1324     QCOMPARE(classDecl->classType(), ClassDeclarationData::Struct);
1325
1326     DUContext* structA = top->childContexts().first();
1327     QVERIFY(structA->parentContext());
1328     QCOMPARE(structA->importedParentContexts().count(), 0);
1329     QCOMPARE(structA->childContexts().count(), 3);
1330     QCOMPARE(structA->localDeclarations().count(), 3);
1331     QCOMPARE(structA->localScopeIdentifier(), QualifiedIdentifier("A"));
1332
1333     Declaration* defI = structA->localDeclarations().first();
1334     QCOMPARE(defI->identifier(), Identifier("i"));
1335     QCOMPARE(defI->uses().count(), 1);
1336     QCOMPARE(defI->uses().begin()->count(), 1);
1337
1338     QCOMPARE(findDeclaration(structA,  Identifier("i")), defI);
1339     QCOMPARE(findDeclaration(structA,  Identifier("b")), noDef);
1340     QCOMPARE(findDeclaration(structA,  Identifier("c")), noDef);
1341
1342     DUContext* ctorImplCtx = structA->childContexts()[1];
1343     QVERIFY(ctorImplCtx->parentContext());
1344     QCOMPARE(ctorImplCtx->importedParentContexts().count(), 1);
1345     QCOMPARE(ctorImplCtx->childContexts().count(), 1);
1346     QCOMPARE(ctorImplCtx->localDeclarations().count(), 0);
1347     QVERIFY(!ctorImplCtx->localScopeIdentifier().isEmpty());
1348     QVERIFY(ctorImplCtx->owner());
1349
1350     DUContext* ctorCtx = ctorImplCtx->importedParentContexts().first().context(0);
1351     QVERIFY(ctorCtx->parentContext());
1352     QCOMPARE(ctorCtx->childContexts().count(), 0);
1353     QCOMPARE(ctorCtx->localDeclarations().count(), 2);
1354     QCOMPARE(ctorCtx->localScopeIdentifier(), QualifiedIdentifier("A")); ///@todo check if it should really be this way
1355
1356     Declaration* defB = ctorCtx->localDeclarations().first();
1357     QCOMPARE(defB->identifier(), Identifier("b"));
1358     QCOMPARE(defB->uses().count(), 0);
1359
1360     Declaration* defC = ctorCtx->localDeclarations()[1];
1361     QCOMPARE(defC->identifier(), Identifier("c"));
1362     QCOMPARE(defC->uses().count(), 1);
1363     QCOMPARE(defC->uses().begin()->count(), 1);
1364
1365     Declaration* defTest = structA->localDeclarations()[2];
1366     QCOMPARE(defTest->identifier(), Identifier("test"));
1367     ClassFunctionDeclaration* classFunDecl = dynamic_cast<ClassFunctionDeclaration*>(defTest);
1368     QVERIFY(classFunDecl);
1369     QVERIFY(classFunDecl->isAbstract());
1370
1371     QCOMPARE(findDeclaration(ctorCtx,  Identifier("i")), defI);
1372     QCOMPARE(findDeclaration(ctorCtx,  Identifier("b")), defB);
1373     QCOMPARE(findDeclaration(ctorCtx,  Identifier("c")), defC);
1374
1375     DUContext* testCtx = structA->childContexts().last();
1376     QCOMPARE(testCtx->childContexts().count(), 0);
1377     QCOMPARE(testCtx->localDeclarations().count(), 1);
1378     QCOMPARE(testCtx->localScopeIdentifier(), QualifiedIdentifier("test")); ///@todo check if it should really be this way
1379
1380     Declaration* defJ = testCtx->localDeclarations().first();
1381     QCOMPARE(defJ->identifier(), Identifier("j"));
1382     QCOMPARE(defJ->uses().count(), 0);
1383
1384     /*DUContext* insideCtorCtx = ctorCtx->childContexts().first();
1385     QCOMPARE(insideCtorCtx->childContexts().count(), 0);
1386     QCOMPARE(insideCtorCtx->localDeclarations().count(), 0);
1387     QVERIFY(insideCtorCtx->localScopeIdentifier().isEmpty());*/
1388
1389   }
1390   {
1391     //                 0         1         2         3         4         5         6         7
1392     //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1393     QByteArray method("struct A { short i; }; struct A instance; void test(struct A * a) { a->i = instance.i; };");
1394
1395     LockedTopDUContext top = parse(method, DumpNone);
1396
1397     QVERIFY(!top->parentContext());
1398     QCOMPARE(top->childContexts().count(), 3);
1399     QCOMPARE(top->localDeclarations().count(), 3);
1400     QVERIFY(top->localScopeIdentifier().isEmpty());
1401
1402     Declaration* defStructA = top->localDeclarations().first();
1403     QCOMPARE(defStructA->identifier(), Identifier("A"));
1404     QCOMPARE(defStructA->uses().count(), 1);
1405     QCOMPARE(defStructA->uses().begin()->count(), 2);
1406     QVERIFY(defStructA->type<CppClassType>());
1407     ClassDeclaration* classDecl = dynamic_cast<ClassDeclaration*>(defStructA);
1408     QVERIFY(classDecl);
1409     QCOMPARE(classDecl->classType(), ClassDeclarationData::Struct);
1410
1411     DUContext* structA = top->childContexts().first();
1412     QCOMPARE(structA->parentContext(), top.m_top);
1413     QCOMPARE(structA->importedParentContexts().count(), 0);
1414     QCOMPARE(structA->childContexts().count(), 0);
1415     QCOMPARE(structA->localDeclarations().count(), 1);
1416     QCOMPARE(structA->localScopeIdentifier(), QualifiedIdentifier("A"));
1417
1418     Declaration* defI = structA->localDeclarations().first();
1419     QCOMPARE(defI->identifier(), Identifier("i"));
1420     QCOMPARE(defI->uses().count(), 1);
1421     QCOMPARE(defI->uses().begin()->count(), 2);
1422
1423     QCOMPARE(findDeclaration(structA,  Identifier("i")), defI);
1424
1425   }
1426 }
1427
1428 void TestDUChain::testDeclareStructInNamespace()
1429 {
1430   TEST_FILE_PARSE_ONLY
1431
1432   {
1433     QByteArray method("namespace A { class B { class C; } ; } namespace A { class A::B::C { }; }");
1434     
1435     LockedTopDUContext top = parse(method, DumpAll);
1436     
1437     QCOMPARE(top->childContexts().count(), 2);
1438     QCOMPARE(top->childContexts()[0]->childContexts().size(), 1);
1439     QCOMPARE(top->childContexts()[0]->childContexts()[0]->localDeclarations().size(), 1);
1440     
1441     ForwardDeclaration* forwardDecl = dynamic_cast<ForwardDeclaration*>(top->childContexts()[0]->childContexts()[0]->localDeclarations()[0]);
1442     QVERIFY(forwardDecl);
1443     QVERIFY(forwardDecl->resolve(top));
1444     
1445   }
1446
1447   {
1448     //                 0         1         2         3         4         5         6         7
1449     //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1450     QByteArray method("struct A {A(); struct B;}; struct A::B { B(); struct C; }; struct A::B::C { A mem; B mem2; void test(A param); }; void A::B::C::test(A param) {};");
1451
1452     LockedTopDUContext top = parse(method, DumpNone);
1453
1454     QVERIFY(!top->parentContext());
1455     QCOMPARE(top->childContexts().count(), 5);
1456     QCOMPARE(top->localDeclarations().count(), 2); //Only one declaration, because the others are nested within helper scope contexts
1457     
1458     QCOMPARE(top->childContexts()[1]->localDeclarations().count(), 1);
1459     QCOMPARE(top->childContexts()[2]->localDeclarations().count(), 1);
1460     QCOMPARE(top->childContexts()[3]->localDeclarations().count(), 1);
1461     
1462     QCOMPARE(top->childContexts()[2]->localScopeIdentifier(), QualifiedIdentifier("A::B"));
1463     QCOMPARE(top->childContexts()[2]->childContexts()[0]->localScopeIdentifier(), QualifiedIdentifier("C"));
1464     QCOMPARE(top->childContexts()[2]->childContexts()[0]->scopeIdentifier(true), QualifiedIdentifier("A::B::C"));
1465     QCOMPARE(top->childContexts()[2]->localDeclarations()[0]->qualifiedIdentifier(), QualifiedIdentifier("A::B::C"));
1466     QVERIFY(top->childContexts()[2]->inSymbolTable());
1467     QVERIFY(top->childContexts()[2]->childContexts()[0]->inSymbolTable());
1468     QVERIFY(top->childContexts()[2]->localDeclarations()[0]->inSymbolTable());
1469     
1470     QualifiedIdentifier search("::A::B::C");
1471     Declaration* cDecl = findDeclaration(top, search);
1472     QVERIFY(cDecl);
1473     QVERIFY(cDecl->logicalInternalContext(top));
1474     QVERIFY(cDecl);
1475     QVERIFY(!cDecl->isForwardDeclaration());
1476     QVERIFY(cDecl->internalContext());
1477     
1478     QCOMPARE(top->childContexts()[2]->childContexts().count(), 1);
1479     QCOMPARE(top->childContexts()[2]->childContexts()[0]->localDeclarations().count(), 3);
1480     kDebug() << top->childContexts()[2]->childContexts()[0]->localDeclarations()[0]->abstractType()->toString();
1481     kDebug() << top->localDeclarations()[0]->abstractType()->toString();
1482     QCOMPARE(top->childContexts()[2]->childContexts()[0]->localDeclarations()[0]->indexedType(), top->localDeclarations()[0]->indexedType());
1483     QCOMPARE(top->childContexts()[2]->childContexts()[0]->localDeclarations()[1]->indexedType(), top->childContexts()[1]->localDeclarations()[0]->indexedType());
1484     kDebug() << top->childContexts()[3]->localDeclarations()[0]->abstractType()->toString();
1485     kDebug() << top->localDeclarations()[0]->abstractType()->toString();
1486     QCOMPARE(top->childContexts()[3]->localDeclarations()[0]->indexedType(), top->localDeclarations()[0]->indexedType());
1487
1488   }
1489   //                 0         1         2         3         4         5         6         7
1490   //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1491   {
1492     QByteArray method("namespace B {class C {struct A;void test();};};using namespace B;struct C::A {};");
1493
1494     LockedTopDUContext top = parse(method, DumpNone);
1495
1496     QVERIFY(!top->parentContext());
1497     QCOMPARE(top->childContexts().count(), 2);
1498     QCOMPARE(top->localDeclarations().count(), 2);
1499     QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 1);
1500     QCOMPARE(top->childContexts()[0]->childContexts().count(), 1);
1501     QCOMPARE(top->childContexts()[0]->childContexts()[0]->localDeclarations().count(), 2);
1502     QVERIFY(top->childContexts()[0]->childContexts()[0]->localDeclarations()[0]->isForwardDeclaration());
1503     KDevelop::ForwardDeclaration* forward = dynamic_cast<KDevelop::ForwardDeclaration*>(top->childContexts()[0]->childContexts()[0]->localDeclarations()[0]);
1504     QVERIFY(forward);
1505     QVERIFY(forward->resolve(top));
1506
1507   }
1508 }
1509 void TestDUChain::testCStruct()
1510 {
1511   TEST_FILE_PARSE_ONLY
1512
1513   //                 0         1         2         3         4         5         6         7
1514   //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1515   QByteArray method("struct A {int i; }; struct A instance; typedef struct { int a; } B, *BPointer;");
1516
1517   LockedTopDUContext top = parse(method, DumpNone);
1518
1519   QVERIFY(!top->parentContext());
1520   QCOMPARE(top->childContexts().count(), 2);
1521   QCOMPARE(top->localDeclarations().count(), 5);
1522
1523   QVERIFY(top->localDeclarations()[0]->kind() == Declaration::Type);
1524   QVERIFY(top->localDeclarations()[1]->kind() == Declaration::Instance);
1525
1526 }
1527
1528 void TestDUChain::testCStruct2()
1529 {
1530   TEST_FILE_PARSE_ONLY
1531
1532   //                 0         1         2         3         4         5         6         7
1533   //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1534   {
1535   QByteArray method("struct A {struct C c; }; struct C { int v; };");
1536
1537   //Expected result: the elaborated type-specifier "struct C" within the declaration "struct A" should create a new global declaration.
1538   
1539
1540   LockedTopDUContext top = parse(method, DumpNone);
1541
1542   QVERIFY(!top->parentContext());
1543   QCOMPARE(top->childContexts().count(), 2);
1544   QCOMPARE(top->localDeclarations().count(), 3); //3 declarations because the elaborated type-specifier "struct C" creates a forward-declaration on the global scope
1545   QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 1);
1546   kDebug() << "TYPE:" << top->childContexts()[0]->localDeclarations()[0]->abstractType()->toString() << typeid(*top->childContexts()[0]->localDeclarations()[0]->abstractType()).name();
1547   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->indexedType(), top->localDeclarations()[1]->indexedType());
1548
1549   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->kind(), Declaration::Instance);
1550   //QVERIFY(top->localDeclarations()[0]->kind() == Declaration::Type);
1551   //QVERIFY(top->localDeclarations()[1]->kind() == Declaration::Instance);
1552   }
1553   {
1554   QByteArray method("struct A {inline struct C c() {}; }; struct C { int v; };");
1555
1556   //Expected result: the elaborated type-specifier "struct C" within the declaration "struct A" should create a new global declaration.
1557   
1558
1559   LockedTopDUContext top = parse(method, DumpNone);
1560
1561   QVERIFY(!top->parentContext());
1562   QCOMPARE(top->childContexts().count(), 2);
1563   QCOMPARE(top->localDeclarations().count(), 3); //3 declarations because the elaborated type-specifier "struct C" creates a forward-declaration on the global scope
1564   QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 1);
1565   kDebug() << "TYPE:" << top->childContexts()[0]->localDeclarations()[0]->abstractType()->toString() << typeid(*top->childContexts()[0]->localDeclarations()[0]->abstractType()).name();
1566   FunctionType::Ptr function(top->childContexts()[0]->localDeclarations()[0]->type<FunctionType>());
1567   QVERIFY(function);
1568   kDebug() << "RETURN:" << function->returnType()->toString() << typeid(*function->returnType()).name();
1569   QCOMPARE(function->returnType()->indexed(), top->localDeclarations()[1]->indexedType());
1570   //QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->indexedType(), top->localDeclarations()[1]->indexedType());
1571
1572   //QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->kind(), Declaration::Instance);
1573   //QVERIFY(top->localDeclarations()[0]->kind() == Declaration::Type);
1574   //QVERIFY(top->localDeclarations()[1]->kind() == Declaration::Instance);
1575   }
1576
1577 }
1578
1579 void TestDUChain::testVariableDeclaration()
1580 {
1581   TEST_FILE_PARSE_ONLY
1582
1583   //                 0         1         2         3         4         5         6         7
1584   //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1585     QByteArray method("int c; A instance(c); A instance(2, 3); A instance(q); bla() {int* i = new A(c); }");
1586
1587   LockedTopDUContext top = parse(method, DumpNone);
1588
1589   QVERIFY(!top->parentContext());
1590   QCOMPARE(top->childContexts().count(), 2);
1591   QCOMPARE(top->localDeclarations().count(), 5);
1592   QCOMPARE(top->localDeclarations()[0]->uses().count(), 1);
1593   QCOMPARE(top->localDeclarations()[0]->uses().begin()->count(), 2);
1594   QVERIFY(top->localScopeIdentifier().isEmpty());
1595
1596 //   IdentifiedType* idType = dynamic_cast<IdentifiedType*>(top->localDeclarations()[1]->abstractType().data());
1597 //   QVERIFY(idType);
1598 //   QCOMPARE( idType->identifier(), QualifiedIdentifier("A") );
1599 //
1600 //   Declaration* defStructA = top->localDeclarations().first();
1601 //   QCOMPARE(defStructA->identifier(), Identifier("A"));
1602
1603 }
1604
1605 void TestDUChain::testDeclareClass()
1606 {
1607   TEST_FILE_PARSE_ONLY
1608
1609   //                 0         1         2         3         4         5         6         7
1610   //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1611   QByteArray method("class A { A() {}; A rec; void test(int); }; void A::test(int j) {}");
1612
1613   LockedTopDUContext top = parse(method, DumpNone);
1614
1615   DumpDotGraph dump;
1616 //  kDebug() << "dot-graph: \n" << dump.dotGraph(top, false);
1617
1618 //  kDebug() << "ENDE ENDE ENDE";
1619 //  kDebug() << "dot-graph: \n" << dump.dotGraph(top, false);
1620
1621   QVERIFY(!top->parentContext());
1622   QCOMPARE(top->childContexts().count(), 3);
1623   QCOMPARE(top->localDeclarations().count(), 2);
1624   QVERIFY(top->localScopeIdentifier().isEmpty());
1625
1626   Declaration* defClassA = top->localDeclarations().first();
1627   QCOMPARE(defClassA->identifier(), Identifier("A"));
1628   QCOMPARE(defClassA->uses().count(), 1);
1629   QCOMPARE(defClassA->uses().begin()->count(), 2);
1630   QVERIFY(defClassA->type<CppClassType>());
1631   QVERIFY(defClassA->internalContext());
1632   QCOMPARE(defClassA->internalContext()->range().start.column, 8); //The class-context should start directly behind the name
1633 //   QVERIFY(function);
1634 //   QCOMPARE(function->returnType(), typeVoid);
1635 //   QCOMPARE(function->arguments().count(), 1);
1636 //   QCOMPARE(function->arguments().first(), typeInt);
1637
1638   QVERIFY(defClassA->internalContext());
1639
1640   QCOMPARE(defClassA->internalContext()->localDeclarations().count(), 3);
1641   QCOMPARE(defClassA->internalContext()->localDeclarations()[1]->abstractType()->indexed(), defClassA->abstractType()->indexed());
1642
1643   DUContext* classA = top->childContexts().first();
1644   QVERIFY(classA->parentContext());
1645   QCOMPARE(classA->importedParentContexts().count(), 0);
1646   QCOMPARE(classA->childContexts().count(), 3);
1647   QCOMPARE(classA->localDeclarations().count(), 3);
1648   QCOMPARE(classA->localScopeIdentifier(), QualifiedIdentifier("A"));
1649
1650   Declaration* defRec = classA->localDeclarations()[1];
1651   QVERIFY(defRec->abstractType());
1652   QCOMPARE(defRec->abstractType()->indexed(), defClassA->abstractType()->indexed());
1653            
1654 }
1655
1656 void TestDUChain::testDeclareFriend()
1657 {
1658   TEST_FILE_PARSE_ONLY
1659
1660   //                 0         1         2         3         4         5         6         7
1661   //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1662   QByteArray method("class B {}; class A { friend class F; friend class B; }; ");
1663
1664   LockedTopDUContext top = parse(method, DumpNone);
1665
1666   DumpDotGraph dump;
1667 //  kDebug() << "dot-graph: \n" << dump.dotGraph(top, false);
1668
1669 //  kDebug() << "ENDE ENDE ENDE";
1670 //  kDebug() << "dot-graph: \n" << dump.dotGraph(top, false);
1671
1672   QVERIFY(!top->parentContext());
1673   QCOMPARE(top->childContexts().count(), 2);
1674   QCOMPARE(top->localDeclarations().count(), 3); //1 Forward-declaration of F
1675   QVERIFY(top->localScopeIdentifier().isEmpty());
1676
1677   Declaration* defClassA = top->localDeclarations()[1];
1678   QCOMPARE(defClassA->identifier(), Identifier("A"));
1679   QCOMPARE(defClassA->uses().count(), 0);
1680   QVERIFY(defClassA->type<CppClassType>());
1681   QVERIFY(defClassA->internalContext());
1682
1683   QCOMPARE(top->localDeclarations()[2]->identifier(), Identifier("F"));
1684   
1685   QCOMPARE(top->childContexts()[1]->localDeclarations().count(), 2); //friend-declaration
1686   QCOMPARE(top->childContexts()[1]->localDeclarations()[0]->identifier(), Identifier("friend"));
1687   QCOMPARE(top->childContexts()[1]->localDeclarations()[1]->identifier(), Identifier("friend"));
1688   
1689   QVERIFY(Cpp::isFriend(top->localDeclarations()[1], top->localDeclarations()[2]));
1690   QVERIFY(Cpp::isFriend(top->localDeclarations()[1], top->localDeclarations()[0]));
1691
1692   QVERIFY(top->localDeclarations()[0]->uses().size());
1693   QVERIFY(top->localDeclarations()[0]->uses().begin()->size());
1694   
1695 }
1696
1697 void TestDUChain::testDeclareNamespace()
1698 {
1699   TEST_FILE_PARSE_ONLY
1700
1701   //                 0         1         2         3         4         5         6         7
1702   //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1703   QByteArray method("namespace foo { int bar; } int bar; int test() { return foo::bar; }");
1704
1705   LockedTopDUContext top = parse(method, DumpNone);
1706
1707
1708   QVERIFY(!top->parentContext());
1709   QCOMPARE(top->childContexts().count(), 3);
1710   QCOMPARE(top->localDeclarations().count(), 3);
1711   QVERIFY(top->localScopeIdentifier().isEmpty());
1712   QCOMPARE(findDeclaration(top, Identifier("foo")), top->localDeclarations()[0]);
1713   QCOMPARE(top->childContexts()[0]->range(), SimpleRange(0, 14, 0, 26));
1714   QVERIFY(top->localDeclarations()[0]->inSymbolTable());
1715
1716   QVERIFY(top->localDeclarations()[0]->inSymbolTable());
1717   QVERIFY(top->localDeclarations()[0]->uses().size());
1718   
1719   DUContext* fooCtx = top->childContexts().first();
1720   QVERIFY(fooCtx->inSymbolTable());
1721   QCOMPARE(fooCtx->childContexts().count(), 0);
1722   QCOMPARE(fooCtx->localDeclarations().count(), 1);
1723   QCOMPARE(fooCtx->localScopeIdentifier(), QualifiedIdentifier("foo"));
1724   QCOMPARE(fooCtx->scopeIdentifier(), QualifiedIdentifier("foo"));
1725
1726   DUContext* testCtx = top->childContexts()[2];
1727   QCOMPARE(testCtx->childContexts().count(), 0);
1728   QCOMPARE(testCtx->localDeclarations().count(), 0);
1729   QCOMPARE(testCtx->localScopeIdentifier(), QualifiedIdentifier("test"));
1730   QCOMPARE(testCtx->scopeIdentifier(), QualifiedIdentifier("test"));
1731
1732   Declaration* bar2 = top->localDeclarations()[1];
1733   QCOMPARE(bar2->identifier(), Identifier("bar"));
1734   QCOMPARE(bar2->qualifiedIdentifier(), QualifiedIdentifier("bar"));
1735   QCOMPARE(bar2->uses().count(), 0);
1736
1737   Declaration* bar = fooCtx->localDeclarations().first();
1738   QCOMPARE(bar->identifier(), Identifier("bar"));
1739   QCOMPARE(bar->qualifiedIdentifier(), QualifiedIdentifier("foo::bar"));
1740   QCOMPARE(findDeclaration(testCtx,  QualifiedIdentifier("foo::bar")), bar);
1741   QCOMPARE(bar->uses().count(), 1);
1742   QCOMPARE(bar->uses().begin()->count(), 1);
1743   QCOMPARE(findDeclaration(top, bar->identifier()), bar2);
1744   QCOMPARE(findDeclaration(top, bar->qualifiedIdentifier()), bar);
1745
1746   QCOMPARE(findDeclaration(top, QualifiedIdentifier("bar")), bar2);
1747   QCOMPARE(findDeclaration(top, QualifiedIdentifier("::bar")), bar2);
1748   QCOMPARE(findDeclaration(top, QualifiedIdentifier("foo::bar")), bar);
1749   QCOMPARE(findDeclaration(top, QualifiedIdentifier("::foo::bar")), bar);
1750
1751   IndexedQualifiedIdentifier fooId(QualifiedIdentifier("foo"));
1752
1753   uint itemCount;
1754   const KDevelop::CodeModelItem* items;
1755   CodeModel::self().items(top->url(), itemCount, items);
1756   for(uint a = 0; a < itemCount; ++a) {
1757     if(items[a].id == fooId) {
1758       QCOMPARE(items[a].referenceCount, 1u); //Once by the namespace, once by the declaration
1759     }
1760   }
1761
1762 }
1763
1764 void TestDUChain::testDeclareNamespace2()
1765 {
1766   TEST_FILE_PARSE_ONLY
1767
1768   //                 0         1         2         3         4         5         6         7
1769   //                 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
1770   QByteArray method("struct A {}; namespace B { struct A : ::A {}; }");
1771
1772   LockedTopDUContext top = parse(method, DumpNone);
1773
1774   QVERIFY(!top->parentContext());
1775   QCOMPARE(top->localDeclarations().count(), 2);
1776   QCOMPARE(top->childContexts().count(), 2);
1777   QCOMPARE(top->childContexts()[1]->localDeclarations().count(), 1);
1778   
1779   CppClassType::Ptr outerA = top->localDeclarations()[0]->abstractType().cast<CppClassType>();
1780   CppClassType::Ptr innerA = top->childContexts()[1]->localDeclarations()[0]->abstractType().cast<CppClassType>();
1781   
1782   QVERIFY(outerA);
1783   QVERIFY(innerA);
1784   
1785   Declaration* klassDecl = innerA->declaration(top);
1786   ClassDeclaration* cppClassDecl = dynamic_cast<ClassDeclaration*>(klassDecl);
1787
1788   QVERIFY(cppClassDecl);
1789   QCOMPARE(cppClassDecl->baseClassesSize(), (uint)1);
1790   QCOMPARE(cppClassDecl->baseClasses()->baseClass, outerA->indexed());
1791
1792 }
1793
1794 void TestDUChain::testSearchAcrossNamespace()
1795 {
1796   TEST_FILE_PARSE_ONLY
1797
1798   //                 0         1         2         3         4         5         6         7
1799   //                 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
1800   QByteArray method("namespace A { class B{}; } class B{}; namespace A{ B bla; }");
1801
1802   LockedTopDUContext top = parse(method, DumpNone);
1803
1804   QVERIFY(!top->parentContext());
1805   QCOMPARE(top->childContexts().count(), 3);
1806   QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 1);
1807   QCOMPARE(top->childContexts()[2]->localDeclarations().count(), 1);
1808   QVERIFY(top->childContexts()[2]->localDeclarations()[0]->abstractType());
1809   QCOMPARE(top->childContexts()[2]->localDeclarations()[0]->abstractType()->indexed(), top->childContexts()[0]->localDeclarations()[0]->abstractType()->indexed());
1810   QVERIFY(!top->childContexts()[2]->localDeclarations()[0]->abstractType().cast<DelayedType>());
1811
1812 }
1813
1814 void TestDUChain::testSearchAcrossNamespace2()
1815 {
1816   TEST_FILE_PARSE_ONLY
1817
1818   //                 0         1         2         3         4         5         6         7
1819   //                 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
1820   QByteArray method("namespace A {class B{}; } namespace A { class C{ void member(B);};  } void A::C::member(B b) {B c;}");
1821
1822   LockedTopDUContext top = parse(method, DumpNone);
1823
1824   QVERIFY(!top->parentContext());
1825   QCOMPARE(top->childContexts().count(), 4);
1826   QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 1);
1827   QCOMPARE(top->childContexts()[1]->localDeclarations().count(), 1);
1828   QCOMPARE(top->childContexts()[2]->localDeclarations().count(), 1);
1829   QCOMPARE(top->childContexts()[2]->type(), DUContext::Function);
1830   QCOMPARE(top->childContexts()[2]->localDeclarations().count(), 1);
1831   QCOMPARE(top->childContexts()[2]->localScopeIdentifier(), QualifiedIdentifier("A::C::member"));
1832   QVERIFY(top->childContexts()[2]->localDeclarations()[0]->abstractType()); //B should be found from that position
1833   QVERIFY(!top->childContexts()[2]->localDeclarations()[0]->abstractType().cast<DelayedType>());
1834   QCOMPARE(top->childContexts()[3]->type(), DUContext::Other);
1835   QCOMPARE(top->childContexts()[3]->localDeclarations().count(), 1);
1836   QVERIFY(top->childContexts()[3]->localDeclarations()[0]->abstractType()); //B should be found from that position
1837   QCOMPARE(top->childContexts()[3]->localScopeIdentifier(), QualifiedIdentifier("A::C::member"));
1838   QVERIFY(!top->childContexts()[3]->localDeclarations()[0]->abstractType().cast<DelayedType>());
1839
1840 }
1841
1842 void TestDUChain::testSearchAcrossNamespace3()
1843 {
1844   TEST_FILE_PARSE_ONLY
1845
1846   //                 0         1         2         3         4         5         6         7
1847   //                 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
1848   QByteArray method("namespace B { class C { }; } namespace A { class C; } using namespace B; namespace A { C c; };");
1849
1850   LockedTopDUContext top = parse(method, DumpNone);
1851
1852   QCOMPARE(top->childContexts().count(), 3);
1853   QCOMPARE(top->localDeclarations().count(), 4);
1854   QCOMPARE(top->childContexts()[2]->localDeclarations().count(), 1);
1855   QCOMPARE(top->childContexts()[2]->localDeclarations()[0]->abstractType()->toString(), QString("A::C"));
1856 }
1857
1858 #define V_CHILD_COUNT(context, cnt) QCOMPARE(context->childContexts().count(), cnt)
1859 #define V_DECLARATION_COUNT(context, cnt) QCOMPARE(context->localDeclarations().count(), cnt)
1860
1861 #define V_USE_COUNT(declaration, cnt) QCOMPARE(declaration->uses().count(), 1); QCOMPARE(declaration->uses().begin()->count(), cnt);
1862
1863
1864 DUContext* childContext(DUContext* ctx, const QString& name) {
1865   foreach(DUContext* child, ctx->childContexts())
1866     if(child->localScopeIdentifier().toString() == name)
1867       return child;
1868   return 0;
1869 }
1870
1871 Declaration* localDeclaration(DUContext* ctx, const QString& name) {
1872   foreach(Declaration* decl, ctx->localDeclarations())
1873     if(decl->identifier().toString() == name)
1874       return decl;
1875   return 0;
1876 }
1877
1878 void TestDUChain::testUsingDeclaration()
1879 {
1880   TEST_FILE_PARSE_ONLY
1881
1882   //                 0         1         2         3         4         5         6         7
1883   //                 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
1884   QByteArray method("namespace n1 { class C{}; C c2; } namespace n2{ using n1::C; using n1::c2; C c = c2; }");
1885
1886   LockedTopDUContext top = parse(method, DumpNone);
1887
1888   V_CHILD_COUNT(top, 2);
1889   QVERIFY(childContext(top, "n1"));
1890   V_DECLARATION_COUNT(childContext(top, "n1"), 2);
1891   QVERIFY(childContext(top, "n2"));
1892   V_DECLARATION_COUNT(childContext(top, "n2"), 3);
1893   V_USE_COUNT(top->childContexts()[0]->localDeclarations()[0], 3);
1894   V_USE_COUNT(top->childContexts()[0]->localDeclarations()[1], 2);
1895   QCOMPARE(localDeclaration(childContext(top, "n2"), "c")->abstractType()->indexed(), top->childContexts()[0]->localDeclarations()[0]->abstractType()->indexed());
1896
1897 }
1898
1899 void TestDUChain::testUsingDeclarationInTemplate()
1900 {
1901   TEST_FILE_PARSE_ONLY
1902
1903   //                 0         1         2         3         4         5         6         7
1904   //                 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
1905   QByteArray method("template<class T> class A { T i; }; template<class Q> struct B: private A<Q> { using A<T>::i; };");
1906
1907   LockedTopDUContext top = parse(method, DumpNone);
1908
1909   Declaration* basicDecl = findDeclaration(top, QualifiedIdentifier("B::i"));
1910   QVERIFY(basicDecl);
1911   kDebug() << typeid(*basicDecl).name() << basicDecl->toString();
1912   QVERIFY(basicDecl->abstractType());
1913   kDebug() << basicDecl->abstractType()->toString();
1914
1915   Declaration* decl = findDeclaration(top, QualifiedIdentifier("B<int>::i"));
1916   QVERIFY(decl);
1917   QVERIFY(decl->abstractType());
1918   QVERIFY(decl->type<IntegralType>());
1919
1920 }
1921
1922 void TestDUChain::testDeclareUsingNamespace2()
1923 {
1924   TEST_FILE_PARSE_ONLY
1925
1926   //                 0         1         2         3         4         5         6         7
1927   //                 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
1928   QByteArray method("namespace foo2 {int bar2; namespace SubFoo { int subBar2; } }; namespace foo { int bar; using namespace foo2; } namespace GFoo{ namespace renamedFoo2 = foo2; using namespace renamedFoo2; using namespace SubFoo; int gf; } using namespace GFoo; int test() { return bar; }");
1929
1930   LockedTopDUContext top = parse(method, DumpNone);
1931
1932   return;
1933
1934   QVERIFY(!top->parentContext());
1935   QCOMPARE(top->childContexts().count(), 5);
1936   QCOMPARE(top->localDeclarations().count(), 5);
1937   QVERIFY(top->localScopeIdentifier().isEmpty());
1938   QVERIFY(findDeclaration(top, Identifier("foo")));
1939
1940   QCOMPARE( top->childContexts().first()->localDeclarations().count(), 2);
1941   Declaration* bar2 = top->childContexts().first()->localDeclarations()[0];
1942   QVERIFY(bar2);
1943   QCOMPARE(bar2->identifier(), Identifier("bar2"));
1944
1945   QCOMPARE( top->childContexts()[1]->localDeclarations().count(), 2);
1946   Declaration* bar = top->childContexts()[1]->localDeclarations()[0];
1947   QVERIFY(bar);
1948   QCOMPARE(bar->identifier(), Identifier("bar"));
1949
1950   QCOMPARE( top->childContexts()[2]->localDeclarations().count(), 4);
1951   Declaration* gf = top->childContexts()[2]->localDeclarations()[3];
1952   QVERIFY(gf);
1953   QCOMPARE(gf->identifier(), Identifier("gf"));
1954
1955   //QCOMPARE(top->namespaceAliases().count(), 1);
1956   //QCOMPARE(top->namespaceAliases().first()->nsIdentifier, QualifiedIdentifier("foo"));
1957
1958   //QCOMPARE(findDeclaration(top, QualifiedIdentifier("bar2")), bar2);
1959   QCOMPARE(findDeclaration(top, QualifiedIdentifier("::bar")), noDef);
1960   QCOMPARE(findDeclaration(top, QualifiedIdentifier("foo::bar2")), bar2);
1961   QCOMPARE(findDeclaration(top, QualifiedIdentifier("foo2::bar2")), bar2);
1962   QCOMPARE(findDeclaration(top, QualifiedIdentifier("::foo::bar2")), bar2);
1963
1964   //bar2 can be found from GFoo
1965   QCOMPARE(findDeclaration(top->childContexts()[2], QualifiedIdentifier("bar2")), bar2);
1966   QCOMPARE(findDeclaration(top->childContexts()[2], QualifiedIdentifier("bar")), noDef);
1967   QCOMPARE(findDeclaration(top, QualifiedIdentifier("gf")), gf);
1968   QCOMPARE(findDeclaration(top, QualifiedIdentifier("bar2")), bar2);
1969   QCOMPARE(findDeclaration(top, QualifiedIdentifier("::GFoo::renamedFoo2::bar2")), bar2);
1970   QVERIFY(findDeclaration(top, QualifiedIdentifier("subBar2")) != noDef);
1971
1972 }
1973
1974 void TestDUChain::testGlobalNamespaceAlias()
1975 {
1976   QByteArray method("namespace foo { int bar(); } namespace afoo = foo; int test() { afoo::bar(); }");
1977   
1978   LockedTopDUContext top( parse(method, DumpAll) );
1979   
1980   QCOMPARE(top->childContexts().count(), 3);
1981   
1982   QCOMPARE(top->localDeclarations().size(), 3);
1983   NamespaceAliasDeclaration* aliasDecl = dynamic_cast<NamespaceAliasDeclaration*>(top->localDeclarations()[1]);
1984   QVERIFY(aliasDecl);
1985   QCOMPARE(aliasDecl->importIdentifier(), QualifiedIdentifier("foo"));
1986   QCOMPARE(aliasDecl->identifier(), Identifier("afoo"));
1987
1988   QCOMPARE(top->childContexts()[0]->localDeclarations().size(), 1);
1989   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().size(), 1);
1990   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().begin()->size(), 1);
1991 }
1992
1993 void TestDUChain::testExternalMemberDeclaration()
1994 {
1995   QByteArray method("struct A { static int m; };\n"
1996                                       "int A::m = 3;");
1997   
1998   LockedTopDUContext top( parse(method, DumpAll) );
1999   
2000   // The declaration of "A::m" is put into a helper-context that makes the scope "A::"
2001   QCOMPARE(top->localDeclarations().size(), 1);
2002   QCOMPARE(top->childContexts().size(), 2);
2003   QCOMPARE(top->localDeclarations()[0]->uses().size(), 1);
2004   // There must be a use for the "A" in "int A::m"
2005   QCOMPARE(top->localDeclarations()[0]->uses().begin()->size(), 1);
2006   QCOMPARE(top->localDeclarations()[0]->uses().begin()->at(0).textRange(), KTextEditor::Range(1, 4, 1, 5));
2007 }
2008
2009 void TestDUChain::testUsingGlobalNamespaceAlias()
2010 {
2011   QByteArray method("namespace foo { int bar(); } namespace afoo = foo; int test() { using namespace afoo; bar(); }");
2012   
2013   LockedTopDUContext top( parse(method, DumpAll) );
2014   
2015   QCOMPARE(top->childContexts().count(), 3);
2016   
2017   QCOMPARE(top->localDeclarations().size(), 3);
2018   NamespaceAliasDeclaration* aliasDecl = dynamic_cast<NamespaceAliasDeclaration*>(top->localDeclarations()[1]);
2019   QVERIFY(aliasDecl);
2020   QCOMPARE(aliasDecl->importIdentifier(), QualifiedIdentifier("foo"));
2021   QCOMPARE(aliasDecl->identifier(), Identifier("afoo"));
2022
2023   QCOMPARE(top->childContexts()[0]->localDeclarations().size(), 1);
2024   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().size(), 1);
2025   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().begin()->size(), 1);
2026 }
2027
2028 void TestDUChain::testGlobalNamespaceAliasCycle()
2029 {
2030   QByteArray method("namespace foo { int bar(); } namespace A = foo; namespace B = A; namespace A = B; "
2031                     "int test() { foo::bar(); A::bar(); B::bar(); } ");
2032   
2033   LockedTopDUContext top( parse(method, DumpAll) );
2034   
2035   QCOMPARE(top->childContexts().count(), 3);
2036   
2037   QCOMPARE(top->localDeclarations().size(), 5); // foo, A, B, A, test
2038   NamespaceAliasDeclaration* aliasDecl1 = dynamic_cast<NamespaceAliasDeclaration*>(top->localDeclarations()[1]);
2039   QVERIFY(aliasDecl1);
2040   QCOMPARE(aliasDecl1->importIdentifier(), QualifiedIdentifier("foo"));
2041   QCOMPARE(aliasDecl1->identifier(), Identifier("A"));
2042   NamespaceAliasDeclaration* aliasDecl2 = dynamic_cast<NamespaceAliasDeclaration*>(top->localDeclarations()[2]);
2043   QVERIFY(aliasDecl2);
2044   QCOMPARE(aliasDecl2->importIdentifier(), QualifiedIdentifier("foo")); // already resolved
2045   QCOMPARE(aliasDecl2->identifier(), Identifier("B"));
2046   NamespaceAliasDeclaration* aliasDecl3 = dynamic_cast<NamespaceAliasDeclaration*>(top->localDeclarations()[3]);
2047   QVERIFY(aliasDecl3);
2048   QCOMPARE(aliasDecl3->importIdentifier(), QualifiedIdentifier("foo")); // already resolved
2049   QCOMPARE(aliasDecl3->identifier(), Identifier("A"));
2050   
2051   QCOMPARE(top->childContexts()[0]->localDeclarations().size(), 1);
2052   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().size(), 1);
2053   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().begin()->size(), 3);
2054 }
2055
2056 void TestDUChain::testUsingGlobalNamespaceAliasCycle()
2057 {
2058   QByteArray method("namespace foo { int bar(); } namespace A = foo; namespace B = A; namespace A = B; "
2059                     "int testA() { using namespace A; bar(); } "
2060                     "int testB() { using namespace B; bar(); }");
2061   
2062   LockedTopDUContext top( parse(method, DumpAll) );
2063   
2064   QCOMPARE(top->childContexts().count(), 5);
2065   
2066   QCOMPARE(top->localDeclarations().size(), 6); // foo, A, B, A, testA, testB
2067   NamespaceAliasDeclaration* aliasDecl1 = dynamic_cast<NamespaceAliasDeclaration*>(top->localDeclarations()[1]);
2068   QVERIFY(aliasDecl1);
2069   QCOMPARE(aliasDecl1->importIdentifier(), QualifiedIdentifier("foo"));
2070   QCOMPARE(aliasDecl1->identifier(), Identifier("A"));
2071   NamespaceAliasDeclaration* aliasDecl2 = dynamic_cast<NamespaceAliasDeclaration*>(top->localDeclarations()[2]);
2072   QVERIFY(aliasDecl2);
2073   QCOMPARE(aliasDecl2->importIdentifier(), QualifiedIdentifier("foo")); // already resolved
2074   QCOMPARE(aliasDecl2->identifier(), Identifier("B"));
2075   NamespaceAliasDeclaration* aliasDecl3 = dynamic_cast<NamespaceAliasDeclaration*>(top->localDeclarations()[3]);
2076   QVERIFY(aliasDecl3);
2077   QCOMPARE(aliasDecl3->importIdentifier(), QualifiedIdentifier("foo")); // already resolved
2078   QCOMPARE(aliasDecl3->identifier(), Identifier("A"));
2079   
2080   QCOMPARE(top->childContexts()[0]->localDeclarations().size(), 1);
2081   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().size(), 1);
2082   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().begin()->size(), 2);
2083 }
2084
2085 void TestDUChain::testLocalNamespaceAlias()
2086 {
2087   QByteArray method("namespace foo { int bar(); } int test() { namespace afoo = foo; afoo::bar(); }");
2088
2089   LockedTopDUContext top( parse(method, DumpAll) );
2090
2091   QCOMPARE(top->childContexts().count(), 3);
2092   QCOMPARE(top->childContexts()[2]->localDeclarations().size(), 1);
2093   NamespaceAliasDeclaration* aliasDecl = dynamic_cast<NamespaceAliasDeclaration*>(top->childContexts()[2]->localDeclarations()[0]);
2094   QVERIFY(aliasDecl);
2095   QCOMPARE(aliasDecl->importIdentifier(), QualifiedIdentifier("foo"));
2096   QCOMPARE(aliasDecl->identifier(), Identifier("afoo"));
2097   QCOMPARE(top->childContexts()[0]->localDeclarations().size(), 1);
2098   
2099   QEXPECT_FAIL("", "Local namespace aliases currently don't work, bug 207548", Abort);
2100   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().size(), 1);
2101   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().begin()->size(), 1);
2102 }
2103
2104 void TestDUChain::testDeclareUsingNamespace()
2105 {
2106   TEST_FILE_PARSE_ONLY
2107
2108   //                 0         1         2         3         4         5         6         7
2109   //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
2110   QByteArray method("namespace foo { int bar; } using namespace foo; namespace alternativeFoo = foo; int test() { return bar; }");
2111
2112   LockedTopDUContext top = parse(method, DumpNone);
2113
2114   QVERIFY(!top->parentContext());
2115   QCOMPARE(top->childContexts().count(), 3);
2116   QCOMPARE(top->localDeclarations().count(), 4);
2117   QVERIFY(top->localScopeIdentifier().isEmpty());
2118   QVERIFY(findDeclaration(top, Identifier("foo")));
2119   QCOMPARE(top->localDeclarations()[0]->uses().size(), 1);
2120   QCOMPARE(top->localDeclarations()[0]->uses().begin()->size(), 2);
2121   QCOMPARE(top->localDeclarations()[0]->uses().begin()->at(0), SimpleRange(0, 65-22, 0, 68-22));
2122   QCOMPARE(top->localDeclarations()[0]->uses().begin()->at(1), SimpleRange(0, 97-22, 0, 100-22));
2123
2124
2125 //   QCOMPARE(top->localDeclarations()[0]->range()
2126   QCOMPARE(top->localDeclarations()[1]->range(), SimpleRange(0, 33, 0, 42));
2127   kDebug() << top->localDeclarations()[2]->range().textRange();
2128   QCOMPARE(top->localDeclarations()[2]->range(), SimpleRange(0, 58, 0, 72));
2129   
2130   
2131   DUContext* fooCtx = top->childContexts().first();
2132   QCOMPARE(fooCtx->childContexts().count(), 0);
2133   QCOMPARE(fooCtx->localDeclarations().count(), 1);
2134   QCOMPARE(fooCtx->localScopeIdentifier(), QualifiedIdentifier("foo"));
2135   QCOMPARE(fooCtx->scopeIdentifier(), QualifiedIdentifier("foo"));
2136
2137   Declaration* bar = fooCtx->localDeclarations().first();
2138   QVERIFY(!bar->isFunctionDeclaration());
2139   QCOMPARE(bar->identifier(), Identifier("bar"));
2140   QCOMPARE(bar->qualifiedIdentifier(), QualifiedIdentifier("foo::bar"));
2141   QCOMPARE(bar->uses().count(), 1);
2142   QCOMPARE(bar->uses().begin()->count(), 1);
2143   //kDebug() << findDeclaration(top, bar->identifier(), top->range().start)->qualifiedIdentifier().toString();
2144   QCOMPARE(findDeclaration(top, bar->identifier(), top->range().start), noDef);
2145   QCOMPARE(findDeclaration(top, bar->identifier()), bar);
2146   QCOMPARE(findDeclaration(top, bar->qualifiedIdentifier()), bar);
2147
2148   QCOMPARE(findDeclaration(top, QualifiedIdentifier("bar")), bar);
2149   QCOMPARE(findDeclaration(top, QualifiedIdentifier("::bar")), bar); //iso c++ 3.4.3 says this must work
2150   QCOMPARE(findDeclaration(top, QualifiedIdentifier("foo::bar")), bar);
2151   QCOMPARE(findDeclaration(top, QualifiedIdentifier("::foo::bar")), bar);
2152   QCOMPARE(findDeclaration(top, QualifiedIdentifier("alternativeFoo::bar")), bar);
2153   QCOMPARE(findDeclaration(top, QualifiedIdentifier("::alternativeFoo::bar")), bar);
2154
2155   DUContext* testCtx = top->childContexts()[2];
2156   QVERIFY(testCtx->parentContext());
2157   QCOMPARE(testCtx->importedParentContexts().count(), 1);
2158   QCOMPARE(testCtx->childContexts().count(), 0);
2159   QCOMPARE(testCtx->localDeclarations().count(), 0);
2160   QCOMPARE(testCtx->localScopeIdentifier(), QualifiedIdentifier("test"));
2161   QCOMPARE(testCtx->scopeIdentifier(), QualifiedIdentifier("test"));
2162
2163 }
2164
2165 void TestDUChain::testSignalSlotDeclaration() {
2166   {
2167     QByteArray text("class C {__qt_signals__: void signal2(); public __qt_slots__: void slot2();}; ");
2168
2169     LockedTopDUContext top = parse(text, DumpNone);
2170
2171     QCOMPARE(top->localDeclarations().count(), 1);
2172     QCOMPARE(top->childContexts().count(), 1);
2173     QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 2);
2174
2175     ClassFunctionDeclaration* classFun = dynamic_cast<ClassFunctionDeclaration*>(top->childContexts()[0]->localDeclarations()[0]);
2176     QVERIFY(classFun);
2177     QVERIFY(classFun->accessPolicy() == ClassMemberDeclaration::Protected);
2178     QVERIFY(classFun->isSignal());
2179
2180     classFun = dynamic_cast<ClassFunctionDeclaration*>(top->childContexts()[0]->localDeclarations()[1]);
2181     QVERIFY(classFun);
2182     QVERIFY(classFun->accessPolicy() == ClassMemberDeclaration::Public);
2183     QVERIFY(classFun->isSlot());
2184
2185   }
2186   {
2187     QByteArray text("namespace A { class B;} class Q { public __qt_slots__: void slot(A::B b, const Q* q); }; ");
2188
2189     LockedTopDUContext top = parse(text, DumpNone);
2190
2191     QCOMPARE(top->localDeclarations().count(), 2);
2192     QCOMPARE(top->childContexts().count(), 2);
2193     QCOMPARE(top->childContexts()[1]->localDeclarations().count(), 1);
2194     QtFunctionDeclaration* qtDecl = dynamic_cast<QtFunctionDeclaration*>(top->childContexts()[1]->localDeclarations()[0]);
2195     QVERIFY(qtDecl);
2196     QCOMPARE(qtDecl->normalizedSignature().str(), QString("A::B,const Q*"));
2197
2198   }
2199   {
2200     // should be valid signals even if the arguments are not found
2201     QByteArray text("class C {__qt_signals__: void signal2(NotFound); public __qt_slots__: void slot2(NotFound);}; ");
2202
2203     LockedTopDUContext top = parse(text, DumpNone);
2204
2205     QCOMPARE(top->localDeclarations().count(), 1);
2206     QCOMPARE(top->childContexts().count(), 1);
2207     QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 2);
2208
2209     ClassFunctionDeclaration* classFun = dynamic_cast<ClassFunctionDeclaration*>(top->childContexts()[0]->localDeclarations()[0]);
2210     QVERIFY(classFun);
2211     QVERIFY(classFun->accessPolicy() == ClassMemberDeclaration::Protected);
2212     QVERIFY(classFun->isSignal());
2213
2214     classFun = dynamic_cast<ClassFunctionDeclaration*>(top->childContexts()[0]->localDeclarations()[1]);
2215     QVERIFY(classFun);
2216     QVERIFY(classFun->accessPolicy() == ClassMemberDeclaration::Public);
2217     QVERIFY(classFun->isSlot());
2218
2219   }
2220 }
2221
2222 void TestDUChain::testSignalSlotUse() {
2223   {
2224     QByteArray text("class TE; class QObject { void connect(QObject* from, const char* signal, QObject* to, const char* slot); void connect(QObject* from, const char* signal, const char* slot); }; class A : public QObject { public __qt_slots__: void slot1(); void slot2(TE*); __qt_signals__: void signal1(TE*, char);void signal2(); public: void test() { \nconnect(this, __qt_signal__( signal1(TE*, const char&)), this, __qt_slot__(slot2(TE*))); \nconnect(this, __qt_signal__(signal2()), \n__qt_slot__(slot1())); } };");
2225
2226     LockedTopDUContext top = parse(text, DumpNone);
2227
2228     QCOMPARE(top->localDeclarations().count(), 3);
2229     QCOMPARE(top->childContexts().count(), 2);
2230     QCOMPARE(top->childContexts()[1]->localDeclarations().count(), 5);
2231     QtFunctionDeclaration* qtDecl = dynamic_cast<QtFunctionDeclaration*>(top->childContexts()[1]->localDeclarations()[0]);
2232     QVERIFY(qtDecl);
2233     QVERIFY(top->childContexts()[1]->localDeclarations()[0]->uses().count());
2234     //kDebug() << top->childContexts()[1]->localDeclarations()[0]->uses().begin()->first().textRange();
2235     //kDebug() << top->childContexts()[1]->localDeclarations()[1]->uses().begin()->first().textRange();
2236     //kDebug() << top->childContexts()[1]->localDeclarations()[2]->uses().begin()->first().textRange();
2237     //kDebug() << top->childContexts()[1]->localDeclarations()[3]->uses().begin()->first().textRange();
2238     QCOMPARE(top->childContexts()[1]->localDeclarations()[0]->uses().begin()->first().textRange(), SimpleRange(3, 12, 3, 17).textRange());
2239     QVERIFY(top->childContexts()[1]->localDeclarations()[1]->uses().count());
2240     QCOMPARE(top->childContexts()[1]->localDeclarations()[1]->uses().begin()->first().textRange(), SimpleRange(1, 75, 1, 80).textRange());
2241     QVERIFY(top->childContexts()[1]->localDeclarations()[2]->uses().count());
2242     QCOMPARE(top->childContexts()[1]->localDeclarations()[2]->uses().begin()->first(), SimpleRange(1, 29, 1, 36));
2243     QVERIFY(top->childContexts()[1]->localDeclarations()[3]->uses().count());
2244     QCOMPARE(top->childContexts()[1]->localDeclarations()[3]->uses().begin()->first(), SimpleRange(2, 28, 2, 35));
2245
2246     QCOMPARE(top->localDeclarations()[0]->uses().count(), 1);
2247     QCOMPARE(top->localDeclarations()[0]->uses().begin()->count(), 4);
2248
2249   }
2250   {
2251     QByteArray text("class QObject { void connect(QObject* from, const char* signal, QObject* to, const char* slot); void connect(QObject* from, const char* signal, const char* slot); }; struct AA : QObject { __qt_signals__: void signal1(int); void signal2(); };struct T{operator AA*() const; };class A : AA { public __qt_slots__: void slot1(); void slot2(); __qt_signals__: void signal1();public: void test() {T t;connect(t, __qt_signal__(signal2()), this, __qt_slot__(slot2()));connect(this, __qt_signal__(signal1(int)), __qt_slot__(slot1())); } }; ");
2252
2253     LockedTopDUContext top = parse(text, DumpNone);
2254
2255     QCOMPARE(top->localDeclarations().count(), 4);
2256     QCOMPARE(top->childContexts().count(), 4);
2257     QCOMPARE(top->childContexts()[3]->localDeclarations().count(), 4);
2258     QVERIFY(top->childContexts()[3]->localDeclarations()[0]->uses().count());
2259     QVERIFY(top->childContexts()[3]->localDeclarations()[1]->uses().count());
2260     QVERIFY(!top->childContexts()[3]->localDeclarations()[2]->uses().count()); //signal1() is not used
2261
2262     QCOMPARE(top->childContexts()[1]->localDeclarations().count(), 2);
2263     ClassDeclaration* classAA = dynamic_cast<ClassDeclaration*>(top->localDeclarations()[1]);
2264     QVERIFY(classAA);
2265     QCOMPARE(classAA->baseClassesSize(), 1u);
2266     QCOMPARE(classAA->baseClasses()[0].access, Declaration::Public);
2267     ClassDeclaration* classA = dynamic_cast<ClassDeclaration*>(top->localDeclarations()[3]);
2268     QVERIFY(classA);
2269     QCOMPARE(classA->baseClassesSize(), 1u);
2270     QCOMPARE(classA->baseClasses()[0].access, Declaration::Private);
2271
2272     QVERIFY(top->childContexts()[1]->localDeclarations()[0]->uses().count());
2273     QVERIFY(top->childContexts()[1]->localDeclarations()[1]->uses().count());
2274
2275   }
2276   {
2277     // test signals without full signal signature specification
2278     QByteArray text("class QObject { void connect(QObject* from, const char* signal, QObject* to, const char* slot);\n"
2279                     "  void connect(QObject* from, const char* signal, const char* slot); };\n"
2280                     "struct AA : QObject { __qt_signals__: void signal1(bool arg1 = false); };\n"
2281                     "class A : AA { public __qt_slots__: void slot1();\n"
2282                     "  public: void test() { connect(this, __qt_signal__(signal1()), this, __qt_slot__(slot1()));} };");
2283     LockedTopDUContext top = parse(text, DumpNone);
2284
2285     QVERIFY(top->problems().isEmpty());
2286
2287     QCOMPARE(top->localDeclarations().count(), 3);
2288     QCOMPARE(top->childContexts().count(), 3);
2289     QCOMPARE(top->childContexts().at(1)->localDeclarations().size(), 1);
2290     ClassFunctionDeclaration* sig = dynamic_cast<ClassFunctionDeclaration*>(top->childContexts().at(1)->localDeclarations().first());
2291     QVERIFY(sig);
2292     QVERIFY(sig->identifier() == Identifier("signal1"));
2293     QVERIFY(sig->isSignal());
2294     QCOMPARE(sig->uses().size(), 1);
2295     QCOMPARE(sig->uses().begin()->count(), 1);
2296     QCOMPARE(sig->uses().begin()->first(), SimpleRange(4, 52, 4, 59));
2297   }
2298 }
2299
2300 void TestDUChain::testFunctionDefinition() {
2301   //               0         1         2         3         4         5         6         7
2302   //               01234567890123456789012345678901234567890123456789012345678901234567890123456789
2303   QByteArray text("class B{}; class A { char at(B* b); A(); ~A(); }; \n char A::at(B* b) {B* b; at(b); }; A::A() : i(3) {}; A::~A() {}; ");
2304
2305   LockedTopDUContext top = parse(text, DumpNone);
2306
2307   QCOMPARE(top->childContexts().count(), 8);
2308   QCOMPARE(top->childContexts()[1]->childContexts().count(), 3);
2309   QCOMPARE(top->childContexts()[1]->localDeclarations().count(), 3);
2310
2311   QCOMPARE(top->childContexts()[4]->type(), DUContext::Function);
2312
2313   Declaration* atInA = top->childContexts()[1]->localDeclarations()[0];
2314
2315   QVERIFY(dynamic_cast<AbstractFunctionDeclaration*>(atInA));
2316
2317   QVERIFY(atInA->internalContext());
2318   QCOMPARE(atInA->internalContext()->range(), SimpleRange(0, 29, 0, 33));
2319   
2320   QCOMPARE(top->localDeclarations().count(), 5);
2321
2322   QVERIFY(top->localDeclarations()[1]->logicalInternalContext(top));
2323   QVERIFY(!top->childContexts()[1]->localDeclarations()[0]->isDefinition());
2324   QVERIFY(!top->childContexts()[1]->localDeclarations()[1]->isDefinition());
2325   QVERIFY(!top->childContexts()[1]->localDeclarations()[2]->isDefinition());
2326
2327   QVERIFY(top->localDeclarations()[2]->isDefinition());
2328   QVERIFY(top->localDeclarations()[3]->isDefinition());
2329   QVERIFY(top->localDeclarations()[4]->isDefinition());
2330
2331   QVERIFY(top->localDeclarations()[2]->internalContext());
2332   QVERIFY(top->localDeclarations()[3]->internalContext());
2333   QVERIFY(top->localDeclarations()[4]->internalContext());
2334
2335   QCOMPARE(top->localDeclarations()[2]->internalContext()->owner(), top->localDeclarations()[2]);
2336   QCOMPARE(top->localDeclarations()[3]->internalContext()->owner(), top->localDeclarations()[3]);
2337   QCOMPARE(top->localDeclarations()[4]->internalContext()->owner(), top->localDeclarations()[4]);
2338
2339   QVERIFY(top->localDeclarations()[1]->logicalInternalContext(top));
2340
2341   QVERIFY(dynamic_cast<FunctionDefinition*>(top->localDeclarations()[2]));
2342   QCOMPARE(static_cast<FunctionDefinition*>(top->localDeclarations()[2])->declaration(), top->childContexts()[1]->localDeclarations()[0]);
2343   QCOMPARE(top->localDeclarations()[2], FunctionDefinition::definition(top->childContexts()[1]->localDeclarations()[0]));
2344
2345   QVERIFY(dynamic_cast<FunctionDefinition*>(top->localDeclarations()[3]));
2346   QCOMPARE(static_cast<FunctionDefinition*>(top->localDeclarations()[3])->declaration(), top->childContexts()[1]->localDeclarations()[1]);
2347   QCOMPARE(top->localDeclarations()[3], FunctionDefinition::definition(top->childContexts()[1]->localDeclarations()[1]));
2348   QCOMPARE(top->childContexts()[5]->owner(), top->localDeclarations()[3]);
2349   QVERIFY(!top->childContexts()[5]->localScopeIdentifier().isEmpty());
2350
2351   QVERIFY(top->localDeclarations()[1]->logicalInternalContext(top));
2352   QVERIFY(dynamic_cast<FunctionDefinition*>(top->localDeclarations()[4]));
2353   QCOMPARE(static_cast<FunctionDefinition*>(top->localDeclarations()[4])->declaration(), top->childContexts()[1]->localDeclarations()[2]);
2354   QCOMPARE(top->localDeclarations()[4], FunctionDefinition::definition(top->childContexts()[1]->localDeclarations()[2]));
2355
2356   QVERIFY(top->localDeclarations()[1]->logicalInternalContext(top));
2357
2358   QCOMPARE(top->childContexts()[3]->owner(), top->localDeclarations()[2]);
2359   QCOMPARE(top->childContexts()[3]->importedParentContexts().count(), 1);
2360   QCOMPARE(top->childContexts()[3]->importedParentContexts()[0].context(0), top->childContexts()[2]);
2361
2362   QCOMPARE(top->childContexts()[2]->importedParentContexts().count(), 1);
2363   QCOMPARE(top->childContexts()[2]->importedParentContexts()[0].context(0), top->childContexts()[1]);
2364
2365
2366   QCOMPARE(findDeclaration(top, QualifiedIdentifier("at")), noDef);
2367
2368   QVERIFY(top->localDeclarations()[2]->internalContext());
2369   QCOMPARE(top->localDeclarations()[2]->internalContext()->localDeclarations().count(), 1);
2370
2371 }
2372
2373 Declaration* declaration(Declaration* decl, TopDUContext* top = 0) {
2374   FunctionDefinition* def = dynamic_cast<FunctionDefinition*>(decl);
2375   if(!def)
2376     return 0;
2377   return def->declaration(top);
2378 }
2379
2380 void TestDUChain::testFunctionDefinition2() {
2381   {
2382     QByteArray text("//????\nclass B{B();}; B::B() {} "); //the ???? tests whether the column-numbers are resistant to special characters
2383
2384     LockedTopDUContext top = parse(text, DumpNone);
2385
2386     QCOMPARE(top->childContexts().count(), 3);
2387
2388     QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 1);
2389     QCOMPARE(top->localDeclarations().count(), 2);
2390
2391     QCOMPARE(top->childContexts()[0]->localDeclarations()[0], declaration(top->localDeclarations()[1], top->topContext()));
2392
2393     QCOMPARE(top->childContexts()[1]->type(), DUContext::Function);
2394     QCOMPARE(top->childContexts()[1]->range().start.column, 20);
2395     QCOMPARE(top->childContexts()[1]->range().end.column, 20);
2396     //Many parts of kdevelop assume that the compound parens are included in the range, so it has to stay like that
2397     QCOMPARE(top->childContexts()[0]->range(), SimpleRange(1, 7, 1, 13));
2398     QCOMPARE(top->childContexts()[2]->range(), SimpleRange(1, 22, 1, 24));
2399
2400     QVERIFY(!top->childContexts()[2]->inSymbolTable());
2401
2402   }
2403   {
2404     QByteArray text("void test(int a, int cc);"); //the ???? tests whether the column-numbers are resistant to special characters
2405
2406     LockedTopDUContext top = parse(text, DumpNone);
2407
2408     QCOMPARE(top->childContexts().count(), 1);
2409
2410     QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 2);
2411
2412     QCOMPARE(top->childContexts()[0]->range().start.column, 10);
2413     QCOMPARE(top->childContexts()[0]->range().end.column, 23);
2414
2415     QCOMPARE(top->childContexts()[0]->localDeclarations()[1]->range().start.column, 21);
2416     QCOMPARE(top->childContexts()[0]->localDeclarations()[1]->range().end.column, 23);
2417
2418     QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->range().start.column, 14);
2419     QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->range().end.column, 15);
2420
2421   }
2422
2423   {
2424     QByteArray text("void test(int, int&);");
2425
2426     LockedTopDUContext top = parse(text, DumpNone);
2427
2428     QCOMPARE(top->childContexts().count(), 1);
2429
2430     QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 2);
2431
2432   }
2433
2434 }
2435
2436 void TestDUChain::testFunctionDefinition4() {
2437   QByteArray text("class B{ B(); }; namespace A{class B{B();};} namespace A{ B::B() {} } ");
2438
2439   LockedTopDUContext top = parse(text, DumpNone);
2440
2441   QCOMPARE(top->childContexts().count(), 3);
2442
2443   QCOMPARE(top->childContexts()[1]->localDeclarations().count(), 1);
2444   QCOMPARE(top->childContexts()[1]->childContexts().count(), 1);
2445   QCOMPARE(top->childContexts()[1]->childContexts()[0]->localDeclarations().count(), 1);
2446   QCOMPARE(top->childContexts()[2]->localDeclarations().count(), 1);
2447
2448   QVERIFY(top->childContexts()[2]->localDeclarations()[0]->isDefinition());
2449   QCOMPARE(declaration(top->childContexts()[2]->localDeclarations()[0]), top->childContexts()[1]->childContexts()[0]->localDeclarations()[0]);
2450   //Verify that the function-definition context also imports the correct class context
2451   QVERIFY(top->childContexts()[2]->localDeclarations()[0]->internalContext()->imports(top->childContexts()[1]->childContexts()[0]));
2452 }
2453
2454 void TestDUChain::testFunctionDefinition3() {
2455   QByteArray text("class B{template<class T> void test(T t); B(int i); int test(int a); int test(char a); template<class T2, class T3> void test(T2 t, T3 t3); int test(Unknown k); int test(Unknown2 k); }; template<class T> void B::test(T t) {}; B::B(int) {}; int B::test(int a){}; int B::test(char a){}; template<class T2, class T3> void B::test(T2 t, T3 t3) {}; int B::test(Unknown k){}; int B::test( Unknown2 k) {}; ");
2456
2457   LockedTopDUContext top = parse(text, DumpNone);
2458
2459   QCOMPARE(top->childContexts().count(), 17);
2460
2461   QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 7);
2462   QCOMPARE(top->localDeclarations().count(), 8);
2463
2464   QVERIFY(top->localDeclarations()[0]->isDefinition()); //Class-declarations are considered definitions too.
2465   QVERIFY(top->localDeclarations()[1]->isDefinition());
2466   QVERIFY(top->localDeclarations()[2]->isDefinition());
2467   QVERIFY(top->localDeclarations()[3]->isDefinition());
2468   QVERIFY(top->localDeclarations()[4]->isDefinition());
2469   QVERIFY(top->localDeclarations()[5]->isDefinition());
2470   QVERIFY(top->localDeclarations()[6]->isDefinition());
2471
2472   kDebug() << top->childContexts()[0]->localDeclarations()[0]->toString();
2473   kDebug() << declaration(top->localDeclarations()[1], top->topContext())->toString();
2474
2475   QCOMPARE(top->childContexts()[0]->localDeclarations()[0], declaration(top->localDeclarations()[1], top->topContext()));
2476   QCOMPARE(top->childContexts()[0]->localDeclarations()[1], declaration(top->localDeclarations()[2], top->topContext()));
2477   QCOMPARE(top->childContexts()[0]->localDeclarations()[2], declaration(top->localDeclarations()[3], top->topContext()));
2478   QCOMPARE(top->childContexts()[0]->localDeclarations()[3], declaration(top->localDeclarations()[4], top->topContext()));
2479   QCOMPARE(top->childContexts()[0]->localDeclarations()[4], declaration(top->localDeclarations()[5], top->topContext()));
2480   QCOMPARE(top->childContexts()[0]->localDeclarations()[5], declaration(top->localDeclarations()[6], top->topContext()));
2481
2482 }
2483
2484 void TestDUChain::testFunctionDefinition5() {
2485   QByteArray text("class Class {typedef Class ClassDef;void test(ClassDef);Class();}; void Class::test(ClassDef i) {Class c;}");
2486   LockedTopDUContext top = parse(text, DumpNone);
2487
2488   QCOMPARE(top->childContexts().count(), 3);
2489   QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 3);
2490   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().count(), 1); //Used from 1 file
2491   QCOMPARE(top->childContexts()[0]->localDeclarations()[0]->uses().begin()->count(), 2); //Used 2 times
2492   QCOMPARE(top->localDeclarations().count(), 2);
2493   QCOMPARE(top->childContexts()[2]->localDeclarations().count(), 1);
2494 }
2495
2496 void TestDUChain::testFunctionDefinition6() {
2497   QByteArray text("class Class {Class(); void test();}; void Class::test(Class c) {int i;}");
2498   LockedTopDUContext top = parse(text, DumpNone);
2499   
2500   //Here we do an update, since there was a bug where updating caused problems here
2501   parse(text, DumpNone, top);
2502
2503   QCOMPARE(top->childContexts().count(), 3);
2504   QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 2);
2505   QCOMPARE(top->localDeclarations().count(), 2);
2506   QCOMPARE(top->childContexts()[1]->localDeclarations().count(), 1);
2507   QList<Declaration*> decls = top->findDeclarations(QualifiedIdentifier("Class"));
2508   QCOMPARE(decls.size(), 1);
2509   kDebug() << "qualified identifier:" << top->childContexts()[0]->localDeclarations()[0]->qualifiedIdentifier();
2510   QVERIFY(!dynamic_cast<FunctionDefinition*>(top->childContexts()[0]->localDeclarations()[0]));
2511   QVERIFY(dynamic_cast<ClassFunctionDeclaration*>(top->childContexts()[0]->localDeclarations()[0]));
2512   QVERIFY(static_cast<ClassFunctionDeclaration*>(top->childContexts()[0]->localDeclarations()[0])->isConstructor());
2513   kDebug() << top->childContexts()[1]->localDeclarations()[0]->abstractType()->toString();
2514   QCOMPARE(top->localDeclarations()[1], top->childContexts()[2]->owner());
2515   QCOMPARE(Cpp::localClassFromCodeContext(top->childContexts()[2]), top->localDeclarations()[0]);
2516   QCOMPARE(Cpp::localClassFromCodeContext(top->childContexts()[1]), top->localDeclarations()[0]);
2517   QVERIFY(top->childContexts()[1]->importers().contains(top->childContexts()[2]));
2518   QCOMPARE(top->childContexts()[1]->localDeclarations()[0]->abstractType()->indexed(), top->localDeclarations()[0]->abstractType()->indexed());
2519 }
2520
2521 void TestDUChain::testLoopNamespaceImport() {
2522   QByteArray text("namespace A {int i;} namespace B { using namespace A; } namespace A{ using namespace B; }; using namespace B; void test() { i += 5; }");
2523   LockedTopDUContext top = parse(text, DumpNone);
2524
2525   QCOMPARE(top->childContexts().count(), 5);
2526   QCOMPARE(top->childContexts()[0]->localDeclarations().count(), 1);
2527   QVERIFY(!top->childContexts()[0]->localDeclarations()[0]->uses().isEmpty());
2528
2529 }
2530
2531 void TestDUChain::testConstructorUses()
2532 {
2533   {
2534     QByteArray text = "struct A { A(A); A(A,A); }; void test() { A w; A a(A(w), A(w, w), w); }";
2535     LockedTopDUContext top = parse(text, DumpAll);
2536     QCOMPARE(top->childContexts().size(), 3);
2537     QCOMPARE(top->childContexts()[2]->localDeclarations().size(), 2);
2538     QCOMPARE(top->childContexts()[2]->localDeclarations()[0]->uses().size(), 1);
2539     QCOMPARE(top->childContexts()[2]->localDeclarations()[0]->uses().begin()->size(), 4);
2540
2541     QCOMPARE(top->childContexts()[0]->localDeclarations().size(), 2);
2542     
2543     ///@todo Make these work! (ExpressionVisitor::buildParametersFromDeclaration)
2544     #if 0
2545     QCOMPARE(top->childContexts()[0]->localDeclarations()[0].uses().size(), 1);
2546     QCOMPARE(top->childContexts()[0]->localDeclarations()[1].uses().size(), 1);
2547     #endif
2548     
2549   }
2550   {
2551     // NOTE: This test is currently broken because only the 2nd case is reported.
2552     QByteArray text;
2553     text += "class Q {\n";
2554     text += "public:\n";
2555     text += "  Q(int var) { }\n";
2556     text += "  Q() { }\n";
2557     text += "};\n";
2558     text += "class B : public Q {\n";
2559     text += "public:\n";
2560     text += "  B(int var) : Q(var) { }\n";
2561     text += "  B() : Q() { }\n";
2562     text += "};\n";
2563     text += "int main(int argc, char* argv[]) {\n";
2564     text += "  Q  a1(123);\n";
2565     text += "  Q  a2 = Q(123);\n";
2566     text += "  Q *a3 = new Q(123);\n";
2567     text += "  Q  a4(argc);\n";
2568     text += "  Q  a12();\n";
2569     text += "  Q  a22 = Q();\n";
2570     text += "  Q *a32 = new Q();\n";
2571     text += "}\n";
2572
2573     LockedTopDUContext top = parse(text, DumpNone);
2574
2575     QCOMPARE(top->childContexts().size(), 4);
2576     QCOMPARE(top->childContexts()[0]->localDeclarations().size(), 2);
2577
2578     // Q(int var)
2579     Declaration *ctorDecl = top->childContexts()[0]->localDeclarations()[0];
2580     QCOMPARE(ctorDecl->uses().size(), 1);
2581     QList<SimpleRange> uses = ctorDecl->uses().values().first();
2582
2583     QCOMPARE(uses.size(), 5);
2584     QCOMPARE(uses[0], SimpleRange(7, 16, 7, 17));
2585     QCOMPARE(uses[1], SimpleRange(11, 7, 11, 8));
2586     QCOMPARE(uses[2], SimpleRange(12, 11, 12, 12));
2587     QCOMPARE(uses[3], SimpleRange(13, 15, 13, 16));
2588     QCOMPARE(uses[4], SimpleRange(14, 7, 14, 8));
2589
2590     // Q()
2591     ctorDecl = top->childContexts()[0]->localDeclarations()[1];
2592     QCOMPARE(ctorDecl->uses().size(), 1);
2593     uses = ctorDecl->uses().values().first();
2594
2595     QCOMPARE(uses.size(), 4);
2596     QCOMPARE(uses[0], SimpleRange(8, 9, 8, 10));
2597     QCOMPARE(uses[1], SimpleRange(15, 8, 15, 9));
2598     QCOMPARE(uses[2], SimpleRange(16, 12, 16, 13));
2599     QCOMPARE(uses[3], SimpleRange(17, 16, 17, 17));
2600
2601   }
2602   {
2603     QByteArray text;
2604     text += "template<typename T>\n";
2605     text += "class Q {\n";
2606     text += "public:\n";
2607     text += "  Q(T var) { }\n";
2608     text += "  Q() { }\n";
2609     text += "};\n";
2610     text += "template<typename T>\n";
2611     text += "class B : public Q<T> {\n";
2612     text += "public:\n";
2613     text += "  B(T var) : Q<T>(var) { }\n";
2614     text += "  B() : Q<T>() { }\n";
2615     text += "};\n";
2616     text += "int main(int argc, char* argv[]) {\n";
2617     text += "  Q<int>  a1(123);\n";
2618     text += "  Q<int>  a2 = Q<int>(123);\n";
2619     text += "  Q<int> *a3 = new Q<int>(123);\n";
2620     text += "  Q<int>  a4(argc);\n";
2621     text += "  Q<int>  a12();\n";
2622     text += "  Q<int>  a22 = Q<int>();\n";
2623     text += "  Q<int> *a32 = new Q<int>();\n";
2624     text += "}\n";
2625
2626     LockedTopDUContext top = parse(text, DumpNone);
2627
2628     QCOMPARE(top->childContexts().size(), 6);
2629     // first one is the template context
2630     QCOMPARE(top->childContexts()[1]->type(), DUContext::Class);
2631     QCOMPARE(top->childContexts()[1]->localDeclarations().size(), 2);
2632
2633     // Q(T var)
2634     Declaration *ctorDecl = top->childContexts()[1]->localDeclarations()[0];
2635     QEXPECT_FAIL("", "no uses get reported for ctors of template classes", Abort);
2636     QCOMPARE(ctorDecl->uses().size(), 1);
2637     ///TODO
2638     /*
2639     QList<SimpleRange> uses = ctorDecl->uses().values().first();
2640