diff --git a/src/qmljsc/CMakeLists.txt b/src/qmljsc/CMakeLists.txt index ac4f877..a1c015c 100644 --- a/src/qmljsc/CMakeLists.txt +++ b/src/qmljsc/CMakeLists.txt @@ -1,28 +1,29 @@ find_package(Qt5 COMPONENTS Core Qml) set(libqmljsc_srcs compiler.cpp error.h - parserstage.cpp - pipeline.cpp - pipelinestage.cpp - prettygeneratorstage.cpp + compilerpipeline.cpp + compilerpass.cpp symboltable.cpp ir/symbol.cpp ir/type.cpp ir/class.cpp ir/object.cpp ir/component.cpp + + compilerpasses/parserpass.cpp + compilerpasses/prettygeneratorpass.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/compiler.cpp b/src/qmljsc/compiler.cpp index 050c189..d85facf 100644 --- a/src/qmljsc/compiler.cpp +++ b/src/qmljsc/compiler.cpp @@ -1,39 +1,38 @@ /* * * Copyright (C) 2015 Jan Marker * * 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 . * */ #include "symboltable.h" #include "compiler.h" using namespace QmlJSc; QmlJSc::Compiler* QmlJSc::Compiler::s_self = 0; QmlJSc::Compiler::Compiler(QObject *parent) : QObject(parent) - , m_symbols(new SymbolTable(this)) { Q_ASSERT_X(!s_self, "QmlJSc::QmlJSc", "QmlJSc should only exist once."); s_self = this; } QmlJSc::Compiler::~Compiler() { s_self = 0; } diff --git a/src/qmljsc/compiler.h b/src/qmljsc/compiler.h index be5628d..828679c 100644 --- a/src/qmljsc/compiler.h +++ b/src/qmljsc/compiler.h @@ -1,50 +1,48 @@ /* * * Copyright (C) 2015 Jan Marker * 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 QMLJSC_H #define QMLJSC_H #include namespace QmlJSc { class SymbolTable; #define compiler QmlJSc::Compiler::instance() class Compiler : public QObject { Q_OBJECT public: explicit Compiler(QObject *parent = 0); virtual ~Compiler(); static Compiler* instance() { return s_self; } - SymbolTable* symbols() { return m_symbols; } private: static Compiler* s_self; - SymbolTable* m_symbols; }; } #endif // QMLJSC_H diff --git a/src/qmljsc/pipelinestage.cpp b/src/qmljsc/compilerpass.cpp similarity index 52% rename from src/qmljsc/pipelinestage.cpp rename to src/qmljsc/compilerpass.cpp index 929c96b..61fef06 100644 --- a/src/qmljsc/pipelinestage.cpp +++ b/src/qmljsc/compilerpass.cpp @@ -1,39 +1,47 @@ /* * Copyright (C) 2015 Jan Marker * * 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 . * */ -#include "pipelinestage.h" +#include "compilerpipeline.h" + +#include "compilerpass.h" using namespace QmlJSc; -PipelineStage::PipelineStage(): QObject() +CompilerPass::CompilerPass(QObject *parent): QObject(parent) { } -void PipelineStage::setPipeline(Pipeline* pipeline) { - m_pipeline = pipeline; +void CompilerPass::connectToSuccessor(CompilerPass *successor) { + connect(this, SIGNAL(finished(QString)), successor, SLOT(process(QString))); + connect(this, SIGNAL(finished(QQmlJS::AST::UiProgram*)), successor, SLOT(process(QQmlJS::AST::UiProgram*))); +} + + +void CompilerPass::process(QString) { + failBecauseOfWrongType(); } -Pipeline* PipelineStage::pipeline() { - return m_pipeline; +void CompilerPass::process(QQmlJS::AST::UiProgram*) { + failBecauseOfWrongType(); } -void PipelineStage::failBecauseOfWrongType() { - Q_STATIC_ASSERT_X(1, "The type is not supported by this stage, is the stage order correct?"); +void CompilerPass::failBecauseOfWrongType() { + Q_STATIC_ASSERT_X(1, "The type is not supported by this compiler pass, is the compiler pass order correct?"); } diff --git a/src/qmljsc/pipelinestage.h b/src/qmljsc/compilerpass.h similarity index 66% rename from src/qmljsc/pipelinestage.h rename to src/qmljsc/compilerpass.h index 88b8f33..a220539 100644 --- a/src/qmljsc/pipelinestage.h +++ b/src/qmljsc/compilerpass.h @@ -1,67 +1,58 @@ /* * Copyright (C) 2015 Jan Marker * * 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 PIPELINESTAGE_H #define PIPELINESTAGE_H #include #include #include "error.h" #include Q_DECLARE_METATYPE(QQmlJS::AST::UiProgram*) namespace QmlJSc { -class Pipeline; +class CompilerPipeline; -class PipelineStage : public QObject +class CompilerPass : public QObject { Q_OBJECT public: - PipelineStage(); + CompilerPass(QObject *parent = 0); - void setPipeline(Pipeline* pipeline); - Pipeline* pipeline(void); - - void connectToSuccessor(PipelineStage *successor) { - connect(this, SIGNAL(finished(QString)), successor, SLOT(process(QString))); - connect(this, SIGNAL(finished(QQmlJS::AST::UiProgram*)), successor, SLOT(process(QQmlJS::AST::UiProgram*))); - } + void connectToSuccessor(CompilerPass *successor); public slots: - virtual void process(QString) { failBecauseOfWrongType(); }; - virtual void process(QQmlJS::AST::UiProgram*) { failBecauseOfWrongType(); }; + virtual void process(QString); + virtual void process(QQmlJS::AST::UiProgram*); signals: void finished(QString); void finished(QQmlJS::AST::UiProgram*); private: void failBecauseOfWrongType(); - -private: - Pipeline* m_pipeline; }; } #endif // PIPELINESTAGE_H diff --git a/src/qmljsc/parserstage.cpp b/src/qmljsc/compilerpasses/parserpass.cpp similarity index 91% rename from src/qmljsc/parserstage.cpp rename to src/qmljsc/compilerpasses/parserpass.cpp index f081f3c..f98e164 100644 --- a/src/qmljsc/parserstage.cpp +++ b/src/qmljsc/compilerpasses/parserpass.cpp @@ -1,50 +1,50 @@ /* * Copyright (C) 2015 Jan Marker * * 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 . * */ -#include "parserstage.h" +#include "parserpass.h" using namespace QmlJSc; -ParserStage::ParserStage() +ParserPass::ParserPass() { } -ParserStage::~ParserStage() +ParserPass::~ParserPass() { } -void ParserStage::process(QString input) +void ParserPass::process(QString input) { QQmlJS::Engine* engine = new QQmlJS::Engine(); QQmlJS::Lexer* lexer = new QQmlJS::Lexer(engine); lexer->setCode(input, 1, true); QQmlJS::Parser* parser = new QQmlJS::Parser(engine); bool successfullyParsed = parser->parse(); if (!successfullyParsed) { Error error(Error::ParseError, parser->errorMessage()); error.setColumn(parser->errorColumnNumber()); error.setLine(parser->errorLineNumber()); throw error; } emit finished(parser->ast()); } diff --git a/src/qmljsc/parserstage.h b/src/qmljsc/compilerpasses/parserpass.h similarity index 90% rename from src/qmljsc/parserstage.h rename to src/qmljsc/compilerpasses/parserpass.h index 5d35f0c..9e5692a 100644 --- a/src/qmljsc/parserstage.h +++ b/src/qmljsc/compilerpasses/parserpass.h @@ -1,48 +1,48 @@ /* * Copyright (C) 2015 Jan Marker * * 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 PARSER_H #define PARSER_H #include #include #include #include -#include "pipelinestage.h" +#include "../compilerpass.h" namespace QmlJSc { -class ParserStage : public PipelineStage +class ParserPass : public CompilerPass { Q_OBJECT public: - ParserStage(); - ~ParserStage(); + ParserPass(); + ~ParserPass(); public slots: void process(QString input) override; }; } #endif // PARSER_H diff --git a/src/qmljsc/prettygeneratorstage.cpp b/src/qmljsc/compilerpasses/prettygeneratorpass.cpp similarity index 74% rename from src/qmljsc/prettygeneratorstage.cpp rename to src/qmljsc/compilerpasses/prettygeneratorpass.cpp index 4ba3189..44fa5c2 100644 --- a/src/qmljsc/prettygeneratorstage.cpp +++ b/src/qmljsc/compilerpasses/prettygeneratorpass.cpp @@ -1,96 +1,99 @@ /* * Copyright (C) 2015 Jan Marker * * 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 . * */ #include #include "compiler.h" +#include "compilerpipeline.h" -#include "prettygeneratorstage.h" +#include "prettygeneratorpass.h" #include "symboltable.h" using namespace QmlJSc; const QString RUNTIME_INHERIT = QStringLiteral("QW_INHERIT"); const QString RUNTIME_CONTEXT = QStringLiteral("QWContext"); const QString TEMPLATE_COMPONENT_HEAD = QStringLiteral( "%1(%2, %3);\n" \ "function %2(parent) {\n" \ " %3.call(this, parent);\n" \ " var __ = new %4(this);\n" \ ); const QString TEMPLATE_COMPONENT_FOOT = QStringLiteral( "\n\n" \ "%1;" ); -PrettyGeneratorStage::PrettyGeneratorStage() : m_output() +PrettyGeneratorPass::PrettyGeneratorPass(SymbolTable* symbolTable) + : m_symbols(symbolTable) + , m_output() { m_componentRoot = false; m_output.setString(new QString()); } -void PrettyGeneratorStage::process(QQmlJS::AST::UiProgram* ast) +void PrettyGeneratorPass::process(QQmlJS::AST::UiProgram* ast) { Q_ASSERT(ast); ast->accept(this); } -bool PrettyGeneratorStage::visit(QQmlJS::AST::UiProgram* uiProgram) +bool PrettyGeneratorPass::visit(QQmlJS::AST::UiProgram* uiProgram) { m_componentRoot = true; return true; } -bool PrettyGeneratorStage::visit(QQmlJS::AST::UiObjectDefinition* objectDefinition) +bool PrettyGeneratorPass::visit(QQmlJS::AST::UiObjectDefinition* objectDefinition) { if (m_componentRoot) { const QString objectIdentifier = objectDefinition->qualifiedTypeNameId->name.toString(); - const QString objectFqi = compiler->symbols()->findType(ModuleImports(), objectIdentifier); + const QString objectFqi = m_symbols->findType(ModuleImports(), objectIdentifier); m_output << TEMPLATE_COMPONENT_HEAD.arg(RUNTIME_INHERIT) .arg("__comp") .arg(objectFqi) .arg(RUNTIME_CONTEXT); m_componentRoot = false; } return true; } -void PrettyGeneratorStage::endVisit(QQmlJS::AST::UiProgram* uiProgram) +void PrettyGeneratorPass::endVisit(QQmlJS::AST::UiProgram* uiProgram) { m_output << TEMPLATE_COMPONENT_FOOT.arg("__comp"); } -void PrettyGeneratorStage::endVisit(QQmlJS::AST::UiObjectDefinition* objectDefinition) +void PrettyGeneratorPass::endVisit(QQmlJS::AST::UiObjectDefinition* objectDefinition) { m_output << '}'; } -void PrettyGeneratorStage::postVisit(QQmlJS::AST::Node* node) +void PrettyGeneratorPass::postVisit(QQmlJS::AST::Node* node) { if (node->kind == QQmlJS::AST::Node::Kind_UiProgram) { m_output.flush(); emit finished(*(m_output.string())); } } diff --git a/src/qmljsc/prettygeneratorstage.h b/src/qmljsc/compilerpasses/prettygeneratorpass.h similarity index 87% rename from src/qmljsc/prettygeneratorstage.h rename to src/qmljsc/compilerpasses/prettygeneratorpass.h index 0948260..9a6145d 100644 --- a/src/qmljsc/prettygeneratorstage.h +++ b/src/qmljsc/compilerpasses/prettygeneratorpass.h @@ -1,57 +1,61 @@ /* * Copyright (C) 2015 Jan Marker * * 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 PRETTYGENERATORSTAGE_H #define PRETTYGENERATORSTAGE_H #include #include -#include "pipelinestage.h" +#include "../symboltable.h" + +#include "../compilerpass.h" namespace QmlJSc { -class PrettyGeneratorStage : public PipelineStage, public QQmlJS::AST::Visitor +class PrettyGeneratorPass : public CompilerPass, public QQmlJS::AST::Visitor { Q_OBJECT public: - PrettyGeneratorStage(); + PrettyGeneratorPass(SymbolTable*); bool visit(QQmlJS::AST::UiProgram*) override; bool visit(QQmlJS::AST::UiObjectDefinition*) override; void endVisit(QQmlJS::AST::UiProgram*) override; void endVisit(QQmlJS::AST::UiObjectDefinition*) override; void postVisit(QQmlJS::AST::Node*) override; public slots: void process(QQmlJS::AST::UiProgram*) override; private: int m_levelSpaceCount = 4; QTextStream m_output; bool m_componentRoot; + SymbolTable* m_symbols; + }; } #endif // PRETTYGENERATORSTAGE_H diff --git a/src/qmljsc/pipeline.cpp b/src/qmljsc/compilerpipeline.cpp similarity index 61% rename from src/qmljsc/pipeline.cpp rename to src/qmljsc/compilerpipeline.cpp index 4f2e9a0..e2c542e 100644 --- a/src/qmljsc/pipeline.cpp +++ b/src/qmljsc/compilerpipeline.cpp @@ -1,78 +1,79 @@ /* * Copyright (C) 2015 Jan Marker * * 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 . * */ #include -#include "pipelinestage.h" +#include "compilerpass.h" -#include "pipeline.h" +#include "compilerpipeline.h" using namespace QmlJSc; -Pipeline::Pipeline() +CompilerPipeline::CompilerPipeline(QObject *parent) + : QObject(parent) { } -Pipeline::~Pipeline() +CompilerPipeline::~CompilerPipeline() { - } -QUrl Pipeline::file() const +QUrl CompilerPipeline::file() const { return m_file; } -void Pipeline::compile(QString& filePath) +void CompilerPipeline::compile(QString& filePath) { m_file = filePath; QFile file(m_file); bool openSuccessful = file.open(QFile::ReadOnly); if (!openSuccessful) { Error error(Error::ReadFileError, file.errorString()); error.setFile(file.fileName()); throw error; } QTextStream stream(&file); QString qmlCode = stream.readAll(); Q_ASSERT(m_pipeline.count() > 0); m_pipeline.first()->process(qmlCode); } -void Pipeline::appendStage(PipelineStage* stage) +void CompilerPipeline::appendCompilerPass(CompilerPass *compilerPass) { - Q_ASSERT(stage); + Q_ASSERT(compilerPass); + + compilerPass->setParent(this); - PipelineStage* lastStage = 0; + CompilerPass *lastCompilerPass = 0; if (m_pipeline.size() > 0) { - lastStage = m_pipeline.last(); - disconnect(lastStage, SIGNAL(finished(QString)), this, SIGNAL(compileFinished(QString))); + lastCompilerPass = m_pipeline.last(); + disconnect(lastCompilerPass, SIGNAL(finished(QString)), this, SIGNAL(compileFinished(QString))); } - m_pipeline.append(stage); - stage->setPipeline(this); + m_pipeline.append(compilerPass); - if (lastStage) { - lastStage->connectToSuccessor(stage); + if (lastCompilerPass) { + lastCompilerPass->connectToSuccessor(compilerPass); } - connect(stage, SIGNAL(finished(QString)), this, SIGNAL(compileFinished(QString))); + connect(compilerPass, SIGNAL(finished(QString)), this, SIGNAL(compileFinished(QString))); } diff --git a/src/qmljsc/pipeline.h b/src/qmljsc/compilerpipeline.h similarity index 76% rename from src/qmljsc/pipeline.h rename to src/qmljsc/compilerpipeline.h index f4d2171..3298e09 100644 --- a/src/qmljsc/pipeline.h +++ b/src/qmljsc/compilerpipeline.h @@ -1,57 +1,61 @@ /* * Copyright (C) 2015 Jan Marker * * 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 PIPELINE_H #define PIPELINE_H #include #include #include #include #include "error.h" namespace QmlJSc { -class PipelineStage; +class CompilerPass; -class Pipeline : public QObject +class CompilerPipeline : public QObject { Q_OBJECT public: - Pipeline(); - ~Pipeline(); + CompilerPipeline(QObject* parent = 0); + ~CompilerPipeline(); - void appendStage(PipelineStage *stage); + /** + * Appends @param compilerPass to the pipeline and takes the + * ownership of @param compilerPass + */ + void appendCompilerPass(CompilerPass *compilerPass); void compile(QString &file); QUrl file() const; signals: void compileFinished(QString output); private: - QLinkedList m_pipeline; + QLinkedList m_pipeline; QString m_file; }; } #endif // PIPELINE_H diff --git a/tests/auto/qmljsc/CMakeLists.txt b/tests/auto/qmljsc/CMakeLists.txt index 36c5f49..fe1eb13 100644 --- a/tests/auto/qmljsc/CMakeLists.txt +++ b/tests/auto/qmljsc/CMakeLists.txt @@ -1,26 +1,26 @@ find_package(Qt5 CONFIG REQUIRED Core Test Qml) function(new_test) set(options ) set(oneValueArgs TEST) set(multiValueArgs RESOURCES) cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) include_directories(${Qt5Qml_PRIVATE_INCLUDE_DIRS}) add_test(NAME ${ARGS_TEST} COMMAND ${ARGS_TEST}) generate_qrc_file(FILENAME "${ARGS_TEST}_resources.qrc" RESOURCES ${ARGS_RESOURCES} FILEPATH_VAR qrcfilepath) qt5_add_resources(ResourceSources ${qrcfilepath}) add_executable(${ARGS_TEST} ${ARGS_TEST}.cpp ${ResourceSources}) qt5_use_modules(${ARGS_TEST} Core Qml Test) target_link_libraries(${ARGS_TEST} libqmljsc) endfunction() new_test(TEST testcompiler) -new_test(TEST testparserstage RESOURCES ../data/minimal/minimal.qml) -new_test(TEST testprettygeneratorstage RESOURCES ../data/minimal/minimal.qml ../data/minimal/minimal.qml.js) -new_test(TEST testpipeline RESOURCES ../data/minimal/minimal.qml) +new_test(TEST testparserpass RESOURCES ../data/minimal/minimal.qml) +new_test(TEST testprettygeneratorpass RESOURCES ../data/minimal/minimal.qml ../data/minimal/minimal.qml.js) +new_test(TEST testcompilerpipeline RESOURCES ../data/minimal/minimal.qml) new_test(TEST testsymboltable RESOURCES ../data/imports/TestModule.0.1.js) new_test(TEST testir) diff --git a/tests/auto/qmljsc/testcompiler.cpp b/tests/auto/qmljsc/testcompiler.cpp index ae6b14b..ec6b2f8 100644 --- a/tests/auto/qmljsc/testcompiler.cpp +++ b/tests/auto/qmljsc/testcompiler.cpp @@ -1,48 +1,32 @@ /* * Copyright (C) 2015 Jan Marker * * 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 . * */ #include #include "../../../src/qmljsc/compiler.h" class TestCompiler : public QObject { Q_OBJECT private slots: - void singleton() { - QmlJSc::Compiler* qmljsc = new QmlJSc::Compiler(); - QCOMPARE(compiler, qmljsc); - delete qmljsc; - } - - void nullAfterDelete() { - QmlJSc::Compiler* qmljsc = new QmlJSc::Compiler(); - delete qmljsc; - QCOMPARE(compiler, static_cast(0)); - } - - void symbolTable() { - QmlJSc::Compiler* qmljsc = new QmlJSc::Compiler(); - QVERIFY(qmljsc->symbols()); - } }; QTEST_MAIN(TestCompiler) #include "testcompiler.moc" diff --git a/tests/auto/qmljsc/testpipeline.cpp b/tests/auto/qmljsc/testcompilerpipeline.cpp similarity index 77% rename from tests/auto/qmljsc/testpipeline.cpp rename to tests/auto/qmljsc/testcompilerpipeline.cpp index 4dab177..9f7c7c6 100644 --- a/tests/auto/qmljsc/testpipeline.cpp +++ b/tests/auto/qmljsc/testcompilerpipeline.cpp @@ -1,193 +1,193 @@ /* * Copyright (C) 2015 Jan Marker * * 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 . * */ #include #include #include #include #include #include #include "QtTest/QSignalSpy" #include #include -#include "../../../src/qmljsc/pipeline.h" -#include "../../../src/qmljsc/pipelinestage.h" +#include "../../../src/qmljsc/compilerpipeline.h" +#include "../../../src/qmljsc/compilerpass.h" -class MockStage : public QmlJSc::PipelineStage { +class MockStage : public QmlJSc::CompilerPass { Q_OBJECT public: void setDoError(bool doError) { m_doError = doError; } bool doError() { return m_doError; } public slots: void process(QString input) { if (doError()) { QmlJSc::Error error; error.setColumn(1); error.setLine(1); error.setDescription("description"); error.setFile(QUrl("qrc:/test/minimal.qml")); throw error; } emit finished(input); } private: bool m_doError; }; class TestPipeline : public QObject { Q_OBJECT public: TestPipeline(); private slots: void initTestCase(); void working_data(); void working(); void error_data(); void error(); void error_non_existent_file(); void cleanupTestCase(); }; TestPipeline::TestPipeline() : QObject() { } void TestPipeline::initTestCase() { } void TestPipeline::cleanupTestCase() { } void TestPipeline::working_data() { - QTest::addColumn("pipeline"); + QTest::addColumn("pipeline"); - QmlJSc::Pipeline* pipeline; + QmlJSc::CompilerPipeline* pipeline; MockStage* mockStage1; MockStage* mockStage2; - pipeline = new QmlJSc::Pipeline(); + pipeline = new QmlJSc::CompilerPipeline(); mockStage1 = new MockStage(); mockStage1->setDoError(false); - pipeline->appendStage(mockStage1); + pipeline->appendCompilerPass(mockStage1); QTest::newRow("one_okay") << pipeline; - pipeline = new QmlJSc::Pipeline(); + pipeline = new QmlJSc::CompilerPipeline(); mockStage1 = new MockStage(); mockStage2 = new MockStage(); mockStage1->setDoError(false); mockStage2->setDoError(false); - pipeline->appendStage(mockStage1); - pipeline->appendStage(mockStage2); + pipeline->appendCompilerPass(mockStage1); + pipeline->appendCompilerPass(mockStage2); QTest::newRow("two_okay") << pipeline; } void TestPipeline::working() { - QFETCH(QmlJSc::Pipeline*, pipeline); + QFETCH(QmlJSc::CompilerPipeline*, pipeline); QSignalSpy finishedSpy(pipeline, SIGNAL(compileFinished(QString))); QString filePath(":/test/minimal.qml"); QFile file(filePath); Q_ASSERT(file.open(QFile::ReadOnly)); QTextStream stream(&file); QString fileContent = stream.readAll(); pipeline->compile(filePath); QCOMPARE(finishedSpy.count(), 1); QCOMPARE(finishedSpy.takeFirst().takeFirst().value(), fileContent); } void TestPipeline::error_data() { - QTest::addColumn("pipeline"); + QTest::addColumn("pipeline"); - QmlJSc::Pipeline* pipeline; + QmlJSc::CompilerPipeline* pipeline; MockStage* mockStage1; MockStage* mockStage2; - pipeline = new QmlJSc::Pipeline(); + pipeline = new QmlJSc::CompilerPipeline(); mockStage1 = new MockStage(); mockStage1->setDoError(true); - pipeline->appendStage(mockStage1); + pipeline->appendCompilerPass(mockStage1); QTest::newRow("one_notokay") << pipeline; - pipeline = new QmlJSc::Pipeline(); + pipeline = new QmlJSc::CompilerPipeline(); mockStage1 = new MockStage(); mockStage2 = new MockStage(); mockStage1->setDoError(true); mockStage2->setDoError(false); - pipeline->appendStage(mockStage1); - pipeline->appendStage(mockStage2); + pipeline->appendCompilerPass(mockStage1); + pipeline->appendCompilerPass(mockStage2); QTest::newRow("first_notokay") << pipeline; } void TestPipeline::error() { - QFETCH(QmlJSc::Pipeline*, pipeline); + QFETCH(QmlJSc::CompilerPipeline*, pipeline); - QSignalSpy finishedSpy(pipeline, &QmlJSc::Pipeline::compileFinished); + QSignalSpy finishedSpy(pipeline, &QmlJSc::CompilerPipeline::compileFinished); QString filePath(":/test/minimal.qml"); try { pipeline->compile(filePath); QFAIL("no exception thrown"); } catch (QmlJSc::Error& error) { QCOMPARE(error.column(), 1); QCOMPARE(error.line(), 1); QCOMPARE(error.description(), QStringLiteral("description")); QCOMPARE(error.file(), QUrl("qrc:/test/minimal.qml")); } QCOMPARE(finishedSpy.count(), 0); } void TestPipeline::error_non_existent_file() { - QmlJSc::Pipeline* pipeline = new QmlJSc::Pipeline(); + QmlJSc::CompilerPipeline* pipeline = new QmlJSc::CompilerPipeline(); QString pathToAtlantis = QStringLiteral(":/test/atlantis.qml"); // does not exist - QSignalSpy finishedSpy(pipeline, &QmlJSc::Pipeline::compileFinished); + QSignalSpy finishedSpy(pipeline, &QmlJSc::CompilerPipeline::compileFinished); try { pipeline->compile(pathToAtlantis); QFAIL("no exception thrown"); } catch (QmlJSc::Error& error) { QCOMPARE(error.type(), QmlJSc::Error::ReadFileError); } QCOMPARE(finishedSpy.count(), 0); } QTEST_MAIN(TestPipeline) -#include "testpipeline.moc" +#include "testcompilerpipeline.moc" diff --git a/tests/auto/qmljsc/testparserstage.cpp b/tests/auto/qmljsc/testparserpass.cpp similarity index 75% rename from tests/auto/qmljsc/testparserstage.cpp rename to tests/auto/qmljsc/testparserpass.cpp index f7235a5..83e57e5 100644 --- a/tests/auto/qmljsc/testparserstage.cpp +++ b/tests/auto/qmljsc/testparserpass.cpp @@ -1,96 +1,104 @@ /* * Copyright (C) 2015 Jan Marker * * 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 . * */ #include #include #include #include #include #include #include #include -#include "../../../src/qmljsc/parserstage.h" +#include "../../../src/qmljsc/compilerpipeline.h" +#include "../../../src/qmljsc/compilerpasses/parserpass.h" -class TestParserStage : public QObject +class TestParserPass : public QObject { Q_OBJECT private slots: void working(); void not_working(); }; -void TestParserStage::working() +void TestParserPass::working() { - QmlJSc::ParserStage stage; + QmlJSc::CompilerPipeline pipeline; + + QmlJSc::ParserPass *parserPass = new QmlJSc::ParserPass(); + pipeline.appendCompilerPass(parserPass); + QFile minimalTestFile(":/test/minimal.qml"); minimalTestFile.open(QFile::ReadOnly); QTextStream minimalTestFileStream(&minimalTestFile); QString minimalTestQml = minimalTestFileStream.readAll(); - QSignalSpy spy(&stage, SIGNAL(finished(QQmlJS::AST::UiProgram*))); + QSignalSpy spy(parserPass, SIGNAL(finished(QQmlJS::AST::UiProgram*))); try { - stage.process(minimalTestQml); + parserPass->process(minimalTestQml); } catch (QmlJSc::Error& error) { QFAIL("no error should occur"); } QCOMPARE(spy.count(), 1); QList stageResult = spy.takeFirst(); QVERIFY2(stageResult.length() == 1, "Only one result should have been sent"); QVariant astVariant = stageResult.takeFirst(); QVERIFY2(astVariant.canConvert(), "Stage produced a wrong result"); QQmlJS::AST::UiProgram* ast = astVariant.value(); QVERIFY2(ast->headers == 0, "There should not be headers"); QVERIFY(ast->members->kind == QQmlJS::AST::Node::Kind_UiObjectMemberList); QVERIFY(ast->members->member->kind == QQmlJS::AST::Node::Kind_UiObjectDefinition); QQmlJS::AST::UiObjectDefinition* memberObjectDefinition = reinterpret_cast(ast->members->member); QCOMPARE(QString().append(memberObjectDefinition->qualifiedTypeNameId->name), QStringLiteral("QtObject")); } -void TestParserStage::not_working() +void TestParserPass::not_working() { - QmlJSc::ParserStage stage; + QmlJSc::CompilerPipeline pipeline; + + QmlJSc::ParserPass *parserPass = new QmlJSc::ParserPass(); + pipeline.appendCompilerPass(parserPass); QString invalidQml = "not valid QML"; - QSignalSpy spy(&stage, SIGNAL(finished(QQmlJS::AST::UiProgram*))); + QSignalSpy spy(parserPass, SIGNAL(finished(QQmlJS::AST::UiProgram*))); try { - stage.process(invalidQml); + parserPass->process(invalidQml); QFAIL("an parse error should have been thrown"); } catch (QmlJSc::Error& error) { QCOMPARE(error.type(), QmlJSc::Error::ParseError); } QCOMPARE(spy.count(), 0); } -QTEST_MAIN(TestParserStage) -#include "testparserstage.moc" +QTEST_MAIN(TestParserPass) +#include "testparserpass.moc" diff --git a/tests/auto/qmljsc/testprettygeneratorstage.cpp b/tests/auto/qmljsc/testprettygeneratorpass.cpp similarity index 68% rename from tests/auto/qmljsc/testprettygeneratorstage.cpp rename to tests/auto/qmljsc/testprettygeneratorpass.cpp index 902008d..60cc15b 100644 --- a/tests/auto/qmljsc/testprettygeneratorstage.cpp +++ b/tests/auto/qmljsc/testprettygeneratorpass.cpp @@ -1,87 +1,86 @@ /* * Copyright (C) 2015 Jan Marker * * 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 . * */ #include #include #include #include #include #include -#include "../../../src/qmljsc/pipeline.h" -#include "../../../src/qmljsc/parserstage.h" -#include "../../../src/qmljsc/prettygeneratorstage.h" +#include "../../../src/qmljsc/compilerpipeline.h" +#include "../../../src/qmljsc/compilerpasses/parserpass.h" +#include "../../../src/qmljsc/compilerpasses/prettygeneratorpass.h" #include "../../../src/qmljsc/compiler.h" -class TestPrettyGeneratorStage : public QObject +class TestPrettyGeneratorPass : public QObject { Q_OBJECT private: private slots: void initTestCase(); void printout_data(); void printout(); }; -void TestPrettyGeneratorStage::initTestCase() +void TestPrettyGeneratorPass::initTestCase() { new QmlJSc::Compiler(); } -void TestPrettyGeneratorStage::printout_data() +void TestPrettyGeneratorPass::printout_data() { QTest::addColumn("qmlFileUrl"); QTest::addColumn("jsFileUrl"); QTest::newRow("minimal") << ":/test/minimal.qml" << ":/test/minimal.qml.js"; } -void TestPrettyGeneratorStage::printout() +void TestPrettyGeneratorPass::printout() { QFETCH(QString, qmlFileUrl); QFETCH(QString, jsFileUrl); QFile jsFile(jsFileUrl); Q_ASSERT(jsFile.open(QFile::ReadOnly)); QTextStream jsFileStream(&jsFile); QString jsFileContent = jsFileStream.readAll(); - QmlJSc::Pipeline* pipeline = new QmlJSc::Pipeline(); - pipeline->appendStage(new QmlJSc::ParserStage()); - pipeline->appendStage(new QmlJSc::PrettyGeneratorStage()); + QmlJSc::SymbolTable symbolTable; + QmlJSc::CompilerPipeline pipeline; + pipeline.appendCompilerPass(new QmlJSc::ParserPass()); + pipeline.appendCompilerPass(new QmlJSc::PrettyGeneratorPass(&symbolTable)); - QSignalSpy pipelineFinished(pipeline, SIGNAL(compileFinished(QString))); + QSignalSpy pipelineFinished(&pipeline, SIGNAL(compileFinished(QString))); - pipeline->compile(qmlFileUrl); + pipeline.compile(qmlFileUrl); QCOMPARE(pipelineFinished.count(), 1); QString compilerOutput = pipelineFinished.takeFirst().takeFirst().value(); QCOMPARE(compilerOutput, jsFileContent); - - delete pipeline; } -QTEST_MAIN(TestPrettyGeneratorStage) -#include "testprettygeneratorstage.moc" +QTEST_MAIN(TestPrettyGeneratorPass) +#include "testprettygeneratorpass.moc"