mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-06 17:26:01 +02:00
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>
This commit is contained in:
parent
0e196ca5f2
commit
78fc903d16
18 changed files with 877 additions and 36 deletions
|
@ -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:
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ public class AllQtTests extends TestSuite {
|
|||
QObjectTests.class,
|
||||
QtContentAssistantTests.class,
|
||||
QtIndexTests.class,
|
||||
QtRegressionTests.class);
|
||||
QtRegressionTests.class,
|
||||
QmlRegisteredTests.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue