Skip to main content
summaryrefslogtreecommitdiffstats
path: root/qt
diff options
context:
space:
mode:
authorAndrew Eidsness2014-01-07 12:45:00 -0500
committerDoug Schaefer2014-01-07 15:21:47 -0500
commit78fc903d16d9dac55ba03db1360f9c00cbb2d01e (patch)
tree2331e88b8a04f7780a14f590159069bb7ce8a1b2 /qt
parent0e196ca5f21239568edf1b013bc8ec0d4327c7a4 (diff)
downloadorg.eclipse.cdt-78fc903d16d9dac55ba03db1360f9c00cbb2d01e.tar.gz
org.eclipse.cdt-78fc903d16d9dac55ba03db1360f9c00cbb2d01e.tar.xz
org.eclipse.cdt-78fc903d16d9dac55ba03db1360f9c00cbb2d01e.zip
Bug 422841 QtIndex API for qmlRegisterType function calls
The Qt spec includes a special function that is used to introduce C++ types to a namespace that is accessible from QML. E.g., qmlRegisterType<Q>( "uri", 1, 0, "QMLType" ); This will create a QML type called QMLType. The type will include the signals, slots, and invokable that are defined in the C++ class Q. The type is accessible in QML using the given URI and the version is 1.0. More information is available at: http://qt-project.org/doc/qt-4.8/qdeclarativeengine.html This patch adds IQmlRegisteredType, a collection of which can be accessed from a new method in QtIndex. This also includes new test cases for this feature. Change-Id: I70c44d1d8d3a0594de44e692a16f7b26396e8464 Signed-off-by: Andrew Eidsness <eclipse@jfront.com> Reviewed-on: https://git.eclipse.org/r/20347 Tested-by: Hudson CI Reviewed-by: Doug Schaefer <dschaefer@qnx.com> IP-Clean: Doug Schaefer <dschaefer@qnx.com>
Diffstat (limited to 'qt')
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/ASTUtil.java23
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QObject.java10
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QmlRegistered.java110
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QtIndexImpl.java35
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QObjectName.java4
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QmlTypeRegistration.java151
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtASTVisitor.java29
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMBinding.java49
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMLinkage.java2
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMNodeType.java10
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMQmlRegistration.java84
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMQmlUncreatableRegistration.java53
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtKeywords.java12
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQmlRegistered.java113
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/QtIndex.java11
-rw-r--r--qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/AllQtTests.java3
-rw-r--r--qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/QmlRegisteredTests.java201
-rw-r--r--qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QObjectConnectCompletion.java13
18 files changed, 877 insertions, 36 deletions
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 27875328dc..3be32730c9 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
@@ -12,6 +12,7 @@ import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Pattern;
+import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
@@ -27,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.model.ICProject;
@@ -34,6 +36,7 @@ import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
+import org.eclipse.cdt.qt.core.QtPlugin;
import org.eclipse.cdt.qt.core.index.IQMethod;
import org.eclipse.cdt.qt.core.index.IQObject;
import org.eclipse.core.resources.IProject;
@@ -76,6 +79,13 @@ public class ASTUtil {
public static String getFullyQualifiedName(IBinding binding) {
if (binding == null)
return null;
+ if (binding instanceof ICPPBinding)
+ try {
+ return getFullyQualifiedName(((ICPPBinding) binding).getQualifiedName());
+ } catch(DOMException e) {
+ QtPlugin.log(e);
+ return null;
+ }
String ownerName = getFullyQualifiedName(binding.getOwner());
return (ownerName == null ? "" : ownerName) + "::" + binding.getName();
@@ -86,11 +96,16 @@ public class ASTUtil {
* input array's elements.
*/
public static String getFullyQualifiedName(String[] qualName) {
- String fullyQualifiedName = "";
- for(int i = 0; i < qualName.length; ++i) {
- fullyQualifiedName += "::" + qualName[i];
+ boolean first = true;
+ StringBuilder str = new StringBuilder();
+ for(String name : qualName) {
+ if (first)
+ first = false;
+ else
+ str.append("::");
+ str.append(name);
}
- return fullyQualifiedName;
+ return str.toString();
}
// NOTE: This expression allows embedded line terminators (?s) for cases where the code looks like:
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 45acab160a..9c958957ad 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,7 +11,6 @@ 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;
@@ -36,15 +35,8 @@ public class QObject implements IQObject {
private final List<IQEnum> enums;
private final Map<String, String> 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 = StripLeadingQual_Regex.matcher(pdomQObject.getName()).replaceAll("$1");
+ this.name = pdomQObject.getName();
this.pdomQObject = pdomQObject;
List<IQMethod> baseSlots = new ArrayList<IQMethod>();
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QmlRegistered.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QmlRegistered.java
new file mode 100644
index 0000000000..46d3ac7983
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QmlRegistered.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2014 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.internal.qt.core.index;
+
+import org.eclipse.cdt.core.dom.ast.IBinding;
+import org.eclipse.cdt.internal.qt.core.pdom.QtPDOMQmlRegistration;
+import org.eclipse.cdt.internal.qt.core.pdom.QtPDOMQmlUncreatableRegistration;
+import org.eclipse.cdt.qt.core.index.IQObject;
+import org.eclipse.cdt.qt.core.index.IQmlRegistered;
+import org.eclipse.core.runtime.CoreException;
+
+public class QmlRegistered implements IQmlRegistered {
+
+ private final QtIndexImpl qtIndex;
+ private final IQmlRegistered.Kind kind;
+ private final String[] ownerName;
+ private final Long version;
+ private final String uri;
+ private final Long major;
+ private final Long minor;
+ private final String qmlName;
+ private final String reason;
+ private IQObject qObject;
+
+ public static QmlRegistered create(QtIndexImpl qtIndex, IBinding pdom) throws CoreException {
+ if (pdom instanceof QtPDOMQmlUncreatableRegistration)
+ return new QmlRegistered(qtIndex, (QtPDOMQmlUncreatableRegistration) pdom);
+ if (pdom instanceof QtPDOMQmlRegistration)
+ return new QmlRegistered(qtIndex, (QtPDOMQmlRegistration) pdom);
+ return null;
+ }
+
+ private QmlRegistered(QtIndexImpl qtIndex, QtPDOMQmlRegistration pdom) throws CoreException {
+ this.qtIndex = qtIndex;
+ this.kind = IQmlRegistered.Kind.Type;
+
+ String qobjName = pdom.getQObjectName();
+ this.ownerName = qobjName == null ? null : qobjName.split("::");
+
+ this.version = pdom.getVersion();
+ this.uri = pdom.getUri();
+ this.major = pdom.getMajor();
+ this.minor = pdom.getMinor();
+ this.qmlName = pdom.getQmlName();
+ this.reason = null;
+ }
+
+ private QmlRegistered(QtIndexImpl qtIndex, QtPDOMQmlUncreatableRegistration pdom) throws CoreException {
+ this.qtIndex = qtIndex;
+ this.kind = IQmlRegistered.Kind.Uncreatable;
+
+ String qobjName = pdom.getQObjectName();
+ this.ownerName = qobjName == null ? null : qobjName.split("::");
+
+ this.version = pdom.getVersion();
+ this.uri = pdom.getUri();
+ this.major = pdom.getMajor();
+ this.minor = pdom.getMinor();
+ this.qmlName = pdom.getQmlName();
+ this.reason = pdom.getReason();
+ }
+
+ @Override
+ public IQmlRegistered.Kind getKind() {
+ return kind;
+ }
+
+ @Override
+ public IQObject getQObject() {
+ if (qObject == null
+ && ownerName != null)
+ qObject = qtIndex.findQObject(ownerName);
+ return qObject;
+ }
+
+ @Override
+ public Long getVersion() {
+ return version;
+ }
+
+ @Override
+ public String getURI() {
+ return uri;
+ }
+
+ @Override
+ public Long getMajor() {
+ return major;
+ }
+
+ @Override
+ public Long getMinor() {
+ return minor;
+ }
+
+ @Override
+ public String getQmlName() {
+ return qmlName;
+ }
+
+ @Override
+ public String getReason() {
+ return reason;
+ }
+}
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 66af6c15cb..326b1363de 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
@@ -7,6 +7,11 @@
*/
package org.eclipse.cdt.internal.qt.core.index;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.regex.Pattern;
+
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.index.IIndex;
@@ -15,8 +20,10 @@ 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.QtKeywords;
import org.eclipse.cdt.qt.core.index.IQGadget;
import org.eclipse.cdt.qt.core.index.IQObject;
+import org.eclipse.cdt.qt.core.index.IQmlRegistered;
import org.eclipse.cdt.qt.core.index.QtIndex;
import org.eclipse.core.runtime.CoreException;
@@ -24,6 +31,11 @@ public class QtIndexImpl extends QtIndex {
private final CDTIndex cdtIndex;
+ private static final Pattern QmlTypeNameRegex
+ = Pattern.compile("^(?:"
+ + QtKeywords.QML_REGISTER_TYPE + '|' + QtKeywords.QML_REGISTER_UNCREATABLE_TYPE
+ + ")<.*>\0(.*)$");
+
private static final IndexFilter QtLinkageFilter = new IndexFilter() {
@Override
public boolean acceptLinkage(ILinkage linkage) {
@@ -50,6 +62,11 @@ public class QtIndexImpl extends QtIndex {
return name == null ? null : cdtIndex.get(new QGadgetImplAccessor(name));
}
+ @Override
+ public Collection<IQmlRegistered> getQmlRegistered() {
+ return cdtIndex.get(new QMLRegisteredAccessor());
+ }
+
private class QObjectImplAccessor implements CDTIndex.Accessor<IQObject> {
private final char[] name;
@@ -92,4 +109,22 @@ public class QtIndexImpl extends QtIndex {
return null;
}
}
+
+ private class QMLRegisteredAccessor implements CDTIndex.Accessor<Collection<IQmlRegistered>> {
+
+ @Override
+ public Collection<IQmlRegistered> access(IIndex index) throws CoreException {
+ Collection<IQmlRegistered> types = null;
+ for(IIndexBinding binding : index.findBindings(QmlTypeNameRegex, false, QtLinkageFilter, null)) {
+ IQmlRegistered qml = QmlRegistered.create(QtIndexImpl.this, binding);
+ if (qml != null) {
+ if (types == null)
+ types = new ArrayList<IQmlRegistered>();
+ types.add(qml);
+ }
+ }
+
+ return types == null ? Collections.<IQmlRegistered>emptyList() : types;
+ }
+ }
}
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 1b80052034..f5c1554300 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
@@ -29,7 +29,9 @@ public class QObjectName extends AbstractQClassName {
public QObjectName(ICPPASTCompositeTypeSpecifier spec) {
super(spec);
- fullyQualifiedName = ASTUtil.getFullyQualifiedName(spec.getName()).toCharArray();
+
+ String fqn = ASTUtil.getFullyQualifiedName(spec.getName());
+ fullyQualifiedName = fqn == null ? new char[0] : fqn.toCharArray();
}
@Override
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QmlTypeRegistration.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QmlTypeRegistration.java
new file mode 100644
index 0000000000..86358c532d
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QmlTypeRegistration.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014 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.internal.qt.core.pdom;
+
+import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
+import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
+import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
+import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
+import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IType;
+import org.eclipse.cdt.core.dom.ast.IValue;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
+import org.eclipse.cdt.internal.qt.core.ASTUtil;
+import org.eclipse.cdt.qt.core.QtKeywords;
+import org.eclipse.cdt.qt.core.index.IQmlRegistered;
+import org.eclipse.core.runtime.CoreException;
+
+public class QmlTypeRegistration extends ASTDelegatedName implements IQtASTName {
+
+ private final ICPPTemplateInstance functionInstanceBinding;
+ private final IASTFunctionCallExpression fnCall;
+ private final IQmlRegistered.Kind kind;
+ private char[] simpleID;
+
+ public QmlTypeRegistration(IASTName ast, ICPPTemplateInstance functionInstanceBinding, IASTFunctionCallExpression fnCall) {
+ super(ast);
+ this.functionInstanceBinding = functionInstanceBinding;
+ this.fnCall = fnCall;
+
+ if (QtKeywords.QML_REGISTER_UNCREATABLE_TYPE.equals(functionInstanceBinding.getName()))
+ this.kind = IQmlRegistered.Kind.Uncreatable;
+ else
+ this.kind = IQmlRegistered.Kind.Type;
+ }
+
+ @Override
+ public char[] getSimpleID() {
+ if (simpleID == null) {
+ IASTInitializerClause[] args = fnCall.getArguments();
+ simpleID = (functionInstanceBinding.getName()
+ + ASTTypeUtil.getArgumentListString(functionInstanceBinding.getTemplateArguments(), true)
+ + "\0("
+ + asStringForName(args, 0) + ','
+ + asStringForName(args, 1) + ','
+ + asStringForName(args, 2) + ','
+ + asStringForName(args, 3) + ')'
+ ).toCharArray();
+ }
+
+ return simpleID;
+ }
+
+ @Override
+ public QtPDOMBinding createPDOMBinding(QtPDOMLinkage linkage) throws CoreException {
+ switch(kind) {
+ case Type:
+ return new QtPDOMQmlRegistration(linkage, this, delegate);
+ case Uncreatable:
+ return new QtPDOMQmlUncreatableRegistration(linkage, this, delegate);
+ }
+ return null;
+ }
+
+ public String getQObjectName() {
+ ICPPTemplateArgument[] args = functionInstanceBinding.getTemplateArguments();
+ if (args.length < 1)
+ return null;
+
+ IType type = args[0].getTypeValue();
+ return type instanceof ICPPBinding ? ASTUtil.getFullyQualifiedName((ICPPBinding) type) : null;
+ }
+
+ public Long getVersion() {
+ ICPPTemplateArgument[] args = functionInstanceBinding.getTemplateArguments();
+ if (args.length < 2)
+ return null;
+
+ IValue val = args[1].getNonTypeValue();
+ return val == null ? null : val.numericalValue();
+ }
+
+ public String getUri() {
+ return getArgAsStringOrNull(0);
+ }
+
+ public Long getMajor() {
+ return getArgAsLongOrNull(1);
+ }
+
+ public Long getMinor() {
+ return getArgAsLongOrNull(2);
+ }
+
+ public String getQmlName() {
+ return getArgAsStringOrNull(3);
+ }
+
+ public String getReason() {
+ return getArgAsStringOrNull(4);
+ }
+
+ private String asStringForName(IASTInitializerClause[] args, int index) {
+ String arg = args.length <= index ? null : asString(args[index]);
+ return arg == null ? "" : arg;
+ }
+
+ private String getArgAsStringOrNull(int index) {
+ IASTInitializerClause[] args = fnCall.getArguments();
+ if (args.length <= index)
+ return null;
+
+ return asString(args[index]);
+ }
+
+ private Long getArgAsLongOrNull(int index) {
+ IASTInitializerClause[] args = fnCall.getArguments();
+ if (args.length <= index)
+ return null;
+
+ String str = asString(args[index]);
+ if (str != null)
+ try {
+ return Long.parseLong(str);
+ } catch(NumberFormatException e) {
+ // This is caused by invalid user code, do not log it
+ }
+
+ return null;
+ }
+
+ private static String asString(IASTInitializerClause init) {
+ if (init instanceof IASTLiteralExpression) {
+ IASTLiteralExpression literal = (IASTLiteralExpression) init;
+ switch(literal.getKind()) {
+ case IASTLiteralExpression.lk_integer_constant:
+ return new String(literal.getValue());
+ case IASTLiteralExpression.lk_string_literal:
+ char[] value = literal.getValue();
+ return new String(value, 1, value.length - 2);
+ }
+ }
+ return null;
+ }
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtASTVisitor.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtASTVisitor.java
index 1629f2b341..a26e161283 100644
--- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtASTVisitor.java
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtASTVisitor.java
@@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
+import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
@@ -33,10 +34,12 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.index.IIndexSymbols;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.parser.scanner.LocationMap;
+import org.eclipse.cdt.internal.qt.core.ASTUtil;
import org.eclipse.cdt.internal.qt.core.QtFunctionCall;
import org.eclipse.cdt.internal.qt.core.QtMethodReference;
import org.eclipse.cdt.internal.qt.core.QtMethodUtil;
@@ -124,7 +127,10 @@ public class QtASTVisitor extends ASTVisitor {
@Override
public int visit(IASTExpression expr) {
if (expr instanceof IASTFunctionCallExpression) {
- Collection<QtMethodReference> refs = QtFunctionCall.getReferences((IASTFunctionCallExpression) expr);
+ IASTFunctionCallExpression call = (IASTFunctionCallExpression) expr;
+
+ // See if this is a QObject::connect or disconnect function call.
+ Collection<QtMethodReference> refs = QtFunctionCall.getReferences(call);
if (refs != null)
for (IASTName ref : refs) {
IASTFileLocation nameLoc = ref.getFileLocation();
@@ -133,6 +139,27 @@ public class QtASTVisitor extends ASTVisitor {
symbols.add(owner, ref, null);
}
}
+
+ // See if this is a qmlRegisterType or qmlRegisterUncreatableType function call.
+ ICPPTemplateInstance templateFn = ASTUtil.resolveFunctionBinding(ICPPTemplateInstance.class, call);
+ if (QtKeywords.is_QmlType(templateFn)) {
+ IASTName fnName = null;
+ IASTExpression fnNameExpr = call.getFunctionNameExpression();
+ if (fnNameExpr instanceof IASTIdExpression) {
+ fnName = ((IASTIdExpression) fnNameExpr).getName();
+ }
+ IASTFileLocation nameLoc = call.getFileLocation();
+ if (nameLoc != null) {
+ QmlTypeRegistration qmlTypeReg = new QmlTypeRegistration(fnName, templateFn, call);
+
+ IASTPreprocessorIncludeStatement owner = nameLoc.getContextInclusionStatement();
+ symbols.add(owner, qmlTypeReg, null);
+
+ // the Qt data references the C++ function template instance specialization
+ if (fnName != null)
+ symbols.add(owner, new ASTNameReference(fnName), qmlTypeReg);
+ }
+ }
}
return super.visit(expr);
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMBinding.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMBinding.java
index d2a772926c..7f2672a96a 100644
--- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMBinding.java
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMBinding.java
@@ -30,10 +30,6 @@ public abstract class QtPDOMBinding extends PDOMBinding {
this.offset = offsetInitializer;
offsetInitializer += sizeof;
}
-
- public long getRecord(long baseRec) {
- return baseRec + offset;
- }
}
protected QtPDOMBinding(QtPDOMLinkage linkage, long record) {
@@ -78,4 +74,49 @@ public abstract class QtPDOMBinding extends PDOMBinding {
return super.getAdapter(adapter);
}
+
+ /**
+ * Returns a Long from the given offset within this node's record. The permitted range of the Long
+ * is [Long.MIN_VALUE, Long.MAX_VALUE). Notice that Long.MAX_VALUE is excluded from the valid range.
+ */
+ protected Long getLongOrNull(long offset) throws CoreException {
+ long val = getDB().getLong(record + offset);
+ return val == Long.MAX_VALUE ? null : Long.valueOf(val);
+ }
+
+ /**
+ * Puts the given Long into the database at the specified offset within this node's record. The permitted
+ * range for val is [Long.MIN_VALUE, Long.MAX_VALUE). Notice that Long.MAX_VALUE is excluded from
+ * the valid range.
+ * <p>
+ * The val parameter is allowed to be null. A value will be stored to the database so that later calls to
+ * {@link #getLongOrNull(long)} will return null;
+ */
+ protected void putLongOrNull(long offset, Long val) throws CoreException {
+ getDB().putLong(record + offset, val == null ? Long.MAX_VALUE : val.longValue());
+ }
+
+ /**
+ * Returns a String from the given offset within this node's record. This method will return null if the
+ * database does not contain an IString at the specified location.
+ */
+ protected String getStringOrNull(long offset) throws CoreException {
+ long rec = getDB().getRecPtr(record + offset);
+ return rec == 0 ? null : getDB().getString(rec).getString();
+ }
+
+ /**
+ * Puts the given String into the database at the specified offset within this node's record. Any IString
+ * that happens to already exist at the specified location will be deleted before the new value is stored.
+ * <p>
+ * The val parameter is allowed to be null. A value will be stored to the database so that later calls to
+ * {@link #getStringOrNull(long)} will return null;
+ */
+ protected void putStringOrNull(long offset, String val) throws CoreException {
+ long rec = getDB().getRecPtr(record + offset);
+ if (rec != 0)
+ getDB().getString(rec).delete();
+
+ getDB().putRecPtr(record + offset, val == null ? 0 : getDB().newString(val).getRecord());
+ }
}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMLinkage.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMLinkage.java
index f6123b1487..ccf88398c7 100644
--- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMLinkage.java
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMLinkage.java
@@ -91,7 +91,7 @@ public class QtPDOMLinkage extends PDOMLinkage {
}
// IBinding#getAdapter cannot create an instance of PDOMBinding because the Linkage is required. This
- // utility method uses #getAdapter to see if an instance has already been create. If not then a new
+ // utility method uses #getAdapter to see if an instance has already been created. If not then a new
// is created and stored in the AST binding.
@Override
public PDOMBinding adaptBinding(IBinding binding, boolean includeLocal) throws CoreException {
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMNodeType.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMNodeType.java
index 0210e1d34c..52f468f4f4 100644
--- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMNodeType.java
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMNodeType.java
@@ -18,7 +18,9 @@ public enum QtPDOMNodeType {
QEnum,
QProperty,
QMethod,
- QGadget;
+ QGadget,
+ QmlTypeRegistration,
+ QmlUncreatableRegistration;
public final int Type = IIndexBindingConstants.LAST_CONSTANT + 1 + ordinal();
@@ -32,7 +34,7 @@ public enum QtPDOMNodeType {
* This version can be reset when the PDOM's version changes because older Qt linkages will
* be dropped (along with everything else in that PDOM).
*/
- public static final int VERSION = 1;
+ public static final int VERSION = 2;
public static QtPDOMNodeType forType(int version, int type) {
// Nothing has been deleted or replaced yet, so the version is ignored.
@@ -60,6 +62,10 @@ public enum QtPDOMNodeType {
return new QtPDOMQMethod(linkage, record);
case QGadget:
return new QtPDOMQGadget(linkage, record);
+ case QmlTypeRegistration:
+ return new QtPDOMQmlRegistration(linkage, record);
+ case QmlUncreatableRegistration:
+ return new QtPDOMQmlUncreatableRegistration(linkage, record);
}
return null;
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMQmlRegistration.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMQmlRegistration.java
new file mode 100644
index 0000000000..fb4db6d124
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMQmlRegistration.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2014 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.internal.qt.core.pdom;
+
+import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.internal.core.pdom.db.Database;
+import org.eclipse.core.runtime.CoreException;
+
+@SuppressWarnings("restriction")
+public class QtPDOMQmlRegistration extends QtPDOMBinding {
+
+ private static int offsetInitializer = QtPDOMBinding.Field.Last.offset;
+ protected static enum Field {
+ CppRecord(Database.PTR_SIZE),
+ QObjectName(Database.PTR_SIZE),
+ Version(8), // Database doesn't have a LONG_SIZE
+ Uri(Database.PTR_SIZE),
+ Major(8),
+ Minor(8),
+ QmlName(Database.PTR_SIZE),
+ Last(0);
+
+ public final int offset;
+
+ private Field(int sizeof) {
+ this.offset = offsetInitializer;
+ offsetInitializer += sizeof;
+ }
+ }
+
+ public QtPDOMQmlRegistration(QtPDOMLinkage linkage, long record) {
+ super(linkage, record);
+ }
+
+ public QtPDOMQmlRegistration(QtPDOMLinkage linkage, QmlTypeRegistration qmlTypeReg, IASTName cppName) throws CoreException {
+ super(linkage, null, qmlTypeReg);
+
+ putStringOrNull(Field.QObjectName.offset, qmlTypeReg.getQObjectName());
+ putLongOrNull(Field.Version.offset, qmlTypeReg.getVersion());
+ putStringOrNull(Field.Uri.offset, qmlTypeReg.getUri());
+ putLongOrNull(Field.Major.offset, qmlTypeReg.getMajor());
+ putLongOrNull(Field.Minor.offset, qmlTypeReg.getMinor());
+ putStringOrNull(Field.QmlName.offset, qmlTypeReg.getQmlName());
+ }
+
+ @Override
+ protected int getRecordSize() {
+ return Field.Last.offset;
+ }
+
+ @Override
+ public int getNodeType() {
+ return QtPDOMNodeType.QmlTypeRegistration.Type;
+ }
+
+ public String getQObjectName() throws CoreException {
+ return getStringOrNull(Field.QObjectName.offset);
+ }
+
+ public Long getVersion() throws CoreException {
+ return getLongOrNull(Field.Version.offset);
+ }
+
+ public Long getMajor() throws CoreException {
+ return getLongOrNull(Field.Major.offset);
+ }
+
+ public Long getMinor() throws CoreException {
+ return getLongOrNull(Field.Minor.offset);
+ }
+
+ public String getUri() throws CoreException {
+ return getStringOrNull(Field.Uri.offset);
+ }
+
+ public String getQmlName() throws CoreException {
+ return getStringOrNull(Field.QmlName.offset);
+ }
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMQmlUncreatableRegistration.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMQmlUncreatableRegistration.java
new file mode 100644
index 0000000000..4f06883266
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMQmlUncreatableRegistration.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014 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.internal.qt.core.pdom;
+
+import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.internal.core.pdom.db.Database;
+import org.eclipse.core.runtime.CoreException;
+
+@SuppressWarnings("restriction")
+public class QtPDOMQmlUncreatableRegistration extends QtPDOMQmlRegistration {
+
+ private static int offsetInitializer = QtPDOMQmlRegistration.Field.Last.offset;
+ protected static enum Field {
+ Reason(Database.PTR_SIZE),
+ Last(0);
+
+ public final int offset;
+
+ private Field(int sizeof) {
+ this.offset = offsetInitializer;
+ offsetInitializer += sizeof;
+ }
+ }
+
+ public QtPDOMQmlUncreatableRegistration(QtPDOMLinkage linkage, long record) {
+ super(linkage, record);
+ }
+
+ public QtPDOMQmlUncreatableRegistration(QtPDOMLinkage linkage, QmlTypeRegistration qmlTypeReg, IASTName cppName) throws CoreException {
+ super(linkage, qmlTypeReg, cppName);
+
+ putStringOrNull(Field.Reason.offset, qmlTypeReg.getReason());
+ }
+
+ @Override
+ protected int getRecordSize() {
+ return Field.Last.offset;
+ }
+
+ @Override
+ public int getNodeType() {
+ return QtPDOMNodeType.QmlUncreatableRegistration.Type;
+ }
+
+ public String getReason() throws CoreException {
+ return getStringOrNull(Field.Reason.offset);
+ }
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtKeywords.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtKeywords.java
index 20f0e368df..5788447342 100644
--- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtKeywords.java
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtKeywords.java
@@ -89,6 +89,18 @@ public class QtKeywords {
&& DISCONNECT.equals(qualName[1]);
}
+ /**
+ * Returns true if the given binding will register a type with the QML type system and false
+ * otherwise.
+ */
+ public static boolean is_QmlType(IBinding binding) {
+ String[] qualName = getFunctionQualifiedName(binding);
+ return qualName != null
+ && qualName.length == 1
+ && (QML_REGISTER_TYPE.equals(qualName[0])
+ || QML_REGISTER_UNCREATABLE_TYPE.equals(qualName[0]));
+ }
+
private static String[] getFunctionQualifiedName(IBinding binding) {
// IBinding#getAdapter returns null when binding is an instance of
// PDOMCPPMethod.
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQmlRegistered.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQmlRegistered.java
new file mode 100644
index 0000000000..23353ea82a
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQmlRegistered.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2014 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.core.index;
+
+/**
+ * Represents a specific QML type registration.
+ * <p>
+ * Qt allows types to be registered with QML by calling the qmlRegisterType function,
+ * e.g.,
+ * <pre>
+ * class Q : public QObject { Q_OBJECT };
+ * qmlRegisterType&lt;Q&gt;( "uri", 1, 0, "Q" );
+ * </pre>
+ * Registers Q in the QML system with the name "Q", in the library imported from "uri"
+ * having the version number 1.0.
+ */
+public interface IQmlRegistered {
+ /**
+ * Identifies the kind of qmlRegister* function that was used to register the
+ * type. Qt 4.8 only defines two kinds, but in 5.0 there several more.
+ * <p>
+ * If a type has been registered more than once, then there will be several
+ * entries for it in the collection returned by {@link QtIndex#getQmlRegistered()}.
+ */
+ public enum Kind {
+ /**
+ * Indicates that the type has been registered with a function call to
+ * qmlRegisterType.
+ */
+ Type,
+
+ /**
+ * Indicates that the type has been registered with a function call to
+ * qmlRegisterUncreatableType.
+ */
+ Uncreatable
+ }
+
+ /**
+ * Returns the kind of function that was used for this registration. In Qt 4.8,
+ * there are two variations of the qmlRegister* function; qmlRegisterType and
+ * qmlRegisterUncreatableType. In Qt 5.0 there are several more.
+ * <p>
+ * It is possible for the same type to be registered in different ways, although
+ * this generally indicates a problem in the client code.
+ */
+ public IQmlRegistered.Kind getKind();
+
+ /**
+ * Returns QObject to which this registration applies. In the sample at {@link IQmlRegistered}
+ * this would return the IQObject for Q.
+ */
+ public IQObject getQObject();
+
+ /**
+ * Returns the specific revision of the IQObject that was registered. Returns null if no
+ * revision was specified.
+ * <p>
+ * E.g.,
+ * <code>
+ * class Q : public QObject
+ * {
+ * Q_OBJECT
+ * signals:
+ * Q_REVISION(2) void sig();
+ * };
+ *
+ * qmlRegisterType<Q>( "uri", 1, 0, "Q1" );
+ * qmlRegisterType<Q, 2>( "uri", 1, 0, "Q2" );
+ * </code>
+ *
+ * The QML type "Q2" would have access to the "sig" signal, while "Q1" would not.
+ *
+ * @see IQMethod#getRevision()
+ * @see IQProperty#getRevision()
+ */
+ public Long getVersion();
+
+ /**
+ * Returns the literal value of the first argument to the function if it can be
+ * resolved and null otherwise.
+ */
+ public String getURI();
+
+ /**
+ * Returns the literal value of the second argument to the function if it can be
+ * resolved and null otherwise.
+ */
+ public Long getMajor();
+
+ /**
+ * Returns the literal value of the third argument to the function if it can be
+ * resolved and null otherwise.
+ */
+ public Long getMinor();
+
+ /**
+ * Returns the literal value of the fourth argument to the function if it can be
+ * resolved and null otherwise.
+ */
+ public String getQmlName();
+
+ /**
+ * Returns the literal value of the fifth argument to qmlRegisterUncreatableType if it
+ * can be resolved and null otherwise.
+ */
+ public String getReason();
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/QtIndex.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/QtIndex.java
index f67a60bc58..c8636146d1 100644
--- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/QtIndex.java
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/QtIndex.java
@@ -7,6 +7,8 @@
*/
package org.eclipse.cdt.qt.core.index;
+import java.util.Collection;
+
import org.eclipse.cdt.internal.qt.core.index.QtFactory;
import org.eclipse.cdt.qt.core.QtPlugin;
import org.eclipse.core.resources.IProject;
@@ -70,4 +72,13 @@ public abstract class QtIndex {
* the given name.
*/
public abstract IQGadget findQGadget(String[] qualifiedName);
+
+ /**
+ * Find and return the types that have been registered with the Qt meta type system. This
+ * is the result of the function calls like:
+ * <pre>
+ * qmlRegisterType<Q>( "uri", 1, 2, "Qv1.2" );
+ * </pre>
+ */
+ public abstract Collection<IQmlRegistered> getQmlRegistered();
}
diff --git a/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/AllQtTests.java b/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/AllQtTests.java
index e5504e0abb..5f47c68c67 100644
--- a/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/AllQtTests.java
+++ b/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/AllQtTests.java
@@ -20,6 +20,7 @@ public class AllQtTests extends TestSuite {
QObjectTests.class,
QtContentAssistantTests.class,
QtIndexTests.class,
- QtRegressionTests.class);
+ QtRegressionTests.class,
+ QmlRegisteredTests.class);
}
}
diff --git a/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/QmlRegisteredTests.java b/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/QmlRegisteredTests.java
new file mode 100644
index 0000000000..b7e85d9fd5
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/QmlRegisteredTests.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2014 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.Collection;
+
+import org.eclipse.cdt.qt.core.index.IQObject;
+import org.eclipse.cdt.qt.core.index.IQmlRegistered;
+import org.eclipse.cdt.qt.core.index.QtIndex;
+
+public class QmlRegisteredTests extends BaseQtTestCase {
+
+ // #include "junit-QObject.hh"
+ // class B : public QObject
+ // {
+ // Q_OBJECT
+ // };
+ //
+ // class D : public B
+ // {
+ // Q_OBJECT
+ // };
+ //
+ // static void func()
+ // {
+ // qmlRegisterType<B>( "b-uri", 1, 2, "B" );
+ // qmlRegisterType<B>( "b-uri.34", 3, 4, "B34" );
+ //
+ // const char * uri = "d-uri";
+ // int maj = 2, min = 3;
+ // const char * qmlName = "D1";
+ // qmlRegisterType<D, 1>( uri, maj, min, qmlName );
+ // }
+ public void testQMLRegisterType() throws Exception {
+ loadComment("qmlregistertype.hh");
+
+ QtIndex qtIndex = QtIndex.getIndex(fProject);
+ assertNotNull(qtIndex);
+
+ IQObject b_qobj = qtIndex.findQObject(new String[]{ "B" });
+ if (!isIndexOk("B", b_qobj))
+ return;
+ assertNotNull(b_qobj);
+
+ Collection<IQmlRegistered> qmlRegistereds = qtIndex.getQmlRegistered();
+ assertNotNull(qmlRegistereds);
+ assertEquals(3, qmlRegistereds.size());
+
+ for(IQmlRegistered qmlRegistered : qmlRegistereds) {
+ IQObject qobj = qmlRegistered.getQObject();
+ assertNotNull(qobj);
+
+ // all values of B should be fully resolved, except for Revision, which was not provided
+ if (qobj.getName().equals("B")) {
+ assertNull(qmlRegistered.getVersion());
+ String qmlName = qmlRegistered.getQmlName();
+ assertNotNull(qmlName);
+ if ("B".equals(qmlName)) {
+ assertEquals(IQmlRegistered.Kind.Type, qmlRegistered.getKind());
+ assertEquals("b-uri", qmlRegistered.getURI());
+ assertEquals(Long.valueOf(1), qmlRegistered.getMajor());
+ assertEquals(Long.valueOf(2), qmlRegistered.getMinor());
+ assertNull(qmlRegistered.getReason());
+ } else if ("B34".equals(qmlName)) {
+ assertEquals(IQmlRegistered.Kind.Type, qmlRegistered.getKind());
+ assertEquals("b-uri.34", qmlRegistered.getURI());
+ assertEquals(Long.valueOf(3), qmlRegistered.getMajor());
+ assertEquals(Long.valueOf(4), qmlRegistered.getMinor());
+ assertNull(qmlRegistered.getReason());
+ } else {
+ fail("unexpected uri for B " + qmlName);
+ }
+
+ // the values for D are not expected to be resolved (yet), but it does have a Revision
+ } else if (qobj.getName().equals("D")) {
+ assertEquals(IQmlRegistered.Kind.Type, qmlRegistered.getKind());
+ assertEquals(Long.valueOf(1), qmlRegistered.getVersion());
+ assertNull(qmlRegistered.getURI());
+ assertNull(qmlRegistered.getMajor());
+ assertNull(qmlRegistered.getMinor());
+ assertNull(qmlRegistered.getQmlName());
+ assertNull(qmlRegistered.getReason());
+
+ } else {
+ fail("unexpected qmlRegistered " + qobj.getName());
+ }
+ }
+ }
+
+ // class T;
+ //
+ // static void func()
+ // {
+ // qmlRegisterType<T>( "t-uri", 3, 4, "qml-T" );
+ // }
+ public void testQMLRegisterFwdDecl() throws Exception {
+ loadComment("qmlregistertype.hh");
+
+ QtIndex qtIndex = QtIndex.getIndex(fProject);
+ assertNotNull(qtIndex);
+
+ Collection<IQmlRegistered> qmlRegistereds = qtIndex.getQmlRegistered();
+ assertNotNull(qmlRegistereds);
+ assertEquals(1, qmlRegistereds.size());
+
+ IQmlRegistered qml = qmlRegistereds.iterator().next();
+ assertNotNull(qml);
+ assertEquals(IQmlRegistered.Kind.Type, qml.getKind());
+ assertEquals("t-uri", qml.getURI());
+ assertEquals(Long.valueOf(3), qml.getMajor());
+ assertEquals(Long.valueOf(4), qml.getMinor());
+ assertEquals("qml-T", qml.getQmlName());
+ assertNull(qml.getReason());
+
+ // The QObject has not been defined, so it cannot be found.
+ assertNull(qml.getQObject());
+ }
+
+ // #include "junit-QObject.hh"
+ // class B : public QObject
+ // {
+ // Q_OBJECT
+ // };
+ //
+ // class D : public B
+ // {
+ // Q_OBJECT
+ // };
+ //
+ // static void func()
+ // {
+ // qmlRegisterUncreatableType<B>( "b-uri", 1, 2, "B", QString( "msg1" ) );
+ // qmlRegisterUncreatableType<B>( "b-uri.34", 3, 4, "B34", QString( "msg2" ) );
+ //
+ // const char * uri = "d-uri";
+ // int maj = 2, min = 3;
+ // const char * qmlName = "D1";
+ // const QString msg( "msg3" );
+ // qmlRegisterUncreatableType<D>( uri, maj, min, qmlName, msg );
+ // }
+ public void testQMLRegisterUncreatableType() throws Exception {
+ loadComment("qmlregistereduncreatabletype.hh");
+
+ QtIndex qtIndex = QtIndex.getIndex(fProject);
+ assertNotNull(qtIndex);
+
+ IQObject b_qobj = qtIndex.findQObject(new String[]{ "B" });
+ if (!isIndexOk("B", b_qobj))
+ return;
+ assertNotNull(b_qobj);
+
+ Collection<IQmlRegistered> qmlRegistereds = qtIndex.getQmlRegistered();
+ assertNotNull(qmlRegistereds);
+ assertEquals(3, qmlRegistereds.size());
+
+ for(IQmlRegistered qmlRegistered : qmlRegistereds) {
+ IQObject qobj = qmlRegistered.getQObject();
+ assertNotNull(qobj);
+
+ // all values of B should be fully resolved, except for Revision, which was not provided
+ if (qobj.getName().equals("B")) {
+ assertNull(qmlRegistered.getVersion());
+ String qmlName = qmlRegistered.getQmlName();
+ assertNotNull(qmlName);
+ if ("B".equals(qmlName)) {
+ assertEquals(IQmlRegistered.Kind.Uncreatable, qmlRegistered.getKind());
+ assertEquals("b-uri", qmlRegistered.getURI());
+ assertEquals(Long.valueOf(1), qmlRegistered.getMajor());
+ assertEquals(Long.valueOf(2), qmlRegistered.getMinor());
+ assertEquals(null/*"msg1"*/, qmlRegistered.getReason());
+ } else if ("B34".equals(qmlName)) {
+ assertEquals(IQmlRegistered.Kind.Uncreatable, qmlRegistered.getKind());
+ assertEquals("b-uri.34", qmlRegistered.getURI());
+ assertEquals(Long.valueOf(3), qmlRegistered.getMajor());
+ assertEquals(Long.valueOf(4), qmlRegistered.getMinor());
+ assertEquals(null/*"msg2"*/, qmlRegistered.getReason());
+ } else {
+ fail("unexpected uri for B " + qmlName);
+ }
+
+ // the values for D are not expected to be resolved (yet), but it does have a Revision
+ } else if (qobj.getName().equals("D")) {
+ assertEquals(IQmlRegistered.Kind.Uncreatable, qmlRegistered.getKind());
+ assertNull(qmlRegistered.getVersion());
+ assertNull(qmlRegistered.getURI());
+ assertNull(qmlRegistered.getMajor());
+ assertNull(qmlRegistered.getMinor());
+ assertNull(qmlRegistered.getQmlName());
+ assertNull(qmlRegistered.getReason());
+
+ } else {
+ fail("unexpected qmlRegistered " + qobj.getName());
+ }
+ }
+ }
+}
diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QObjectConnectCompletion.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QObjectConnectCompletion.java
index a68dd4fec8..20caa39d8a 100644
--- a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QObjectConnectCompletion.java
+++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QObjectConnectCompletion.java
@@ -21,7 +21,6 @@ import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
-import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
@@ -133,18 +132,6 @@ public class QObjectConnectCompletion {
}
}
- private static boolean is_QObject_connect(ICEditorContentAssistInvocationContext context, IASTCompletionContext astContext, IASTName name) {
-
- // Bug332201: Qt content assist should always be applied to the most specific part of
- // the target name.
- IBinding[] funcBindings = astContext.findBindings(name.getLastName(), !context.isContextInformationStyle());
- for (IBinding funcBinding : funcBindings)
- if (QtKeywords.is_QObject_connect(funcBinding))
- return true;
-
- return false;
- }
-
// Copied from org.eclipse.cdt.internal.ui.text.CParameterListValidator
private static int indexOfClosingPeer(String code, char left, char right, int pos) {
int level = 0;

Back to the top