2009-02-09 10:21:29 +01:00
|
|
|
|
|
|
|
|
#include <QtTest>
|
|
|
|
|
#include <QObject>
|
2009-02-09 11:35:57 +01:00
|
|
|
|
|
|
|
|
#include <AST.h>
|
|
|
|
|
#include <ASTVisitor.h>
|
|
|
|
|
#include <TranslationUnit.h>
|
2009-02-09 10:21:29 +01:00
|
|
|
#include <CppDocument.h>
|
|
|
|
|
#include <LookupContext.h>
|
|
|
|
|
#include <Symbols.h>
|
|
|
|
|
#include <Overview.h>
|
|
|
|
|
|
|
|
|
|
CPLUSPLUS_USE_NAMESPACE
|
|
|
|
|
|
2009-02-09 11:56:09 +01:00
|
|
|
template <template <typename, typename> class _Map, typename _T1, typename _T2>
|
|
|
|
|
_Map<_T2, _T1> invert(const _Map<_T1, _T2> &m)
|
|
|
|
|
{
|
|
|
|
|
_Map<_T2, _T1> i;
|
|
|
|
|
typename _Map<_T1, _T2>::const_iterator it = m.constBegin();
|
|
|
|
|
for (; it != m.constEnd(); ++it) {
|
|
|
|
|
i.insertMulti(it.value(), it.key());
|
|
|
|
|
}
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-09 11:35:57 +01:00
|
|
|
class ClassSymbols: protected ASTVisitor,
|
|
|
|
|
public QMap<ClassSpecifierAST *, Class *>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
ClassSymbols(Control *control)
|
|
|
|
|
: ASTVisitor(control)
|
|
|
|
|
{ }
|
|
|
|
|
|
2009-02-09 11:56:09 +01:00
|
|
|
QMap<ClassSpecifierAST *, Class *> asMap() const
|
|
|
|
|
{ return *this; }
|
|
|
|
|
|
2009-02-09 11:35:57 +01:00
|
|
|
void operator()(AST *ast)
|
|
|
|
|
{ accept(ast); }
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
virtual bool visit(ClassSpecifierAST *ast)
|
|
|
|
|
{
|
|
|
|
|
Class *classSymbol = ast->class_symbol;
|
|
|
|
|
Q_ASSERT(classSymbol != 0);
|
|
|
|
|
|
|
|
|
|
insert(ast, classSymbol);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2009-02-09 10:21:29 +01:00
|
|
|
class tst_Lookup: public QObject
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
|
|
private Q_SLOTS:
|
|
|
|
|
void base_class_defined_1();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void tst_Lookup::base_class_defined_1()
|
|
|
|
|
{
|
|
|
|
|
Overview overview;
|
|
|
|
|
|
|
|
|
|
const QByteArray source = "\n"
|
|
|
|
|
"class base {};\n"
|
|
|
|
|
"class derived: public base {};\n";
|
|
|
|
|
|
|
|
|
|
Document::Ptr doc = Document::create("base_class_defined_1");
|
|
|
|
|
doc->setSource(source);
|
|
|
|
|
doc->parse();
|
|
|
|
|
doc->check();
|
|
|
|
|
|
|
|
|
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
|
|
|
|
QCOMPARE(doc->globalSymbolCount(), 2U);
|
|
|
|
|
|
|
|
|
|
Snapshot snapshot;
|
|
|
|
|
snapshot.insert(doc->fileName(), doc);
|
|
|
|
|
|
2009-02-09 11:56:09 +01:00
|
|
|
Document::Ptr emptyDoc = Document::create("<empty>");
|
2009-02-09 10:21:29 +01:00
|
|
|
|
|
|
|
|
Class *baseClass = doc->globalSymbolAt(0)->asClass();
|
|
|
|
|
QVERIFY(baseClass);
|
|
|
|
|
|
|
|
|
|
Class *derivedClass = doc->globalSymbolAt(1)->asClass();
|
|
|
|
|
QVERIFY(derivedClass);
|
|
|
|
|
|
|
|
|
|
LookupContext ctx(derivedClass, emptyDoc, doc, snapshot);
|
|
|
|
|
|
|
|
|
|
const QList<Symbol *> candidates =
|
|
|
|
|
ctx.resolveClass(derivedClass->baseClassAt(0)->name());
|
|
|
|
|
|
|
|
|
|
QCOMPARE(candidates.size(), 1);
|
|
|
|
|
QCOMPARE(candidates.at(0), baseClass);
|
2009-02-09 11:35:57 +01:00
|
|
|
|
|
|
|
|
TranslationUnit *unit = doc->translationUnit();
|
|
|
|
|
QVERIFY(unit != 0);
|
|
|
|
|
|
|
|
|
|
TranslationUnitAST *ast = unit->ast()->asTranslationUnit();
|
|
|
|
|
QVERIFY(ast != 0);
|
|
|
|
|
|
|
|
|
|
ClassSymbols classSymbols(doc->control());
|
|
|
|
|
classSymbols(ast);
|
|
|
|
|
|
|
|
|
|
QCOMPARE(classSymbols.size(), 2);
|
2009-02-09 11:56:09 +01:00
|
|
|
|
|
|
|
|
const QMap<Class *, ClassSpecifierAST *> classToAST =
|
|
|
|
|
invert(classSymbols.asMap());
|
|
|
|
|
|
|
|
|
|
QVERIFY(classToAST.value(baseClass) != 0);
|
|
|
|
|
QVERIFY(classToAST.value(derivedClass) != 0);
|
2009-02-09 10:21:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QTEST_APPLESS_MAIN(tst_Lookup)
|
|
|
|
|
#include "tst_lookup.moc"
|