diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/ASTUtil.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/ASTUtil.java index 7fc4bbaa414..27875328dc8 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/ASTUtil.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/ASTUtil.java @@ -61,6 +61,38 @@ public class ASTUtil { return cProject.getProject(); } + /** + * Return the fully qualified name of the binding for the given name. Returns null + * if the name has no binding. Tries to resolve the binding if needed. + */ + public static String getFullyQualifiedName(IASTName name) { + return getFullyQualifiedName(name.resolveBinding()); + } + + /** + * Return the fully qualified name of the given binding. Returns null if there + * is no binding. + */ + public static String getFullyQualifiedName(IBinding binding) { + if (binding == null) + return null; + + String ownerName = getFullyQualifiedName(binding.getOwner()); + return (ownerName == null ? "" : ownerName) + "::" + binding.getName(); + } + + /** + * Create and return a string representation of the fully qualified name in the + * input array's elements. + */ + public static String getFullyQualifiedName(String[] qualName) { + String fullyQualifiedName = ""; + for(int i = 0; i < qualName.length; ++i) { + fullyQualifiedName += "::" + qualName[i]; + } + return fullyQualifiedName; + } + // NOTE: This expression allows embedded line terminators (?s) for cases where the code looks like: // QObject::connect( &a, SIGNAL( // sig1( diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtMethodReference.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtMethodReference.java index 0405c2275d1..42afecd5ae0 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtMethodReference.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtMethodReference.java @@ -160,7 +160,7 @@ public class QtMethodReference extends ASTNameReference { } @Override - public char[] toCharArray() { + public char[] getSimpleID() { return expansionParam.toCharArray(); } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QObject.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QObject.java index 9c958957ad9..45acab160a7 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QObject.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QObject.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.internal.qt.core.pdom.QtPDOMProperty; @@ -35,8 +36,15 @@ public class QObject implements IQObject { private final List enums; private final Map classInfos; + /** + * QObjects are stored in the QtLinkage using their fully qualified name. The API + * for IQObject does not expect the leading ::, so they are stripped when the + * object is read from the PDOM. + */ + private static Pattern StripLeadingQual_Regex = Pattern.compile("^::(.*)$"); + public QObject(QtIndexImpl qtIndex, CDTIndex cdtIndex, QtPDOMQObject pdomQObject) throws CoreException { - this.name = pdomQObject.getName(); + this.name = StripLeadingQual_Regex.matcher(pdomQObject.getName()).replaceAll("$1"); this.pdomQObject = pdomQObject; List baseSlots = new ArrayList(); diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QtIndexImpl.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QtIndexImpl.java index 9bc3f02bd72..66af6c15cbb 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QtIndexImpl.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QtIndexImpl.java @@ -12,6 +12,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IndexFilter; +import org.eclipse.cdt.internal.qt.core.ASTUtil; import org.eclipse.cdt.internal.qt.core.pdom.AbstractQtPDOMClass; import org.eclipse.cdt.internal.qt.core.pdom.QtPDOMQObject; import org.eclipse.cdt.qt.core.index.IQGadget; @@ -51,12 +52,11 @@ public class QtIndexImpl extends QtIndex { private class QObjectImplAccessor implements CDTIndex.Accessor { - private final char[][] name; + private final char[] name; public QObjectImplAccessor(String[] qualName) { - name = new char[qualName.length][]; - for(int i = 0; i < name.length; ++i) - name[i] = qualName[i].toCharArray(); + // QObjects are stored in the Qt linkage using their fully qualified name. + name = ASTUtil.getFullyQualifiedName(qualName).toCharArray(); } @Override diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/ASTDelegatedName.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/ASTDelegatedName.java index 3e0cb5b7a1f..f90305bbd69 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/ASTDelegatedName.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/ASTDelegatedName.java @@ -149,18 +149,18 @@ public abstract class ASTDelegatedName implements IASTName { } @Override - public char[] toCharArray() { - return delegate.toCharArray(); + public char[] getSimpleID() { + return delegate.getSimpleID(); } @Override - public char[] getSimpleID() { - return toCharArray(); + public char[] toCharArray() { + return getSimpleID(); } @Override public char[] getLookupKey() { - return toCharArray(); + return getSimpleID(); } @Override diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QObjectName.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QObjectName.java index d1d78258046..1b800520349 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QObjectName.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QObjectName.java @@ -14,6 +14,7 @@ import java.util.Map; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.internal.qt.core.ASTUtil; import org.eclipse.core.runtime.CoreException; /** @@ -22,11 +23,19 @@ import org.eclipse.core.runtime.CoreException; */ public class QObjectName extends AbstractQClassName { + private final char[] fullyQualifiedName; private final List properties = new ArrayList(); private final Map classInfos = new LinkedHashMap(); public QObjectName(ICPPASTCompositeTypeSpecifier spec) { super(spec); + fullyQualifiedName = ASTUtil.getFullyQualifiedName(spec.getName()).toCharArray(); + } + + @Override + public char[] getSimpleID() { + // The Qt linkage uses the full qualified name when storing QObjects into the index. + return fullyQualifiedName; } public List getProperties() { diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQObject.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQObject.java index 383ca73112b..53ad1e9edb6 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQObject.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQObject.java @@ -65,7 +65,7 @@ public interface IQObject extends IQElement { } /** - * Returns the name of the class. + * Returns the fully qualified name of the class. */ public String getName(); diff --git a/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/QObjectTests.java b/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/QObjectTests.java index 9a13400cb19..7fd4e96ad4b 100644 --- a/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/QObjectTests.java +++ b/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/QObjectTests.java @@ -452,6 +452,37 @@ public class QObjectTests extends BaseQtTestCase { 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 signals = qobj.getSignals(); + assertNotNull(signals); + + Collection locals = signals.locals(); + assertNotNull(locals); + + Iterator 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());