summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libs/qmljs/qmljsinterpreter.cpp81
-rw-r--r--src/libs/qmljs/qmljsinterpreter.h31
-rw-r--r--src/libs/qmljs/qmljsvalueowner.cpp86
-rw-r--r--src/libs/qmljs/qmljsvalueowner.h6
-rw-r--r--src/plugins/qmljseditor/qmljscompletionassist.cpp88
-rw-r--r--src/plugins/qmljseditor/qmljscompletionassist.h5
6 files changed, 223 insertions, 74 deletions
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index 5a0dbefa4a..b231815d6d 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -152,7 +152,7 @@ public:
{
}
- virtual int argumentCount() const
+ virtual int namedArgumentCount() const
{
return _method.parameterNames().size();
}
@@ -1219,7 +1219,7 @@ const Value *FunctionValue::returnValue() const
return valueOwner()->unknownValue();
}
-int FunctionValue::argumentCount() const
+int FunctionValue::namedArgumentCount() const
{
return 0;
}
@@ -1234,6 +1234,11 @@ QString FunctionValue::argumentName(int index) const
return QString::fromLatin1("arg%1").arg(index + 1);
}
+int FunctionValue::optionalNamedArgumentCount() const
+{
+ return 0;
+}
+
bool FunctionValue::isVariadic() const
{
return true;
@@ -1255,7 +1260,10 @@ void FunctionValue::accept(ValueVisitor *visitor) const
}
Function::Function(ValueOwner *valueOwner)
- : FunctionValue(valueOwner), _returnValue(0)
+ : FunctionValue(valueOwner)
+ , _returnValue(0)
+ , _optionalNamedArgumentCount(0)
+ , _isVariadic(false)
{
setClassName("Function");
}
@@ -1284,11 +1292,26 @@ void Function::setReturnValue(const Value *returnValue)
_returnValue = returnValue;
}
-int Function::argumentCount() const
+void Function::setVariadic(bool variadic)
+{
+ _isVariadic = variadic;
+}
+
+void Function::setOptionalNamedArgumentCount(int count)
+{
+ _optionalNamedArgumentCount = count;
+}
+
+int Function::namedArgumentCount() const
{
return _arguments.size();
}
+int Function::optionalNamedArgumentCount() const
+{
+ return _optionalNamedArgumentCount;
+}
+
const Value *Function::argument(int index) const
{
return _arguments.at(index);
@@ -1309,6 +1332,11 @@ const Value *Function::invoke(const Activation *) const
return _returnValue;
}
+bool Function::isVariadic() const
+{
+ return _isVariadic;
+}
+
////////////////////////////////////////////////////////////////////////////////
// typing environment
////////////////////////////////////////////////////////////////////////////////
@@ -1879,13 +1907,47 @@ bool ASTVariableReference::getSourceLocation(QString *fileName, int *line, int *
return true;
}
+namespace {
+class UsesArgumentsArray : protected Visitor
+{
+ bool _usesArgumentsArray;
+
+public:
+ bool operator()(FunctionBody *ast)
+ {
+ if (!ast || !ast->elements)
+ return false;
+ _usesArgumentsArray = false;
+ Node::accept(ast->elements, this);
+ return _usesArgumentsArray;
+ }
+
+protected:
+ bool visit(ArrayMemberExpression *ast)
+ {
+ if (IdentifierExpression *idExp = cast<IdentifierExpression *>(ast->base)) {
+ if (idExp->name == QLatin1String("arguments"))
+ _usesArgumentsArray = true;
+ }
+ return true;
+ }
+
+ // don't go into nested functions
+ bool visit(FunctionBody *) { return false; }
+};
+} // anonymous namespace
+
ASTFunctionValue::ASTFunctionValue(FunctionExpression *ast, const Document *doc, ValueOwner *valueOwner)
- : FunctionValue(valueOwner), _ast(ast), _doc(doc)
+ : FunctionValue(valueOwner)
+ , _ast(ast)
+ , _doc(doc)
{
setPrototype(valueOwner->functionPrototype());
for (FormalParameterList *it = ast->formals; it; it = it->next)
_argumentNames.append(it->name.toString());
+
+ _isVariadic = UsesArgumentsArray()(ast->body);
}
ASTFunctionValue::~ASTFunctionValue()
@@ -1897,7 +1959,7 @@ FunctionExpression *ASTFunctionValue::ast() const
return _ast;
}
-int ASTFunctionValue::argumentCount() const
+int ASTFunctionValue::namedArgumentCount() const
{
return _argumentNames.size();
}
@@ -1913,6 +1975,11 @@ QString ASTFunctionValue::argumentName(int index) const
return FunctionValue::argumentName(index);
}
+bool ASTFunctionValue::isVariadic() const
+{
+ return _isVariadic;
+}
+
bool ASTFunctionValue::getSourceLocation(QString *fileName, int *line, int *column) const
{
*fileName = _doc->fileName();
@@ -2021,7 +2088,7 @@ const ASTSignal *ASTSignal::asAstSignal() const
return this;
}
-int ASTSignal::argumentCount() const
+int ASTSignal::namedArgumentCount() const
{
int count = 0;
for (UiParameterList *it = _ast->parameters; it; it = it->next)
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index f989d5f3a1..c13f3d6b9a 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -583,11 +583,24 @@ public:
virtual const Value *returnValue() const;
- virtual int argumentCount() const;
- virtual const Value *argument(int index) const;
+ // Access to the names of arguments
+ // Named arguments can be optional (usually known for builtins only)
+ virtual int namedArgumentCount() const;
virtual QString argumentName(int index) const;
+
+ // The number of optional named arguments
+ // Example: JSON.stringify(value[, replacer[, space]])
+ // has namedArgumentCount = 3
+ // and optionalNamedArgumentCount = 2
+ virtual int optionalNamedArgumentCount() const;
+
+ // Whether the function accepts an unlimited number of arguments
+ // after the named ones. Defaults to false.
+ // Example: Math.max(...)
virtual bool isVariadic() const;
+ virtual const Value *argument(int index) const;
+
virtual const Value *invoke(const Activation *activation) const;
// Value interface
@@ -603,18 +616,24 @@ public:
void addArgument(const Value *argument, const QString &name = QString());
void setReturnValue(const Value *returnValue);
+ void setVariadic(bool variadic);
+ void setOptionalNamedArgumentCount(int count);
// FunctionValue interface
virtual const Value *returnValue() const;
- virtual int argumentCount() const;
+ virtual int namedArgumentCount() const;
+ virtual int optionalNamedArgumentCount() const;
virtual const Value *argument(int index) const;
virtual QString argumentName(int index) const;
virtual const Value *invoke(const Activation *activation) const;
+ virtual bool isVariadic() const;
private:
ValueList _arguments;
QStringList _argumentNames;
const Value *_returnValue;
+ int _optionalNamedArgumentCount;
+ bool _isVariadic;
};
@@ -799,6 +818,7 @@ class QMLJS_EXPORT ASTFunctionValue: public FunctionValue
AST::FunctionExpression *_ast;
const Document *_doc;
QList<QString> _argumentNames;
+ bool _isVariadic;
public:
ASTFunctionValue(AST::FunctionExpression *ast, const Document *doc, ValueOwner *valueOwner);
@@ -806,8 +826,9 @@ public:
AST::FunctionExpression *ast() const;
- virtual int argumentCount() const;
+ virtual int namedArgumentCount() const;
virtual QString argumentName(int index) const;
+ virtual bool isVariadic() const;
virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
};
@@ -851,7 +872,7 @@ public:
const ObjectValue *bodyScope() const { return _bodyScope; }
// FunctionValue interface
- virtual int argumentCount() const;
+ virtual int namedArgumentCount() const;
virtual const Value *argument(int index) const;
virtual QString argumentName(int index) const;
diff --git a/src/libs/qmljs/qmljsvalueowner.cpp b/src/libs/qmljs/qmljsvalueowner.cpp
index 5fa3635ecd..0b3a7bd265 100644
--- a/src/libs/qmljs/qmljsvalueowner.cpp
+++ b/src/libs/qmljs/qmljsvalueowner.cpp
@@ -499,21 +499,20 @@ QString ValueOwner::typeId(const Value *value)
return _typeId(value);
}
-Function *ValueOwner::addFunction(ObjectValue *object, const QString &name, const Value *result, int argumentCount)
+Function *ValueOwner::addFunction(ObjectValue *object, const QString &name, const Value *result, int argumentCount, int optionalCount, bool variadic)
{
- Function *function = newFunction();
+ Function *function = addFunction(object, name, argumentCount, optionalCount, variadic);
function->setReturnValue(result);
- for (int i = 0; i < argumentCount; ++i)
- function->addArgument(unknownValue());
- object->setMember(name, function);
return function;
}
-Function *ValueOwner::addFunction(ObjectValue *object, const QString &name, int argumentCount)
+Function *ValueOwner::addFunction(ObjectValue *object, const QString &name, int argumentCount, int optionalCount, bool variadic)
{
Function *function = newFunction();
for (int i = 0; i < argumentCount; ++i)
function->addArgument(unknownValue());
+ function->setVariadic(variadic);
+ function->setOptionalNamedArgumentCount(optionalCount);
object->setMember(name, function);
return function;
}
@@ -538,46 +537,58 @@ void ValueOwner::initializePrototypes()
_objectCtor->setPrototype(_functionPrototype);
_objectCtor->setMember("prototype", _objectPrototype);
_objectCtor->setReturnValue(newObject());
+ _objectCtor->addArgument(unknownValue(), "value");
+ _objectCtor->setOptionalNamedArgumentCount(1);
_functionCtor = new FunctionCtor(this);
_functionCtor->setPrototype(_functionPrototype);
_functionCtor->setMember("prototype", _functionPrototype);
_functionCtor->setReturnValue(newFunction());
+ _functionCtor->setVariadic(true);
_arrayCtor = new ArrayCtor(this);
_arrayCtor->setPrototype(_functionPrototype);
_arrayCtor->setMember("prototype", _arrayPrototype);
_arrayCtor->setReturnValue(newArray());
+ _arrayCtor->setVariadic(true);
_stringCtor = new StringCtor(this);
_stringCtor->setPrototype(_functionPrototype);
_stringCtor->setMember("prototype", _stringPrototype);
_stringCtor->setReturnValue(stringValue());
+ _stringCtor->addArgument(unknownValue(), "value");
+ _stringCtor->setOptionalNamedArgumentCount(1);
_booleanCtor = new BooleanCtor(this);
_booleanCtor->setPrototype(_functionPrototype);
_booleanCtor->setMember("prototype", _booleanPrototype);
_booleanCtor->setReturnValue(booleanValue());
+ _booleanCtor->addArgument(unknownValue(), "value");
_numberCtor = new NumberCtor(this);
_numberCtor->setPrototype(_functionPrototype);
_numberCtor->setMember("prototype", _numberPrototype);
_numberCtor->setReturnValue(numberValue());
+ _numberCtor->addArgument(unknownValue(), "value");
+ _numberCtor->setOptionalNamedArgumentCount(1);
_dateCtor = new DateCtor(this);
_dateCtor->setPrototype(_functionPrototype);
_dateCtor->setMember("prototype", _datePrototype);
_dateCtor->setReturnValue(_datePrototype);
+ _dateCtor->setVariadic(true);
_regexpCtor = new RegExpCtor(this);
_regexpCtor->setPrototype(_functionPrototype);
_regexpCtor->setMember("prototype", _regexpPrototype);
_regexpCtor->setReturnValue(_regexpPrototype);
+ _regexpCtor->addArgument(unknownValue(), "pattern");
+ _regexpCtor->addArgument(unknownValue(), "flags");
addFunction(_objectCtor, "getPrototypeOf", 1);
addFunction(_objectCtor, "getOwnPropertyDescriptor", 2);
addFunction(_objectCtor, "getOwnPropertyNames", newArray(), 1);
- addFunction(_objectCtor, "create", 1);
+ addFunction(_objectCtor, "create", 1, 1);
addFunction(_objectCtor, "defineProperty", 3);
addFunction(_objectCtor, "defineProperties", 2);
addFunction(_objectCtor, "seal", 1);
@@ -599,8 +610,8 @@ void ValueOwner::initializePrototypes()
_functionPrototype->setMember("constructor", _functionCtor);
addFunction(_functionPrototype, "toString", stringValue(), 0);
addFunction(_functionPrototype, "apply", 2);
- addFunction(_functionPrototype, "call", 1);
- addFunction(_functionPrototype, "bind", 1);
+ addFunction(_functionPrototype, "call", 1, 0, true);
+ addFunction(_functionPrototype, "bind", 1, 0, true);
// set up the default Array prototype
addFunction(_arrayCtor, "isArray", booleanValue(), 1);
@@ -608,35 +619,35 @@ void ValueOwner::initializePrototypes()
_arrayPrototype->setMember("constructor", _arrayCtor);
addFunction(_arrayPrototype, "toString", stringValue(), 0);
addFunction(_arrayPrototype, "toLocalString", stringValue(), 0);
- addFunction(_arrayPrototype, "concat", 0);
+ addFunction(_arrayPrototype, "concat", 0, 0, true);
addFunction(_arrayPrototype, "join", 1);
addFunction(_arrayPrototype, "pop", 0);
- addFunction(_arrayPrototype, "push", 0);
+ addFunction(_arrayPrototype, "push", 0, 0, true);
addFunction(_arrayPrototype, "reverse", 0);
addFunction(_arrayPrototype, "shift", 0);
addFunction(_arrayPrototype, "slice", 2);
addFunction(_arrayPrototype, "sort", 1);
addFunction(_arrayPrototype, "splice", 2);
- addFunction(_arrayPrototype, "unshift", 0);
- addFunction(_arrayPrototype, "indexOf", numberValue(), 1);
- addFunction(_arrayPrototype, "lastIndexOf", numberValue(), 1);
- addFunction(_arrayPrototype, "every", 1);
- addFunction(_arrayPrototype, "some", 1);
- addFunction(_arrayPrototype, "forEach", 1);
- addFunction(_arrayPrototype, "map", 1);
- addFunction(_arrayPrototype, "filter", 1);
- addFunction(_arrayPrototype, "reduce", 1);
- addFunction(_arrayPrototype, "reduceRight", 1);
+ addFunction(_arrayPrototype, "unshift", 0, 0, true);
+ addFunction(_arrayPrototype, "indexOf", numberValue(), 2, 1);
+ addFunction(_arrayPrototype, "lastIndexOf", numberValue(), 2, 1);
+ addFunction(_arrayPrototype, "every", 2, 1);
+ addFunction(_arrayPrototype, "some", 2, 1);
+ addFunction(_arrayPrototype, "forEach", 2, 1);
+ addFunction(_arrayPrototype, "map", 2, 1);
+ addFunction(_arrayPrototype, "filter", 2, 1);
+ addFunction(_arrayPrototype, "reduce", 2, 1);
+ addFunction(_arrayPrototype, "reduceRight", 2, 1);
// set up the default String prototype
- addFunction(_stringCtor, "fromCharCode", stringValue(), 0);
+ addFunction(_stringCtor, "fromCharCode", stringValue(), 0, 0, true);
_stringPrototype->setMember("constructor", _stringCtor);
addFunction(_stringPrototype, "toString", stringValue(), 0);
addFunction(_stringPrototype, "valueOf", stringValue(), 0);
addFunction(_stringPrototype, "charAt", stringValue(), 1);
addFunction(_stringPrototype, "charCodeAt", stringValue(), 1);
- addFunction(_stringPrototype, "concat", stringValue(), 0);
+ addFunction(_stringPrototype, "concat", stringValue(), 0, 0, true);
addFunction(_stringPrototype, "indexOf", numberValue(), 2);
addFunction(_stringPrototype, "lastIndexOf", numberValue(), 2);
addFunction(_stringPrototype, "localeCompare", booleanValue(), 1);
@@ -669,7 +680,7 @@ void ValueOwner::initializePrototypes()
addFunction(_numberCtor, "fromCharCode", 0);
_numberPrototype->setMember("constructor", _numberCtor);
- addFunction(_numberPrototype, "toString", stringValue(), 0);
+ addFunction(_numberPrototype, "toString", stringValue(), 1, 1);
addFunction(_numberPrototype, "toLocaleString", stringValue(), 0);
addFunction(_numberPrototype, "valueOf", numberValue(), 0);
addFunction(_numberPrototype, "toFixed", numberValue(), 1);
@@ -697,8 +708,8 @@ void ValueOwner::initializePrototypes()
addFunction(_mathObject, "exp", numberValue(), 1);
addFunction(_mathObject, "floor", numberValue(), 1);
addFunction(_mathObject, "log", numberValue(), 1);
- addFunction(_mathObject, "max", numberValue(), 0);
- addFunction(_mathObject, "min", numberValue(), 0);
+ addFunction(_mathObject, "max", numberValue(), 0, 0, true);
+ addFunction(_mathObject, "min", numberValue(), 0, 0, true);
addFunction(_mathObject, "pow", numberValue(), 2);
addFunction(_mathObject, "random", numberValue(), 1);
addFunction(_mathObject, "round", numberValue(), 1);
@@ -708,6 +719,7 @@ void ValueOwner::initializePrototypes()
// set up the default Boolean prototype
addFunction(_dateCtor, "parse", numberValue(), 1);
+ addFunction(_dateCtor, "UTC", numberValue(), 7, 5);
addFunction(_dateCtor, "now", numberValue(), 0);
_datePrototype->setMember("constructor", _dateCtor);
@@ -737,18 +749,18 @@ void ValueOwner::initializePrototypes()
addFunction(_datePrototype, "setTime", 1);
addFunction(_datePrototype, "setMilliseconds", 1);
addFunction(_datePrototype, "setUTCMilliseconds", 1);
- addFunction(_datePrototype, "setSeconds", 1);
- addFunction(_datePrototype, "setUTCSeconds", 1);
- addFunction(_datePrototype, "setMinutes", 1);
- addFunction(_datePrototype, "setUTCMinutes", 1);
- addFunction(_datePrototype, "setHours", 1);
- addFunction(_datePrototype, "setUTCHours", 1);
+ addFunction(_datePrototype, "setSeconds", 2, 1);
+ addFunction(_datePrototype, "setUTCSeconds", 2, 1);
+ addFunction(_datePrototype, "setMinutes", 3, 2);
+ addFunction(_datePrototype, "setUTCMinutes", 3, 2);
+ addFunction(_datePrototype, "setHours", 4, 3);
+ addFunction(_datePrototype, "setUTCHours", 4, 3);
addFunction(_datePrototype, "setDate", 1);
addFunction(_datePrototype, "setUTCDate", 1);
- addFunction(_datePrototype, "setMonth", 1);
- addFunction(_datePrototype, "setUTCMonth", 1);
- addFunction(_datePrototype, "setFullYear", 1);
- addFunction(_datePrototype, "setUTCFullYear", 1);
+ addFunction(_datePrototype, "setMonth", 2, 1);
+ addFunction(_datePrototype, "setUTCMonth", 2, 1);
+ addFunction(_datePrototype, "setFullYear", 3, 2);
+ addFunction(_datePrototype, "setUTCFullYear", 3, 2);
addFunction(_datePrototype, "toUTCString", stringValue(), 0);
addFunction(_datePrototype, "toISOString", stringValue(), 0);
addFunction(_datePrototype, "toJSON", stringValue(), 1);
@@ -829,10 +841,12 @@ void ValueOwner::initializePrototypes()
f = addFunction(json, "parse", objectPrototype());
f->addArgument(stringValue(), "text");
f->addArgument(functionPrototype(), "reviver");
+ f->setOptionalNamedArgumentCount(1);
f = addFunction(json, "stringify", stringValue());
f->addArgument(unknownValue(), "value");
f->addArgument(unknownValue(), "replacer");
f->addArgument(unknownValue(), "space");
+ f->setOptionalNamedArgumentCount(2);
_globalObject->setMember("JSON", json);
// global Qt object, in alphabetic order
diff --git a/src/libs/qmljs/qmljsvalueowner.h b/src/libs/qmljs/qmljsvalueowner.h
index 0a4a33cf0e..d1edfe0248 100644
--- a/src/libs/qmljs/qmljsvalueowner.h
+++ b/src/libs/qmljs/qmljsvalueowner.h
@@ -142,8 +142,10 @@ public:
private:
void initializePrototypes();
- Function *addFunction(ObjectValue *object, const QString &name, const Value *result, int argumentCount = 0);
- Function *addFunction(ObjectValue *object, const QString &name, int argumentCount = 0);
+ Function *addFunction(ObjectValue *object, const QString &name, const Value *result,
+ int argumentCount = 0, int optionalCount = 0, bool variadic = false);
+ Function *addFunction(ObjectValue *object, const QString &name,
+ int argumentCount = 0, int optionalCount = 0, bool variadic = false);
private:
ObjectValue *_objectPrototype;
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;