forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -50,6 +50,7 @@
|
|||||||
#include <cplusplus/MatchingText.h>
|
#include <cplusplus/MatchingText.h>
|
||||||
#include <cplusplus/Overview.h>
|
#include <cplusplus/Overview.h>
|
||||||
#include <cplusplus/ExpressionUnderCursor.h>
|
#include <cplusplus/ExpressionUnderCursor.h>
|
||||||
|
#include <cplusplus/BackwardsScanner.h>
|
||||||
#include <cplusplus/TokenUnderCursor.h>
|
#include <cplusplus/TokenUnderCursor.h>
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
@@ -860,7 +861,8 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (! resolvedTypes.isEmpty()) {
|
if (! resolvedTypes.isEmpty()) {
|
||||||
if (m_completionOperator == T_LPAREN && completeConstructorOrFunction(resolvedTypes, context)) {
|
if (m_completionOperator == T_LPAREN &&
|
||||||
|
completeConstructorOrFunction(resolvedTypes, context, endOfExpression)) {
|
||||||
return m_startPosition;
|
return m_startPosition;
|
||||||
|
|
||||||
} else if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) &&
|
} else if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) &&
|
||||||
@@ -899,7 +901,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
|
|||||||
// If it's a class, add completions for the constructors
|
// If it's a class, add completions for the constructors
|
||||||
foreach (const TypeOfExpression::Result &result, results) {
|
foreach (const TypeOfExpression::Result &result, results) {
|
||||||
if (result.first->isClassType()) {
|
if (result.first->isClassType()) {
|
||||||
if (completeConstructorOrFunction(results, context))
|
if (completeConstructorOrFunction(results, context, endOfExpression))
|
||||||
return m_startPosition;
|
return m_startPosition;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -912,7 +914,8 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpression::Result> &results,
|
bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpression::Result> &results,
|
||||||
const LookupContext &context)
|
const LookupContext &context,
|
||||||
|
int endOfExpression)
|
||||||
{
|
{
|
||||||
QList<Function *> functions;
|
QList<Function *> functions;
|
||||||
|
|
||||||
@@ -1002,6 +1005,77 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (! functions.isEmpty()) {
|
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
|
// Recreate if necessary
|
||||||
if (!m_functionArgumentWidget)
|
if (!m_functionArgumentWidget)
|
||||||
|
@@ -117,7 +117,8 @@ private:
|
|||||||
bool completeInclude(const QTextCursor &cursor);
|
bool completeInclude(const QTextCursor &cursor);
|
||||||
|
|
||||||
bool completeConstructorOrFunction(const QList<CPlusPlus::TypeOfExpression::Result> &,
|
bool completeConstructorOrFunction(const QList<CPlusPlus::TypeOfExpression::Result> &,
|
||||||
const CPlusPlus::LookupContext &);
|
const CPlusPlus::LookupContext &,
|
||||||
|
int endOfExpression);
|
||||||
|
|
||||||
bool completeMember(const QList<CPlusPlus::TypeOfExpression::Result> &,
|
bool completeMember(const QList<CPlusPlus::TypeOfExpression::Result> &,
|
||||||
const CPlusPlus::LookupContext &context);
|
const CPlusPlus::LookupContext &context);
|
||||||
|
Reference in New Issue
Block a user