summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Eidsness2013-02-20 13:23:40 (EST)
committerDoug Schaefer2013-02-20 16:13:49 (EST)
commit1908efec3811e8c24030a5b38140b00fbb66ca61 (patch)
tree939ff7f33080e64acc20850c9059157315cb7baf
parent24ba7ff6880c98cab8a77144dc1c8f08c8d8db9c (diff)
downloadorg.eclipse.cdt-1908efec3811e8c24030a5b38140b00fbb66ca61.zip
org.eclipse.cdt-1908efec3811e8c24030a5b38140b00fbb66ca61.tar.gz
org.eclipse.cdt-1908efec3811e8c24030a5b38140b00fbb66ca61.tar.bz2
qt slot/signal auto-completerefs/changes/32/10532/3
Tags signal and slot methods when the index is created. Uses these tags to suggest values inside of SIGNAL and SLOT macro expansions. Enabled only for projects with the QtNature. Recognizes QObject::connect function calls and suggests SIGNAL(a) and SLOT(a) for the 2nd and 4th parameters. When expanding the SIGNAL and SLOT macros within a call to QObject::connect, suggests signals and slots based on the type of the previous parameter. E.g. in QObjectA a; QObjectB b; QObject::connect( &a, SIGNAL(*), &b, SLOT(**) ); The content assistant will suggest the methods of type QObjectA that have been marked as signals at *, and the methods of QObjectB that have been marked as slots at **. Change-Id: Ia6aaa71724547b0977e322399a500f072004767a Reviewed-on: https://git.eclipse.org/r/10532 Reviewed-by: Doug Schaefer <dschaefer@qnx.com> IP-Clean: Doug Schaefer <dschaefer@qnx.com> Tested-by: Doug Schaefer <dschaefer@qnx.com>
-rw-r--r--qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF2
-rw-r--r--qt/org.eclipse.cdt.qt.core/plugin.xml16
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/Activator.java30
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtKeywords.java6
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtPlugin.java38
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/internal/core/QtSignalSlotTagger.java101
-rw-r--r--qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF6
-rw-r--r--qt/org.eclipse.cdt.qt.ui/plugin.xml12
-rw-r--r--qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/qt/internal/ui/QtCompletionProposalComputer.java392
-rw-r--r--qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/qt/ui/QtUIPlugin.java (renamed from qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/qt/ui/Activator.java)8
10 files changed, 574 insertions, 37 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 67bb08f..31d4aee 100644
--- a/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF
+++ b/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: CDT Qt Support Core
Bundle-SymbolicName: org.eclipse.cdt.qt.core;singleton:=true
Bundle-Version: 1.0.0.qualifier
-Bundle-Activator: org.eclipse.cdt.qt.core.Activator
+Bundle-Activator: org.eclipse.cdt.qt.core.QtPlugin
Bundle-Vendor: Eclipse CDT
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.core.resources,
diff --git a/qt/org.eclipse.cdt.qt.core/plugin.xml b/qt/org.eclipse.cdt.qt.core/plugin.xml
index 959e784..d31e961 100644
--- a/qt/org.eclipse.cdt.qt.core/plugin.xml
+++ b/qt/org.eclipse.cdt.qt.core/plugin.xml
@@ -50,4 +50,20 @@
</run>
</runtime>
</extension>
+ <extension
+ point="org.eclipse.cdt.core.tagger"
+ id="qt.signalslots"
+ name="Qt Signal/Slot Tagger">
+ <bindingTagger
+ local-id="signalslot.tagger"
+ class="org.eclipse.cdt.qt.internal.core.QtSignalSlotTagger">
+ <enablement>
+ <with variable="projectNatures">
+ <iterate operator="or">
+ <equals value="org.eclipse.cdt.qt.core.qtNature"/>
+ </iterate>
+ </with>
+ </enablement>
+ </bindingTagger>
+ </extension>
</plugin>
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/Activator.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/Activator.java
deleted file mode 100644
index 2e3a4ec..0000000
--- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/Activator.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.eclipse.cdt.qt.core;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-public class Activator implements BundleActivator {
-
- private static BundleContext context;
-
- static BundleContext getContext() {
- return context;
- }
-
- /*
- * (non-Javadoc)
- * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
- */
- public void start(BundleContext bundleContext) throws Exception {
- Activator.context = bundleContext;
- }
-
- /*
- * (non-Javadoc)
- * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
- */
- public void stop(BundleContext bundleContext) throws Exception {
- Activator.context = null;
- }
-
-}
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 36b2112..381655e 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
@@ -17,4 +17,10 @@ public class QtKeywords
public static final String Q_SLOTS = "Q_SLOTS";
public static final String SIGNALS = "signals";
public static final String SLOTS = "slots";
+
+ public static final String SIGNAL = "SIGNAL";
+ public static final String SLOT = "SLOT";
+
+ public static final String QOBJECT = "QObject";
+ public static final String CONNECT = "connect";
}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtPlugin.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtPlugin.java
new file mode 100644
index 0000000..825b561
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtPlugin.java
@@ -0,0 +1,38 @@
+package org.eclipse.cdt.qt.core;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class QtPlugin implements BundleActivator {
+
+ public static final String ID = "org.eclipse.cdt.qt.core";
+ public static final String SIGNAL_SLOT_TAGGER_ID = ID + ".signalslot.tagger";
+
+ public static final int SignalSlot_Mask_signal = 1;
+ public static final int SignalSlot_Mask_slot = 2;
+
+ private static BundleContext context;
+
+ static BundleContext getContext() {
+ return context;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext bundleContext) throws Exception {
+ QtPlugin.context = bundleContext;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext bundleContext) throws Exception {
+ QtPlugin.context = null;
+ }
+
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/internal/core/QtSignalSlotTagger.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/internal/core/QtSignalSlotTagger.java
new file mode 100644
index 0000000..a82b3c1
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/internal/core/QtSignalSlotTagger.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013 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.internal.core;
+
+import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
+import org.eclipse.cdt.core.dom.ast.IASTMacroExpansionLocation;
+import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
+import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
+import org.eclipse.cdt.core.dom.ast.IBinding;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
+import org.eclipse.cdt.core.dom.ast.tag.IBindingTagger;
+import org.eclipse.cdt.core.dom.ast.tag.ITag;
+import org.eclipse.cdt.core.dom.ast.tag.ITagWriter;
+import org.eclipse.cdt.core.dom.ast.tag.IWritableTag;
+import org.eclipse.cdt.qt.core.QtKeywords;
+import org.eclipse.cdt.qt.core.QtPlugin;
+
+public class QtSignalSlotTagger implements IBindingTagger
+{
+ private static ICPPASTVisibilityLabel findVisibilityLabel( ICPPMethod method, IASTNode ast )
+ {
+ // the visibility cannot be found without an ast
+ if( ast == null )
+ return null;
+
+ IASTNode methodDecl = ast;
+ ICPPASTCompositeTypeSpecifier classType = null;
+ while( methodDecl != null
+ && classType == null )
+ {
+ IASTNode parent = methodDecl.getParent();
+ if( parent instanceof ICPPASTCompositeTypeSpecifier )
+ classType = (ICPPASTCompositeTypeSpecifier)parent;
+ else
+ methodDecl = parent;
+ }
+
+ if( methodDecl == null
+ || classType == null )
+ return null;
+
+ ICPPASTVisibilityLabel lastLabel = null;
+ for( IASTDeclaration decl : classType.getMembers() )
+ {
+ if( decl instanceof ICPPASTVisibilityLabel )
+ lastLabel = (ICPPASTVisibilityLabel)decl;
+ else if( decl == methodDecl )
+ return lastLabel;
+ }
+
+ return null;
+ }
+
+ @Override
+ public ITag process( ITagWriter tagWriter, IBinding binding, IASTName ast )
+ {
+ // only methods a be signals or slots
+ if( ! ( binding instanceof ICPPMethod ) )
+ return null;
+
+ // a visibility label is required in order to decide whether the method is a signal/slot
+ ICPPMethod method = (ICPPMethod)binding;
+ ICPPASTVisibilityLabel v = findVisibilityLabel( method, ast );
+ if( v == null )
+ return null;
+
+ byte bitset = 0;
+ for( IASTNodeLocation loc : v.getNodeLocations() )
+ if( loc instanceof IASTMacroExpansionLocation )
+ {
+ IASTMacroExpansionLocation macroExpansion = (IASTMacroExpansionLocation)loc;
+ IASTPreprocessorMacroExpansion exp = macroExpansion.getExpansion();
+ String macro = exp.getMacroReference().toString();
+
+ if( QtKeywords.SIGNALS.equals( macro ) || QtKeywords.Q_SIGNALS.equals( macro ) )
+ bitset |= QtPlugin.SignalSlot_Mask_signal;
+ else if( QtKeywords.SLOTS.equals( macro ) || QtKeywords.Q_SLOTS.equals( macro ) )
+ bitset |= QtPlugin.SignalSlot_Mask_slot;
+ }
+
+ if( bitset != 0 )
+ {
+ IWritableTag tag = tagWriter.createTag( QtPlugin.SIGNAL_SLOT_TAGGER_ID, 1 );
+ if( tag != null
+ && tag.putByte( 0, bitset ) )
+ return tag;
+ }
+
+ return null;
+ }
+}
diff --git a/qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF b/qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF
index 0e024d2..856b83c 100644
--- a/qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF
+++ b/qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF
@@ -3,13 +3,15 @@ Bundle-ManifestVersion: 2
Bundle-Name: CDT Qt Support UI
Bundle-SymbolicName: org.eclipse.cdt.qt.ui;singleton:=true
Bundle-Version: 1.0.0.qualifier
-Bundle-Activator: org.eclipse.cdt.qt.ui.Activator
+Bundle-Activator: org.eclipse.cdt.qt.ui.QtUIPlugin
Bundle-Vendor: Eclipse CDT
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.cdt.ui,
org.eclipse.cdt.core,
- org.eclipse.cdt.qt.core
+ org.eclipse.cdt.qt.core,
+ org.eclipse.jface.text,
+ org.eclipse.core.resources
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
diff --git a/qt/org.eclipse.cdt.qt.ui/plugin.xml b/qt/org.eclipse.cdt.qt.ui/plugin.xml
index 7d86d31..e03dd26 100644
--- a/qt/org.eclipse.cdt.qt.ui/plugin.xml
+++ b/qt/org.eclipse.cdt.qt.ui/plugin.xml
@@ -23,4 +23,16 @@
</enablement>
</semanticHighlighting>
</extension>
+ <extension
+ point="org.eclipse.cdt.ui.completionProposalComputer"
+ id="QtCompletionProposalComputer"
+ name="Qt Completion Proposal Computer">
+ <completionProposalComputer
+ categoryId="org.eclipse.cdt.ui.parserProposalCategory"
+ class="org.eclipse.cdt.qt.internal.ui.QtCompletionProposalComputer"
+ activate="true">
+ <partition type="__dftl_partition_content_type"/>
+ <partition type="__c_preprocessor"/>
+ </completionProposalComputer>
+ </extension>
</plugin>
diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/qt/internal/ui/QtCompletionProposalComputer.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/qt/internal/ui/QtCompletionProposalComputer.java
new file mode 100644
index 0000000..733e088
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/qt/internal/ui/QtCompletionProposalComputer.java
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 2013 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.internal.ui;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
+import org.eclipse.cdt.core.dom.ast.IASTCompletionContext;
+import org.eclipse.cdt.core.dom.ast.IASTCompletionNode;
+import org.eclipse.cdt.core.dom.ast.IASTExpression;
+import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
+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.IPointerType;
+import org.eclipse.cdt.core.dom.ast.IType;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
+import org.eclipse.cdt.core.dom.ast.tag.ITag;
+import org.eclipse.cdt.core.dom.ast.tag.ITagReader;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
+import org.eclipse.cdt.internal.ui.text.contentassist.CCompletionProposal;
+import org.eclipse.cdt.internal.ui.text.contentassist.CContentAssistInvocationContext;
+import org.eclipse.cdt.internal.ui.text.contentassist.ParsingBasedProposalComputer;
+import org.eclipse.cdt.internal.ui.text.contentassist.RelevanceConstants;
+import org.eclipse.cdt.qt.core.QtKeywords;
+import org.eclipse.cdt.qt.core.QtNature;
+import org.eclipse.cdt.qt.core.QtPlugin;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+
+@SuppressWarnings( "restriction" )
+public class QtCompletionProposalComputer extends ParsingBasedProposalComputer
+{
+ private boolean isApplicable( CContentAssistInvocationContext context )
+ {
+ ITranslationUnit tu = context.getTranslationUnit();
+ if( tu == null )
+ return false;
+
+ ICProject cProject = tu.getCProject();
+ if( cProject == null )
+ return false;
+
+ IProject project = cProject.getProject();
+ if( project == null )
+ return false;
+
+ try
+ {
+ return project.hasNature( QtNature.ID );
+ }
+ catch( CoreException e )
+ {
+ CUIPlugin.log( e );
+ return false;
+ }
+ }
+
+ private static boolean is_QObject_connect( CContentAssistInvocationContext context, IASTCompletionContext astContext, IASTName name )
+ {
+ IASTName connectName = name.getLastName();
+ if( ! QtKeywords.CONNECT.equals( new String( connectName.getSimpleID() ) ) )
+ return false;
+
+ IBinding[] funcBindings = astContext.findBindings( connectName, ! context.isContextInformationStyle() );
+ for( IBinding funcBinding : funcBindings )
+ if( funcBinding instanceof ICPPFunction )
+ {
+ IBinding ownerBinding = ( (ICPPFunction)funcBinding ).getOwner();
+ if( ownerBinding != null && QtKeywords.QOBJECT.equals( ownerBinding.getName() ) )
+ return true;
+ }
+
+ return false;
+ }
+
+ private static class Completion
+ {
+ private final String replacement;
+ private final String display;
+ private final int cursorOffset;
+
+ public static final Completion SIGNAL = new Completion( "SIGNAL()", "SIGNAL(a)", -1 );
+ public static final Completion SLOT = new Completion( "SLOT()", "SLOT(a)", -1 );
+
+ public Completion( String replacement )
+ {
+ this( replacement, replacement, 0 );
+ }
+
+ public Completion( String replacement, String display, int cursorOffset )
+ {
+ this.replacement = replacement;
+ this.display = display;
+ this.cursorOffset = cursorOffset;
+ }
+
+ public ICompletionProposal createProposal( CContentAssistInvocationContext context )
+ {
+ int repLength = replacement.length();
+ int repOffset = context.getInvocationOffset();
+ CCompletionProposal p = new CCompletionProposal( replacement, repOffset, repLength, null, display, RelevanceConstants.DEFAULT_TYPE_RELEVANCE, context.getViewer() );
+ p.setCursorPosition( repLength + cursorOffset );
+ return p;
+ }
+
+ @Override
+ public String toString()
+ {
+ if( replacement == null )
+ return super.toString();
+ return replacement + '@' + cursorOffset;
+ }
+ }
+
+ private static interface MethodFilter
+ {
+ public boolean keep( ICPPMethod method );
+
+ public static class Qt
+ {
+ public static final MethodFilter Signal = new MethodFilter()
+ {
+ @Override
+ public boolean keep( ICPPMethod method )
+ {
+ ITagReader tagReader = CCorePlugin.getTagService().findTagReader( method );
+ if( tagReader == null )
+ return false;
+
+ ITag tag = tagReader.getTag( QtPlugin.SIGNAL_SLOT_TAGGER_ID );
+ if( tag == null )
+ return false;
+
+ int result = tag.getByte( 0 );
+ return result != ITag.Fail
+ && ( ( result & QtPlugin.SignalSlot_Mask_signal ) == QtPlugin.SignalSlot_Mask_signal );
+ }
+ };
+
+ public static final MethodFilter Slot = new MethodFilter()
+ {
+ @Override
+ public boolean keep( ICPPMethod method )
+ {
+ ITagReader tagReader = CCorePlugin.getTagService().findTagReader( method );
+ if( tagReader == null )
+ return false;
+
+ ITag tag = tagReader.getTag( QtPlugin.SIGNAL_SLOT_TAGGER_ID );
+ if( tag == null )
+ return false;
+
+ int result = tag.getByte( 0 );
+ return result != ITag.Fail
+ && ( ( result & QtPlugin.SignalSlot_Mask_slot ) == QtPlugin.SignalSlot_Mask_slot );
+ }
+ };
+ }
+ }
+
+ private static Iterable<ICPPMethod> filterMethods( final ICPPClassType cls, final MethodFilter filter )
+ {
+ return new Iterable<ICPPMethod>()
+ {
+ @Override
+ public Iterator<ICPPMethod> iterator()
+ {
+ return new Iterator<ICPPMethod>()
+ {
+ private int index = 0;
+ private final ICPPMethod[] methods = cls.getMethods();
+
+ @Override
+ public boolean hasNext()
+ {
+ for( ; index < methods.length; ++index )
+ if( filter.keep( methods[index] ) )
+ return true;
+ return false;
+ }
+
+ @Override public ICPPMethod next() { return methods[index++]; }
+ @Override public void remove() { }
+ };
+ }
+ };
+ }
+
+ private static String getSignature( ICPPMethod method )
+ {
+ StringBuilder signature = new StringBuilder();
+
+ signature.append( method.getName() );
+ signature.append( '(' );
+ boolean first = true;
+ for( ICPPParameter param : method.getParameters() )
+ {
+ if( first )
+ first = false;
+ else
+ signature.append( ", " );
+ signature.append( ASTTypeUtil.getType( param.getType() ) );
+ }
+
+ signature.append( ')' );
+ return signature.toString();
+ }
+
+ private static void addCompletionsFor( Collection<Completion> completions, IASTInitializerClause init, MethodFilter filter )
+ {
+ if( !( init instanceof ICPPASTInitializerClause ) )
+ return;
+
+ ICPPEvaluation eval = ( (ICPPASTInitializerClause)init ).getEvaluation();
+ if( eval == null )
+ return;
+
+ IType type = eval.getTypeOrFunctionSet( init );
+ while( type instanceof IPointerType )
+ type = ( (IPointerType)type ).getType();
+
+ if( type instanceof ICPPClassType )
+ for( ICPPMethod signal : filterMethods( (ICPPClassType)type, filter ) )
+ completions.add( new Completion( getSignature( signal ) ) );
+ }
+
+ // Copied from org.eclipse.cdt.internal.ui.text.CParameterListValidator
+ private static int indexOfClosingPeer(String code, char left, char right, int pos) {
+ int level= 0;
+ final int length= code.length();
+ while (pos < length) {
+ char ch= code.charAt(pos);
+ if (ch == left) {
+ ++level;
+ } else if (ch == right) {
+ if (--level == 0) {
+ return pos;
+ }
+ }
+ ++pos;
+ }
+ return -1;
+ }
+
+ // Copied from org.eclipse.cdt.internal.ui.text.CParameterListValidator
+ private static int[] computeCommaPositions(String code) {
+ final int length= code.length();
+ int pos= 0;
+ List<Integer> positions= new ArrayList<Integer>();
+ positions.add(new Integer(-1));
+ while (pos < length && pos != -1) {
+ char ch= code.charAt(pos);
+ switch (ch) {
+ case ',':
+ positions.add(new Integer(pos));
+ break;
+ case '(':
+ pos= indexOfClosingPeer(code, '(', ')', pos);
+ break;
+ case '<':
+ pos= indexOfClosingPeer(code, '<', '>', pos);
+ break;
+ case '[':
+ pos= indexOfClosingPeer(code, '[', ']', pos);
+ break;
+ default:
+ break;
+ }
+ if (pos != -1)
+ pos++;
+ }
+ positions.add(new Integer(length));
+
+ int[] fields= new int[positions.size()];
+ for (int i= 0; i < fields.length; i++)
+ fields[i]= positions.get(i).intValue();
+ return fields;
+ }
+
+
+ private void addConnectParameterCompletions( List<ICompletionProposal> proposals, CContentAssistInvocationContext context, IASTCompletionNode completionNode, String prefix )
+ {
+ IASTName[] names = completionNode.getNames();
+ List<Completion> completions = new LinkedList<Completion>();
+
+ for( IASTName name : names )
+ {
+ // The node isn't properly hooked up, must have backtracked out of this node
+ if( name.getTranslationUnit() == null )
+ continue;
+
+ IASTCompletionContext astContext = name.getCompletionContext();
+ if( astContext == null || ! ( astContext instanceof IASTNode ) )
+ continue;
+ IASTNode astNode = (IASTNode)astContext;
+
+ if( is_QObject_connect( context, astContext, name ) )
+ {
+ int parseOffset = context.getParseOffset();
+ int invocationOffset = context.getInvocationOffset();
+
+ String unparsed = "";
+ try { unparsed = context.getDocument().get( parseOffset, invocationOffset - parseOffset ); }
+ catch( BadLocationException e ) { CCorePlugin.log( e ); }
+
+ if( unparsed.length() > 0 && unparsed.charAt( 0 ) == '(' )
+ unparsed = unparsed.substring( 1 );
+
+ int[] commas = computeCommaPositions( unparsed );
+ switch( commas.length )
+ {
+ case 3:
+ completions.add( Completion.SIGNAL );
+ break;
+ case 5:
+ completions.add( Completion.SLOT );
+ break;
+ }
+ }
+ else if( astNode.getPropertyInParent() == IASTFunctionCallExpression.ARGUMENT )
+ {
+ IASTNode parent = astNode.getParent();
+ if( ! ( parent instanceof IASTFunctionCallExpression ) )
+ continue;
+ IASTFunctionCallExpression call = (IASTFunctionCallExpression)parent;
+ IASTExpression nameExpr = call.getFunctionNameExpression();
+ if( !( nameExpr instanceof IASTIdExpression ) )
+ continue;
+ IASTIdExpression funcNameIdExpr = (IASTIdExpression)nameExpr;
+ IASTName funcName = funcNameIdExpr.getName();
+
+ if( !is_QObject_connect( context, astContext, funcName ) )
+ continue;
+
+ IASTInitializerClause[] args = call.getArguments();
+ switch( args.length )
+ {
+ case 2:
+ //if( QtKeywords.SIGNAL.equals( prefix ) )
+ addCompletionsFor( completions, args[0], MethodFilter.Qt.Signal );
+ break;
+ case 4:
+ if( QtKeywords.SLOT.equals( prefix ) )
+ addCompletionsFor( completions, args[2], MethodFilter.Qt.Slot );
+ break;
+ }
+ }
+ }
+
+ for( Completion completion : completions )
+ {
+ ICompletionProposal proposal = completion.createProposal( context );
+ if( proposal != null )
+ proposals.add( proposal );
+ }
+ }
+
+ @Override
+ protected List<ICompletionProposal> computeCompletionProposals( CContentAssistInvocationContext context, IASTCompletionNode completionNode, String prefix ) throws CoreException
+ {
+ if( !isApplicable( context ) )
+ return Collections.emptyList();
+
+ List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();
+ addConnectParameterCompletions( proposals, context, completionNode, prefix );
+ return proposals;
+ }
+}
diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/qt/ui/Activator.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/qt/ui/QtUIPlugin.java
index 5d1039b..d4b781e 100644
--- a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/qt/ui/Activator.java
+++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/qt/ui/QtUIPlugin.java
@@ -6,18 +6,18 @@ import org.osgi.framework.BundleContext;
/**
* The activator class controls the plug-in life cycle
*/
-public class Activator extends AbstractUIPlugin {
+public class QtUIPlugin extends AbstractUIPlugin {
// The plug-in ID
public static final String PLUGIN_ID = "org.eclipse.cdt.qt.ui"; //$NON-NLS-1$
// The shared instance
- private static Activator plugin;
+ private static QtUIPlugin plugin;
/**
* The constructor
*/
- public Activator() {
+ public QtUIPlugin() {
}
/*
@@ -43,7 +43,7 @@ public class Activator extends AbstractUIPlugin {
*
* @return the shared instance
*/
- public static Activator getDefault() {
+ public static QtUIPlugin getDefault() {
return plugin;
}