forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -152,7 +152,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int argumentCount() const
|
virtual int namedArgumentCount() const
|
||||||
{
|
{
|
||||||
return _method.parameterNames().size();
|
return _method.parameterNames().size();
|
||||||
}
|
}
|
||||||
@@ -1219,7 +1219,7 @@ const Value *FunctionValue::returnValue() const
|
|||||||
return valueOwner()->unknownValue();
|
return valueOwner()->unknownValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
int FunctionValue::argumentCount() const
|
int FunctionValue::namedArgumentCount() const
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1234,6 +1234,11 @@ QString FunctionValue::argumentName(int index) const
|
|||||||
return QString::fromLatin1("arg%1").arg(index + 1);
|
return QString::fromLatin1("arg%1").arg(index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FunctionValue::optionalNamedArgumentCount() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool FunctionValue::isVariadic() const
|
bool FunctionValue::isVariadic() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -1255,7 +1260,10 @@ void FunctionValue::accept(ValueVisitor *visitor) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
Function::Function(ValueOwner *valueOwner)
|
Function::Function(ValueOwner *valueOwner)
|
||||||
: FunctionValue(valueOwner), _returnValue(0)
|
: FunctionValue(valueOwner)
|
||||||
|
, _returnValue(0)
|
||||||
|
, _optionalNamedArgumentCount(0)
|
||||||
|
, _isVariadic(false)
|
||||||
{
|
{
|
||||||
setClassName("Function");
|
setClassName("Function");
|
||||||
}
|
}
|
||||||
@@ -1284,11 +1292,26 @@ void Function::setReturnValue(const Value *returnValue)
|
|||||||
_returnValue = 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();
|
return _arguments.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Function::optionalNamedArgumentCount() const
|
||||||
|
{
|
||||||
|
return _optionalNamedArgumentCount;
|
||||||
|
}
|
||||||
|
|
||||||
const Value *Function::argument(int index) const
|
const Value *Function::argument(int index) const
|
||||||
{
|
{
|
||||||
return _arguments.at(index);
|
return _arguments.at(index);
|
||||||
@@ -1309,6 +1332,11 @@ const Value *Function::invoke(const Activation *) const
|
|||||||
return _returnValue;
|
return _returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Function::isVariadic() const
|
||||||
|
{
|
||||||
|
return _isVariadic;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// typing environment
|
// typing environment
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1879,13 +1907,47 @@ bool ASTVariableReference::getSourceLocation(QString *fileName, int *line, int *
|
|||||||
return true;
|
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)
|
ASTFunctionValue::ASTFunctionValue(FunctionExpression *ast, const Document *doc, ValueOwner *valueOwner)
|
||||||
: FunctionValue(valueOwner), _ast(ast), _doc(doc)
|
: FunctionValue(valueOwner)
|
||||||
|
, _ast(ast)
|
||||||
|
, _doc(doc)
|
||||||
{
|
{
|
||||||
setPrototype(valueOwner->functionPrototype());
|
setPrototype(valueOwner->functionPrototype());
|
||||||
|
|
||||||
for (FormalParameterList *it = ast->formals; it; it = it->next)
|
for (FormalParameterList *it = ast->formals; it; it = it->next)
|
||||||
_argumentNames.append(it->name.toString());
|
_argumentNames.append(it->name.toString());
|
||||||
|
|
||||||
|
_isVariadic = UsesArgumentsArray()(ast->body);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTFunctionValue::~ASTFunctionValue()
|
ASTFunctionValue::~ASTFunctionValue()
|
||||||
@@ -1897,7 +1959,7 @@ FunctionExpression *ASTFunctionValue::ast() const
|
|||||||
return _ast;
|
return _ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASTFunctionValue::argumentCount() const
|
int ASTFunctionValue::namedArgumentCount() const
|
||||||
{
|
{
|
||||||
return _argumentNames.size();
|
return _argumentNames.size();
|
||||||
}
|
}
|
||||||
@@ -1913,6 +1975,11 @@ QString ASTFunctionValue::argumentName(int index) const
|
|||||||
return FunctionValue::argumentName(index);
|
return FunctionValue::argumentName(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ASTFunctionValue::isVariadic() const
|
||||||
|
{
|
||||||
|
return _isVariadic;
|
||||||
|
}
|
||||||
|
|
||||||
bool ASTFunctionValue::getSourceLocation(QString *fileName, int *line, int *column) const
|
bool ASTFunctionValue::getSourceLocation(QString *fileName, int *line, int *column) const
|
||||||
{
|
{
|
||||||
*fileName = _doc->fileName();
|
*fileName = _doc->fileName();
|
||||||
@@ -2021,7 +2088,7 @@ const ASTSignal *ASTSignal::asAstSignal() const
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASTSignal::argumentCount() const
|
int ASTSignal::namedArgumentCount() const
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (UiParameterList *it = _ast->parameters; it; it = it->next)
|
for (UiParameterList *it = _ast->parameters; it; it = it->next)
|
||||||
|
@@ -583,11 +583,24 @@ public:
|
|||||||
|
|
||||||
virtual const Value *returnValue() const;
|
virtual const Value *returnValue() const;
|
||||||
|
|
||||||
virtual int argumentCount() const;
|
// Access to the names of arguments
|
||||||
virtual const Value *argument(int index) const;
|
// Named arguments can be optional (usually known for builtins only)
|
||||||
|
virtual int namedArgumentCount() const;
|
||||||
virtual QString argumentName(int index) 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 bool isVariadic() const;
|
||||||
|
|
||||||
|
virtual const Value *argument(int index) const;
|
||||||
|
|
||||||
virtual const Value *invoke(const Activation *activation) const;
|
virtual const Value *invoke(const Activation *activation) const;
|
||||||
|
|
||||||
// Value interface
|
// Value interface
|
||||||
@@ -603,18 +616,24 @@ public:
|
|||||||
|
|
||||||
void addArgument(const Value *argument, const QString &name = QString());
|
void addArgument(const Value *argument, const QString &name = QString());
|
||||||
void setReturnValue(const Value *returnValue);
|
void setReturnValue(const Value *returnValue);
|
||||||
|
void setVariadic(bool variadic);
|
||||||
|
void setOptionalNamedArgumentCount(int count);
|
||||||
|
|
||||||
// FunctionValue interface
|
// FunctionValue interface
|
||||||
virtual const Value *returnValue() const;
|
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 const Value *argument(int index) const;
|
||||||
virtual QString argumentName(int index) const;
|
virtual QString argumentName(int index) const;
|
||||||
virtual const Value *invoke(const Activation *activation) const;
|
virtual const Value *invoke(const Activation *activation) const;
|
||||||
|
virtual bool isVariadic() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ValueList _arguments;
|
ValueList _arguments;
|
||||||
QStringList _argumentNames;
|
QStringList _argumentNames;
|
||||||
const Value *_returnValue;
|
const Value *_returnValue;
|
||||||
|
int _optionalNamedArgumentCount;
|
||||||
|
bool _isVariadic;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -799,6 +818,7 @@ class QMLJS_EXPORT ASTFunctionValue: public FunctionValue
|
|||||||
AST::FunctionExpression *_ast;
|
AST::FunctionExpression *_ast;
|
||||||
const Document *_doc;
|
const Document *_doc;
|
||||||
QList<QString> _argumentNames;
|
QList<QString> _argumentNames;
|
||||||
|
bool _isVariadic;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ASTFunctionValue(AST::FunctionExpression *ast, const Document *doc, ValueOwner *valueOwner);
|
ASTFunctionValue(AST::FunctionExpression *ast, const Document *doc, ValueOwner *valueOwner);
|
||||||
@@ -806,8 +826,9 @@ public:
|
|||||||
|
|
||||||
AST::FunctionExpression *ast() const;
|
AST::FunctionExpression *ast() const;
|
||||||
|
|
||||||
virtual int argumentCount() const;
|
virtual int namedArgumentCount() const;
|
||||||
virtual QString argumentName(int index) const;
|
virtual QString argumentName(int index) const;
|
||||||
|
virtual bool isVariadic() const;
|
||||||
|
|
||||||
virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
|
virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
|
||||||
};
|
};
|
||||||
@@ -851,7 +872,7 @@ public:
|
|||||||
const ObjectValue *bodyScope() const { return _bodyScope; }
|
const ObjectValue *bodyScope() const { return _bodyScope; }
|
||||||
|
|
||||||
// FunctionValue interface
|
// FunctionValue interface
|
||||||
virtual int argumentCount() const;
|
virtual int namedArgumentCount() const;
|
||||||
virtual const Value *argument(int index) const;
|
virtual const Value *argument(int index) const;
|
||||||
virtual QString argumentName(int index) const;
|
virtual QString argumentName(int index) const;
|
||||||
|
|
||||||
|
@@ -499,21 +499,20 @@ QString ValueOwner::typeId(const Value *value)
|
|||||||
return _typeId(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);
|
function->setReturnValue(result);
|
||||||
for (int i = 0; i < argumentCount; ++i)
|
|
||||||
function->addArgument(unknownValue());
|
|
||||||
object->setMember(name, function);
|
|
||||||
return 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();
|
Function *function = newFunction();
|
||||||
for (int i = 0; i < argumentCount; ++i)
|
for (int i = 0; i < argumentCount; ++i)
|
||||||
function->addArgument(unknownValue());
|
function->addArgument(unknownValue());
|
||||||
|
function->setVariadic(variadic);
|
||||||
|
function->setOptionalNamedArgumentCount(optionalCount);
|
||||||
object->setMember(name, function);
|
object->setMember(name, function);
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
@@ -538,46 +537,58 @@ void ValueOwner::initializePrototypes()
|
|||||||
_objectCtor->setPrototype(_functionPrototype);
|
_objectCtor->setPrototype(_functionPrototype);
|
||||||
_objectCtor->setMember("prototype", _objectPrototype);
|
_objectCtor->setMember("prototype", _objectPrototype);
|
||||||
_objectCtor->setReturnValue(newObject());
|
_objectCtor->setReturnValue(newObject());
|
||||||
|
_objectCtor->addArgument(unknownValue(), "value");
|
||||||
|
_objectCtor->setOptionalNamedArgumentCount(1);
|
||||||
|
|
||||||
_functionCtor = new FunctionCtor(this);
|
_functionCtor = new FunctionCtor(this);
|
||||||
_functionCtor->setPrototype(_functionPrototype);
|
_functionCtor->setPrototype(_functionPrototype);
|
||||||
_functionCtor->setMember("prototype", _functionPrototype);
|
_functionCtor->setMember("prototype", _functionPrototype);
|
||||||
_functionCtor->setReturnValue(newFunction());
|
_functionCtor->setReturnValue(newFunction());
|
||||||
|
_functionCtor->setVariadic(true);
|
||||||
|
|
||||||
_arrayCtor = new ArrayCtor(this);
|
_arrayCtor = new ArrayCtor(this);
|
||||||
_arrayCtor->setPrototype(_functionPrototype);
|
_arrayCtor->setPrototype(_functionPrototype);
|
||||||
_arrayCtor->setMember("prototype", _arrayPrototype);
|
_arrayCtor->setMember("prototype", _arrayPrototype);
|
||||||
_arrayCtor->setReturnValue(newArray());
|
_arrayCtor->setReturnValue(newArray());
|
||||||
|
_arrayCtor->setVariadic(true);
|
||||||
|
|
||||||
_stringCtor = new StringCtor(this);
|
_stringCtor = new StringCtor(this);
|
||||||
_stringCtor->setPrototype(_functionPrototype);
|
_stringCtor->setPrototype(_functionPrototype);
|
||||||
_stringCtor->setMember("prototype", _stringPrototype);
|
_stringCtor->setMember("prototype", _stringPrototype);
|
||||||
_stringCtor->setReturnValue(stringValue());
|
_stringCtor->setReturnValue(stringValue());
|
||||||
|
_stringCtor->addArgument(unknownValue(), "value");
|
||||||
|
_stringCtor->setOptionalNamedArgumentCount(1);
|
||||||
|
|
||||||
_booleanCtor = new BooleanCtor(this);
|
_booleanCtor = new BooleanCtor(this);
|
||||||
_booleanCtor->setPrototype(_functionPrototype);
|
_booleanCtor->setPrototype(_functionPrototype);
|
||||||
_booleanCtor->setMember("prototype", _booleanPrototype);
|
_booleanCtor->setMember("prototype", _booleanPrototype);
|
||||||
_booleanCtor->setReturnValue(booleanValue());
|
_booleanCtor->setReturnValue(booleanValue());
|
||||||
|
_booleanCtor->addArgument(unknownValue(), "value");
|
||||||
|
|
||||||
_numberCtor = new NumberCtor(this);
|
_numberCtor = new NumberCtor(this);
|
||||||
_numberCtor->setPrototype(_functionPrototype);
|
_numberCtor->setPrototype(_functionPrototype);
|
||||||
_numberCtor->setMember("prototype", _numberPrototype);
|
_numberCtor->setMember("prototype", _numberPrototype);
|
||||||
_numberCtor->setReturnValue(numberValue());
|
_numberCtor->setReturnValue(numberValue());
|
||||||
|
_numberCtor->addArgument(unknownValue(), "value");
|
||||||
|
_numberCtor->setOptionalNamedArgumentCount(1);
|
||||||
|
|
||||||
_dateCtor = new DateCtor(this);
|
_dateCtor = new DateCtor(this);
|
||||||
_dateCtor->setPrototype(_functionPrototype);
|
_dateCtor->setPrototype(_functionPrototype);
|
||||||
_dateCtor->setMember("prototype", _datePrototype);
|
_dateCtor->setMember("prototype", _datePrototype);
|
||||||
_dateCtor->setReturnValue(_datePrototype);
|
_dateCtor->setReturnValue(_datePrototype);
|
||||||
|
_dateCtor->setVariadic(true);
|
||||||
|
|
||||||
_regexpCtor = new RegExpCtor(this);
|
_regexpCtor = new RegExpCtor(this);
|
||||||
_regexpCtor->setPrototype(_functionPrototype);
|
_regexpCtor->setPrototype(_functionPrototype);
|
||||||
_regexpCtor->setMember("prototype", _regexpPrototype);
|
_regexpCtor->setMember("prototype", _regexpPrototype);
|
||||||
_regexpCtor->setReturnValue(_regexpPrototype);
|
_regexpCtor->setReturnValue(_regexpPrototype);
|
||||||
|
_regexpCtor->addArgument(unknownValue(), "pattern");
|
||||||
|
_regexpCtor->addArgument(unknownValue(), "flags");
|
||||||
|
|
||||||
addFunction(_objectCtor, "getPrototypeOf", 1);
|
addFunction(_objectCtor, "getPrototypeOf", 1);
|
||||||
addFunction(_objectCtor, "getOwnPropertyDescriptor", 2);
|
addFunction(_objectCtor, "getOwnPropertyDescriptor", 2);
|
||||||
addFunction(_objectCtor, "getOwnPropertyNames", newArray(), 1);
|
addFunction(_objectCtor, "getOwnPropertyNames", newArray(), 1);
|
||||||
addFunction(_objectCtor, "create", 1);
|
addFunction(_objectCtor, "create", 1, 1);
|
||||||
addFunction(_objectCtor, "defineProperty", 3);
|
addFunction(_objectCtor, "defineProperty", 3);
|
||||||
addFunction(_objectCtor, "defineProperties", 2);
|
addFunction(_objectCtor, "defineProperties", 2);
|
||||||
addFunction(_objectCtor, "seal", 1);
|
addFunction(_objectCtor, "seal", 1);
|
||||||
@@ -599,8 +610,8 @@ void ValueOwner::initializePrototypes()
|
|||||||
_functionPrototype->setMember("constructor", _functionCtor);
|
_functionPrototype->setMember("constructor", _functionCtor);
|
||||||
addFunction(_functionPrototype, "toString", stringValue(), 0);
|
addFunction(_functionPrototype, "toString", stringValue(), 0);
|
||||||
addFunction(_functionPrototype, "apply", 2);
|
addFunction(_functionPrototype, "apply", 2);
|
||||||
addFunction(_functionPrototype, "call", 1);
|
addFunction(_functionPrototype, "call", 1, 0, true);
|
||||||
addFunction(_functionPrototype, "bind", 1);
|
addFunction(_functionPrototype, "bind", 1, 0, true);
|
||||||
|
|
||||||
// set up the default Array prototype
|
// set up the default Array prototype
|
||||||
addFunction(_arrayCtor, "isArray", booleanValue(), 1);
|
addFunction(_arrayCtor, "isArray", booleanValue(), 1);
|
||||||
@@ -608,35 +619,35 @@ void ValueOwner::initializePrototypes()
|
|||||||
_arrayPrototype->setMember("constructor", _arrayCtor);
|
_arrayPrototype->setMember("constructor", _arrayCtor);
|
||||||
addFunction(_arrayPrototype, "toString", stringValue(), 0);
|
addFunction(_arrayPrototype, "toString", stringValue(), 0);
|
||||||
addFunction(_arrayPrototype, "toLocalString", stringValue(), 0);
|
addFunction(_arrayPrototype, "toLocalString", stringValue(), 0);
|
||||||
addFunction(_arrayPrototype, "concat", 0);
|
addFunction(_arrayPrototype, "concat", 0, 0, true);
|
||||||
addFunction(_arrayPrototype, "join", 1);
|
addFunction(_arrayPrototype, "join", 1);
|
||||||
addFunction(_arrayPrototype, "pop", 0);
|
addFunction(_arrayPrototype, "pop", 0);
|
||||||
addFunction(_arrayPrototype, "push", 0);
|
addFunction(_arrayPrototype, "push", 0, 0, true);
|
||||||
addFunction(_arrayPrototype, "reverse", 0);
|
addFunction(_arrayPrototype, "reverse", 0);
|
||||||
addFunction(_arrayPrototype, "shift", 0);
|
addFunction(_arrayPrototype, "shift", 0);
|
||||||
addFunction(_arrayPrototype, "slice", 2);
|
addFunction(_arrayPrototype, "slice", 2);
|
||||||
addFunction(_arrayPrototype, "sort", 1);
|
addFunction(_arrayPrototype, "sort", 1);
|
||||||
addFunction(_arrayPrototype, "splice", 2);
|
addFunction(_arrayPrototype, "splice", 2);
|
||||||
addFunction(_arrayPrototype, "unshift", 0);
|
addFunction(_arrayPrototype, "unshift", 0, 0, true);
|
||||||
addFunction(_arrayPrototype, "indexOf", numberValue(), 1);
|
addFunction(_arrayPrototype, "indexOf", numberValue(), 2, 1);
|
||||||
addFunction(_arrayPrototype, "lastIndexOf", numberValue(), 1);
|
addFunction(_arrayPrototype, "lastIndexOf", numberValue(), 2, 1);
|
||||||
addFunction(_arrayPrototype, "every", 1);
|
addFunction(_arrayPrototype, "every", 2, 1);
|
||||||
addFunction(_arrayPrototype, "some", 1);
|
addFunction(_arrayPrototype, "some", 2, 1);
|
||||||
addFunction(_arrayPrototype, "forEach", 1);
|
addFunction(_arrayPrototype, "forEach", 2, 1);
|
||||||
addFunction(_arrayPrototype, "map", 1);
|
addFunction(_arrayPrototype, "map", 2, 1);
|
||||||
addFunction(_arrayPrototype, "filter", 1);
|
addFunction(_arrayPrototype, "filter", 2, 1);
|
||||||
addFunction(_arrayPrototype, "reduce", 1);
|
addFunction(_arrayPrototype, "reduce", 2, 1);
|
||||||
addFunction(_arrayPrototype, "reduceRight", 1);
|
addFunction(_arrayPrototype, "reduceRight", 2, 1);
|
||||||
|
|
||||||
// set up the default String prototype
|
// set up the default String prototype
|
||||||
addFunction(_stringCtor, "fromCharCode", stringValue(), 0);
|
addFunction(_stringCtor, "fromCharCode", stringValue(), 0, 0, true);
|
||||||
|
|
||||||
_stringPrototype->setMember("constructor", _stringCtor);
|
_stringPrototype->setMember("constructor", _stringCtor);
|
||||||
addFunction(_stringPrototype, "toString", stringValue(), 0);
|
addFunction(_stringPrototype, "toString", stringValue(), 0);
|
||||||
addFunction(_stringPrototype, "valueOf", stringValue(), 0);
|
addFunction(_stringPrototype, "valueOf", stringValue(), 0);
|
||||||
addFunction(_stringPrototype, "charAt", stringValue(), 1);
|
addFunction(_stringPrototype, "charAt", stringValue(), 1);
|
||||||
addFunction(_stringPrototype, "charCodeAt", 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, "indexOf", numberValue(), 2);
|
||||||
addFunction(_stringPrototype, "lastIndexOf", numberValue(), 2);
|
addFunction(_stringPrototype, "lastIndexOf", numberValue(), 2);
|
||||||
addFunction(_stringPrototype, "localeCompare", booleanValue(), 1);
|
addFunction(_stringPrototype, "localeCompare", booleanValue(), 1);
|
||||||
@@ -669,7 +680,7 @@ void ValueOwner::initializePrototypes()
|
|||||||
addFunction(_numberCtor, "fromCharCode", 0);
|
addFunction(_numberCtor, "fromCharCode", 0);
|
||||||
|
|
||||||
_numberPrototype->setMember("constructor", _numberCtor);
|
_numberPrototype->setMember("constructor", _numberCtor);
|
||||||
addFunction(_numberPrototype, "toString", stringValue(), 0);
|
addFunction(_numberPrototype, "toString", stringValue(), 1, 1);
|
||||||
addFunction(_numberPrototype, "toLocaleString", stringValue(), 0);
|
addFunction(_numberPrototype, "toLocaleString", stringValue(), 0);
|
||||||
addFunction(_numberPrototype, "valueOf", numberValue(), 0);
|
addFunction(_numberPrototype, "valueOf", numberValue(), 0);
|
||||||
addFunction(_numberPrototype, "toFixed", numberValue(), 1);
|
addFunction(_numberPrototype, "toFixed", numberValue(), 1);
|
||||||
@@ -697,8 +708,8 @@ void ValueOwner::initializePrototypes()
|
|||||||
addFunction(_mathObject, "exp", numberValue(), 1);
|
addFunction(_mathObject, "exp", numberValue(), 1);
|
||||||
addFunction(_mathObject, "floor", numberValue(), 1);
|
addFunction(_mathObject, "floor", numberValue(), 1);
|
||||||
addFunction(_mathObject, "log", numberValue(), 1);
|
addFunction(_mathObject, "log", numberValue(), 1);
|
||||||
addFunction(_mathObject, "max", numberValue(), 0);
|
addFunction(_mathObject, "max", numberValue(), 0, 0, true);
|
||||||
addFunction(_mathObject, "min", numberValue(), 0);
|
addFunction(_mathObject, "min", numberValue(), 0, 0, true);
|
||||||
addFunction(_mathObject, "pow", numberValue(), 2);
|
addFunction(_mathObject, "pow", numberValue(), 2);
|
||||||
addFunction(_mathObject, "random", numberValue(), 1);
|
addFunction(_mathObject, "random", numberValue(), 1);
|
||||||
addFunction(_mathObject, "round", numberValue(), 1);
|
addFunction(_mathObject, "round", numberValue(), 1);
|
||||||
@@ -708,6 +719,7 @@ void ValueOwner::initializePrototypes()
|
|||||||
|
|
||||||
// set up the default Boolean prototype
|
// set up the default Boolean prototype
|
||||||
addFunction(_dateCtor, "parse", numberValue(), 1);
|
addFunction(_dateCtor, "parse", numberValue(), 1);
|
||||||
|
addFunction(_dateCtor, "UTC", numberValue(), 7, 5);
|
||||||
addFunction(_dateCtor, "now", numberValue(), 0);
|
addFunction(_dateCtor, "now", numberValue(), 0);
|
||||||
|
|
||||||
_datePrototype->setMember("constructor", _dateCtor);
|
_datePrototype->setMember("constructor", _dateCtor);
|
||||||
@@ -737,18 +749,18 @@ void ValueOwner::initializePrototypes()
|
|||||||
addFunction(_datePrototype, "setTime", 1);
|
addFunction(_datePrototype, "setTime", 1);
|
||||||
addFunction(_datePrototype, "setMilliseconds", 1);
|
addFunction(_datePrototype, "setMilliseconds", 1);
|
||||||
addFunction(_datePrototype, "setUTCMilliseconds", 1);
|
addFunction(_datePrototype, "setUTCMilliseconds", 1);
|
||||||
addFunction(_datePrototype, "setSeconds", 1);
|
addFunction(_datePrototype, "setSeconds", 2, 1);
|
||||||
addFunction(_datePrototype, "setUTCSeconds", 1);
|
addFunction(_datePrototype, "setUTCSeconds", 2, 1);
|
||||||
addFunction(_datePrototype, "setMinutes", 1);
|
addFunction(_datePrototype, "setMinutes", 3, 2);
|
||||||
addFunction(_datePrototype, "setUTCMinutes", 1);
|
addFunction(_datePrototype, "setUTCMinutes", 3, 2);
|
||||||
addFunction(_datePrototype, "setHours", 1);
|
addFunction(_datePrototype, "setHours", 4, 3);
|
||||||
addFunction(_datePrototype, "setUTCHours", 1);
|
addFunction(_datePrototype, "setUTCHours", 4, 3);
|
||||||
addFunction(_datePrototype, "setDate", 1);
|
addFunction(_datePrototype, "setDate", 1);
|
||||||
addFunction(_datePrototype, "setUTCDate", 1);
|
addFunction(_datePrototype, "setUTCDate", 1);
|
||||||
addFunction(_datePrototype, "setMonth", 1);
|
addFunction(_datePrototype, "setMonth", 2, 1);
|
||||||
addFunction(_datePrototype, "setUTCMonth", 1);
|
addFunction(_datePrototype, "setUTCMonth", 2, 1);
|
||||||
addFunction(_datePrototype, "setFullYear", 1);
|
addFunction(_datePrototype, "setFullYear", 3, 2);
|
||||||
addFunction(_datePrototype, "setUTCFullYear", 1);
|
addFunction(_datePrototype, "setUTCFullYear", 3, 2);
|
||||||
addFunction(_datePrototype, "toUTCString", stringValue(), 0);
|
addFunction(_datePrototype, "toUTCString", stringValue(), 0);
|
||||||
addFunction(_datePrototype, "toISOString", stringValue(), 0);
|
addFunction(_datePrototype, "toISOString", stringValue(), 0);
|
||||||
addFunction(_datePrototype, "toJSON", stringValue(), 1);
|
addFunction(_datePrototype, "toJSON", stringValue(), 1);
|
||||||
@@ -829,10 +841,12 @@ void ValueOwner::initializePrototypes()
|
|||||||
f = addFunction(json, "parse", objectPrototype());
|
f = addFunction(json, "parse", objectPrototype());
|
||||||
f->addArgument(stringValue(), "text");
|
f->addArgument(stringValue(), "text");
|
||||||
f->addArgument(functionPrototype(), "reviver");
|
f->addArgument(functionPrototype(), "reviver");
|
||||||
|
f->setOptionalNamedArgumentCount(1);
|
||||||
f = addFunction(json, "stringify", stringValue());
|
f = addFunction(json, "stringify", stringValue());
|
||||||
f->addArgument(unknownValue(), "value");
|
f->addArgument(unknownValue(), "value");
|
||||||
f->addArgument(unknownValue(), "replacer");
|
f->addArgument(unknownValue(), "replacer");
|
||||||
f->addArgument(unknownValue(), "space");
|
f->addArgument(unknownValue(), "space");
|
||||||
|
f->setOptionalNamedArgumentCount(2);
|
||||||
_globalObject->setMember("JSON", json);
|
_globalObject->setMember("JSON", json);
|
||||||
|
|
||||||
// global Qt object, in alphabetic order
|
// global Qt object, in alphabetic order
|
||||||
|
@@ -142,8 +142,10 @@ public:
|
|||||||
private:
|
private:
|
||||||
void initializePrototypes();
|
void initializePrototypes();
|
||||||
|
|
||||||
Function *addFunction(ObjectValue *object, const QString &name, const Value *result, int argumentCount = 0);
|
Function *addFunction(ObjectValue *object, const QString &name, const Value *result,
|
||||||
Function *addFunction(ObjectValue *object, const QString &name, int argumentCount = 0);
|
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:
|
private:
|
||||||
ObjectValue *_objectPrototype;
|
ObjectValue *_objectPrototype;
|
||||||
|
@@ -41,6 +41,8 @@
|
|||||||
#include <texteditor/codeassist/genericproposal.h>
|
#include <texteditor/codeassist/genericproposal.h>
|
||||||
#include <texteditor/codeassist/functionhintproposal.h>
|
#include <texteditor/codeassist/functionhintproposal.h>
|
||||||
#include <texteditor/codeassist/ifunctionhintproposalmodel.h>
|
#include <texteditor/codeassist/ifunctionhintproposalmodel.h>
|
||||||
|
#include <texteditor/texteditorsettings.h>
|
||||||
|
#include <texteditor/completionsettings.h>
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
@@ -111,6 +113,13 @@ public:
|
|||||||
virtual void operator()(const Value *base, const QString &name, const Value *value) = 0;
|
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
|
class CompletionAdder : public PropertyProcessor
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@@ -127,8 +136,15 @@ public:
|
|||||||
virtual void operator()(const Value *base, const QString &name, const Value *value)
|
virtual void operator()(const Value *base, const QString &name, const Value *value)
|
||||||
{
|
{
|
||||||
Q_UNUSED(base)
|
Q_UNUSED(base)
|
||||||
Q_UNUSED(value)
|
QVariant data;
|
||||||
addCompletion(completions, name, icon, order);
|
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;
|
QIcon icon;
|
||||||
@@ -319,6 +335,8 @@ bool isLiteral(AST::Node *ast)
|
|||||||
|
|
||||||
} // Anonymous
|
} // Anonymous
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(CompleteFunctionCall)
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
// QmlJSAssistProposalItem
|
// QmlJSAssistProposalItem
|
||||||
// -----------------------
|
// -----------------------
|
||||||
@@ -338,12 +356,21 @@ void QmlJSAssistProposalItem::applyContextualContent(TextEditor::BaseTextEditor
|
|||||||
editor->setCursorPosition(basePosition);
|
editor->setCursorPosition(basePosition);
|
||||||
editor->remove(currentPosition - basePosition);
|
editor->remove(currentPosition - basePosition);
|
||||||
|
|
||||||
QString replaceable;
|
QString content = text();
|
||||||
const QString &content = text();
|
int cursorOffset = 0;
|
||||||
if (content.endsWith(QLatin1String(": ")))
|
|
||||||
replaceable = QLatin1String(": ");
|
const CompletionSettings &completionSettings =
|
||||||
else if (content.endsWith(QLatin1Char('.')))
|
TextEditorSettings::instance()->completionSettings();
|
||||||
replaceable = QLatin1String(".");
|
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;
|
int replacedLength = 0;
|
||||||
for (int i = 0; i < replaceable.length(); ++i) {
|
for (int i = 0; i < replaceable.length(); ++i) {
|
||||||
const QChar a = replaceable.at(i);
|
const QChar a = replaceable.at(i);
|
||||||
@@ -355,6 +382,8 @@ void QmlJSAssistProposalItem::applyContextualContent(TextEditor::BaseTextEditor
|
|||||||
}
|
}
|
||||||
const int length = editor->position() - basePosition + replacedLength;
|
const int length = editor->position() - basePosition + replacedLength;
|
||||||
editor->replace(length, content);
|
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
|
class FunctionHintProposalModel : public TextEditor::IFunctionHintProposalModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FunctionHintProposalModel(const QString &functionName, const QStringList &signature)
|
FunctionHintProposalModel(const QString &functionName, const QStringList &namedArguments,
|
||||||
|
int optionalNamedArguments, bool isVariadic)
|
||||||
: m_functionName(functionName)
|
: m_functionName(functionName)
|
||||||
, m_signature(signature)
|
, m_namedArguments(namedArguments)
|
||||||
, m_minimumArgumentCount(signature.size())
|
, m_optionalNamedArguments(optionalNamedArguments)
|
||||||
|
, m_isVariadic(isVariadic)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual void reset() {}
|
virtual void reset() {}
|
||||||
@@ -376,8 +407,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_functionName;
|
QString m_functionName;
|
||||||
QStringList m_signature;
|
QStringList m_namedArguments;
|
||||||
int m_minimumArgumentCount;
|
int m_optionalNamedArguments;
|
||||||
|
bool m_isVariadic;
|
||||||
};
|
};
|
||||||
|
|
||||||
QString FunctionHintProposalModel::text(int index) const
|
QString FunctionHintProposalModel::text(int index) const
|
||||||
@@ -388,11 +420,13 @@ QString FunctionHintProposalModel::text(int index) const
|
|||||||
prettyMethod += QString::fromLatin1("function ");
|
prettyMethod += QString::fromLatin1("function ");
|
||||||
prettyMethod += m_functionName;
|
prettyMethod += m_functionName;
|
||||||
prettyMethod += QLatin1Char('(');
|
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)
|
if (i != 0)
|
||||||
prettyMethod += QLatin1String(", ");
|
prettyMethod += QLatin1String(", ");
|
||||||
|
|
||||||
QString arg = m_signature.at(i);
|
QString arg = m_namedArguments.at(i);
|
||||||
if (arg.isEmpty()) {
|
if (arg.isEmpty()) {
|
||||||
arg = QLatin1String("arg");
|
arg = QLatin1String("arg");
|
||||||
arg += QString::number(i + 1);
|
arg += QString::number(i + 1);
|
||||||
@@ -400,6 +434,13 @@ QString FunctionHintProposalModel::text(int index) const
|
|||||||
|
|
||||||
prettyMethod += arg;
|
prettyMethod += arg;
|
||||||
}
|
}
|
||||||
|
if (m_isVariadic) {
|
||||||
|
if (m_namedArguments.size())
|
||||||
|
prettyMethod += QLatin1String(", ");
|
||||||
|
prettyMethod += QLatin1String("...");
|
||||||
|
}
|
||||||
|
if (m_optionalNamedArguments)
|
||||||
|
prettyMethod += QLatin1Char(']');
|
||||||
prettyMethod += QLatin1Char(')');
|
prettyMethod += QLatin1Char(')');
|
||||||
return prettyMethod;
|
return prettyMethod;
|
||||||
}
|
}
|
||||||
@@ -472,10 +513,12 @@ IAssistProposal *QmlJSCompletionAssistProcessor::createContentProposal() const
|
|||||||
return proposal;
|
return proposal;
|
||||||
}
|
}
|
||||||
|
|
||||||
IAssistProposal *QmlJSCompletionAssistProcessor::createHintProposal(const QString &functionName,
|
IAssistProposal *QmlJSCompletionAssistProcessor::createHintProposal(
|
||||||
const QStringList &signature) const
|
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);
|
IAssistProposal *proposal = new FunctionHintProposal(m_startPosition, model);
|
||||||
return proposal;
|
return proposal;
|
||||||
}
|
}
|
||||||
@@ -642,11 +685,12 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface
|
|||||||
if (indexOfDot != -1)
|
if (indexOfDot != -1)
|
||||||
functionName = functionName.mid(indexOfDot + 1);
|
functionName = functionName.mid(indexOfDot + 1);
|
||||||
|
|
||||||
QStringList signature;
|
QStringList namedArguments;
|
||||||
for (int i = 0; i < f->argumentCount(); ++i)
|
for (int i = 0; i < f->namedArgumentCount(); ++i)
|
||||||
signature.append(f->argumentName(i));
|
namedArguments.append(f->argumentName(i));
|
||||||
|
|
||||||
return createHintProposal(functionName.trimmed(), signature);
|
return createHintProposal(functionName.trimmed(), namedArguments,
|
||||||
|
f->optionalNamedArgumentCount(), f->isVariadic());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -99,8 +99,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
TextEditor::IAssistProposal *createContentProposal() const;
|
TextEditor::IAssistProposal *createContentProposal() const;
|
||||||
TextEditor::IAssistProposal *createHintProposal(const QString &functionName,
|
TextEditor::IAssistProposal *createHintProposal(
|
||||||
const QStringList &signature) const;
|
const QString &functionName, const QStringList &namedArguments,
|
||||||
|
int optionalNamedArguments, bool isVariadic) const;
|
||||||
|
|
||||||
bool acceptsIdleEditor() const;
|
bool acceptsIdleEditor() const;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user