diff options
author | Andrew Eidsness | 2014-01-07 17:45:00 +0000 |
---|---|---|
committer | Doug Schaefer | 2014-01-07 20:21:47 +0000 |
commit | 78fc903d16d9dac55ba03db1360f9c00cbb2d01e (patch) | |
tree | 2331e88b8a04f7780a14f590159069bb7ce8a1b2 | |
parent | 0e196ca5f21239568edf1b013bc8ec0d4327c7a4 (diff) | |
download | org.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>
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 27875328dc8..3be32730c9f 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 45acab160a7..9c958957ad9 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 00000000000..46d3ac79839 --- /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 66af6c15cbb..326b1363de3 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 1b800520349..f5c15543001 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 00000000000..86358c532d7 --- /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 1629f2b341f..a26e1612834 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 d2a772926c5..7f2672a96a1 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 f6123b14878..ccf88398c71 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 0210e1d34c9..52f468f4f47 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 00000000000..fb4db6d1245 --- /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 00000000000..4f068832663 --- /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 20f0e368df5..57884473422 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 00000000000..23353ea82ac --- /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<Q>( "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 f67a60bc583..c8636146d1f 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 e5504e0abba..5f47c68c67a 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 00000000000..b7e85d9fd55 --- /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 a68dd4fec89..20caa39d8a0 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; |