/* * Copyright (c) 2013, 2015 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.cdt.qt.tests; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.internal.qt.core.index.IQEnum; import org.eclipse.cdt.internal.qt.core.index.IQMethod; import org.eclipse.cdt.internal.qt.core.index.IQObject; import org.eclipse.cdt.internal.qt.core.index.IQProperty; import org.eclipse.cdt.internal.qt.core.index.QtIndex; import org.eclipse.cdt.internal.qt.core.index.IQProperty.Attribute; public class QObjectTests extends BaseQtTestCase { // #include "junit-QObject.hh" // class T {}; // class B1 : public QObject {Q_OBJECT}; // class B2 : public QObject {Q_OBJECT}; // class B3 : public QObject {Q_OBJECT}; // class D1 : public B1, public B2, private B3, public T {Q_OBJECT}; // class D2 : public T, public QObject {}; public void testGetBases() throws Exception { loadComment("bases.hh"); QtIndex qtIndex = QtIndex.getIndex(fProject); assertNotNull(qtIndex); IQObject qobj_B1 = qtIndex.findQObject(new String[]{ "B1" }); if (!isIndexOk("B1", qobj_B1)) return; IQObject qobj_D1 = qtIndex.findQObject(new String[]{ "D1" }); assertNotNull(qobj_B1); assertNotNull(qobj_D1); Collection<IQObject> d1_bases = qobj_D1.getBases(); assertNotNull(d1_bases); assertEquals(2, d1_bases.size()); Iterator<IQObject> iterator = d1_bases.iterator(); assertEquals(qobj_B1.getName(), iterator.next().getName()); assertEquals("B2", iterator.next().getName()); // D2 is not a QObject because it doesn't expand the Q_OBJECT macro IQObject qobj_D2 = qtIndex.findQObject(new String[]{ "D2" }); assertNull(qobj_D2); } // #include "junit-QObject.hh" // class Q0 : public QObject // { // Q_OBJECT // public: // enum EB { eb0 = 0xff }; // }; // class Q : public QObject // { // Q_OBJECT // // enum E0 { e0a, e0b }; // // Q_ENUMS( E0 Q0::EB ) // Q_ENUMS( E1 ) // // enum E1 { e1a, e1b = 2 }; // }; public void testEnums() throws Exception { loadComment("qenums.hh"); QtIndex qtIndex = QtIndex.getIndex(fProject); assertNotNull(qtIndex); IQObject qobj = qtIndex.findQObject(new String[]{ "Q" }); if (!isIndexOk("Q", qobj)) return; assertNotNull(qobj); Collection<IQEnum> qEnums = qobj.getEnums(); assertNotNull(qEnums); assertEquals(3, qEnums.size()); for(IQEnum qEnum : qEnums) { String name = qEnum.getName(); assertFalse(qEnum.isFlag()); if ("E0".equals(name)) { Collection<IQEnum.Enumerator> enumerators = qEnum.getEnumerators(); assertNotNull(enumerators); assertEquals(2, enumerators.size()); for (IQEnum.Enumerator enumerator : enumerators) { Long ordinal = enumerator.getOrdinal(); if (Long.valueOf(0).equals(ordinal)) assertEquals("e0a", enumerator.getName()); else if (Long.valueOf(1).equals(ordinal)) assertEquals("e0b", enumerator.getName()); else fail("unexpected " + name + "::" + enumerator.getName() + " = " + String.valueOf(ordinal)); } } else if("E1".equals(name)) { Collection<IQEnum.Enumerator> enumerators = qEnum.getEnumerators(); assertNotNull(enumerators); assertEquals(2, enumerators.size()); for (IQEnum.Enumerator enumerator : enumerators) { Long ordinal = enumerator.getOrdinal(); if (Long.valueOf(0).equals(ordinal)) assertEquals("e1a", enumerator.getName()); else if (Long.valueOf(2).equals(ordinal)) assertEquals("e1b", enumerator.getName()); else fail("unexpected " + name + "::" + enumerator.getName() + " = " + String.valueOf(ordinal)); } } else if("Q0::EB".equals(name)) { Collection<IQEnum.Enumerator> enumerators = qEnum.getEnumerators(); assertNotNull(enumerators); assertEquals(1, enumerators.size()); for (IQEnum.Enumerator enumerator : enumerators) { Long ordinal = enumerator.getOrdinal(); if (Long.valueOf(255).equals(ordinal)) assertEquals("eb0", enumerator.getName()); else fail("unexpected " + name + "::" + enumerator.getName() + " = " + String.valueOf(ordinal)); } } else { fail("unexpected Q_ENUM " + name); } } } // #include "junit-QObject.hh" // class Q : public QObject // { // Q_OBJECT // enum Enum { e0 }; // Q_DECLARE_FLAGS(Flag, Enum) // Q_FLAGS(Flag); // enum Enum2 { e2 }; // Q_FLAGS(Flag2); // Q_DECLARE_FLAGS(Flag2, Enum2) // Q_DECLARE_FLAGS(Flag2b, Enum2) // enum Enum3 { e3 }; // Q_DECLARE_FLAGS(Flag3, Enum3) // }; public void testFlags() throws Exception { loadComment("qflags.hh"); QtIndex qtIndex = QtIndex.getIndex(fProject); assertNotNull(qtIndex); IQObject qobj = qtIndex.findQObject(new String[]{ "Q" }); if (!isIndexOk("Q", qobj)) return; assertNotNull(qobj); Collection<IQEnum> qEnums = qobj.getEnums(); assertNotNull(qEnums); assertEquals(2, qEnums.size()); for(IQEnum qEnum : qEnums) { assertNotNull(qEnum); assertTrue(qEnum.isFlag()); if ("Flag".equals(qEnum.getName())) { Collection<IQEnum.Enumerator> enumerators = qEnum.getEnumerators(); assertNotNull(enumerators); assertEquals(1, enumerators.size()); assertEquals("e0", enumerators.iterator().next().getName()); } else if("Flag2".equals(qEnum.getName())) { Collection<IQEnum.Enumerator> enumerators = qEnum.getEnumerators(); assertNotNull(enumerators); assertEquals(1, enumerators.size()); assertEquals("e2", enumerators.iterator().next().getName()); } else fail("unexpected Q_FLAGS " + qEnum.getName()); } } // #include "junit-QObject.hh" // class B : public QObject // { // Q_OBJECT // Q_PROPERTY(bool allowed READ isAllowed) // public: // bool isAllowed() const { return false; } // }; public void testOwner() throws Exception { loadComment("owner.hh"); QtIndex qtIndex = QtIndex.getIndex(fProject); assertNotNull(qtIndex); IQObject qobj = qtIndex.findQObject(new String[]{ "B" }); if (!isIndexOk("B", qobj)) return; assertNotNull(qobj); Collection<IQProperty> properties = qobj.getProperties().locals(); assertNotNull(properties); assertEquals(1, properties.size()); IQProperty property = properties.iterator().next(); assertNotNull(property); assertTrue(qobj == property.getOwner()); } // #include "junit-QObject.hh" // template <typename T> class T {}; // class Q : public QObject // { // Q_OBJECT // // bool getProp() const; // // // strange cases found by grep'ing for Q_PROPERTY in the qt4 headers // Q_PROPERTY( bool prop1 READ getProp ) // Q_PROPERTY( T<bool> prop2 READ getProp ) // Q_PROPERTY( T<bool *> prop3 READ getProp ) // Q_PROPERTY( bool *prop4 READ getProp ) // Q_PROPERTY( bool prop5 ) // Q_PROPERTY( bool *prop6 ) // // Q_PROPERTY( bool read1 READ readMethod ) // Q_PROPERTY( bool read2 READ readMethod2 FINAL ) // // // from qtoolbar.h // Q_PROPERTY( Namespace::Type allowedAreas1 ) // Q_PROPERTY( Qt::ToolBarAreas allowedAreas2 READ allowedAreas WRITE setAllowedAreas // DESIGNABLE (qobject_cast<QMainWindow *>(parentWidget()) != 0) // NOTIFY allowedAreasChanged ) // // bool readMethod(); // bool readMethod2() const { return false; } // Qt::ToolBarAreas allowedAreas() const; // void setAllowedAreas( Qt::ToolBarAreas ) { } // Q_SIGNAL void allowedAreasChanged(); // }; public void testQProperties() throws Exception { loadComment("q_property.hh"); QtIndex qtIndex = QtIndex.getIndex(fProject); assertNotNull(qtIndex); IQObject qobj = qtIndex.findQObject(new String[]{ "Q" }); if (!isIndexOk("Q", qobj)) return; assertNotNull(qobj); assert_checkQProperties( qobj, new ExpectedQProperty("bool", "prop1", Attribute.READ, "getProp"), new ExpectedQProperty("T<bool>", "prop2", Attribute.READ, "getProp"), new ExpectedQProperty("T<bool *>", "prop3", Attribute.READ, "getProp"), new ExpectedQProperty("bool *", "prop4", Attribute.READ, "getProp"), new ExpectedQProperty("bool", "prop5"), new ExpectedQProperty("bool *", "prop6"), new ExpectedQProperty("bool", "read1", Attribute.READ, "readMethod"), new ExpectedQProperty("bool", "read2", Attribute.READ ,"readMethod2", Attribute.FINAL), new ExpectedQProperty("Namespace::Type", "allowedAreas1" ), new ExpectedQProperty("Qt::ToolBarAreas", "allowedAreas2", Attribute.READ, "allowedAreas", Attribute.WRITE, "setAllowedAreas", Attribute.DESIGNABLE, "(qobject_cast<QMainWindow *>(parentWidget()) != 0)", Attribute.NOTIFY, "allowedAreasChanged") ); } // #include "junit-QObject.hh" // class B : public QObject // { // Q_OBJECT // Q_PROPERTY(bool allowed READ isAllowed) // public: // bool isAllowed() const { return false; } // }; // class D1 : public B // { // Q_OBJECT // Q_PROPERTY(bool allowed READ isAllowed_d) // public: // bool isAllowed_d() const { return false; } // }; public void testGetOverridden() throws Exception { loadComment("getOverridden.hh"); QtIndex qtIndex = QtIndex.getIndex(fProject); assertNotNull(qtIndex); IQObject base_qobj = qtIndex.findQObject(new String[]{ "B" }); if (!isIndexOk("B", base_qobj)) return; assertNotNull(base_qobj); IQObject.IMembers<IQProperty> base_qprops = base_qobj.getProperties(); assertNotNull(base_qprops); assertEquals(1, base_qprops.all().size()); assertEquals(1, base_qprops.locals().size()); assertEquals(1, base_qprops.withoutOverrides().size()); IQObject derived_qobj1 = qtIndex.findQObject(new String[]{ "D1" }); assertNotNull(derived_qobj1); IQObject.IMembers<IQProperty> derived_qprops1 = derived_qobj1.getProperties(); assertNotNull(derived_qprops1); assertEquals(2, derived_qprops1.all().size()); assertEquals(1, derived_qprops1.locals().size()); assertEquals(1, derived_qprops1.withoutOverrides().size()); } // #include "junit-QObject.hh" // class B : public QObject // { // Q_OBJECT // Q_CLASSINFO( "key1", "value1" ) // Q_CLASSINFO( "key2", "value\"2" ) // public: // bool isAllowed() const { return false; } // }; // class D : public B // { // Q_OBJECT // Q_CLASSINFO( "key2", "overridden value" ) // public: // bool isAllowed() const { return false; } // }; public void testClassInfos() throws Exception { loadComment("classinfos.hh"); QtIndex qtIndex = QtIndex.getIndex(fProject); assertNotNull(qtIndex); IQObject qobj_b = qtIndex.findQObject(new String[]{ "B" }); if (!isIndexOk("B", qobj_b)) return; assertNotNull(qobj_b); assertEquals("value1", qobj_b.getClassInfo("key1")); assertEquals("value\\\"2", qobj_b.getClassInfo("key2")); IQObject qobj_d = qtIndex.findQObject(new String[]{ "D" }); assertNotNull(qobj_d); assertEquals("value1", qobj_d.getClassInfo("key1")); // inherited assertEquals("overridden value", qobj_d.getClassInfo("key2")); } private static class ExpectedQProperty { public final String type; public final String name; Object[] attributes; public ExpectedQProperty(String type, String name, Object... attributes) { this.type = type; this.name = name; this.attributes = attributes; } } /** * A utility method for testing Q_PROPERTYs. The given object is checked for the list of * values. Only the locally declared properties are checked and the list must be complete. */ private static void assert_checkQProperties(IQObject qobj, ExpectedQProperty... expectedProperties) throws Exception { // this map is used to make sure that all expected attributes are found Map<String, ExpectedQProperty> qprops = new HashMap<String, QObjectTests.ExpectedQProperty>(); for(ExpectedQProperty qprop : expectedProperties) if (qprops.containsKey(qprop.name)) fail("duplicate properties in expected list " + qprop.name); else qprops.put(qprop.name, qprop); for(IQProperty qprop : qobj.getProperties().locals()) { ExpectedQProperty expected = qprops.remove(qprop.getName()); assertNotNull("unexpected or duplicate attribute " + qprop.getName(), expected); assertEquals("unexpected type for " + expected.name, expected.type, qprop.getType()); assertEquals("unexpected type for " + expected.name, expected.name, qprop.getName()); // make sure that all attributes that were found were expected Set<Attribute> allAttrs = new HashSet<Attribute>(Arrays.asList(Attribute.values())); for(int i = 0; i < expected.attributes.length; ++i) { Attribute attr = (Attribute)expected.attributes[i]; // make sure the test is valid -- search for each attribute at most once assertTrue(allAttrs.remove(attr)); if (!attr.hasValue) assertNotNull("missing " + attr.toString(), attr.valueIn(qprop)); else if(i >= (expected.attributes.length - 1) || expected.attributes[i + 1] instanceof Attribute) fail("INVALID TEST CASE: " + attr + " should have a value, but one was not provided" ); else { Object exp = expected.attributes[++i]; assertEquals(attr.toString(), exp, attr.valueIn(qprop)); } } // make sure there is no value for all other attributes for(Attribute attr : allAttrs) assertTrue("unexpectedly found value for " + attr, attr.valueIn(qprop) == null); } // make sure that all expected properties were found StringBuilder missingAttrs = new StringBuilder(); for(String propName : qprops.keySet()) { if (missingAttrs.length() > 0) missingAttrs.append(", "); missingAttrs.append(propName); } assertTrue("missing properties " + missingAttrs.toString(), missingAttrs.length() == 0); } // #include "junit-QObject.hh" // class Q : public QObject // { // Q_OBJECT // signals: // public: void notASignal(); // Q_SIGNALS: void signal(); // public: void notAnotherSignal(); // Q_SIGNAL void anotherSignal(); // }; public void testSimpleSignal() throws Exception { loadComment("simple_signal.hh"); QtIndex qtIndex = QtIndex.getIndex(fProject); assertNotNull(qtIndex); IQObject qobj = qtIndex.findQObject(new String[]{ "Q" }); if (!isIndexOk("Q", qobj)) return; assertNotNull(qobj); IQObject.IMembers<IQMethod> signals = qobj.getSignals(); assertNotNull(signals); Collection<IQMethod> locals = signals.locals(); assertNotNull(locals); Iterator<IQMethod> i = locals.iterator(); assertTrue(i.hasNext()); assert_checkQMethod(i.next(), qobj, "signal", IQMethod.Kind.Signal, null); assertTrue(i.hasNext()); assert_checkQMethod(i.next(), qobj, "anotherSignal", IQMethod.Kind.Signal, null); assertFalse(i.hasNext()); } // #include "junit-QObject.hh" // namespace N { // class Q : public QObject // { // Q_OBJECT // Q_SIGNAL void aSignal(); // }; // } public void testQObjectInNamespace() throws Exception { loadComment("namespace_qobj.hh"); QtIndex qtIndex = QtIndex.getIndex(fProject); assertNotNull(qtIndex); IQObject qobj = qtIndex.findQObject(new String[]{ "N", "Q" }); if (!isIndexOk("N::Q", qobj)) return; assertNotNull(qobj); IQObject.IMembers<IQMethod> signals = qobj.getSignals(); assertNotNull(signals); Collection<IQMethod> locals = signals.locals(); assertNotNull(locals); Iterator<IQMethod> i = locals.iterator(); assertTrue(i.hasNext()); assert_checkQMethod(i.next(), qobj, "aSignal", IQMethod.Kind.Signal, null); assertFalse(i.hasNext()); } private static void assert_checkQMethod(IQMethod method, IQObject expectedOwner, String expectedName, IQMethod.Kind expectedKind, Long expectedRevision) throws Exception { assertEquals(expectedKind, method.getKind()); assertEquals(expectedName, method.getName()); assertSame(method.getName(), expectedOwner, method.getOwner()); assertEquals(expectedRevision, method.getRevision()); } // #include "junit-QObject.hh" // class Q : public QObject // { // Q_OBJECT // // // From the QML test suite -- this is not valid C++. The Qt moc generates duplicate const, // // but our CDT-based implementation is not able to do the same. Instead we generate what // // would be the correct C++ signature. // Q_INVOKABLE void someFunc(const QList<const QString const*> const &p1, QString p2 = "Hello"); // // // variations on the above // Q_INVOKABLE void someFunc1(const QList<const QString const*> &p1, QString p2 = "Hello"); // Q_INVOKABLE void someFunc2(QList<const QString const*> const &p1, QString p2 = "Hello"); // Q_INVOKABLE void someFunc3(const QList<const QString *> &p1, QString p2 = "Hello"); // Q_INVOKABLE void someFunc4(const QList<QString const*> &p1, QString p2 = "Hello"); // Q_INVOKABLE void someFunc5(const QList<const QString *> &p1, QString p2 = "Hello") const; // Q_INVOKABLE void someFunc6(const QList<QString *const> &p1, QString p2 = "Hello"); // }; public void testInvokables() throws Exception { loadComment("invokables.hh"); QtIndex qtIndex = QtIndex.getIndex(fProject); assertNotNull(qtIndex); IQObject qobj = qtIndex.findQObject(new String[]{ "Q" }); if (!isIndexOk("Q", qobj)) return; assertNotNull(qobj); IQObject.IMembers<IQMethod> invokables = qobj.getInvokables(); assertNotNull(invokables); assertEquals(7, invokables.locals().size()); for(IQMethod invokable : invokables.locals()) { assertTrue(invokable.getName(), qobj == invokable.getOwner()); assertEquals(invokable.getName(), IQMethod.Kind.Invokable, invokable.getKind()); assertNull(invokable.getRevision()); if ("someFunc".equals(invokable.getName())) assertTrue(invokable.getSignatures().contains("someFunc(QList<const QString*>,QString)")); else if ("someFunc1".equals(invokable.getName())) assertTrue(invokable.getSignatures().contains("someFunc1(QList<const QString*>,QString)")); else if ("someFunc2".equals(invokable.getName())) assertTrue(invokable.getSignatures().contains("someFunc2(QList<const QString*>,QString)")); else if ("someFunc3".equals(invokable.getName())) assertTrue(invokable.getSignatures().contains("someFunc3(QList<const QString*>,QString)")); else if ("someFunc4".equals(invokable.getName())) assertTrue(invokable.getSignatures().contains("someFunc4(QList<const QString*>,QString)")); else if ("someFunc5".equals(invokable.getName())) assertTrue(invokable.getSignatures().contains("someFunc5(QList<const QString*>,QString)")); else if ("someFunc6".equals(invokable.getName())) assertTrue(invokable.getSignatures().contains("someFunc6(QList<QString*const>,QString)")); else fail("unexpected invokable " + invokable.getName()); } } // #include "junit-QObject.hh" // class QUnrelated : public QObject { Q_OBJECT }; // class Q : public QObject // { // Q_OBJECT // Q_SIGNAL void signal1(); // Q_SLOT void slot1(); // // void f1(); // void f2() // { // Q q, *q_sender = this, *q_receiver = this; // QUnrelated *q_unrelated; // QMetaMethod meta = q.metaObject()->method( 0 ); // // // static bool connect(const QObject *sender, const char *signal, // // const QObject *receiver, const char *member, // // Qt::ConnectionType = Qt::AutoConnection); // QObject::connect( q_sender, SIGNAL(signal1()), q_receiver, SIGNAL(signal1()) ); // QObject::connect( q_sender, SIGNAL(signal1()), q_receiver, SLOT(slot1()) ); // QObject::connect( q_sender, SIGNAL(signal1()), q_receiver, SIGNAL(signal1()), Qt::AutoConnection ); // QObject::connect( q_sender, SIGNAL(signal1()), q_receiver, SLOT(slot1()), Qt::AutoConnection ); // q_unrelated->connect( q_sender, SIGNAL(signal1()), q_receiver, SIGNAL(signal1()) ); // q_unrelated->connect( q_sender, SIGNAL(signal1()), q_receiver, SLOT(slot1()) ); // q_unrelated->connect( q_sender, SIGNAL(signal1()), q_receiver, SIGNAL(signal1()), Qt::AutoConnection ); // q_unrelated->connect( q_sender, SIGNAL(signal1()), q_receiver, SLOT(slot1()), Qt::AutoConnection ); // // // static bool connect(const QObject *sender, const QMetaMethod &signal, // // const QObject *receiver, const QMetaMethod &method, // // Qt::ConnectionType type = Qt::AutoConnection); // QObject::connect( q_sender, meta, q_receiver, meta ); // QObject::connect( q_sender, meta, q_receiver, meta, Qt::AutoConnection ); // q_unrelated->connect( q_sender, meta, q_receiver, meta ); // q_unrelated->connect( q_sender, meta, q_receiver, meta, Qt::AutoConnection ); // // // inline bool connect(const QObject *sender, const char *signal, // // const char *member, // // Qt::ConnectionType type = Qt::AutoConnection) const; // q_receiver->connect( q_sender, SIGNAL(signal1()), SIGNAL(signal1()) ); // q_receiver->connect( q_sender, SIGNAL(signal1()), SLOT(slot1()) ); // q_receiver->connect( q_sender, SIGNAL(signal1()), SIGNAL(signal1()), Qt::AutoConnection ); // q_receiver->connect( q_sender, SIGNAL(signal1()), SLOT(slot1()), Qt::AutoConnection ); // // // static bool disconnect(const QObject *sender, const char *signal, // // const QObject *receiver, const char *member); // QObject::disconnect( q_sender, SIGNAL(signal1()), q_receiver, SIGNAL(signal1()) ); // QObject::disconnect( q_sender, SIGNAL(signal1()), q_receiver, SLOT(slot1()) ); // q_unrelated->disconnect( q_sender, SIGNAL(signal1()), q_receiver, SIGNAL(signal1()) ); // q_unrelated->disconnect( q_sender, SIGNAL(signal1()), q_receiver, SLOT(slot1()) ); // // // static bool disconnect(const QObject *sender, const QMetaMethod &signal, // // const QObject *receiver, const QMetaMethod &member); // QObject::disconnect( q_sender, meta, q_receiver, meta ); // q_unrelated->disconnect( q_sender, meta, q_receiver, meta ); // // // inline bool disconnect(const char *signal = 0, // // const QObject *receiver = 0, const char *member = 0); // q_sender->disconnect( SIGNAL(signal1()), q_receiver, SIGNAL(signal1()) ); // q_sender->disconnect( SIGNAL(signal1()), q_receiver, SLOT(slot1()) ); // q_sender->disconnect( SIGNAL(signal1()), q_receiver ); // q_sender->disconnect( SIGNAL(signal1()) ); // q_sender->disconnect(); // // // inline bool disconnect(const QObject *receiver, const char *member = 0); // q_sender->disconnect( q_receiver, SIGNAL(signal1()) ); // q_sender->disconnect( q_receiver, SLOT(slot1()) ); // q_sender->disconnect( q_receiver ); // } // }; // // This is exactly the same as the inline function body. It is duplicated here because of // // an old bug where the function definitions were not properly indexed (for Qt). // void Q::f1() // { // Q q, *q_sender = this, *q_receiver = this; // QUnrelated *q_unrelated; // QMetaMethod meta = q.metaObject()->method( 0 ); // // // static bool connect(const QObject *sender, const char *signal, // // const QObject *receiver, const char *member, // // Qt::ConnectionType = Qt::AutoConnection); // QObject::connect( q_sender, SIGNAL(signal1()), q_receiver, SIGNAL(signal1()) ); // QObject::connect( q_sender, SIGNAL(signal1()), q_receiver, SLOT(slot1()) ); // QObject::connect( q_sender, SIGNAL(signal1()), q_receiver, SIGNAL(signal1()), Qt::AutoConnection ); // QObject::connect( q_sender, SIGNAL(signal1()), q_receiver, SLOT(slot1()), Qt::AutoConnection ); // q_unrelated->connect( q_sender, SIGNAL(signal1()), q_receiver, SIGNAL(signal1()) ); // q_unrelated->connect( q_sender, SIGNAL(signal1()), q_receiver, SLOT(slot1()) ); // q_unrelated->connect( q_sender, SIGNAL(signal1()), q_receiver, SIGNAL(signal1()), Qt::AutoConnection ); // q_unrelated->connect( q_sender, SIGNAL(signal1()), q_receiver, SLOT(slot1()), Qt::AutoConnection ); // // // static bool connect(const QObject *sender, const QMetaMethod &signal, // // const QObject *receiver, const QMetaMethod &method, // // Qt::ConnectionType type = Qt::AutoConnection); // QObject::connect( q_sender, meta, q_receiver, meta ); // QObject::connect( q_sender, meta, q_receiver, meta, Qt::AutoConnection ); // q_unrelated->connect( q_sender, meta, q_receiver, meta ); // q_unrelated->connect( q_sender, meta, q_receiver, meta, Qt::AutoConnection ); // // // inline bool connect(const QObject *sender, const char *signal, // // const char *member, // // Qt::ConnectionType type = Qt::AutoConnection) const; // q_receiver->connect( q_sender, SIGNAL(signal1()), SIGNAL(signal1()) ); // q_receiver->connect( q_sender, SIGNAL(signal1()), SLOT(slot1()) ); // q_receiver->connect( q_sender, SIGNAL(signal1()), SIGNAL(signal1()), Qt::AutoConnection ); // q_receiver->connect( q_sender, SIGNAL(signal1()), SLOT(slot1()), Qt::AutoConnection ); // // // static bool disconnect(const QObject *sender, const char *signal, // // const QObject *receiver, const char *member); // QObject::disconnect( q_sender, SIGNAL(signal1()), q_receiver, SIGNAL(signal1()) ); // QObject::disconnect( q_sender, SIGNAL(signal1()), q_receiver, SLOT(slot1()) ); // q_unrelated->disconnect( q_sender, SIGNAL(signal1()), q_receiver, SIGNAL(signal1()) ); // q_unrelated->disconnect( q_sender, SIGNAL(signal1()), q_receiver, SLOT(slot1()) ); // // // static bool disconnect(const QObject *sender, const QMetaMethod &signal, // // const QObject *receiver, const QMetaMethod &member); // QObject::disconnect( q_sender, meta, q_receiver, meta ); // q_unrelated->disconnect( q_sender, meta, q_receiver, meta ); // // // inline bool disconnect(const char *signal = 0, // // const QObject *receiver = 0, const char *member = 0); // q_sender->disconnect( SIGNAL(signal1()), q_receiver, SIGNAL(signal1()) ); // q_sender->disconnect( SIGNAL(signal1()), q_receiver, SLOT(slot1()) ); // q_sender->disconnect( SIGNAL(signal1()), q_receiver ); // q_sender->disconnect( SIGNAL(signal1()) ); // q_sender->disconnect(); // // // inline bool disconnect(const QObject *receiver, const char *member = 0); // q_sender->disconnect( q_receiver, SIGNAL(signal1()) ); // q_sender->disconnect( q_receiver, SLOT(slot1()) ); // q_sender->disconnect( q_receiver ); // } public void testSignalSlotReferences() throws Exception { loadComment("sig_slot_refs.hh"); waitForIndexer(fCProject); // References are from the function's IBinding. assertNotNull(fIndex); fIndex.acquireReadLock(); try { char[][] Q_signal1_qn = new char[][]{ "Q".toCharArray(), "signal1".toCharArray() }; IIndexBinding[] Q_signal1s = fIndex.findBindings(Q_signal1_qn, IndexFilter.CPP_DECLARED_OR_IMPLICIT, npm()); assertNotNull(Q_signal1s); assertEquals(1, Q_signal1s.length); IIndexBinding Q_signal1 = Q_signal1s[0]; assertNotNull(Q_signal1); char[][] Q_slot1_qn = new char[][]{ "Q".toCharArray(), "slot1".toCharArray() }; IIndexBinding[] Q_slot1s = fIndex.findBindings(Q_slot1_qn, IndexFilter.CPP_DECLARED_OR_IMPLICIT, npm()); assertNotNull(Q_slot1s); assertEquals(1, Q_slot1s.length); IIndexBinding Q_slot1 = Q_slot1s[0]; assertNotNull(Q_slot1); // Each valid variant of the connect function call should have one reference // in the inline function (f2) and one reference in the function with a separate // definition (f1). int expectedSignalRefs = 2 * 30; int expectedSlotRefs = 2 * 10; IIndexName[] signalRefs = fIndex.findReferences(Q_signal1); assertNotNull(signalRefs); assertEquals(expectedSignalRefs, signalRefs.length); IIndexName[] slotRefs = fIndex.findReferences(Q_slot1); assertNotNull(slotRefs); assertEquals(expectedSlotRefs, slotRefs.length); } finally { fIndex.releaseReadLock(); } } }