Asserts for KWin scripts
Further debugging functionality for KWin scripts. Added assert methods validate the to be tested parameter and throw a script error if the value is not valid. Following methods are available: * assert(value) * assertTrue(boolean) * assertFalse(boolean) * assertEquals(expected, actual) * assertNull(nullValue) * assertNotNull(notNullValue) All methods take an additional optional parameter which is used as the error message if provided. Methods to validate the number of arguments and types of the parameters are added and throw syntax or type errors. REVIEW: 104870
This commit is contained in:
parent
c3fce865ee
commit
1f97345e35
5 changed files with 284 additions and 0 deletions
|
@ -122,6 +122,7 @@ if(KWIN_BUILD_SCRIPTING)
|
|||
scripting/workspace_wrapper.cpp
|
||||
scripting/meta.cpp
|
||||
scripting/scriptedeffect.cpp
|
||||
scripting/scriptingutils.cpp
|
||||
scripting/timer.cpp
|
||||
)
|
||||
endif(KWIN_BUILD_SCRIPTING)
|
||||
|
|
|
@ -49,6 +49,54 @@
|
|||
<read></read>
|
||||
<detaileddescription>Registers keySequence as a global shortcut. When the shortcut is invoked the callback will be called. Title and text are used to name the shortcut and make it available to the global shortcut configuration module.</detaileddescription>
|
||||
</memberdef>
|
||||
<memberdef kind="function">
|
||||
<type>Q_SCRIPTABLE bool</type>
|
||||
<definition>bool KWin::Scripting::assert</definition>
|
||||
<argsstring>(bool value, QString message = QString())</argsstring>
|
||||
<name>assert</name>
|
||||
<read></read>
|
||||
<detaileddescription>Aborts the execution of the script if value does not evaluate to true. If message is provided an error is thrown with the given message, if not provided an error with default message is thrown.</detaileddescription>
|
||||
</memberdef>
|
||||
<memberdef kind="function">
|
||||
<type>Q_SCRIPTABLE bool</type>
|
||||
<definition>bool KWin::Scripting::assertTrue</definition>
|
||||
<argsstring>(bool value, QString message = QString())</argsstring>
|
||||
<name>assertTrue</name>
|
||||
<read></read>
|
||||
<detaileddescription>Aborts the execution of the script if value does not evaluate to true. If message is provided an error is thrown with the given message, if not provided an error with default message is thrown.</detaileddescription>
|
||||
</memberdef>
|
||||
<memberdef kind="function">
|
||||
<type>Q_SCRIPTABLE bool</type>
|
||||
<definition>bool KWin::Scripting::assertFalse</definition>
|
||||
<argsstring>(bool value, QString message = QString())</argsstring>
|
||||
<name>assertFalse</name>
|
||||
<read></read>
|
||||
<detaileddescription>Aborts the execution of the script if value does not evaluate to false. If message is provided an error is thrown with the given message, if not provided an error with default message is thrown.</detaileddescription>
|
||||
</memberdef>
|
||||
<memberdef kind="function">
|
||||
<type>Q_SCRIPTABLE bool</type>
|
||||
<definition>bool KWin::Scripting::assertEquals</definition>
|
||||
<argsstring>(QVariant expected, QVariant actual, QString message = QString())</argsstring>
|
||||
<name>assertEquals</name>
|
||||
<read></read>
|
||||
<detaileddescription>Aborts the execution of the script if the actual value is not equal to the expected value. If message is provided an error is thrown with the given message, if not provided an error with default message is thrown.</detaileddescription>
|
||||
</memberdef>
|
||||
<memberdef kind="function">
|
||||
<type>Q_SCRIPTABLE bool</type>
|
||||
<definition>bool KWin::Scripting::assertNull</definition>
|
||||
<argsstring>(QVariant value, QString message = QString())</argsstring>
|
||||
<name>assertNull</name>
|
||||
<read></read>
|
||||
<detaileddescription>Aborts the execution of the script if value is not null. If message is provided an error is thrown with the given message, if not provided an error with default message is thrown.</detaileddescription>
|
||||
</memberdef>
|
||||
<memberdef kind="function">
|
||||
<type>Q_SCRIPTABLE bool</type>
|
||||
<definition>bool KWin::Scripting::assertNotNull</definition>
|
||||
<argsstring>(QVariant value, QString message = QString())</argsstring>
|
||||
<name>assertNotNull</name>
|
||||
<read></read>
|
||||
<detaileddescription>Aborts the execution of the script if value is null. If message is provided an error is thrown with the given message, if not provided an error with default message is thrown.</detaileddescription>
|
||||
</memberdef>
|
||||
</sectiondef>
|
||||
</compounddef>
|
||||
</doxygen>
|
||||
|
|
|
@ -88,6 +88,57 @@ QScriptValue kwinScriptGlobalShortcut(QScriptContext *context, QScriptEngine *en
|
|||
return KWin::globalShortcut<KWin::AbstractScript*>(context, engine);
|
||||
}
|
||||
|
||||
QScriptValue kwinAssertTrue(QScriptContext *context, QScriptEngine *engine)
|
||||
{
|
||||
return KWin::scriptingAssert<bool>(context, engine, 1, 2, true);
|
||||
}
|
||||
|
||||
QScriptValue kwinAssertFalse(QScriptContext *context, QScriptEngine *engine)
|
||||
{
|
||||
return KWin::scriptingAssert<bool>(context, engine, 1, 2, false);
|
||||
}
|
||||
|
||||
QScriptValue kwinAssertEquals(QScriptContext *context, QScriptEngine *engine)
|
||||
{
|
||||
return KWin::scriptingAssert<QVariant>(context, engine, 2, 3);
|
||||
}
|
||||
|
||||
QScriptValue kwinAssertNull(QScriptContext *context, QScriptEngine *engine)
|
||||
{
|
||||
if (!KWin::validateParameters(context, 1, 2)) {
|
||||
return engine->undefinedValue();
|
||||
}
|
||||
if (!context->argument(0).isNull()) {
|
||||
if (context->argumentCount() == 2) {
|
||||
context->throwError(QScriptContext::UnknownError, context->argument(1).toString());
|
||||
} else {
|
||||
context->throwError(QScriptContext::UnknownError,
|
||||
i18nc("Assertion failed in KWin script with given value",
|
||||
"Assertion failed: %1 is not null", context->argument(0).toString()));
|
||||
}
|
||||
return engine->undefinedValue();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QScriptValue kwinAssertNotNull(QScriptContext *context, QScriptEngine *engine)
|
||||
{
|
||||
if (!KWin::validateParameters(context, 1, 2)) {
|
||||
return engine->undefinedValue();
|
||||
}
|
||||
if (context->argument(0).isNull()) {
|
||||
if (context->argumentCount() == 2) {
|
||||
context->throwError(QScriptContext::UnknownError, context->argument(1).toString());
|
||||
} else {
|
||||
context->throwError(QScriptContext::UnknownError,
|
||||
i18nc("Assertion failed in KWin script",
|
||||
"Assertion failed: argument is null"));
|
||||
}
|
||||
return engine->undefinedValue();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
KWin::AbstractScript::AbstractScript(int id, QString scriptName, QString pluginName, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_scriptId(id)
|
||||
|
@ -144,6 +195,19 @@ void KWin::AbstractScript::installScriptFunctions(QScriptEngine* engine)
|
|||
engine->globalObject().setProperty("readConfig", configFunc);
|
||||
// add global Shortcut
|
||||
registerGlobalShortcutFunction(this, engine, kwinScriptGlobalShortcut);
|
||||
// add assertions
|
||||
QScriptValue assertTrueFunc = engine->newFunction(kwinAssertTrue);
|
||||
engine->globalObject().setProperty("assertTrue", assertTrueFunc);
|
||||
engine->globalObject().setProperty("assert", assertTrueFunc);
|
||||
QScriptValue assertFalseFunc = engine->newFunction(kwinAssertFalse);
|
||||
engine->globalObject().setProperty("assertFalse", assertFalseFunc);
|
||||
QScriptValue assertEqualsFunc = engine->newFunction(kwinAssertEquals);
|
||||
engine->globalObject().setProperty("assertEquals", assertEqualsFunc);
|
||||
QScriptValue assertNullFunc = engine->newFunction(kwinAssertNull);
|
||||
engine->globalObject().setProperty("assertNull", assertNullFunc);
|
||||
engine->globalObject().setProperty("assertEquals", assertEqualsFunc);
|
||||
QScriptValue assertNotNullFunc = engine->newFunction(kwinAssertNotNull);
|
||||
engine->globalObject().setProperty("assertNotNull", assertNotNullFunc);
|
||||
// global properties
|
||||
engine->globalObject().setProperty("KWin", engine->newQMetaObject(&WorkspaceWrapper::staticMetaObject));
|
||||
QScriptValue workspace = engine->newQObject(AbstractScript::workspace(), QScriptEngine::QtOwnership,
|
||||
|
|
46
scripting/scriptingutils.cpp
Normal file
46
scripting/scriptingutils.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
#include "scriptingutils.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
bool validateParameters(QScriptContext *context, int min, int max)
|
||||
{
|
||||
if (context->argumentCount() < min || context->argumentCount() > max) {
|
||||
context->throwError(QScriptContext::SyntaxError,
|
||||
i18nc("syntax error in KWin script", "Invalid number of arguments"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool validateArgumentType<QVariant>(QScriptContext *context, int argument)
|
||||
{
|
||||
const bool result =context->argument(argument).toVariant().isValid();
|
||||
if (!result) {
|
||||
context->throwError(QScriptContext::TypeError,
|
||||
i18nc("KWin Scripting function received incorrect value for an expected type",
|
||||
"%1 is not a variant type", context->argument(argument).toString()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -24,11 +24,80 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <KDE/KAction>
|
||||
#include <KDE/KActionCollection>
|
||||
#include <KDE/KDebug>
|
||||
#include <KDE/KLocalizedString>
|
||||
#include <QtScript/QScriptEngine>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
/**
|
||||
* Validates that argument at @p index of given @p context is of required type.
|
||||
* Throws a type error in the scripting context if there is a type mismatch.
|
||||
* @param context The scripting context in which the argument type needs to be validated.
|
||||
* @param index The argument index to validate
|
||||
* @returns @c true if the argument is of required type, @c false otherwise
|
||||
**/
|
||||
template<class T>
|
||||
bool validateArgumentType(QScriptContext *context, int index)
|
||||
{
|
||||
const bool result = context->argument(index).toVariant().canConvert<T>();
|
||||
if (!result) {
|
||||
context->throwError(QScriptContext::TypeError,
|
||||
i18nc("KWin Scripting function received incorrect value for an expected type",
|
||||
"%1 is not of required type", context->argument(index).toString()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the argument of @p context is of specified type.
|
||||
* Throws a type error in the scripting context if there is a type mismatch.
|
||||
* @param context The scripting context in which the argument type needs to be validated.
|
||||
* @returns @c true if the argument is of required type, @c false otherwise
|
||||
**/
|
||||
template<class T>
|
||||
bool validateArgumentType(QScriptContext *context)
|
||||
{
|
||||
return validateArgumentType<T>(context, 0);
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
bool validateArgumentType(QScriptContext *context)
|
||||
{
|
||||
if (!validateArgumentType<T>(context)) {
|
||||
return false;
|
||||
}
|
||||
return validateArgumentType<U>(context, 1);
|
||||
}
|
||||
|
||||
template<class T, class U, class V>
|
||||
bool validateArgumentType(QScriptContext *context)
|
||||
{
|
||||
if (!validateArgumentType<T, U>(context)) {
|
||||
return false;
|
||||
}
|
||||
return validateArgumentType<V>(context, 2);
|
||||
}
|
||||
|
||||
template<class T, class U, class V, class W>
|
||||
bool validateArgumentType(QScriptContext *context)
|
||||
{
|
||||
if (!validateArgumentType<T, U, V>(context)) {
|
||||
return false;
|
||||
}
|
||||
return validateArgumentType<W>(context, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the argument count of @p context is at least @p min and @p max.
|
||||
* Throws a syntax error in the script context if argument count mismatch.
|
||||
* @param context The ScriptContext for which the argument count needs to be validated
|
||||
* @param min The minimum number of arguments.
|
||||
* @param max The maximum number of arguments
|
||||
* @returns @c true if the argument count is correct, otherwise @c false
|
||||
**/
|
||||
bool validateParameters(QScriptContext *context, int min, int max);
|
||||
|
||||
template<class T>
|
||||
QScriptValue globalShortcut(QScriptContext *context, QScriptEngine *engine)
|
||||
{
|
||||
|
@ -63,6 +132,62 @@ void callGlobalShortcutCallback(T script, QObject *sender)
|
|||
value.call();
|
||||
};
|
||||
|
||||
template<class T>
|
||||
QScriptValue scriptingAssert(QScriptContext *context, QScriptEngine *engine, int min, int max, T defaultVal = T())
|
||||
{
|
||||
if (!validateParameters(context, min, max)) {
|
||||
return engine->undefinedValue();
|
||||
}
|
||||
switch (context->argumentCount()) {
|
||||
case 1:
|
||||
if (!validateArgumentType<T>(context)) {
|
||||
return engine->undefinedValue();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (max == 2) {
|
||||
if (!validateArgumentType<T, QString>(context)) {
|
||||
return engine->undefinedValue();
|
||||
}
|
||||
} else {
|
||||
if (!validateArgumentType<T, T>(context)) {
|
||||
return engine->undefinedValue();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (!validateArgumentType<T, T, QString>(context)) {
|
||||
return engine->undefinedValue();
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (max == 2) {
|
||||
if (context->argument(0).toVariant().value<T>() != defaultVal) {
|
||||
if (context->argumentCount() == max) {
|
||||
context->throwError(QScriptContext::UnknownError, context->argument(max - 1).toString());
|
||||
} else {
|
||||
context->throwError(QScriptContext::UnknownError,
|
||||
i18nc("Assertion failed in KWin script with given value",
|
||||
"Assertion failed: %1", context->argument(0).toString()));
|
||||
}
|
||||
return engine->undefinedValue();
|
||||
}
|
||||
} else {
|
||||
if (context->argument(0).toVariant().value<T>() != context->argument(1).toVariant().value<T>()) {
|
||||
if (context->argumentCount() == max) {
|
||||
context->throwError(QScriptContext::UnknownError, context->argument(max - 1).toString());
|
||||
} else {
|
||||
context->throwError(QScriptContext::UnknownError,
|
||||
i18nc("Assertion failed in KWin script with expected value and actual value",
|
||||
"Assertion failed: Expected %1, got %2",
|
||||
context->argument(0).toString(), context->argument(1).toString()));
|
||||
}
|
||||
return engine->undefinedValue();
|
||||
}
|
||||
}
|
||||
return engine->newVariant(true);
|
||||
}
|
||||
|
||||
inline void registerGlobalShortcutFunction(QObject *parent, QScriptEngine *engine, QScriptEngine::FunctionSignature function)
|
||||
{
|
||||
QScriptValue shortcutFunc = engine->newFunction(function);
|
||||
|
|
Loading…
Reference in a new issue