summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kamm <christian.d.kamm@nokia.com>2009-10-19 14:14:28 +0200
committerChristian Kamm <christian.d.kamm@nokia.com>2009-10-20 12:55:14 +0200
commite3479d99423dddeae5e88bc13bfd5385a88bde43 (patch)
treefef9cf86496b5a3a44c1eaa8b768dcc2c8a787a1
parent56f755efe8f5c367b284347c73b9221ca0160de1 (diff)
downloadqt-creator-e3479d99423dddeae5e88bc13bfd5385a88bde43.tar.gz
Add completion for function signatures.
You now get the function parameters as a completion suggestion when declaring or defining a function. The tooltip for function calls is unchanged. Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com> (cherry picked from commit 202fef42ca2104a7113958c0cbfbdf1cce2024f8)
-rw-r--r--src/plugins/cpptools/cppcodecompletion.cpp80
-rw-r--r--src/plugins/cpptools/cppcodecompletion.h3
2 files changed, 79 insertions, 4 deletions
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 42cd69ff77..c0e832fba9 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -49,6 +49,7 @@
#include <cplusplus/MatchingText.h>
#include <cplusplus/Overview.h>
#include <cplusplus/ExpressionUnderCursor.h>
+#include <cplusplus/BackwardsScanner.h>
#include <cplusplus/TokenUnderCursor.h>
#include <coreplugin/icore.h>
@@ -857,7 +858,8 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
}
if (! resolvedTypes.isEmpty()) {
- if (m_completionOperator == T_LPAREN && completeConstructorOrFunction(resolvedTypes, context)) {
+ if (m_completionOperator == T_LPAREN &&
+ completeConstructorOrFunction(resolvedTypes, context, endOfExpression)) {
return m_startPosition;
} else if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) &&
@@ -896,7 +898,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
// If it's a class, add completions for the constructors
foreach (const TypeOfExpression::Result &result, results) {
if (result.first->isClassType()) {
- if (completeConstructorOrFunction(results, context))
+ if (completeConstructorOrFunction(results, context, endOfExpression))
return m_startPosition;
break;
}
@@ -909,7 +911,8 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
}
bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpression::Result> &results,
- const LookupContext &context)
+ const LookupContext &context,
+ int endOfExpression)
{
QList<Function *> functions;
@@ -999,6 +1002,77 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
}
if (! functions.isEmpty()) {
+ // There are two options:
+ // 1. If this is a function call, we want to pop up a tooltip that shows the user
+ // the possible overloads with their argument types and names.
+ // 2. If this is a function definition, we want to offer autocompletion of
+ // the function signature.
+
+ // Here we evaluate a first criterion: function definitions will only
+ // happen in class or namespace scope.
+
+ // get current line and column
+ TextEditor::BaseTextEditor *edit = qobject_cast<TextEditor::BaseTextEditor *>(m_editor->widget());
+ int lineSigned = 0, columnSigned = 0;
+ edit->convertPosition(m_editor->position(), &lineSigned, &columnSigned);
+ unsigned line = lineSigned, column = columnSigned;
+
+ // find a scope that encloses the current location, starting from the lastVisibileSymbol
+ // and moving outwards
+ Scope *sc = context.symbol()->scope();
+ while (sc->enclosingScope()) {
+ unsigned startLine, startColumn;
+ context.thisDocument()->translationUnit()->getPosition(sc->owner()->startOffset(), &startLine, &startColumn);
+ unsigned endLine, endColumn;
+ context.thisDocument()->translationUnit()->getPosition(sc->owner()->endOffset(), &endLine, &endColumn);
+
+ if (startLine <= line && line <= endLine)
+ if ((startLine != line || startColumn <= column)
+ && (endLine != line || column <= endColumn))
+ break;
+
+ sc = sc->enclosingScope();
+ }
+
+ if (sc->isClassScope() || sc->isNamespaceScope())
+ {
+ // It may still be a function call. If the whole line parses as a function
+ // declaration, we should be certain that it isn't.
+ bool autocompleteSignature = false;
+
+ QTextCursor tc(edit->document());
+ tc.setPosition(endOfExpression);
+ BackwardsScanner bs(tc);
+ QString possibleDecl = bs.mid(bs.startOfLine(bs.startToken())).trimmed().append("();");
+
+ Document::Ptr doc = Document::create(QLatin1String("<completion>"));
+ doc->setSource(possibleDecl.toLatin1());
+ if (doc->parse(Document::ParseDeclaration)) {
+ doc->check();
+ if (SimpleDeclarationAST *sd = doc->translationUnit()->ast()->asSimpleDeclaration()) {
+ if (sd->declarators->declarator->postfix_declarators
+ && sd->declarators->declarator->postfix_declarators->asFunctionDeclarator()) {
+ autocompleteSignature = true;
+ }
+ }
+ }
+
+ if (autocompleteSignature) {
+ // set up signature autocompletion
+ foreach (Function *f, functions) {
+ Overview overview;
+ overview.setShowArgumentNames(true);
+
+ TextEditor::CompletionItem item(this);
+ item.text = overview(f->type());
+ item.text = item.text.mid(1, item.text.size()-2);
+ m_completions.append(item);
+ }
+ return true;
+ }
+ }
+
+ // set up function call tooltip
// Recreate if necessary
if (!m_functionArgumentWidget)
diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h
index f8c7664728..d2bf549b16 100644
--- a/src/plugins/cpptools/cppcodecompletion.h
+++ b/src/plugins/cpptools/cppcodecompletion.h
@@ -114,7 +114,8 @@ private:
bool completeInclude(const QTextCursor &cursor);
bool completeConstructorOrFunction(const QList<CPlusPlus::TypeOfExpression::Result> &,
- const CPlusPlus::LookupContext &);
+ const CPlusPlus::LookupContext &,
+ int endOfExpression);
bool completeMember(const QList<CPlusPlus::TypeOfExpression::Result> &,
const CPlusPlus::LookupContext &context);