From bada254d4cdc3a6cd188619fce554b4b2abffb67 Mon Sep 17 00:00:00 2001 From: Furkan Uzumcu Date: Sun, 7 Feb 2021 17:07:04 -0500 Subject: qmlformat: Use a struct to hold the command line options Keeping the parser and the code that uses the command line options in the same function increases the number of lines for the same function, making it harder to read, and the number of arguments for parseFile function, makes it harder to understand and maintain. This commit adds an `Options` struct to hold on to the command line options and a build function to create the `Options` object. Change-Id: I5dec0a5a5e990f413ee65bf2eba2ea1087e0ea28 Reviewed-by: Maximilian Goldstein Reviewed-by: Ulf Hermann (cherry picked from commit 1c35c8f71eb6863498548c6724f82be01d872b33) Reviewed-by: Qt Cherry-pick Bot --- tools/qmlformat/main.cpp | 192 +++++++++++++++++++++++++++-------------------- 1 file changed, 112 insertions(+), 80 deletions(-) diff --git a/tools/qmlformat/main.cpp b/tools/qmlformat/main.cpp index a7e6c64bf3..da3c1772fb 100644 --- a/tools/qmlformat/main.cpp +++ b/tools/qmlformat/main.cpp @@ -44,8 +44,24 @@ #include "dumpastvisitor.h" #include "restructureastvisitor.h" -bool parseFile(const QString &filename, bool inplace, bool verbose, bool force, - int indentWidth, bool tabs, const QString &newline) +struct Options +{ + bool verbose = false; + bool inplace = false; + bool force = false; + bool tabs = false; + bool valid = false; + + int indentWidth = 4; + bool indentWidthSet = false; + QString newline = "native"; + + QStringList files; + QStringList arguments; + QStringList errors; +}; + +bool parseFile(const QString &filename, const Options &options) { QFile file(filename); @@ -79,10 +95,10 @@ bool parseFile(const QString &filename, bool inplace, bool verbose, bool force, // Try to attach comments to AST nodes CommentAstVisitor comment(&engine, parser.rootNode()); - if (verbose) + if (options.verbose) qWarning().noquote() << comment.attachedComments().size() << "comment(s) attached."; - if (verbose) { + if (options.verbose) { int orphaned = 0; for (const auto& orphanList : comment.orphanComments().values()) @@ -95,12 +111,12 @@ bool parseFile(const QString &filename, bool inplace, bool verbose, bool force, RestructureAstVisitor restructure(parser.rootNode()); // Turn AST back into source code - if (verbose) + if (options.verbose) qWarning().noquote() << "Dumping" << filename; - DumpAstVisitor dump(&engine, parser.rootNode(), &comment, tabs ? 1 : indentWidth, - tabs ? DumpAstVisitor::Indentation::Tabs - : DumpAstVisitor::Indentation::Spaces); + DumpAstVisitor dump( + &engine, parser.rootNode(), &comment, options.tabs ? 1 : options.indentWidth, + options.tabs ? DumpAstVisitor::Indentation::Tabs : DumpAstVisitor::Indentation::Spaces); QString dumpCode = dump.toString(); @@ -109,7 +125,7 @@ bool parseFile(const QString &filename, bool inplace, bool verbose, bool force, bool dumpSuccess = parser.parse(); if (!dumpSuccess) { - if (verbose) { + if (options.verbose) { const auto diagnosticMessages = parser.diagnosticMessages(); for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) { qWarning().noquote() << QString::fromLatin1(":%2 : %3") @@ -121,7 +137,7 @@ bool parseFile(const QString &filename, bool inplace, bool verbose, bool force, } if (dump.error() || !dumpSuccess) { - if (force) { + if (options.force) { qWarning().noquote() << "An error has occurred. The output may not be reliable."; } else { qWarning().noquote() << "An error has occurred. Aborting."; @@ -129,50 +145,43 @@ bool parseFile(const QString &filename, bool inplace, bool verbose, bool force, } } + const bool native = options.newline == "native"; + + if (!native) { + if (options.newline == "macos") { + dumpCode = dumpCode.replace("\n", "\r"); + } else if (options.newline == "windows") { + dumpCode = dumpCode.replace("\n", "\r\n"); + } else if (options.newline == "unix") { + // Nothing needs to be done for unix line-endings + } else { + qWarning().noquote() << "Unknown line ending type" << options.newline; + return false; + } + } - const bool native = newline == "native"; - - if (!native) { - if (newline == "macos") { - dumpCode = dumpCode.replace("\n","\r"); - } else if (newline == "windows") { - dumpCode = dumpCode.replace("\n", "\r\n"); - } else if (newline == "unix") { - // Nothing needs to be done for unix line-endings - } else { - qWarning().noquote() << "Unknown line ending type" << newline; - return false; - } - } - - if (inplace) { - if (verbose) - qWarning().noquote() << "Writing to file" << filename; - - if (!file.open(native ? QIODevice::WriteOnly | QIODevice::Text : QIODevice::WriteOnly)) - { - qWarning().noquote() << "Failed to open" << filename << "for writing"; - return false; - } - - file.write(dumpCode.toUtf8()); - file.close(); - } else { - QFile out; - out.open(stdout, QIODevice::WriteOnly); - out.write(dumpCode.toUtf8()); - } + if (options.inplace) { + if (options.verbose) + qWarning().noquote() << "Writing to file" << filename; + + if (!file.open(native ? QIODevice::WriteOnly | QIODevice::Text : QIODevice::WriteOnly)) { + qWarning().noquote() << "Failed to open" << filename << "for writing"; + return false; + } + + file.write(dumpCode.toUtf8()); + file.close(); + } else { + QFile out; + out.open(stdout, QIODevice::WriteOnly); + out.write(dumpCode.toUtf8()); + } return true; } -int main(int argc, char *argv[]) +Options buildCommandLineOptions(const QCoreApplication &app) { - QCoreApplication app(argc, argv); - QCoreApplication::setApplicationName("qmlformat"); - QCoreApplication::setApplicationVersion("1.0"); - - bool success = true; #if QT_CONFIG(commandlineparser) QCommandLineParser parser; parser.setApplicationDescription("Formats QML files according to the QML Coding Conventions."); @@ -206,56 +215,79 @@ int main(int argc, char *argv[]) parser.process(app); - const auto positionalArguments = parser.positionalArguments(); + bool indentWidthOkay = false; + const int indentWidth = parser.value("indent-width").toInt(&indentWidthOkay); + if (!indentWidthOkay) { + Options options; + options.errors.push_back("Error: Invalid value passed to -w"); + return options; + } - if (positionalArguments.isEmpty() && !parser.isSet("files")) - parser.showHelp(-1); + QStringList files; + QFile file(parser.value("files")); + file.open(QIODevice::Text | QIODevice::ReadOnly); + if (file.isOpen()) { + QTextStream in(&file); + while (!in.atEnd()) { + QString file = in.readLine(); - if (!parser.isSet("inplace") && parser.value("newline") != "native") { - qWarning() << "Error: The -l option can only be used with -i"; - return -1; - } + if (file.isEmpty()) + continue; - if (parser.isSet("indent-width") && parser.isSet("tabs")) { - qWarning() << "Error: Cannot use --indent-width with --tabs"; - return -1; + files.push_back(file); + } } - bool indentWidthOkay = false; - int indentWidth = parser.value("indent-width").toInt(&indentWidthOkay); + Options options; + options.verbose = parser.isSet("verbose"); + options.inplace = parser.isSet("inplace"); + options.force = parser.isSet("force"); + options.tabs = parser.isSet("tabs"); + options.valid = true; + + options.indentWidth = indentWidth; + options.indentWidthSet = parser.isSet("indent-width"); + options.newline = parser.value("newline"); + options.files = files; + options.arguments = parser.positionalArguments(); + return options; +#else + return Options {}; +#endif +} + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + QCoreApplication::setApplicationName("qmlformat"); + QCoreApplication::setApplicationVersion("1.0"); + + const auto options = buildCommandLineOptions(app); + if (!options.valid) { + for (const auto &error : options.errors) { + qWarning().noquote() << error; + } - if (!indentWidthOkay) { - qWarning() << "Error: Invalid value passed to -w"; return -1; } - if (parser.isSet("files")) { - if (!positionalArguments.isEmpty()) + bool success = true; + if (!options.files.isEmpty()) { + if (!options.arguments.isEmpty()) qWarning() << "Warning: Positional arguments are ignored when -F is used"; - QFile file(parser.value("files")); - file.open(QIODevice::Text | QIODevice::ReadOnly); - QTextStream in(&file); - while (!in.atEnd()) { - QString file = in.readLine(); - - if (file.isEmpty()) - continue; + for (const QString &file : options.files) { + Q_ASSERT(!file.isEmpty()); - if (!parseFile(file, true, parser.isSet("verbose"), - parser.isSet("force"), indentWidth, parser.isSet("tabs"), - parser.value("newline"))) + if (!parseFile(file, options)) success = false; } } else { - for (const QString &file : parser.positionalArguments()) { - if (!parseFile(file, parser.isSet("inplace"), parser.isSet("verbose"), - parser.isSet("force"), indentWidth, - parser.isSet("tabs"), parser.value("newline"))) + for (const QString &file : options.arguments) { + if (!parseFile(file, options)) success = false; } } -#endif return success ? 0 : 1; } -- cgit v1.2.3