Skip to main content
summaryrefslogtreecommitdiffstats
path: root/qt
diff options
context:
space:
mode:
authorAndrew Eidsness2014-01-08 12:57:25 -0500
committerDoug Schaefer2014-01-10 10:38:13 -0500
commit030bfc50fb028aeba7b329787955b8e17a51d2da (patch)
treed0ada4c4e56893fcf4bfaf7208c7a08a8ffceb63 /qt
parent86c55d882149be600534104814fa2b520f363a0a (diff)
downloadorg.eclipse.cdt-030bfc50fb028aeba7b329787955b8e17a51d2da.tar.gz
org.eclipse.cdt-030bfc50fb028aeba7b329787955b8e17a51d2da.tar.xz
org.eclipse.cdt-030bfc50fb028aeba7b329787955b8e17a51d2da.zip
Bug 425102 QObject::connect content assist broken
The QObject::connect content assistant does not work when the receiver of the function call is an implicit this. E.g., class Q : public QObject { Q_OBJECT f() { this->connect( ... ); // works connect( ... ); // does not work QObject::connect( ... ) // does not work } }; I've changed the Qt's ASTUtil.getReceiverType to navigate to the ICPPClassType through the IScope's. The previous implementation was relying on the connect function call being an IASTField I've also added a test case for this problem. Change-Id: I96c29a9a452280068bda39a63414c50008bfad37 Signed-off-by: Andrew Eidsness <eclipse@jfront.com> Reviewed-on: https://git.eclipse.org/r/20399 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/META-INF/MANIFEST.MF2
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/ASTUtil.java28
-rw-r--r--qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/ASTUtilTests.java76
-rw-r--r--qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/AllQtTests.java1
-rw-r--r--qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/BaseQtTestCase.java14
5 files changed, 102 insertions, 19 deletions
diff --git a/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF b/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF
index 08f15f4857..38ced9002f 100644
--- a/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF
+++ b/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF
@@ -14,7 +14,7 @@ Require-Bundle: org.eclipse.core.runtime,
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Bundle-Localization: plugin
-Export-Package: org.eclipse.cdt.internal.qt.core;x-friends:="org.eclipse.cdt.qt.ui",
+Export-Package: org.eclipse.cdt.internal.qt.core;x-friends:="org.eclipse.cdt.qt.ui,org.eclipse.cdt.qt.tests",
org.eclipse.cdt.internal.qt.core.index;x-friends:="org.eclipse.cdt.qt.tests",
org.eclipse.cdt.internal.qt.core.parser;x-friends:="org.eclipse.cdt.qt.ui",
org.eclipse.cdt.qt.core,
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 3be32730c9..6a2392ebb8 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
@@ -22,13 +22,14 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
+import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
-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.ICPPClassScope;
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;
@@ -36,6 +37,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.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.qt.core.QtPlugin;
import org.eclipse.cdt.qt.core.index.IQMethod;
import org.eclipse.cdt.qt.core.index.IQObject;
@@ -144,21 +146,17 @@ public class ASTUtil {
}
public static ICPPClassType getReceiverType(IASTFunctionCallExpression fncall) {
+ // See the thread that starts at:
+ // http://dev.eclipse.org/mhonarc/lists/cdt-dev/msg26972.html
+ try {
+ for(IScope scope = CPPVisitor.getContainingScope(fncall); scope != null; scope = scope.getParent())
+ if (scope instanceof ICPPClassScope)
+ return ((ICPPClassScope) scope).getClassType();
+ } catch (DOMException e) {
+ QtPlugin.log(e);
+ }
- // NOTE: This cannot rely on the Evaluation because we're in a contest assist context.
- // At this point is likely that the full function call is not complete, so at least
- // some of the eval leads to a Problem. We don't need the Eval anyhow, just lookup
- // the type of the receiver.
-
- IASTExpression fnName = fncall.getFunctionNameExpression();
- if (!(fnName instanceof ICPPASTFieldReference))
- return null;
-
- ICPPASTFieldReference fieldRef = (ICPPASTFieldReference) fnName;
- ICPPASTExpression receiver = fieldRef.getFieldOwner();
-
- IType recvType = getBaseType(receiver);
- return recvType instanceof ICPPClassType ? (ICPPClassType) recvType : null;
+ return null;
}
/**
diff --git a/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/ASTUtilTests.java b/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/ASTUtilTests.java
new file mode 100644
index 0000000000..b12509e2f5
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/ASTUtilTests.java
@@ -0,0 +1,76 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
+import org.eclipse.cdt.core.parser.ParserLanguage;
+import org.eclipse.cdt.core.parser.tests.ast2.AST2TestBase;
+import org.eclipse.cdt.internal.qt.core.ASTUtil;
+
+public class ASTUtilTests extends AST2TestBase {
+
+ // class T
+ // {
+ // void callee() { }
+ // void caller() { this->callee(); callee(); T::callee(); }
+ // };
+ // void T::callee() { this->caller(); caller(); T::caller(); }
+ public void testGetReceiverType() throws Exception {
+ IASTTranslationUnit tu = parse();
+ assertNotNull(tu);
+
+ // Find the callee function call.
+ ArrayList<IASTFunctionCallExpression> fnCalls = new ArrayList<IASTFunctionCallExpression>();
+ collectChildren(fnCalls, tu, IASTFunctionCallExpression.class);
+ assertEquals(6, fnCalls.size());
+
+ assertNotNull(fnCalls.get(0));
+ assertNotNull(fnCalls.get(1));
+ assertNotNull(fnCalls.get(2));
+ assertNotNull(fnCalls.get(3));
+ assertNotNull(fnCalls.get(4));
+ assertNotNull(fnCalls.get(5));
+
+ ICPPClassType recvr0 = ASTUtil.getReceiverType(fnCalls.get(0));
+ ICPPClassType recvr1 = ASTUtil.getReceiverType(fnCalls.get(1));
+ ICPPClassType recvr2 = ASTUtil.getReceiverType(fnCalls.get(2));
+ ICPPClassType recvr3 = ASTUtil.getReceiverType(fnCalls.get(3));
+ ICPPClassType recvr4 = ASTUtil.getReceiverType(fnCalls.get(4));
+ ICPPClassType recvr5 = ASTUtil.getReceiverType(fnCalls.get(5));
+
+ assertNotNull(recvr0);
+ assertNotNull(recvr1);
+ assertNotNull(recvr2);
+ assertNotNull(recvr3);
+ assertNotNull(recvr4);
+ assertNotNull(recvr5);
+ assertSame(recvr0, recvr1);
+ assertSame(recvr1, recvr2);
+ assertSame(recvr3, recvr4);
+ assertSame(recvr4, recvr5);
+ }
+
+ private IASTTranslationUnit parse() throws Exception {
+ String[] contents = BaseQtTestCase.getContentsForTest(getClass(), 1);
+ return parse(contents[0], ParserLanguage.CPP);
+ }
+
+ private static <T> void collectChildren(List<T> list, IASTNode node, Class<T> cls) {
+ if (cls.isAssignableFrom(node.getClass()))
+ list.add(cls.cast(node));
+
+ for(IASTNode child : node.getChildren())
+ collectChildren(list, child, cls);
+ }
+}
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 5f47c68c67..4282134d05 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
@@ -15,6 +15,7 @@ public class AllQtTests extends TestSuite {
public static Test suite() throws Exception {
return
new TestSuite(
+ ASTUtilTests.class,
QMakeTests.class,
QGadgetTests.class,
QObjectTests.class,
diff --git a/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/BaseQtTestCase.java b/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/BaseQtTestCase.java
index 8bc1d1b755..fd7210bf17 100644
--- a/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/BaseQtTestCase.java
+++ b/qt/org.eclipse.cdt.qt.tests/src/org/eclipse/cdt/qt/tests/BaseQtTestCase.java
@@ -112,18 +112,26 @@ public class BaseQtTestCase extends BaseTestCase {
loadComment("junit-QObject.hh");
}
- private String[] getContentsForTest(int blocks) throws Exception {
- String callingMethod = Thread.currentThread().getStackTrace()[3].getMethodName();
+ private static String[] getContentsForTest(Class<?> testCaseCls, int frames, int blocks) throws Exception {
+ String callingMethod = Thread.currentThread().getStackTrace()[frames].getMethodName();
CharSequence[] help= TestSourceReader.getContentsForTest(
- QtTestPlugin.getDefault().getBundle(), "src", getClass(), callingMethod, blocks);
+ QtTestPlugin.getDefault().getBundle(), "src", testCaseCls, callingMethod, blocks);
String[] result= new String[help.length];
int i= 0;
for (CharSequence buf : help) {
result[i++]= buf.toString();
}
return result;
+ }
+
+ private String[] getContentsForTest(int blocks) throws Exception {
+ return getContentsForTest(getClass(), 4, blocks);
}
+ /*package*/ static String[] getContentsForTest(Class<?> testCaseCls, int blocks) throws Exception {
+ return getContentsForTest(testCaseCls, 4, blocks);
+ }
+
/**
* The implementation of TestSourceReader (called from BaseTestCase) imposes some restrictions
* on the caller of #loadComment.

Back to the top