diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/qmlcachegen/Qt5QuickCompilerConfig.cmake.in | 2 | ||||
-rw-r--r-- | tools/qmlcachegen/qmlcachegen.cpp | 7 | ||||
-rw-r--r-- | tools/qmlcachegen/qmlcachegen.pro | 1 | ||||
-rw-r--r-- | tools/qmlcachegen/qtquickcompiler.prf | 12 | ||||
-rw-r--r-- | tools/qmlcachegen/resourcefilter.cpp | 172 | ||||
-rw-r--r-- | tools/qmllint/fakemetaobject.cpp | 14 | ||||
-rw-r--r-- | tools/qmllint/fakemetaobject.h | 3 | ||||
-rw-r--r-- | tools/qmllint/findunqualified.cpp | 37 | ||||
-rw-r--r-- | tools/qmllint/findunqualified.h | 3 | ||||
-rw-r--r-- | tools/qmllint/main.cpp | 5 | ||||
-rw-r--r-- | tools/qmllint/qcoloroutput.cpp | 11 | ||||
-rw-r--r-- | tools/qmllint/qcoloroutput_p.h | 2 | ||||
-rw-r--r-- | tools/qmllint/qmljstypedescriptionreader.cpp | 51 |
13 files changed, 248 insertions, 72 deletions
diff --git a/tools/qmlcachegen/Qt5QuickCompilerConfig.cmake.in b/tools/qmlcachegen/Qt5QuickCompilerConfig.cmake.in index baa437a947..be2113b258 100644 --- a/tools/qmlcachegen/Qt5QuickCompilerConfig.cmake.in +++ b/tools/qmlcachegen/Qt5QuickCompilerConfig.cmake.in @@ -50,7 +50,7 @@ but not all the files it references. get_filename_component(input_resource ${_resource} ABSOLUTE) - configure_file(${input_resource} ${new_resource_file} COPYONLY) + execute_process(COMMAND ${compiler_path} --filter-resource-file ${input_resource} -o ${new_resource_file} OUTPUT_VARIABLE remaining_files) list(APPEND filtered_rcc_files ${new_resource_file}) list(APPEND loader_flags \"--resource-file-mapping=${_resource}=${new_resource_file}\") diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp index 18415afd1d..b1670c940d 100644 --- a/tools/qmlcachegen/qmlcachegen.cpp +++ b/tools/qmlcachegen/qmlcachegen.cpp @@ -47,6 +47,7 @@ using namespace QQmlJS; +int filterResourceFile(const QString &input, const QString &output); bool generateLoader(const QStringList &compiledFiles, const QString &output, const QStringList &resourceFileMappings, QString *errorString); QString symbolNamespaceForPath(const QString &relativePath); @@ -417,6 +418,8 @@ int main(int argc, char **argv) parser.addHelpOption(); parser.addVersionOption(); + QCommandLineOption filterResourceFileOption(QStringLiteral("filter-resource-file"), QCoreApplication::translate("main", "Filter out QML/JS files from a resource file that can be cached ahead of time instead")); + parser.addOption(filterResourceFileOption); QCommandLineOption resourceFileMappingOption(QStringLiteral("resource-file-mapping"), QCoreApplication::translate("main", "Path from original resource file to new one"), QCoreApplication::translate("main", "old-name:new-name")); parser.addOption(resourceFileMappingOption); QCommandLineOption resourceOption(QStringLiteral("resource"), QCoreApplication::translate("main", "Qt resource file that might later contain one of the compiled files"), QCoreApplication::translate("main", "resource-file-name")); @@ -462,6 +465,10 @@ int main(int argc, char **argv) if (outputFileName.isEmpty()) outputFileName = inputFile + QLatin1Char('c'); + if (parser.isSet(filterResourceFileOption)) { + return filterResourceFile(inputFile, outputFileName); + } + if (target == GenerateLoader) { ResourceFileMapper mapper(sources); diff --git a/tools/qmlcachegen/qmlcachegen.pro b/tools/qmlcachegen/qmlcachegen.pro index 910cb657d7..bee0b9a37e 100644 --- a/tools/qmlcachegen/qmlcachegen.pro +++ b/tools/qmlcachegen/qmlcachegen.pro @@ -4,6 +4,7 @@ QT = qmldevtools-private DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII SOURCES = qmlcachegen.cpp \ + resourcefilter.cpp \ generateloader.cpp \ resourcefilemapper.cpp TARGET = qmlcachegen diff --git a/tools/qmlcachegen/qtquickcompiler.prf b/tools/qmlcachegen/qtquickcompiler.prf index 0129122157..a31a7f5714 100644 --- a/tools/qmlcachegen/qtquickcompiler.prf +++ b/tools/qmlcachegen/qtquickcompiler.prf @@ -1,5 +1,15 @@ if(qtc_run|lupdate_run): return() +!contains(QT, qml) { + qt_modules = \ + $$replace(QT, -private$, _private) \ + $$replace(QT_PRIVATE, -private$, _private) + qt_modules = $$resolve_depends(qt_modules, "QT.", ".depends" ".run_depends") + !contains(qt_modules, qml): \ + return() + unset(qt_modules) +} + qtPrepareTool(QML_CACHEGEN, qmlcachegen, _FILTER) qtPrepareTool(QMAKE_RCC, rcc, _DEP) @@ -28,7 +38,7 @@ for(res, RESOURCES) { contains(rccContents,.*\\.js$)|contains(rccContents,.*\\.qml$)|contains(rccContents,.*\\.mjs$) { new_resource = $$qmlCacheResourceFileOutputName($$res) mkpath($$dirname(new_resource)) - system($$QMAKE_QMAKE -install qinstall $$system_quote($$absRes) $$system_quote($$new_resource)) + dummy = $$system($$QML_CACHEGEN_FILTER --filter-resource-file -o $$system_quote($$new_resource) $$system_quote($$absRes)) NEWRESOURCES += $$new_resource QMLCACHE_LOADER_FLAGS += --resource-file-mapping=$$shell_quote($$absRes=$$new_resource) diff --git a/tools/qmlcachegen/resourcefilter.cpp b/tools/qmlcachegen/resourcefilter.cpp new file mode 100644 index 0000000000..261102dcbe --- /dev/null +++ b/tools/qmlcachegen/resourcefilter.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QString> +#include <QXmlStreamReader> +#include <QFile> +#include <QDir> + +int filterResourceFile(const QString &input, const QString &output) +{ + enum State { + InitialState, + InRCC, + InResource, + InFile + }; + State state = InitialState; + + QString prefix; + QString currentFileName; + QXmlStreamAttributes fileAttributes; + + QFile file(input); + if (!file.open(QIODevice::ReadOnly)) { + fprintf(stderr, "Cannot open %s for reading.\n", qPrintable(input)); + return EXIT_FAILURE; + } + + QDir inputDirectory = QFileInfo(file).absoluteDir(); + QDir outputDirectory = QFileInfo(output).absoluteDir(); + + QString outputString; + QXmlStreamWriter writer(&outputString); + writer.setAutoFormatting(true); + + QXmlStreamReader reader(&file); + while (!reader.atEnd()) { + switch (reader.readNext()) { + case QXmlStreamReader::StartDocument: { + QStringRef version = reader.documentVersion(); + if (!version.isEmpty()) + writer.writeStartDocument(version.toString()); + else + writer.writeStartDocument(); + break; + } + case QXmlStreamReader::EndDocument: + writer.writeEndDocument(); + break; + case QXmlStreamReader::StartElement: + if (reader.name() == QStringLiteral("RCC")) { + if (state != InitialState) { + fprintf(stderr, "Unexpected RCC tag in line %d\n", int(reader.lineNumber())); + return EXIT_FAILURE; + } + state = InRCC; + } else if (reader.name() == QStringLiteral("qresource")) { + if (state != InRCC) { + fprintf(stderr, "Unexpected qresource tag in line %d\n", int(reader.lineNumber())); + return EXIT_FAILURE; + } + state = InResource; + QXmlStreamAttributes attributes = reader.attributes(); + if (attributes.hasAttribute(QStringLiteral("prefix"))) + prefix = attributes.value(QStringLiteral("prefix")).toString(); + if (!prefix.startsWith(QLatin1Char('/'))) + prefix.prepend(QLatin1Char('/')); + if (!prefix.endsWith(QLatin1Char('/'))) + prefix.append(QLatin1Char('/')); + } else if (reader.name() == QStringLiteral("file")) { + if (state != InResource) { + fprintf(stderr, "Unexpected file tag in line %d\n", int(reader.lineNumber())); + return EXIT_FAILURE; + } + state = InFile; + fileAttributes = reader.attributes(); + continue; + } + writer.writeStartElement(reader.name().toString()); + writer.writeAttributes(reader.attributes()); + continue; + + case QXmlStreamReader::EndElement: + if (reader.name() == QStringLiteral("file")) { + if (state != InFile) { + fprintf(stderr, "Unexpected end of file tag in line %d\n", int(reader.lineNumber())); + return EXIT_FAILURE; + } + state = InResource; + continue; + } else if (reader.name() == QStringLiteral("qresource")) { + if (state != InResource) { + fprintf(stderr, "Unexpected end of qresource tag in line %d\n", int(reader.lineNumber())); + return EXIT_FAILURE; + } + state = InRCC; + } else if (reader.name() == QStringLiteral("RCC")) { + if (state != InRCC) { + fprintf(stderr, "Unexpected end of RCC tag in line %d\n", int(reader.lineNumber())); + return EXIT_FAILURE; + } + state = InitialState; + } + writer.writeEndElement(); + continue; + + case QXmlStreamReader::Characters: + if (reader.isWhitespace()) + break; + if (state != InFile) + return EXIT_FAILURE; + currentFileName = reader.text().toString(); + if (currentFileName.isEmpty()) + continue; + + writer.writeStartElement(QStringLiteral("file")); + + if (!fileAttributes.hasAttribute(QStringLiteral("alias"))) + fileAttributes.append(QStringLiteral("alias"), currentFileName); + + currentFileName = inputDirectory.absoluteFilePath(currentFileName); + currentFileName = outputDirectory.relativeFilePath(currentFileName); + + writer.writeAttributes(fileAttributes); + writer.writeCharacters(currentFileName); + writer.writeEndElement(); + continue; + + default: break; + } + } + + QFile outputFile(output); + if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + fprintf(stderr, "Cannot open %s for writing.\n", qPrintable(output)); + return EXIT_FAILURE; + } + const QByteArray outputStringUtf8 = outputString.toUtf8(); + if (outputFile.write(outputStringUtf8) != outputStringUtf8.size()) + return EXIT_FAILURE; + + outputFile.close(); + if (outputFile.error() != QFileDevice::NoError) + return EXIT_FAILURE; + + + return EXIT_SUCCESS; +} diff --git a/tools/qmllint/fakemetaobject.cpp b/tools/qmllint/fakemetaobject.cpp index 514bb2fe42..8319ae6713 100644 --- a/tools/qmllint/fakemetaobject.cpp +++ b/tools/qmllint/fakemetaobject.cpp @@ -46,8 +46,8 @@ QString FakeMetaEnum::name() const void FakeMetaEnum::setName(const QString &name) { m_name = name; } -void FakeMetaEnum::addKey(const QString &key, int value) -{ m_keys.append(key); m_values.append(value); } +void FakeMetaEnum::addKey(const QString &key) +{ m_keys.append(key); } QString FakeMetaEnum::key(int index) const { return m_keys.at(index); } @@ -73,10 +73,6 @@ void FakeMetaEnum::addToHash(QCryptographicHash &hash) const hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar)); } - len = m_values.size(); - hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); - foreach (int value, m_values) - hash.addData(reinterpret_cast<const char *>(&value), sizeof(value)); } QString FakeMetaEnum::describe(int baseIndent) const @@ -84,16 +80,14 @@ QString FakeMetaEnum::describe(int baseIndent) const QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent); QString res = QLatin1String("Enum "); res += name(); - res += QLatin1String(":{"); + res += QLatin1String(": ["); for (int i = 0; i < keyCount(); ++i) { res += newLine; res += QLatin1String(" "); res += key(i); - res += QLatin1String(": "); - res += QString::number(m_values.value(i, -1)); } res += newLine; - res += QLatin1Char('}'); + res += QLatin1Char(']'); return res; } diff --git a/tools/qmllint/fakemetaobject.h b/tools/qmllint/fakemetaobject.h index 4e0ea1f8b3..ae76596343 100644 --- a/tools/qmllint/fakemetaobject.h +++ b/tools/qmllint/fakemetaobject.h @@ -46,7 +46,6 @@ namespace LanguageUtils { class FakeMetaEnum { QString m_name; QStringList m_keys; - QList<int> m_values; public: FakeMetaEnum(); @@ -57,7 +56,7 @@ public: QString name() const; void setName(const QString &name); - void addKey(const QString &key, int value); + void addKey(const QString &key); QString key(int index) const; int keyCount() const; QStringList keys() const; diff --git a/tools/qmllint/findunqualified.cpp b/tools/qmllint/findunqualified.cpp index 4404ddf49a..52cc36aeeb 100644 --- a/tools/qmllint/findunqualified.cpp +++ b/tools/qmllint/findunqualified.cpp @@ -40,8 +40,6 @@ #include <private/qqmljsparser_p.h> #include <private/qv4codegen_p.h> -QDebug operator<<(QDebug dbg, const QQmlJS::AST::SourceLocation &loc); - static QQmlJS::TypeDescriptionReader createReaderForFile(QString const &filename) { QFile f(filename); @@ -139,9 +137,8 @@ void FindUnqualifiedIDVisitor::importHelper(QString id, QString prefix, int majo if (QFile::exists(qmltypesPath)) { auto reader = createReaderForFile(qmltypesPath); auto succ = reader(&objects, &moduleApis, &dependencies); - if (!succ) { - qDebug() << reader.errorMessage(); - } + if (!succ) + m_colorOut.writeUncolored(reader.errorMessage()); break; } } @@ -292,13 +289,17 @@ FindUnqualifiedIDVisitor::localQmlFile2FakeMetaObject(QString filePath) } else if (cast<VariableStatement *>(sourceElement->sourceElement)) { // nothing to do } else { - qDebug() << "unsupportedd sourceElement at" << sourceElement->firstSourceLocation() - << sourceElement->sourceElement->kind; + const auto loc = sourceElement->firstSourceLocation(); + m_colorOut.writeUncolored( + "unsupportedd sourceElement at " + + QString::fromLatin1("%1:%2: ").arg(loc.startLine).arg(loc.startColumn) + + QString::number(sourceElement->sourceElement->kind)); } break; } default: { - qDebug() << "unsupported element of kind" << initMembers->member->kind; + m_colorOut.writeUncolored("unsupported element of kind " + + QString::number(initMembers->member->kind)); } } initMembers = initMembers->next; @@ -368,9 +369,8 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiProgram *) while (it.hasNext()) { auto reader = createReaderForFile(it.next()); auto succ = reader(&objects, &moduleApis, &dependencies); - if (!succ) { - qDebug() << reader.errorMessage(); - } + if (!succ) + m_colorOut.writeUncolored(reader.errorMessage()); } } // add builtins @@ -578,13 +578,15 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::IdentifierExpression *idexp) } FindUnqualifiedIDVisitor::FindUnqualifiedIDVisitor(QStringList const &qmltypeDirs, - const QString &code, const QString &fileName) + const QString &code, const QString &fileName, + bool silent) : m_rootScope(new ScopeTree { ScopeType::JSFunctionScope, "global" }), m_currentScope(m_rootScope.get()), m_qmltypeDirs(qmltypeDirs), m_code(code), m_rootId(QLatin1String("<id>")), - m_filePath(fileName) + m_filePath(fileName), + m_colorOut(silent) { // setup color output m_colorOut.insertColorMapping(Error, ColorOutput::RedForeground); @@ -806,12 +808,3 @@ void FindUnqualifiedIDVisitor::endVisit(QQmlJS::AST::UiObjectDefinition *) { leaveEnvironment(); } - -QDebug operator<<(QDebug dbg, const QQmlJS::AST::SourceLocation &loc) -{ - QDebugStateSaver saver(dbg); - dbg.nospace() << loc.startLine; - dbg.nospace() << ":"; - dbg.nospace() << loc.startColumn; - return dbg.maybeSpace(); -} diff --git a/tools/qmllint/findunqualified.h b/tools/qmllint/findunqualified.h index f7d1aab1f4..98e14f8dc7 100644 --- a/tools/qmllint/findunqualified.h +++ b/tools/qmllint/findunqualified.h @@ -43,7 +43,8 @@ enum class ScopeType; class FindUnqualifiedIDVisitor : public QQmlJS::AST::Visitor { public: - explicit FindUnqualifiedIDVisitor(QStringList const &qmltypeDirs, const QString& code, const QString& fileName); + explicit FindUnqualifiedIDVisitor(QStringList const &qmltypeDirs, const QString& code, + const QString& fileName, bool silent); ~FindUnqualifiedIDVisitor() override; bool check(); diff --git a/tools/qmllint/main.cpp b/tools/qmllint/main.cpp index 235ec16c6e..0fa2ab53e4 100644 --- a/tools/qmllint/main.cpp +++ b/tools/qmllint/main.cpp @@ -50,7 +50,8 @@ static bool lint_file(const QString &filename, const bool silent, const bool war { QFile file(filename); if (!file.open(QFile::ReadOnly)) { - qWarning() << "Failed to open file" << filename << file.error(); + if (!silent) + qWarning() << "Failed to open file" << filename << file.error(); return false; } @@ -76,7 +77,7 @@ static bool lint_file(const QString &filename, const bool silent, const bool war if (success && !isJavaScript && warnUnqualied) { auto root = parser.rootNode(); - FindUnqualifiedIDVisitor v { qmltypeDirs, code, filename}; + FindUnqualifiedIDVisitor v { qmltypeDirs, code, filename, silent }; root->accept(&v); success = v.check(); } diff --git a/tools/qmllint/qcoloroutput.cpp b/tools/qmllint/qcoloroutput.cpp index d2e723700a..eb4c721663 100644 --- a/tools/qmllint/qcoloroutput.cpp +++ b/tools/qmllint/qcoloroutput.cpp @@ -39,7 +39,7 @@ class ColorOutputPrivate { public: - ColorOutputPrivate() : currentColorID(-1) + ColorOutputPrivate(bool silent) : currentColorID(-1), silent(silent) { /* - QIODevice::Unbuffered because we want it to appear when the user actually calls, performance @@ -53,6 +53,7 @@ public: ColorOutput::ColorMapping colorMapping; int currentColorID; bool coloringEnabled; + bool silent; static const char *const foregrounds[]; static const char *const backgrounds[]; @@ -238,7 +239,7 @@ ColorOutput::ColorMapping ColorOutput::colorMapping() const /*! Constructs a ColorOutput instance, ready for use. */ -ColorOutput::ColorOutput() : d(new ColorOutputPrivate()) +ColorOutput::ColorOutput(bool silent) : d(new ColorOutputPrivate(silent)) { } @@ -258,7 +259,8 @@ ColorOutput::~ColorOutput() = default; // must be here so that QScopedPointer ha */ void ColorOutput::write(const QString &message, int colorID) { - d->write(colorify(message, colorID)); + if (!d->silent) + d->write(colorify(message, colorID)); } /*! @@ -269,7 +271,8 @@ void ColorOutput::write(const QString &message, int colorID) */ void ColorOutput::writeUncolored(const QString &message) { - d->write(message + QLatin1Char('\n')); + if (!d->silent) + d->write(message + QLatin1Char('\n')); } /*! diff --git a/tools/qmllint/qcoloroutput_p.h b/tools/qmllint/qcoloroutput_p.h index 710bf5db74..aefa765a87 100644 --- a/tools/qmllint/qcoloroutput_p.h +++ b/tools/qmllint/qcoloroutput_p.h @@ -89,7 +89,7 @@ public: typedef QFlags<ColorCodeComponent> ColorCode; typedef QHash<int, ColorCode> ColorMapping; - ColorOutput(); + ColorOutput(bool silent); ~ColorOutput(); void setColorMapping(const ColorMapping &cMapping); diff --git a/tools/qmllint/qmljstypedescriptionreader.cpp b/tools/qmllint/qmljstypedescriptionreader.cpp index 542cdf99eb..44a0d6f8b7 100644 --- a/tools/qmllint/qmljstypedescriptionreader.cpp +++ b/tools/qmllint/qmljstypedescriptionreader.cpp @@ -666,39 +666,34 @@ void TypeDescriptionReader::readEnumValues(AST::UiScriptBinding *ast, LanguageUt return; } - ExpressionStatement *expStmt = AST::cast<ExpressionStatement *>(ast->statement); + auto *expStmt = AST::cast<ExpressionStatement *>(ast->statement); if (!expStmt) { - addError(ast->statement->firstSourceLocation(), tr("Expected object literal after colon.")); - return; - } - - ObjectPattern *objectLit = AST::cast<ObjectPattern *>(expStmt->expression); - if (!objectLit) { - addError(expStmt->firstSourceLocation(), tr("Expected object literal after colon.")); + addError(ast->statement->firstSourceLocation(), tr("Expected expression after colon.")); return; } - for (PatternPropertyList *it = objectLit->properties; it; it = it->next) { - PatternProperty *assignement = AST::cast<PatternProperty *>(it->property); - if (assignement) { - StringLiteralPropertyName *propName = AST::cast<StringLiteralPropertyName *>(assignement->name); - NumericLiteral *value = AST::cast<NumericLiteral *>(assignement->initializer); - UnaryMinusExpression *minus = AST::cast<UnaryMinusExpression *>(assignement->initializer); - if (minus) - value = AST::cast<NumericLiteral *>(minus->expression); - if (!propName || !value) { - addError(objectLit->firstSourceLocation(), tr("Expected object literal to contain only 'string: number' elements.")); - continue; + if (auto *objectLit = AST::cast<ObjectPattern *>(expStmt->expression)) { + for (PatternPropertyList *it = objectLit->properties; it; it = it->next) { + if (PatternProperty *assignement = it->property) { + if (auto *name = AST::cast<StringLiteralPropertyName *>(assignement->name)) { + fme->addKey(name->id.toString()); + continue; + } } - - double v = value->value; - if (minus) - v = -v; - fme->addKey(propName->id.toString(), v); - continue; + addError(it->firstSourceLocation(), tr("Expected strings as enum keys.")); + } + } else if (auto *arrayLit = AST::cast<ArrayPattern *>(expStmt->expression)) { + for (PatternElementList *it = arrayLit->elements; it; it = it->next) { + if (PatternElement *element = it->element) { + if (auto *name = AST::cast<StringLiteral *>(element->initializer)) { + fme->addKey(name->value.toString()); + continue; + } + } + addError(it->firstSourceLocation(), tr("Expected strings as enum keys.")); } - PatternPropertyList *getterSetter = AST::cast<PatternPropertyList *>(it->next); - if (getterSetter) - addError(objectLit->firstSourceLocation(), tr("Enum should not contain getter and setters, but only 'string: number' elements.")); + } else { + addError(ast->statement->firstSourceLocation(), + tr("Expected either array or object literal as enum definition.")); } } |