| /* |
| * Copyright (c) 2013, 2015 QNX Software Systems and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| */ |
| 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.IQProperty.Attribute; |
| import org.eclipse.cdt.internal.qt.core.index.QtIndex; |
| |
| 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<>(); |
| 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<>(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(); |
| } |
| } |
| } |