From f2da7a80acf7ea66ae1b172f2e1124ab6abb4248 Mon Sep 17 00:00:00 2001 From: Dmitrii Akshintsev Date: Thu, 14 Mar 2024 12:48:38 +0100 Subject: QMLFormat | Support ESM formatting Adding tests for Ecmascript Module formatting Change-Id: Iaac7be13d9c1ed1119afc5ebdd9b09a990ed944a Task-number: QTBUG-123386 Reviewed-by: Sami Shalayel Reviewed-by: Qt CI Bot Reviewed-by: Ulf Hermann --- tests/auto/qml/qmlformat/data/esm.formatted.mjs | 44 ++++++++++++++++ tests/auto/qml/qmlformat/data/esm.mjs | 33 ++++++++++++ .../qml/qmlformat/data/mini_esm.formattedTabs.mjs | 20 ++++++++ tests/auto/qml/qmlformat/data/mini_esm.mjs | 3 ++ tests/auto/qml/qmlformat/tst_qmlformat.cpp | 59 +++++++++++++++++++--- 5 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 tests/auto/qml/qmlformat/data/esm.formatted.mjs create mode 100644 tests/auto/qml/qmlformat/data/esm.mjs create mode 100644 tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs create mode 100644 tests/auto/qml/qmlformat/data/mini_esm.mjs (limited to 'tests/auto/qml/qmlformat') diff --git a/tests/auto/qml/qmlformat/data/esm.formatted.mjs b/tests/auto/qml/qmlformat/data/esm.formatted.mjs new file mode 100644 index 0000000000..f0b3fd7753 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/esm.formatted.mjs @@ -0,0 +1,44 @@ +//Imports +import defaultExport from "module-name"; +import * as name from "module-name"; +import { export1 } from "module-name"; +import { export1 as alias1 } from "module-name"; +import { default as alias } from "module-name"; +import { export1, export2 } from "module-name"; +import { export1, export2 as alias2 } from "module-name"; +import defaultExport, { export1, a } from "module-name"; +import defaultExport, * as name from "module-name"; +import "module-name"; + +// Exporting declarations +export let name1, name2; // also var +export const name1 = 1, name2 = 2; // also var, let +export function functionName() {} +export class ClassName { + constructor(h){ + this.h = h; + } +} +export function* generatorFunctionName() {} +export const { + name1, + name2: bar +} = o; +export const [name1, name2] = array; + +// Export list +export { name1, nameN }; +export { variable1 as name1, variable2 as name2, nameN }; +export { name1 as default }; + +// Default exports +export default function* generatorFunctionName() { + return 1; +} + +// Aggregating modules +export * from "module-name"; +export { name1, nameN } from "module-name"; +export { import1 as name1, import2 as name2, nameN } from "module-name"; +export { default } from "module-name"; +export { default as name1 } from "module-name"; diff --git a/tests/auto/qml/qmlformat/data/esm.mjs b/tests/auto/qml/qmlformat/data/esm.mjs new file mode 100644 index 0000000000..83e22fdedd --- /dev/null +++ b/tests/auto/qml/qmlformat/data/esm.mjs @@ -0,0 +1,33 @@ +//Imports +import defaultExport from "module-name"; +import * as name from "module-name" +import {export1} from "module-name"; +import { export1 as alias1 } from "module-name"; +import { default as alias } from "module-name" +import { export1, export2 } from "module-name"; +import {export1,export2 as alias2} from "module-name"; +import defaultExport,{export1,a} from "module-name" +import defaultExport, * as name from "module-name"; +import "module-name"; + + +// Exporting declarations +export let name1,name2; // also var +export const name1=1,name2=2 // also var, let +export function functionName() {} +export class ClassName{constructor(h){this.h=h;}} +export function* generatorFunctionName() {} +export const {name1, name2: bar}=o;export const [name1,name2]=array + +// Export list +export {name1,nameN};export {variable1 as name1,variable2 as name2,nameN } +export {name1 as default}; + +// Default exports +export default function* generatorFunctionName() {return 1;} + +// Aggregating modules +export * from "module-name"; +export { name1,nameN} from "module-name" +export { import1 as name1, import2 as name2,nameN } from "module-name";export { default, } from "module-name"; +export { default as name1 } from "module-name"; diff --git a/tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs b/tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs new file mode 100644 index 0000000000..37f8ccb698 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs @@ -0,0 +1,20 @@ +//Imports +import defaultExport from "module-name"; +import "module-name"; +export class ClassName { + constructor(h){ + this.h = h; + } +} +export const { + n1, + n3, + n4, + name2: bar +} = o; +export const [name1, name2] = array; +function stuff() { + var l = () => { + 1 + 1; + }; +} diff --git a/tests/auto/qml/qmlformat/data/mini_esm.mjs b/tests/auto/qml/qmlformat/data/mini_esm.mjs new file mode 100644 index 0000000000..9d6c2406dc --- /dev/null +++ b/tests/auto/qml/qmlformat/data/mini_esm.mjs @@ -0,0 +1,3 @@ +//Imports +import defaultExport from "module-name";import "module-name";export class ClassName{constructor(h){this.h=h;}} +export const {n1,n3,n4,name2:bar}=o;export const [name1,name2]=array;function stuff(){var l=()=>{1+1};}; diff --git a/tests/auto/qml/qmlformat/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp index c10c1ca154..9dd0a6329e 100644 --- a/tests/auto/qml/qmlformat/tst_qmlformat.cpp +++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp @@ -16,6 +16,25 @@ using namespace QQmlJS::Dom; +// TODO refactor extension helpers +const QString QML_EXT = ".qml"; +const QString JS_EXT = ".js"; +const QString MJS_EXT = ".mjs"; + +static QStringView fileExt(QStringView filename) +{ + if (filename.endsWith(QML_EXT)) { + return QML_EXT; + } + if (filename.endsWith(JS_EXT)) { + return JS_EXT; + } + if (filename.endsWith(MJS_EXT)) { + return MJS_EXT; + } + Q_UNREACHABLE(); +}; + class TestQmlformat: public QQmlDataTest { Q_OBJECT @@ -46,11 +65,14 @@ private Q_SLOTS: void plainJS_data(); void plainJS(); + + void ecmascriptModule(); + private: QString readTestFile(const QString &path); //TODO(QTBUG-117849) refactor this helper function QString runQmlformat(const QString &fileToFormat, QStringList args, bool shouldSucceed = true, - RunOption rOption = RunOption::OnCopy, bool isQml = true); + RunOption rOption = RunOption::OnCopy, QStringView ext = QML_EXT); QString formatInMemory(const QString &fileToFormat, bool *didSucceed = nullptr, LineWriterOptions options = LineWriterOptions(), WriteOutChecks extraChecks = WriteOutCheck::ReparseCompare, @@ -385,6 +407,10 @@ void TestQmlformat::testFormat_data() << "threeFunctionsOneLine.js" << "threeFunctions.formattedFuncSpacing.js" << QStringList{ "-n", "--functions-spacing" } << RunOption::OnCopy; + + QTest::newRow("esm_tabIndents") + << "mini_esm.mjs" + << "mini_esm.formattedTabs.mjs" << QStringList{ "-t" } << RunOption::OnCopy; } void TestQmlformat::testFormat() @@ -394,11 +420,11 @@ void TestQmlformat::testFormat() QFETCH(QStringList, args); QFETCH(RunOption, runOption); - bool isQml = file.endsWith(QLatin1String(".qml")); - auto formatted = runQmlformat(testFile(file), args, true, runOption, isQml); + auto formatted = runQmlformat(testFile(file), args, true, runOption, fileExt(file)); QEXPECT_FAIL("normalizedFunctionSpacing", "Normalize && function spacing are not yet supported for JS", Abort); - QCOMPARE(formatted, readTestFile(fileFormatted)); + auto exp = readTestFile(fileFormatted); + QCOMPARE(formatted, exp); } void TestQmlformat::plainJS_data() @@ -451,7 +477,25 @@ void TestQmlformat::plainJS() // TODO(QTBUG-119770) QEXPECT_FAIL("legacyDirectivesWithComments", "see QTBUG-119770", Abort); auto exp = readTestFile(fileFormatted); - QCOMPARE(output, readTestFile(fileFormatted)); + QCOMPARE(output, exp); +} + +void TestQmlformat::ecmascriptModule() +{ + QString file("esm.mjs"); + QString formattedFile("esm.formatted.mjs"); + + bool wasSuccessful; + LineWriterOptions opts; +#ifdef Q_OS_WIN + opts.lineEndings = QQmlJS::Dom::LineWriterOptions::LineEndings::Windows; +#endif + QString output = formatInMemory(testFile(file), &wasSuccessful, opts, WriteOutCheck::None); + + QVERIFY(wasSuccessful && !output.isEmpty()); + + auto exp = readTestFile(formattedFile); + QCOMPARE(output, readTestFile(formattedFile)); } #if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled @@ -623,12 +667,11 @@ void TestQmlformat::testFilesOption() } QString TestQmlformat::runQmlformat(const QString &fileToFormat, QStringList args, - bool shouldSucceed, RunOption rOptions, bool isQml) + bool shouldSucceed, RunOption rOptions, QStringView ext) { // Copy test file to temporary location QTemporaryDir tempDir; - const QString ext = isQml ? ".qml" : ".js"; - const QString tempFile = tempDir.path() + QDir::separator() + "to_format" + ext; + const QString tempFile = (tempDir.path() + QDir::separator() + "to_format") % ext; if (rOptions == RunOption::OnCopy) { QFile::copy(fileToFormat, tempFile); -- cgit v1.2.3