diff options
-rw-r--r-- | src/libs/qmljs/qmljsinterpreter.cpp | 81 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsinterpreter.h | 31 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsvalueowner.cpp | 86 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsvalueowner.h | 6 | ||||
-rw-r--r-- | src/plugins/qmljseditor/qmljscompletionassist.cpp | 88 | ||||
-rw-r--r-- | src/plugins/qmljseditor/qmljscompletionassist.h | 5 |
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; |