void tst_Lookup::class_with_baseclass() { const QByteArray source = "\n" "@implementation BaseZoo {} -(void)baseDecl; -(void)baseMethod{} @end\n" "@interface Zoo: BaseZoo {} +(id)alloc; -(id)init; @end\n" "@implementation Zoo +(id)alloc{} -(id)init{} -(void)dealloc{} @end\n"; Document::Ptr doc = Document::create("class_with_baseclass"); doc->setUtf8Source(source); doc->parse(); doc->check(); QVERIFY(doc->diagnosticMessages().isEmpty()); QCOMPARE(doc->globalSymbolCount(), 3U); Snapshot snapshot; snapshot.insert(doc); Document::Ptr emptyDoc = Document::create("<empty>"); ObjCClass *baseZoo = doc->globalSymbolAt(0)->asObjCClass(); QVERIFY(baseZoo); QVERIFY(!baseZoo->isInterface()); QCOMPARE(baseZoo->memberCount(), 2U); ObjCClass *zooIface = doc->globalSymbolAt(1)->asObjCClass(); QVERIFY(zooIface); QVERIFY(zooIface->isInterface()); QVERIFY(zooIface->baseClass()->name() == baseZoo->name()); ObjCClass *zooImpl = doc->globalSymbolAt(2)->asObjCClass(); QVERIFY(zooImpl); QVERIFY(!zooImpl->isInterface()); QCOMPARE(zooImpl->memberCount(), 3U); Declaration *baseDecl = baseZoo->memberAt(0)->asDeclaration(); QVERIFY(baseDecl); QVERIFY(baseDecl->name() && baseDecl->name()->identifier()); QCOMPARE(QLatin1String(baseDecl->name()->identifier()->chars()), QLatin1String("baseDecl")); ObjCMethod *baseMethod = baseZoo->memberAt(1)->asObjCMethod(); QVERIFY(baseMethod); QVERIFY(baseMethod->name() && baseMethod->name()->identifier()); QCOMPARE(QLatin1String(baseMethod->name()->identifier()->chars()), QLatin1String("baseMethod")); const LookupContext context(doc, snapshot); LookupScope *objClass = context.lookupType(baseZoo->name(), zooImpl->enclosingScope()); QVERIFY(objClass != 0); QVERIFY(objClass->symbols().contains(baseZoo)); QList<LookupItem> results = context.lookup(baseDecl->name(), zooImpl); QCOMPARE(results.size(), 1); QCOMPARE(results.at(0).declaration(), baseDecl); results = context.lookup(baseMethod->name(), zooImpl); QCOMPARE(results.size(), 1); QCOMPARE(results.at(0).declaration(), baseMethod); }
void tst_Lookup::iface_impl_scoping() { const QByteArray source = "\n" "@interface Scooping{}-(int)method1:(int)arg;-(void)method2;@end\n" "@implementation Scooping-(int)method1:(int)arg{return arg;}@end\n"; Document::Ptr doc = Document::create("class_with_protocol_with_protocol"); doc->setUtf8Source(source); doc->parse(); doc->check(); QVERIFY(doc->diagnosticMessages().isEmpty()); QCOMPARE(doc->globalSymbolCount(), 2U); Snapshot snapshot; snapshot.insert(doc); ObjCClass *iface = doc->globalSymbolAt(0)->asObjCClass(); QVERIFY(iface); QVERIFY(iface->isInterface()); ObjCClass *impl = doc->globalSymbolAt(1)->asObjCClass(); QVERIFY(impl); QVERIFY(!impl->isInterface()); QCOMPARE(iface->memberCount(), 2U); QCOMPARE(impl->memberCount(), 1U); ObjCMethod *method1Impl = impl->memberAt(0)->asObjCMethod(); QVERIFY(method1Impl); QCOMPARE(method1Impl->identifier()->chars(), "method1"); // get the body of method1 QCOMPARE(method1Impl->memberCount(), 2U); Argument *method1Arg = method1Impl->memberAt(0)->asArgument(); QVERIFY(method1Arg); QCOMPARE(method1Arg->identifier()->chars(), "arg"); QVERIFY(method1Arg->type()->isIntegerType()); Block *method1Body = method1Impl->memberAt(1)->asBlock(); QVERIFY(method1Body); const LookupContext context(doc, snapshot); { // verify if we can resolve "arg" in the body QCOMPARE(method1Impl->argumentCount(), 1U); Argument *arg = method1Impl->argumentAt(0)->asArgument(); QVERIFY(arg); QVERIFY(arg->name()); QVERIFY(arg->name()->identifier()); QCOMPARE(arg->name()->identifier()->chars(), "arg"); QVERIFY(arg->type()->isIntegerType()); const QList<LookupItem> candidates = context.lookup(arg->name(), method1Body->enclosingScope()); QCOMPARE(candidates.size(), 1); QVERIFY(candidates.at(0).declaration()->type()->asIntegerType()); } Declaration *method2 = iface->memberAt(1)->asDeclaration(); QVERIFY(method2); QCOMPARE(method2->identifier()->chars(), "method2"); { // verify if we can resolve "method2" in the body const QList<LookupItem> candidates = context.lookup(method2->name(), method1Body->enclosingScope()); QCOMPARE(candidates.size(), 1); QCOMPARE(candidates.at(0).declaration(), method2); } }
void tst_Lookup::simple_class_1() { const QByteArray source = "\n" "@interface Zoo {} +(id)alloc; -(id)init; @end\n" "@implementation Zoo +(id)alloc{} -(id)init{} -(void)dealloc{} @end\n"; Document::Ptr doc = Document::create("simple_class_1"); doc->setUtf8Source(source); doc->parse(); doc->check(); QVERIFY(doc->diagnosticMessages().isEmpty()); QCOMPARE(doc->globalSymbolCount(), 2U); Snapshot snapshot; snapshot.insert(doc); ObjCClass *iface = doc->globalSymbolAt(0)->asObjCClass(); QVERIFY(iface); QVERIFY(iface->isInterface()); QCOMPARE(iface->memberCount(), 2U); ObjCClass *impl = doc->globalSymbolAt(1)->asObjCClass(); QVERIFY(impl); QVERIFY(!impl->isInterface()); QCOMPARE(impl->memberCount(), 3U); Declaration *allocMethodIface = iface->memberAt(0)->asDeclaration(); QVERIFY(allocMethodIface); QVERIFY(allocMethodIface->name() && allocMethodIface->name()->identifier()); QCOMPARE(QLatin1String(allocMethodIface->name()->identifier()->chars()), QLatin1String("alloc")); ObjCMethod *allocMethodImpl = impl->memberAt(0)->asObjCMethod(); QVERIFY(allocMethodImpl); QVERIFY(allocMethodImpl->name() && allocMethodImpl->name()->identifier()); QCOMPARE(QLatin1String(allocMethodImpl->name()->identifier()->chars()), QLatin1String("alloc")); ObjCMethod *deallocMethod = impl->memberAt(2)->asObjCMethod(); QVERIFY(deallocMethod); QVERIFY(deallocMethod->name() && deallocMethod->name()->identifier()); QCOMPARE(QLatin1String(deallocMethod->name()->identifier()->chars()), QLatin1String("dealloc")); const LookupContext context(doc, snapshot); // check class resolving: LookupScope *klass = context.lookupType(impl->name(), impl->enclosingScope()); QVERIFY(klass != 0); QCOMPARE(klass->symbols().size(), 2); QVERIFY(klass->symbols().contains(iface)); QVERIFY(klass->symbols().contains(impl)); // check method resolving: QList<LookupItem> results = context.lookup(allocMethodImpl->name(), impl); QCOMPARE(results.size(), 2); QCOMPARE(results.at(0).declaration(), allocMethodIface); QCOMPARE(results.at(1).declaration(), allocMethodImpl); results = context.lookup(deallocMethod->name(), impl); QCOMPARE(results.size(), 1); QCOMPARE(results.at(0).declaration(), deallocMethod); }