diff --git a/src/qmljsc/CMakeLists.txt b/src/qmljsc/CMakeLists.txt index 02c0d92..de6618b 100644 --- a/src/qmljsc/CMakeLists.txt +++ b/src/qmljsc/CMakeLists.txt @@ -1,33 +1,34 @@ find_package(Qt5 COMPONENTS Core Qml) set(libqmljsc_srcs compiler.cpp error.cpp compilerpipeline.cpp compilerpass.cpp ir/objecttree.cpp ir/module.cpp ir/file.cpp ir/typesystem.cpp compilerpasses/parserpass.cpp compilerpasses/prettygeneratorpass.cpp + moduleloading/moduleloading.cpp moduleloading/abstractmoduleloader.cpp moduleloading/javascriptmoduleloader.cpp - moduleloading/moduleloading.cpp + moduleloading/qtqmlmoduleloader.cpp utils/shortsymbolname.cpp ) add_library(libqmljsc SHARED ${libqmljsc_srcs}) qt5_use_modules(libqmljsc Core Qml) include_directories(${Qt5Qml_PRIVATE_INCLUDE_DIRS}) set(qmljsc_srcs main.cpp ) add_executable(qmljsc ${qmljsc_srcs}) target_link_libraries(qmljsc libqmljsc) diff --git a/src/qmljsc/moduleloading/qtqmlmoduleloader.cpp b/src/qmljsc/moduleloading/qtqmlmoduleloader.cpp new file mode 100644 index 0000000..790f3c5 --- /dev/null +++ b/src/qmljsc/moduleloading/qtqmlmoduleloader.cpp @@ -0,0 +1,174 @@ +/* + * Qml.js Compiler - a QML to JS compiler bringing QML's power to the web. + * + * Copyright (C) 2015 Anton Kreuzkamp + * + * 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 3 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 . + * + */ + +// Own +#include "qtqmlmoduleloader.h" +#include "ir/typesystem.h" +#include "ir/module.h" +#include "error.h" + +using namespace QmlJSc; + +QtQmlModuleLoader *QtQmlModuleLoader::create(IR::Module *module) +{ + return new QtQmlModuleLoader(module); +} + +QtQmlModuleLoader::QtQmlModuleLoader(IR::Module *module) + : AbstractModuleLoader(module) +{} + +bool QmlJSc::QtQmlModuleLoader::canLoad() +{ + return module()->importDescription().name == "QtQml"; +} + +void QtQmlModuleLoader::doLoad() +{ + IR::Module *module = AbstractModuleLoader::module(); + + IR::Property *p = 0; + IR::Method *m = 0; + IR::Signal *s = 0; + + // Basic types + IR::Type *boolType = new IR::Type; + boolType->setName("bool"); + boolType->setJavaScriptName("Boolean"); + module->addType(boolType); + + IR::Type *doubleType = new IR::Type; + doubleType->setName("double"); + doubleType->setJavaScriptName("QWDouble"); + module->addType(doubleType); + + IR::Type *enumType = new IR::Type; + enumType->setName("enum"); + enumType->setJavaScriptName("QWEnum"); + module->addType(enumType); + + IR::Type *intType = new IR::Type; + intType->setName("int"); + intType->setJavaScriptName("QWInt"); + module->addType(intType); + + IR::Type *listType = new IR::Type; + listType->setName("list"); + listType->setJavaScriptName("QWList"); + // TODO: Add list-flag (Requires T504) + module->addType(listType); + + IR::Type *realType = new IR::Type; + realType->setName("real"); + realType->setJavaScriptName("QWReal"); + module->addType(realType); + + IR::Type *stringType = new IR::Type; + stringType->setName("string"); + stringType->setJavaScriptName("String"); + module->addType(stringType); + + IR::Type *urlType = new IR::Type; + urlType->setName("url"); + urlType->setJavaScriptName("QWUrl"); + module->addType(urlType); + + IR::Type *varType = new IR::Type; + varType->setName("var"); + varType->setJavaScriptName("QWVar"); + module->addType(varType); + + // === Classes === + + // Component + IR::Type *componentClass = new IR::Type( IR::Type::Flags(IR::Type::IsInstantiable | IR::Type::IsComponent) ); + componentClass->setName("Component"); + componentClass->setJavaScriptName("QWComponent"); + p = componentClass->addProperty("progress"); + p->type = realType; + p = componentClass->addProperty("status"); + p->type = enumType; + p = componentClass->addProperty("url"); + p->type = urlType; + m = componentClass->addMethod("createObject"); + m->parameters.append("parent"); + m->parameters.append("properties"); + m = componentClass->addMethod("errorString"); + m = componentClass->addMethod("incubateObject"); + m->parameters.append("parent"); + m->parameters.append("properties"); + m->parameters.append("mode"); + + IR::Type *componentAttached = new IR::Type(IR::Type::IsInstantiable); + componentAttached->addSignal("completed"); + componentAttached->addSignal("destruction"); + componentClass->setAttachedType(componentAttached); + module->addType(componentClass); + + // QtObject + IR::Type *qtobjectClass = new IR::Type(IR::Type::IsInstantiable); + qtobjectClass->setName("QtObject"); + qtobjectClass->setJavaScriptName("QWObject"); + p = qtobjectClass->addProperty("objectName"); + p->type = stringType; + module->addType(qtobjectClass); + + // Binding + IR::Type *bindingClass = new IR::Type(IR::Type::IsInstantiable); + bindingClass->setName("Binding"); + p = bindingClass->addProperty("property"); + p->type = stringType; + p = bindingClass->addProperty("target"); + p->type = qtobjectClass; + p = bindingClass->addProperty("value"); + p->type = varType; + p = bindingClass->addProperty("when"); + p->type = boolType; + module->addType(bindingClass); + + // Connections + IR::Type *connectionsClass = new IR::Type(IR::Type::IsInstantiable); + connectionsClass->setName("Connections"); + p = connectionsClass->addProperty("ignoreUnknownSignals"); + p->type = boolType; + p = connectionsClass->addProperty("target"); + p->type = qtobjectClass; + module->addType(connectionsClass); + + // Timer + IR::Type *timerClass = new IR::Type(IR::Type::IsInstantiable); + timerClass->setName("Timer"); + p = timerClass->addProperty("interval"); + p->type = intType; + p = timerClass->addProperty("repeat"); + p->type = boolType; + p = timerClass->addProperty("running"); + p->type = boolType; + p = timerClass->addProperty("triggeredOnStart"); + p->type = boolType; + timerClass->addSignal("triggered"); + timerClass->addMethod("restart"); + timerClass->addMethod("start"); + timerClass->addMethod("stop"); + module->addType(timerClass); + + module->setLoadingState(IR::Module::Successful); +} + diff --git a/src/qmljsc/moduleloading/qtqmlmoduleloader.h b/src/qmljsc/moduleloading/qtqmlmoduleloader.h new file mode 100644 index 0000000..c47fe54 --- /dev/null +++ b/src/qmljsc/moduleloading/qtqmlmoduleloader.h @@ -0,0 +1,54 @@ +/* + * Qml.js Compiler - a QML to JS compiler bringing QML's power to the web. + * + * Copyright (C) 2015 Anton Kreuzkamp + * + * 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 3 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 . + * + */ + +#ifndef QTQMLMODULELOADER_H +#define QTQMLMODULELOADER_H + +#include "abstractmoduleloader.h" + +//Qt +#include + +namespace QmlJSc { + +namespace IR { + class Module; +} + +/** + * This class creates the QtQml module, including all the basic types that exist + * in QML and ECMAScript. Especially as there's no module for the ECMAScript + * API, we have an extra loader class for it. + */ +class QtQmlModuleLoader : public AbstractModuleLoader +{ +public: + static QtQmlModuleLoader *create(IR::Module *module); + + bool canLoad() override; + void doLoad() override; + +private: + QtQmlModuleLoader(IR::Module *module); +}; + +} // namespace QMLJSc + +#endif // QTQMLMODULELOADER_H diff --git a/tests/auto/qmljsc/testmodules.cpp b/tests/auto/qmljsc/testmodules.cpp index 312404e..f474d31 100644 --- a/tests/auto/qmljsc/testmodules.cpp +++ b/tests/auto/qmljsc/testmodules.cpp @@ -1,259 +1,394 @@ /* * Qml.js Compiler - a QML to JS compiler bringing QML's power to the web. * * Copyright (C) 2015 Anton Kreuzkamp * * 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 3 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 . * */ // Qt #include #include #include #include // Qt private #include // own #include "../../../src/qmljsc/compiler.h" #include "../../../src/qmljsc/moduleloading/moduleloading.h" #include "../../../src/qmljsc/moduleloading/javascriptmoduleloader.h" +#include "../../../src/qmljsc/moduleloading/qtqmlmoduleloader.h" #include "../../../src/qmljsc/ir/module.h" class TestModules : public QObject { Q_OBJECT private slots: + void initTestCase(); void loadMinimalModule(); + void loadQtQml(); void loadModule(); void testShortSymbolName(); }; using namespace QmlJSc; using namespace QmlJSc::IR; using namespace QQmlJS; -void TestModules::loadMinimalModule() +void TestModules::initTestCase() { - Compiler comp; + new Compiler; + compiler->addIncludePath(":/test/"); + ModuleLoading::registerModuleLoader(&JavaScriptModuleLoader::create); + ModuleLoading::registerModuleLoader(&QtQmlModuleLoader::create); +} +void TestModules::loadMinimalModule() +{ const ImportDescription testImportDescription = {ImportDescription::Kind_ModuleImport, "MinimalModule", 0, 1}; - compiler->addIncludePath(":/test/"); IR::Module *module = ModuleLoading::loadModule(testImportDescription); module->waitForLoaded(); Type *a = module->type("A"); Type *b = module->type("B"); Type *c = module->type("C"); Type *d = module->type("D"); Type *e = module->type("E"); QCOMPARE((int)module->loadingState(), (int)Module::Successful); QVERIFY(a); QVERIFY(b); QVERIFY(c); QVERIFY(d); QVERIFY(!e); QCOMPARE(a->name(), QStringLiteral("A")); QCOMPARE(b->name(), QStringLiteral("B")); QCOMPARE(c->name(), QStringLiteral("C")); QCOMPARE(d->name(), QStringLiteral("D")); QVERIFY(b->property("minimalProp")); QVERIFY(c->property("otherPropWithType")); QVERIFY(c->property("yaPropWithType")); QVERIFY(d->property("readonlyProp")); QVERIFY(d->property("otherPropWithType")); QVERIFY(!d->property("yaPropWithType")); IR::Property *readonlyProp = d->property("readonlyProp"); QVERIFY(readonlyProp); QCOMPARE(readonlyProp->type, d); QCOMPARE(readonlyProp->readOnly, true); IR::Method *prototypeMethod = b->method("prototypeMethod"); QVERIFY(prototypeMethod); QCOMPARE(prototypeMethod->name, QStringLiteral("prototypeMethod")); IR::Method *bPrototypeMethod = b->method("prototypeMethod"); QVERIFY(bPrototypeMethod); QCOMPARE(bPrototypeMethod->parameters.size(), 0); IR::Method *bPrototypeMethod2 = b->method("prototypeMethod2"); QVERIFY(bPrototypeMethod2); QCOMPARE(bPrototypeMethod2->parameters.size(), 1); QCOMPARE(bPrototypeMethod2->parameters[0], QStringLiteral("prop")); IR::Method *bConstructorMethod = b->method("constructorMethod"); QVERIFY(bConstructorMethod); QCOMPARE(bConstructorMethod->parameters.size(), 2); QCOMPARE(bConstructorMethod->parameters[0], QStringLiteral("prop1")); QCOMPARE(bConstructorMethod->parameters[1], QStringLiteral("prop2")); QVERIFY(c->method("prototypeMethod")); QVERIFY(c->method("constructorMethod")); QVERIFY(d->method("prototypeMethod")); QVERIFY(d->method("constructorMethod")); IR::Signal *someSignal = d->signal("someSignal"); QVERIFY(someSignal); QCOMPARE(someSignal->parameters.size(), 0); IR::Signal *anotherSignal = d->signal("anotherSignal"); QVERIFY(anotherSignal); QCOMPARE(anotherSignal->parameters.size(), 2); QCOMPARE(anotherSignal->parameters[0].name, QStringLiteral("arg1")); QCOMPARE(anotherSignal->parameters[0].type, a); QCOMPARE(anotherSignal->parameters[1].name, QStringLiteral("arg2")); QCOMPARE(anotherSignal->parameters[1].type, a); } +void TestModules::loadQtQml() +{ + const ImportDescription qtqmlImportDescription = {ImportDescription::Kind_ModuleImport, "QtQml", 1, 0}; + IR::Module *qtqmlModule = ModuleLoading::loadModule(qtqmlImportDescription); + qtqmlModule->waitForLoaded(); + + IR::Property *p = 0; + IR::Method *m = 0; + IR::Signal *s = 0; + + Type *boolType = qtqmlModule->type("bool"); + QVERIFY(boolType); + QCOMPARE(qtqmlModule->typeFromJSName("Boolean"), boolType); + + Type *doubleType = qtqmlModule->type("double"); + QVERIFY(doubleType); + QCOMPARE(qtqmlModule->typeFromJSName("QWDouble"), doubleType); + + Type *enumType = qtqmlModule->type("enum"); + QVERIFY(enumType); + QCOMPARE(qtqmlModule->typeFromJSName("QWEnum"), enumType); + + Type *intType = qtqmlModule->type("int"); + QVERIFY(intType); + QCOMPARE(qtqmlModule->typeFromJSName("QWInt"), intType); + + Type *listType = qtqmlModule->type("list"); + QVERIFY(listType); + QCOMPARE(qtqmlModule->typeFromJSName("QWList"), listType); + + Type *realType = qtqmlModule->type("real"); + QVERIFY(realType); + QCOMPARE(qtqmlModule->typeFromJSName("QWReal"), realType); + + Type *stringType = qtqmlModule->type("string"); + QVERIFY(stringType); + QCOMPARE(qtqmlModule->typeFromJSName("String"), stringType); + + Type *urlType = qtqmlModule->type("url"); + QVERIFY(urlType); + QCOMPARE(qtqmlModule->typeFromJSName("QWUrl"), urlType); + + Type *varType = qtqmlModule->type("var"); + QVERIFY(varType); + QCOMPARE(qtqmlModule->typeFromJSName("QWVar"), varType); + + Type *componentClass = qtqmlModule->type("Component"); + QVERIFY(componentClass); + QCOMPARE(qtqmlModule->typeFromJSName("QWComponent"), componentClass); + QVERIFY(componentClass->flags() & IR::Type::IsComponent); + QVERIFY(p = componentClass->property("progress")); + QCOMPARE(p->type, realType); + QVERIFY(p = componentClass->property("status")); + QCOMPARE(p->type, enumType); + QVERIFY(p = componentClass->property("url")); + QCOMPARE(p->type, urlType); + QVERIFY(!componentClass->property("heyo")); + QVERIFY(!componentClass->method("heyo")); + QVERIFY(m = componentClass->method("createObject")); + QCOMPARE(m->parameters.count(), 2); + QCOMPARE(m->parameters.at(0), QStringLiteral("parent")); + QCOMPARE(m->parameters.at(1), QStringLiteral("properties")); + QVERIFY(m = componentClass->method("errorString")); + QCOMPARE(m->parameters.count(), 0); + QVERIFY(m = componentClass->method("incubateObject")); + QCOMPARE(m->parameters.count(), 3); + QCOMPARE(m->parameters.at(0), QStringLiteral("parent")); + QCOMPARE(m->parameters.at(1), QStringLiteral("properties")); + QCOMPARE(m->parameters.at(2), QStringLiteral("mode")); + Type *componentAttached = componentClass->attachedType(); + QVERIFY(componentAttached); + QVERIFY(s = componentAttached->signal("completed")); + QCOMPARE(s->parameters.count(), 0); + QVERIFY(!componentAttached->property("completed")); + QVERIFY(!componentAttached->method("completed")); + QVERIFY(s = componentAttached->signal("destruction")); + QCOMPARE(s->parameters.count(), 0); + + Type *qtobjectClass = qtqmlModule->type("QtObject"); + QVERIFY(qtobjectClass); + QCOMPARE(qtqmlModule->typeFromJSName("QWObject"), qtobjectClass); + QVERIFY(p = qtobjectClass->property("objectName")); + QCOMPARE(p->type, stringType); + + Type *bindingClass = qtqmlModule->type("Binding"); + QVERIFY(bindingClass); + QVERIFY(p = bindingClass->property("property")); + QCOMPARE(p->type, stringType); + QVERIFY(p = bindingClass->property("target")); + QCOMPARE(p->type, qtobjectClass); + QVERIFY(p = bindingClass->property("value")); + QCOMPARE(p->type, varType); + QVERIFY(p = bindingClass->property("when")); + QCOMPARE(p->type, boolType); + + + Type *connectionsClass = qtqmlModule->type("Connections"); + QVERIFY(connectionsClass); + QVERIFY(p = connectionsClass->property("ignoreUnknownSignals")); + QCOMPARE(p->type, boolType); + QVERIFY(p = connectionsClass->property("target")); + QCOMPARE(p->type, qtobjectClass); + + + Type *timerClass = qtqmlModule->type("Timer"); + QVERIFY(timerClass); + QVERIFY(p = timerClass->property("interval")); + QCOMPARE(p->type, intType); + QVERIFY(p = timerClass->property("repeat")); + QCOMPARE(p->type, boolType); + QVERIFY(p = timerClass->property("running")); + QCOMPARE(p->type, boolType); + QVERIFY(p = timerClass->property("triggeredOnStart")); + QCOMPARE(p->type, boolType); + QVERIFY(timerClass->method("restart")); + QVERIFY(timerClass->method("start")); + QVERIFY(timerClass->method("stop")); + QVERIFY(s = timerClass->signal("triggered")); + QCOMPARE(s->parameters.count(), 0); +} + void TestModules::loadModule() { QSKIP("This will be implemented later (Task T488)."); - Compiler c; - + const ImportDescription qtqmlImportDescription = {ImportDescription::Kind_ModuleImport, "QtQml", 1, 0}; const ImportDescription testImportDescription = {ImportDescription::Kind_ModuleImport, "TestModule", 0, 1}; - compiler->addIncludePath(":/test/"); IR::Module *module = ModuleLoading::loadModule(testImportDescription); + IR::Module *qtqmlModule = ModuleLoading::loadModule(qtqmlImportDescription); module->waitForLoaded(); + qtqmlModule->waitForLoaded(); Type *pastry = module->type("Pastry"); Type *cake = module->type("Cake"); Type *pizza = module->type("Pizza"); Type *printer = module->type("Printer"); QVERIFY(module->loadingState() == Module::Successful); QVERIFY(pastry); QVERIFY(cake); QVERIFY(pizza); QVERIFY(!printer); QCOMPARE(pastry->name(), QStringLiteral("Pastry")); QCOMPARE(cake->name(), QStringLiteral("Cake")); QCOMPARE(pizza->name(), QStringLiteral("Pizza")); - QVERIFY(pastry->property("bakingTime")); - QVERIFY(cake->property("containsRawEgg")); - QVERIFY(cake->property("bakingTime")); - QVERIFY(pizza->property("isCalzone")); - QVERIFY(pizza->property("topping")); + IR::Property *p = 0; + QVERIFY(p = pastry->property("bakingTime")); + QCOMPARE(p->type, qtqmlModule->type("int")); + QVERIFY(p = cake->property("containsRawEgg")); + QCOMPARE(p->type, qtqmlModule->type("bool")); + QVERIFY(p = cake->property("bakingTime")); + QCOMPARE(p->type, qtqmlModule->type("int")); + QVERIFY(p = pizza->property("isCalzone")); + QCOMPARE(p->type, qtqmlModule->type("bool")); + QVERIFY(p = pizza->property("topping")); + QCOMPARE(p->type, qtqmlModule->type("var")); QVERIFY(!pizza->property("containsRawEgg")); IR::Property *baked = pizza->property("baked"); QVERIFY(baked); QCOMPARE(baked->readOnly, true); QVERIFY(pastry->method("eat")); QVERIFY(pastry->method("bake")); QVERIFY(pizza->method("eat")); QVERIFY(pizza->method("bake")); QVERIFY(pizza->signal("bakingFinished")); } void TestModules::testShortSymbolName() { ShortSymbolName nA('A'); ShortSymbolName nB('B'); ShortSymbolName nZ('Z'); ShortSymbolName na('a'); ShortSymbolName nb('b'); ShortSymbolName nz('z'); ShortSymbolName nA0("A0"); ShortSymbolName nA1("A1"); ShortSymbolName nA9("A9"); ShortSymbolName nAA("AA"); ShortSymbolName nAB("AB"); ShortSymbolName nAZ("AZ"); ShortSymbolName nAa("Aa"); ShortSymbolName nAb("Ab"); ShortSymbolName nAz("Az"); ShortSymbolName na0("a0"); ShortSymbolName na1("a1"); ShortSymbolName na9("a9"); ShortSymbolName naA("aA"); ShortSymbolName naB("aB"); ShortSymbolName naZ("aZ"); ShortSymbolName naa("aa"); ShortSymbolName nab("ab"); ShortSymbolName naz("az"); ShortSymbolName nZ9("Z9"); ShortSymbolName nZZ("ZZ"); ShortSymbolName nZz("Zz"); ShortSymbolName nz9("z9"); ShortSymbolName nzZ("zZ"); ShortSymbolName nzz("zz"); ShortSymbolName nA5dh("A5dh"); ShortSymbolName nA5dz("A5dz"); ShortSymbolName nA5zz("A5zz"); ShortSymbolName nAzzz("Azzz"); ShortSymbolName nZzzz("Zzzz"); ShortSymbolName nzzzz("zzzz"); QCOMPARE(static_cast(++nA), QStringLiteral("B")); QCOMPARE(static_cast(++nB), QStringLiteral("C")); QCOMPARE(static_cast(++nZ), QStringLiteral("A0")); QCOMPARE(static_cast(++na), QStringLiteral("b")); QCOMPARE(static_cast(++nb), QStringLiteral("c")); QCOMPARE(static_cast(++nz), QStringLiteral("a0")); QCOMPARE(static_cast(++nA0), QStringLiteral("A1")); QCOMPARE(static_cast(++nA1), QStringLiteral("A2")); QCOMPARE(static_cast(++nA9), QStringLiteral("AA")); QCOMPARE(static_cast(++nAA), QStringLiteral("AB")); QCOMPARE(static_cast(++nAB), QStringLiteral("AC")); QCOMPARE(static_cast(++nAZ), QStringLiteral("Aa")); QCOMPARE(static_cast(++nAa), QStringLiteral("Ab")); QCOMPARE(static_cast(++nAb), QStringLiteral("Ac")); QCOMPARE(static_cast(++nAz), QStringLiteral("B0")); QCOMPARE(static_cast(++na0), QStringLiteral("a1")); QCOMPARE(static_cast(++na1), QStringLiteral("a2")); QCOMPARE(static_cast(++na9), QStringLiteral("aA")); QCOMPARE(static_cast(++naA), QStringLiteral("aB")); QCOMPARE(static_cast(++naB), QStringLiteral("aC")); QCOMPARE(static_cast(++naZ), QStringLiteral("aa")); QCOMPARE(static_cast(++naa), QStringLiteral("ab")); QCOMPARE(static_cast(++nab), QStringLiteral("ac")); QCOMPARE(static_cast(++naz), QStringLiteral("b0")); QCOMPARE(static_cast(++nZ9), QStringLiteral("ZA")); QCOMPARE(static_cast(++nZZ), QStringLiteral("Za")); QCOMPARE(static_cast(++nZz), QStringLiteral("A00")); QCOMPARE(static_cast(++nz9), QStringLiteral("zA")); QCOMPARE(static_cast(++nzZ), QStringLiteral("za")); QCOMPARE(static_cast(++nzz), QStringLiteral("a00")); QCOMPARE(static_cast(++nA5dh), QStringLiteral("A5di")); QCOMPARE(static_cast(++nA5dz), QStringLiteral("A5e0")); QCOMPARE(static_cast(++nA5zz), QStringLiteral("A600")); QCOMPARE(static_cast(++nAzzz), QStringLiteral("B000")); QCOMPARE(static_cast(++nZzzz), QStringLiteral("A0000")); QCOMPARE(static_cast(++nzzzz), QStringLiteral("a0000")); } QTEST_MAIN(TestModules) #include "testmodules.moc"