diff options
author | Christian Kamm <christian.d.kamm@nokia.com> | 2011-11-16 09:56:53 +0100 |
---|---|---|
committer | Christian Kamm <christian.d.kamm@nokia.com> | 2011-11-16 11:20:37 +0100 |
commit | b671baeffbf6e2bef5ae23303aa4367ca170cd3f (patch) | |
tree | da2b46d7541ef01f07112326df56740c5ae7d455 /src/plugins/qmljseditor | |
parent | 8e236db9f50b649a35902033550ea7dc692cbe99 (diff) | |
download | qt-creator-b671baeffbf6e2bef5ae23303aa4367ca170cd3f.tar.gz |
QmlJS: Improve completion and hints for functions.
* FunctionValues know about optional arguments (for builtins)
* ASTFunctionValues only report themselves as variadic if they
use the 'arguments' array.
* Function argument hint shows optional args and variadic.
* Completion automatically adds parentheses.
Change-Id: Ib2598600ff8b1ce8c5de3bcabd24a3e171ff3a57
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Diffstat (limited to 'src/plugins/qmljseditor')
-rw-r--r-- | src/plugins/qmljseditor/qmljscompletionassist.cpp | 88 | ||||
-rw-r--r-- | src/plugins/qmljseditor/qmljscompletionassist.h | 5 |
2 files changed, 69 insertions, 24 deletions
diff --git a/src/plugins/qmljseditor/qmljscompletionassist.cpp b/src/plugins/qmljseditor/qmljscompletionassist.cpp index 25b451decf..ac594e9770 100644 --- a/src/plugins/qmljseditor/qmljscompletionassist.cpp +++ b/src/plugins/qmljseditor/qmljscompletionassist.cpp @@ -41,6 +41,8 @@ #include <texteditor/codeassist/genericproposal.h> #include <texteditor/codeassist/functionhintproposal.h> #include <texteditor/codeassist/ifunctionhintproposalmodel.h> +#include <texteditor/texteditorsettings.h> +#include <texteditor/completionsettings.h> #include <utils/qtcassert.h> @@ -111,6 +113,13 @@ public: virtual void operator()(const Value *base, const QString &name, const Value *value) = 0; }; +class CompleteFunctionCall +{ +public: + CompleteFunctionCall(bool hasArguments = true) : hasArguments(hasArguments) {} + bool hasArguments; +}; + class CompletionAdder : public PropertyProcessor { protected: @@ -127,8 +136,15 @@ public: virtual void operator()(const Value *base, const QString &name, const Value *value) { Q_UNUSED(base) - Q_UNUSED(value) - addCompletion(completions, name, icon, order); + QVariant data; + if (const FunctionValue *func = value->asFunctionValue()) { + // constructors usually also have other interesting members, + // don't consider them pure functions and complete the '()' + if (!func->lookupMember("prototype", 0, 0, false)) { + data = QVariant::fromValue(CompleteFunctionCall(func->namedArgumentCount() || func->isVariadic())); + } + } + addCompletion(completions, name, icon, order, data); } QIcon icon; @@ -319,6 +335,8 @@ bool isLiteral(AST::Node *ast) } // Anonymous +Q_DECLARE_METATYPE(CompleteFunctionCall) + // ----------------------- // QmlJSAssistProposalItem // ----------------------- @@ -338,12 +356,21 @@ void QmlJSAssistProposalItem::applyContextualContent(TextEditor::BaseTextEditor editor->setCursorPosition(basePosition); editor->remove(currentPosition - basePosition); - QString replaceable; - const QString &content = text(); - if (content.endsWith(QLatin1String(": "))) - replaceable = QLatin1String(": "); - else if (content.endsWith(QLatin1Char('.'))) - replaceable = QLatin1String("."); + QString content = text(); + int cursorOffset = 0; + + const CompletionSettings &completionSettings = + TextEditorSettings::instance()->completionSettings(); + const bool autoInsertBrackets = completionSettings.m_autoInsertBrackets; + + if (autoInsertBrackets && data().canConvert<CompleteFunctionCall>()) { + CompleteFunctionCall function = data().value<CompleteFunctionCall>(); + content += QLatin1String("()"); + if (function.hasArguments) + cursorOffset = -1; + } + + QString replaceable = content; int replacedLength = 0; for (int i = 0; i < replaceable.length(); ++i) { const QChar a = replaceable.at(i); @@ -355,6 +382,8 @@ void QmlJSAssistProposalItem::applyContextualContent(TextEditor::BaseTextEditor } const int length = editor->position() - basePosition + replacedLength; editor->replace(length, content); + if (cursorOffset) + editor->setCursorPosition(editor->position() + cursorOffset); } // ------------------------- @@ -363,10 +392,12 @@ void QmlJSAssistProposalItem::applyContextualContent(TextEditor::BaseTextEditor class FunctionHintProposalModel : public TextEditor::IFunctionHintProposalModel { public: - FunctionHintProposalModel(const QString &functionName, const QStringList &signature) + FunctionHintProposalModel(const QString &functionName, const QStringList &namedArguments, + int optionalNamedArguments, bool isVariadic) : m_functionName(functionName) - , m_signature(signature) - , m_minimumArgumentCount(signature.size()) + , m_namedArguments(namedArguments) + , m_optionalNamedArguments(optionalNamedArguments) + , m_isVariadic(isVariadic) {} virtual void reset() {} @@ -376,8 +407,9 @@ public: private: QString m_functionName; - QStringList m_signature; - int m_minimumArgumentCount; + QStringList m_namedArguments; + int m_optionalNamedArguments; + bool m_isVariadic; }; QString FunctionHintProposalModel::text(int index) const @@ -388,11 +420,13 @@ QString FunctionHintProposalModel::text(int index) const prettyMethod += QString::fromLatin1("function "); prettyMethod += m_functionName; prettyMethod += QLatin1Char('('); - for (int i = 0; i < m_minimumArgumentCount; ++i) { + for (int i = 0; i < m_namedArguments.size(); ++i) { + if (i == m_namedArguments.size() - m_optionalNamedArguments) + prettyMethod += QLatin1Char('['); if (i != 0) prettyMethod += QLatin1String(", "); - QString arg = m_signature.at(i); + QString arg = m_namedArguments.at(i); if (arg.isEmpty()) { arg = QLatin1String("arg"); arg += QString::number(i + 1); @@ -400,6 +434,13 @@ QString FunctionHintProposalModel::text(int index) const prettyMethod += arg; } + if (m_isVariadic) { + if (m_namedArguments.size()) + prettyMethod += QLatin1String(", "); + prettyMethod += QLatin1String("..."); + } + if (m_optionalNamedArguments) + prettyMethod += QLatin1Char(']'); prettyMethod += QLatin1Char(')'); return prettyMethod; } @@ -472,10 +513,12 @@ IAssistProposal *QmlJSCompletionAssistProcessor::createContentProposal() const return proposal; } -IAssistProposal *QmlJSCompletionAssistProcessor::createHintProposal(const QString &functionName, - const QStringList &signature) const +IAssistProposal *QmlJSCompletionAssistProcessor::createHintProposal( + const QString &functionName, const QStringList &namedArguments, + int optionalNamedArguments, bool isVariadic) const { - IFunctionHintProposalModel *model = new FunctionHintProposalModel(functionName, signature); + IFunctionHintProposalModel *model = new FunctionHintProposalModel( + functionName, namedArguments, optionalNamedArguments, isVariadic); IAssistProposal *proposal = new FunctionHintProposal(m_startPosition, model); return proposal; } @@ -642,11 +685,12 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface if (indexOfDot != -1) functionName = functionName.mid(indexOfDot + 1); - QStringList signature; - for (int i = 0; i < f->argumentCount(); ++i) - signature.append(f->argumentName(i)); + QStringList namedArguments; + for (int i = 0; i < f->namedArgumentCount(); ++i) + namedArguments.append(f->argumentName(i)); - return createHintProposal(functionName.trimmed(), signature); + return createHintProposal(functionName.trimmed(), namedArguments, + f->optionalNamedArgumentCount(), f->isVariadic()); } } } diff --git a/src/plugins/qmljseditor/qmljscompletionassist.h b/src/plugins/qmljseditor/qmljscompletionassist.h index a7227f0829..f31dddaa03 100644 --- a/src/plugins/qmljseditor/qmljscompletionassist.h +++ b/src/plugins/qmljseditor/qmljscompletionassist.h @@ -99,8 +99,9 @@ public: private: TextEditor::IAssistProposal *createContentProposal() const; - TextEditor::IAssistProposal *createHintProposal(const QString &functionName, - const QStringList &signature) const; + TextEditor::IAssistProposal *createHintProposal( + const QString &functionName, const QStringList &namedArguments, + int optionalNamedArguments, bool isVariadic) const; bool acceptsIdleEditor() const; |