Show the argument names from the method's signature.

This commit is contained in:
Roberto Raggi
2010-01-26 10:50:30 +01:00
parent 3294fbf8bf
commit 2512a684d5
3 changed files with 136 additions and 31 deletions

View File

@@ -47,11 +47,58 @@ namespace {
#ifndef NO_DECLARATIVE_BACKEND #ifndef NO_DECLARATIVE_BACKEND
class MetaFunction: public FunctionValue
{
QMetaMethod _method;
public:
MetaFunction(const QMetaMethod &method, Engine *engine)
: FunctionValue(engine), _method(method)
{
engine->registerObject(this);
}
virtual const Value *returnValue() const
{
return engine()->undefinedValue();
}
virtual int argumentCount() const
{
return _method.parameterNames().size();
}
virtual const Value *argument(int) const
{
return engine()->undefinedValue();
}
virtual QString argumentName(int index) const
{
if (index < _method.parameterNames().size())
return _method.parameterNames().at(index);
return FunctionValue::argumentName(index);
}
virtual bool isVariadic() const
{
return false;
}
virtual const Value *invoke(const Activation *) const
{
return engine()->undefinedValue();
}
};
class QmlObjectValue: public ObjectValue class QmlObjectValue: public ObjectValue
{ {
public: public:
QmlObjectValue(const QMetaObject *metaObject, Engine *engine) QmlObjectValue(const QMetaObject *metaObject, Engine *engine)
: ObjectValue(engine), _metaObject(metaObject) {} : ObjectValue(engine), _metaObject(metaObject)
{
}
virtual ~QmlObjectValue() {} virtual ~QmlObjectValue() {}
@@ -64,6 +111,28 @@ public:
return propertyValue(prop); return propertyValue(prop);
} }
for (int index = 0; index < _metaObject->methodCount(); ++index) {
QMetaMethod method = _metaObject->method(index);
const QString signature = QString::fromUtf8(method.signature());
const int indexOfParen = signature.indexOf(QLatin1Char('('));
if (indexOfParen == -1)
continue; // skip it, invalid signature.
const QString methodName = signature.left(indexOfParen);
if (methodName != name) {
continue;
} else if (method.methodType() == QMetaMethod::Slot && method.access() == QMetaMethod::Public) {
return new MetaFunction(method, engine());
} else if (method.methodType() == QMetaMethod::Signal && method.access() != QMetaMethod::Private) {
return new MetaFunction(method, engine());
}
}
return ObjectValue::lookupMember(name); return ObjectValue::lookupMember(name);
} }
@@ -76,9 +145,9 @@ public:
} }
for (int index = 0; index < _metaObject->methodCount(); ++index) { for (int index = 0; index < _metaObject->methodCount(); ++index) {
QMetaMethod meth = _metaObject->method(index); QMetaMethod method = _metaObject->method(index);
const QString signature = QString::fromUtf8(meth.signature()); const QString signature = QString::fromUtf8(method.signature());
const int indexOfParen = signature.indexOf(QLatin1Char('(')); const int indexOfParen = signature.indexOf(QLatin1Char('('));
if (indexOfParen == -1) if (indexOfParen == -1)
@@ -86,12 +155,12 @@ public:
const QString methodName = signature.left(indexOfParen); const QString methodName = signature.left(indexOfParen);
if (meth.methodType() == QMetaMethod::Slot && meth.access() == QMetaMethod::Public) { if (method.methodType() == QMetaMethod::Slot && method.access() == QMetaMethod::Public) {
processor->processSlot(methodName, engine()->undefinedValue()); processor->processSlot(methodName, engine()->undefinedValue());
} else if (meth.methodType() == QMetaMethod::Signal && meth.access() != QMetaMethod::Private) { } else if (method.methodType() == QMetaMethod::Signal && method.access() != QMetaMethod::Private) {
// process the signal // process the signal
processor->processSignal(methodName, engine()->undefinedValue()); // ### FIXME: assign a decent type to the signal processor->processSignal(methodName, engine()->undefinedValue());
QString slotName; QString slotName;
slotName += QLatin1String("on"); slotName += QLatin1String("on");
@@ -99,7 +168,7 @@ public:
slotName += methodName.midRef(1); slotName += methodName.midRef(1);
// process the generated slot // process the generated slot
processor->processGeneratedSlot(slotName, engine()->undefinedValue()); // ### FIXME: assign a decent type to the slot processor->processGeneratedSlot(slotName, engine()->undefinedValue());
} }
} }
@@ -803,11 +872,36 @@ const Value *FunctionValue::call(const ObjectValue *thisObject, const ValueList
return invoke(&activation); return invoke(&activation);
} }
const Value *FunctionValue::returnValue() const
{
return engine()->undefinedValue();
}
int FunctionValue::argumentCount() const int FunctionValue::argumentCount() const
{ {
return 0; return 0;
} }
const Value *FunctionValue::argument(int) const
{
return engine()->undefinedValue();
}
QString FunctionValue::argumentName(int index) const
{
return QString::fromLatin1("arg%1").arg(index);
}
bool FunctionValue::isVariadic() const
{
return true;
}
const Value *FunctionValue::invoke(const Activation *activation) const
{
return activation->thisObject(); // ### FIXME: it should return undefined
}
const FunctionValue *FunctionValue::asFunctionValue() const const FunctionValue *FunctionValue::asFunctionValue() const
{ {
return this; return this;
@@ -1202,6 +1296,11 @@ const ObjectValue *Engine::mathObject() const
return _mathObject; return _mathObject;
} }
void Engine::registerObject(ObjectValue *object)
{
_objects.append(object);
}
const Value *Engine::convertToBoolean(const Value *value) const Value *Engine::convertToBoolean(const Value *value)
{ {
return _convertToNumber(value); // ### implement convert to bool return _convertToNumber(value); // ### implement convert to bool
@@ -1423,8 +1522,8 @@ void Engine::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(), 1); addFunction(_mathObject, "max", numberValue(), 0);
addFunction(_mathObject, "min", numberValue(), 1); addFunction(_mathObject, "min", numberValue(), 0);
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);
@@ -1535,23 +1634,6 @@ ObjectValue *Engine::newQmlObject(const QString &name)
#endif #endif
} }
const Value *FunctionValue::invoke(const Activation *activation) const
{
return activation->thisObject(); // ### FIXME: it should return undefined
}
const Value *FunctionValue::argument(int /*index*/) const
{
return engine()->undefinedValue();
}
const Value *FunctionValue::returnValue() const
{
return engine()->undefinedValue();
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// convert to number // convert to number
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@@ -295,6 +295,8 @@ public:
virtual int argumentCount() const; virtual int argumentCount() const;
virtual const Value *argument(int index) const; virtual const Value *argument(int index) const;
virtual QString argumentName(int index) const;
virtual bool isVariadic() const;
virtual const Value *invoke(const Activation *activation) const; virtual const Value *invoke(const Activation *activation) const;
@@ -444,6 +446,8 @@ public:
ObjectValue *globalObject() const; ObjectValue *globalObject() const;
const ObjectValue *mathObject() const; const ObjectValue *mathObject() const;
void registerObject(ObjectValue *object);
// prototypes // prototypes
ObjectValue *objectPrototype() const; ObjectValue *objectPrototype() const;
ObjectValue *functionPrototype() const; ObjectValue *functionPrototype() const;

View File

@@ -487,7 +487,9 @@ class FunctionArgumentWidget : public QLabel
{ {
public: public:
FunctionArgumentWidget(); FunctionArgumentWidget();
void showFunctionHint(const QString &functionName, int minimumArgumentCount, int startPosition); void showFunctionHint(const QString &functionName,
const QStringList &signature,
int startPosition);
protected: protected:
bool eventFilter(QObject *obj, QEvent *e); bool eventFilter(QObject *obj, QEvent *e);
@@ -497,6 +499,7 @@ private:
void updateHintText(); void updateHintText();
QString m_functionName; QString m_functionName;
QStringList m_signature;
int m_minimumArgumentCount; int m_minimumArgumentCount;
int m_startpos; int m_startpos;
int m_currentarg; int m_currentarg;
@@ -563,13 +566,14 @@ FunctionArgumentWidget::FunctionArgumentWidget():
qApp->installEventFilter(this); qApp->installEventFilter(this);
} }
void FunctionArgumentWidget::showFunctionHint(const QString &functionName, int mininumArgumentCount, int startPosition) void FunctionArgumentWidget::showFunctionHint(const QString &functionName, const QStringList &signature, int startPosition)
{ {
if (m_startpos == startPosition) if (m_startpos == startPosition)
return; return;
m_functionName = functionName; m_functionName = functionName;
m_minimumArgumentCount = mininumArgumentCount; m_signature = signature;
m_minimumArgumentCount = signature.size();
m_startpos = startPosition; m_startpos = startPosition;
m_current = 0; m_current = 0;
m_escapePressed = false; m_escapePressed = false;
@@ -663,7 +667,17 @@ void FunctionArgumentWidget::updateHintText()
QString prettyMethod; QString prettyMethod;
prettyMethod += QString::fromLatin1("function "); prettyMethod += QString::fromLatin1("function ");
prettyMethod += m_functionName; prettyMethod += m_functionName;
prettyMethod += QLatin1String("(arguments...)"); prettyMethod += QLatin1Char('(');
for (int i = 0; i < m_minimumArgumentCount; ++i) {
if (i != 0)
prettyMethod += QLatin1String(", ");
prettyMethod += QLatin1String("arg");
if (m_minimumArgumentCount != 1)
prettyMethod += QString::number(i + 1);
}
prettyMethod += QLatin1Char(')');
m_numberLabel->setText(prettyMethod); m_numberLabel->setText(prettyMethod);
@@ -970,7 +984,12 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
if (!m_functionArgumentWidget) if (!m_functionArgumentWidget)
m_functionArgumentWidget = new QmlJSEditor::Internal::FunctionArgumentWidget; m_functionArgumentWidget = new QmlJSEditor::Internal::FunctionArgumentWidget;
m_functionArgumentWidget->showFunctionHint(functionName.trimmed(), f->argumentCount(), QStringList signature;
for (int i = 0; i < f->argumentCount(); ++i)
signature.append(f->argumentName(i));
m_functionArgumentWidget->showFunctionHint(functionName.trimmed(),
signature,
m_startPosition); m_startPosition);
} }