From 17c35a8d985d47eae6fca11c25cb95b424e2eea2 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 18 Feb 2025 14:53:25 -0500 Subject: [PATCH] Condense parser error messages --- include/core/parseutil.h | 19 +++-- include/lib/orderedjson.h | 6 +- src/core/parseutil.cpp | 59 ++++++--------- src/lib/orderedjson.cpp | 8 +- src/project.cpp | 146 +++++++++++++++++++++---------------- src/ui/prefab.cpp | 8 +- src/ui/regionmapeditor.cpp | 18 ++--- 7 files changed, 135 insertions(+), 129 deletions(-) diff --git a/include/core/parseutil.h b/include/core/parseutil.h index b220597a..b8ba9f55 100644 --- a/include/core/parseutil.h +++ b/include/core/parseutil.h @@ -44,25 +44,24 @@ class ParseUtil public: ParseUtil(); void set_root(const QString &dir); - static QString readTextFile(const QString &path); + static QString readTextFile(const QString &path, QString *error = nullptr); void invalidateTextFile(const QString &path); static int textFileLineCount(const QString &path); QList parseAsm(const QString &filename); QStringList readCArray(const QString &filename, const QString &label); QMap readCArrayMulti(const QString &filename); - QMap readNamedIndexCArray(const QString &text, const QString &label); + QMap readNamedIndexCArray(const QString &text, const QString &label, QString *error = nullptr); QString readCIncbin(const QString &text, const QString &label); QMap readCIncbinMulti(const QString &filepath); QStringList readCIncbinArray(const QString &filename, const QString &label); - QMap readCDefinesByRegex(const QString &filename, const QStringList ®exList); - QMap readCDefinesByName(const QString &filename, const QStringList &names); - QStringList readCDefineNames(const QString &filename, const QStringList ®exList); + QMap readCDefinesByRegex(const QString &filename, const QStringList ®exList, QString *error = nullptr); + QMap readCDefinesByName(const QString &filename, const QStringList &names, QString *error = nullptr); + QStringList readCDefineNames(const QString &filename, const QStringList ®exList, QString *error = nullptr); tsl::ordered_map> readCStructs(const QString &, const QString & = "", const QHash& = {}); QList getLabelMacros(const QList&, const QString&); QStringList getLabelValues(const QList&, const QString&); - bool tryParseJsonFile(QJsonDocument *out, const QString &filepath); - bool tryParseOrderedJsonFile(poryjson::Json::object *out, const QString &filepath); - bool ensureFieldsExist(const QJsonObject &obj, const QList &fields); + bool tryParseJsonFile(QJsonDocument *out, const QString &filepath, QString *error = nullptr); + bool tryParseOrderedJsonFile(poryjson::Json::object *out, const QString &filepath, QString *error = nullptr); // Returns the 1-indexed line number for the definition of scriptLabel in the scripts file at filePath. // Returns 0 if a definition for scriptLabel cannot be found. @@ -102,8 +101,8 @@ private: QMap expressions; // Map of all define names encountered to their expressions QStringList filteredNames; // List of define names that matched the search text, in the order that they were encountered }; - ParsedDefines readCDefines(const QString &filename, const QStringList &filterList, bool useRegex); - QMap evaluateCDefines(const QString &filename, const QStringList &filterList, bool useRegex); + ParsedDefines readCDefines(const QString &filename, const QStringList &filterList, bool useRegex, QString *error); + QMap evaluateCDefines(const QString &filename, const QStringList &filterList, bool useRegex, QString *error); bool defineNameMatchesFilter(const QString &name, const QStringList &filterList) const; bool defineNameMatchesFilter(const QString &name, const QList &filterList) const; diff --git a/include/lib/orderedjson.h b/include/lib/orderedjson.h index 386937f9..544112f1 100644 --- a/include/lib/orderedjson.h +++ b/include/lib/orderedjson.h @@ -182,15 +182,15 @@ public: // Parse. If parse fails, return Json() and assign an error message to err. static Json parse(const QString & in, - QString & err, + QString * err = nullptr, JsonParse strategy = JsonParse::STANDARD); static Json parse(const char * in, - QString & err, + QString * err = nullptr, JsonParse strategy = JsonParse::STANDARD) { if (in) { return parse(QString(in), err, strategy); } else { - err = "null input"; + if (err) *err = "null input"; return nullptr; } } diff --git a/src/core/parseutil.cpp b/src/core/parseutil.cpp index d67989ae..9769d86e 100644 --- a/src/core/parseutil.cpp +++ b/src/core/parseutil.cpp @@ -67,10 +67,10 @@ QString ParseUtil::createErrorMessage(const QString &message, const QString &exp return QString("%1:%2:%3: %4").arg(this->file).arg(lineNum).arg(colNum).arg(message); } -QString ParseUtil::readTextFile(const QString &path) { +QString ParseUtil::readTextFile(const QString &path, QString *error) { QFile file(path); if (!file.open(QIODevice::ReadOnly)) { - logError(QString("Could not open '%1': ").arg(path) + file.errorString()); + if (error) *error = file.errorString(); return QString(); } QTextStream in(&file); @@ -380,7 +380,7 @@ bool ParseUtil::defineNameMatchesFilter(const QString &name, const QListfile = filename; @@ -389,12 +389,9 @@ ParseUtil::ParsedDefines ParseUtil::readCDefines(const QString &filename, const } QString filepath = this->root + "/" + this->file; - this->text = readTextFile(filepath); - - if (this->text.isNull()) { - logError(QString("Failed to read C defines file: '%1'").arg(filepath)); + this->text = readTextFile(filepath, error); + if (this->text.isNull()) return result; - } static const QRegularExpression re_extraChars("(//.*)|(\\/+\\*+[^*]*\\*+\\/+)"); this->text.replace(re_extraChars, ""); @@ -466,8 +463,8 @@ ParseUtil::ParsedDefines ParseUtil::readCDefines(const QString &filename, const } // Read all the define names and their expressions in the specified file, then evaluate the ones matching the search text (and any they depend on). -QMap ParseUtil::evaluateCDefines(const QString &filename, const QStringList &filterList, bool useRegex) { - ParsedDefines defines = readCDefines(filename, filterList, useRegex); +QMap ParseUtil::evaluateCDefines(const QString &filename, const QStringList &filterList, bool useRegex, QString *error) { + ParsedDefines defines = readCDefines(filename, filterList, useRegex, error); // Evaluate defines QMap filteredValues; @@ -486,20 +483,20 @@ QMap ParseUtil::evaluateCDefines(const QString &filename, const QS } // Find and evaluate a specific set of defines with known names. -QMap ParseUtil::readCDefinesByName(const QString &filename, const QStringList &names) { - return evaluateCDefines(filename, names, false); +QMap ParseUtil::readCDefinesByName(const QString &filename, const QStringList &names, QString *error) { + return evaluateCDefines(filename, names, false, error); } // Find and evaluate an unknown list of defines with a known name pattern. -QMap ParseUtil::readCDefinesByRegex(const QString &filename, const QStringList ®exList) { - return evaluateCDefines(filename, regexList, true); +QMap ParseUtil::readCDefinesByRegex(const QString &filename, const QStringList ®exList, QString *error) { + return evaluateCDefines(filename, regexList, true, error); } // Find an unknown list of defines with a known name pattern. // Similar to readCDefinesByRegex, but for cases where we only need to show a list of define names. // We can skip evaluating any expressions (and by extension skip reporting any errors from this process). -QStringList ParseUtil::readCDefineNames(const QString &filename, const QStringList ®exList) { - return readCDefines(filename, regexList, true).filteredNames; +QStringList ParseUtil::readCDefineNames(const QString &filename, const QStringList ®exList, QString *error) { + return readCDefines(filename, regexList, true, error).filteredNames; } QStringList ParseUtil::readCArray(const QString &filename, const QString &label) { @@ -558,8 +555,8 @@ QMap ParseUtil::readCArrayMulti(const QString &filename) { return map; } -QMap ParseUtil::readNamedIndexCArray(const QString &filename, const QString &label) { - this->text = readTextFile(this->root + "/" + filename); +QMap ParseUtil::readNamedIndexCArray(const QString &filename, const QString &label, QString *error) { + this->text = readTextFile(this->root + "/" + filename, error); QMap map; QRegularExpression re_text(QString(R"(\b%1\b\s*(\[?[^\]]*\])?\s*=\s*\{([^\}]*)\})").arg(label)); @@ -659,10 +656,10 @@ QStringList ParseUtil::getLabelValues(const QList &list, const QStr return values; } -bool ParseUtil::tryParseJsonFile(QJsonDocument *out, const QString &filepath) { +bool ParseUtil::tryParseJsonFile(QJsonDocument *out, const QString &filepath, QString *error) { QFile file(filepath); if (!file.open(QIODevice::ReadOnly)) { - logError(QString("Error: Could not open %1 for reading").arg(filepath)); + if (error) *error = file.errorString(); return false; } @@ -671,7 +668,7 @@ bool ParseUtil::tryParseJsonFile(QJsonDocument *out, const QString &filepath) { const QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseError); file.close(); if (parseError.error != QJsonParseError::NoError) { - logError(QString("Error: Failed to parse json file %1: %2").arg(filepath).arg(parseError.errorString())); + if (error) *error = parseError.errorString(); return false; } @@ -679,23 +676,15 @@ bool ParseUtil::tryParseJsonFile(QJsonDocument *out, const QString &filepath) { return true; } -bool ParseUtil::tryParseOrderedJsonFile(poryjson::Json::object *out, const QString &filepath) { +bool ParseUtil::tryParseOrderedJsonFile(poryjson::Json::object *out, const QString &filepath, QString *error) { QString err; - QString jsonTxt = readTextFile(filepath); - *out = OrderedJson::parse(jsonTxt, err).object_items(); - if (!err.isEmpty()) { - logError(QString("Error: Failed to parse json file %1: %2").arg(filepath).arg(err)); + QString jsonTxt = readTextFile(filepath, error); + if (error && !error->isEmpty()) { return false; } - return true; -} - -bool ParseUtil::ensureFieldsExist(const QJsonObject &obj, const QList &fields) { - for (QString field : fields) { - if (!obj.contains(field)) { - logError(QString("JSON object is missing field '%1'.").arg(field)); - return false; - } + *out = OrderedJson::parse(jsonTxt, error).object_items(); + if (error && !error->isEmpty()) { + return false; } return true; } diff --git a/src/lib/orderedjson.cpp b/src/lib/orderedjson.cpp index e1a600aa..24bb264a 100644 --- a/src/lib/orderedjson.cpp +++ b/src/lib/orderedjson.cpp @@ -393,7 +393,7 @@ struct JsonParser final { */ const QString &str; int i; - QString &err; + QString *err; bool failed; const JsonParse strategy; @@ -407,8 +407,8 @@ struct JsonParser final { template T fail(QString &&msg, const T err_ret) { - if (!failed) - err = std::move(msg); + if (!failed && err) + *err = std::move(msg); failed = true; return err_ret; } @@ -775,7 +775,7 @@ struct JsonParser final { }; }//namespace { -Json Json::parse(const QString &in, QString &err, JsonParse strategy) { +Json Json::parse(const QString &in, QString *err, JsonParse strategy) { JsonParser parser { in, 0, err, false, strategy }; Json result = parser.parse_json(0); diff --git a/src/project.cpp b/src/project.cpp index ecad57dd..330c58c2 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -196,8 +196,9 @@ void Project::initTopLevelMapFields() { bool Project::readMapJson(const QString &mapName, QJsonDocument * out) { const QString mapFilepath = QString("%1%2/map.json").arg(projectConfig.getFilePath(ProjectFilePath::data_map_folders)).arg(mapName); - if (!parser.tryParseJsonFile(out, QString("%1/%2").arg(this->root).arg(mapFilepath))) { - logError(QString("Failed to read map data from %1").arg(mapFilepath)); + QString error; + if (!parser.tryParseJsonFile(out, QString("%1/%2").arg(this->root).arg(mapFilepath), &error)) { + logError(QString("Failed to read map data from '%1': %2").arg(mapFilepath).arg(error)); return false; } return true; @@ -514,8 +515,9 @@ bool Project::readMapLayouts() { const QString fullFilepath = QString("%1/%2").arg(this->root).arg(layoutsFilepath); fileWatcher.addPath(fullFilepath); QJsonDocument layoutsDoc; - if (!parser.tryParseJsonFile(&layoutsDoc, fullFilepath)) { - logError(QString("Failed to read map layouts from %1").arg(fullFilepath)); + QString error; + if (!parser.tryParseJsonFile(&layoutsDoc, fullFilepath, &error)) { + logError(QString("Failed to read map layouts from '%1': %2").arg(fullFilepath).arg(error)); return false; } @@ -1626,13 +1628,15 @@ bool Project::readWildMonData() { this->pokemonMaxLevel = qMax(this->pokemonMinLevel, this->pokemonMaxLevel); // Read encounter data - QString wildMonJsonFilepath = QString("%1/%2").arg(root).arg(projectConfig.getFilePath(ProjectFilePath::json_wild_encounters)); + const QString wildMonJsonBaseFilepath = projectConfig.getFilePath(ProjectFilePath::json_wild_encounters); + QString wildMonJsonFilepath = QString("%1/%2").arg(root).arg(wildMonJsonBaseFilepath); fileWatcher.addPath(wildMonJsonFilepath); OrderedJson::object wildMonObj; - if (!parser.tryParseOrderedJsonFile(&wildMonObj, wildMonJsonFilepath)) { + QString error; + if (!parser.tryParseOrderedJsonFile(&wildMonObj, wildMonJsonFilepath, &error)) { // Failing to read wild encounters data is not a critical error, the encounter editor will just be disabled - logWarn(QString("Failed to read wild encounters from %1").arg(wildMonJsonFilepath)); + logWarn(QString("Failed to read wild encounters from '%1': %2").arg(wildMonJsonBaseFilepath).arg(error)); return true; } @@ -1761,8 +1765,9 @@ bool Project::readMapGroups() { const QString filepath = root + "/" + projectConfig.getFilePath(ProjectFilePath::json_map_groups); fileWatcher.addPath(filepath); QJsonDocument mapGroupsDoc; - if (!parser.tryParseJsonFile(&mapGroupsDoc, filepath)) { - logError(QString("Failed to read map groups from %1").arg(filepath)); + QString error; + if (!parser.tryParseJsonFile(&mapGroupsDoc, filepath, &error)) { + logError(QString("Failed to read map groups from '%1': %2").arg(filepath).arg(error)); return false; } @@ -2268,8 +2273,9 @@ bool Project::readRegionMapSections() { QJsonDocument doc; const QString baseFilepath = projectConfig.getFilePath(ProjectFilePath::json_region_map_entries); const QString filepath = QString("%1/%2").arg(this->root).arg(baseFilepath); - if (!parser.tryParseJsonFile(&doc, filepath)) { - logError(QString("Failed to read region map sections from '%1'").arg(baseFilepath)); + QString error; + if (!parser.tryParseJsonFile(&doc, filepath, &error)) { + logError(QString("Failed to read region map sections from '%1': %2").arg(baseFilepath).arg(error)); return false; } fileWatcher.addPath(filepath); @@ -2394,8 +2400,9 @@ bool Project::readHealLocations() { QJsonDocument doc; const QString baseFilepath = projectConfig.getFilePath(ProjectFilePath::json_heal_locations); const QString filepath = QString("%1/%2").arg(this->root).arg(baseFilepath); - if (!parser.tryParseJsonFile(&doc, filepath)) { - logError(QString("Failed to read heal locations from '%1'").arg(baseFilepath)); + QString error; + if (!parser.tryParseJsonFile(&doc, filepath, &error)) { + logError(QString("Failed to read heal locations from '%1': %2").arg(baseFilepath).arg(error)); return false; } fileWatcher.addPath(filepath); @@ -2421,9 +2428,10 @@ bool Project::readItemNames() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_items)}; const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_items); fileWatcher.addPath(root + "/" + filename); - itemNames = parser.readCDefineNames(filename, regexList); - if (itemNames.isEmpty()) - logWarn(QString("Failed to read item constants from %1").arg(filename)); + QString error; + this->itemNames = parser.readCDefineNames(filename, regexList, &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read item constants from '%1': %2").arg(filename).arg(error)); return true; } @@ -2431,9 +2439,10 @@ bool Project::readFlagNames() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_flags)}; const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_flags); fileWatcher.addPath(root + "/" + filename); - flagNames = parser.readCDefineNames(filename, regexList); - if (flagNames.isEmpty()) - logWarn(QString("Failed to read flag constants from %1").arg(filename)); + QString error; + this->flagNames = parser.readCDefineNames(filename, regexList, &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read flag constants from '%1': %2").arg(filename).arg(error)); return true; } @@ -2441,9 +2450,10 @@ bool Project::readVarNames() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_vars)}; const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_vars); fileWatcher.addPath(root + "/" + filename); - varNames = parser.readCDefineNames(filename, regexList); - if (varNames.isEmpty()) - logWarn(QString("Failed to read var constants from %1").arg(filename)); + QString error; + this->varNames = parser.readCDefineNames(filename, regexList, &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read var constants from '%1': %2").arg(filename).arg(error)); return true; } @@ -2451,18 +2461,20 @@ bool Project::readMovementTypes() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_movement_types)}; const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_obj_event_movement); fileWatcher.addPath(root + "/" + filename); - movementTypes = parser.readCDefineNames(filename, regexList); - if (movementTypes.isEmpty()) - logWarn(QString("Failed to read movement type constants from %1").arg(filename)); + QString error; + this->movementTypes = parser.readCDefineNames(filename, regexList, &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read movement type constants from '%1': %2").arg(filename).arg(error)); return true; } bool Project::readInitialFacingDirections() { QString filename = projectConfig.getFilePath(ProjectFilePath::initial_facing_table); fileWatcher.addPath(root + "/" + filename); - facingDirections = parser.readNamedIndexCArray(filename, projectConfig.getIdentifier(ProjectIdentifier::symbol_facing_directions)); - if (facingDirections.isEmpty()) - logWarn(QString("Failed to read initial movement type facing directions from %1").arg(filename)); + QString error; + this->facingDirections = parser.readNamedIndexCArray(filename, projectConfig.getIdentifier(ProjectIdentifier::symbol_facing_directions), &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read initial movement type facing directions from '%1': %2").arg(filename).arg(error)); return true; } @@ -2470,9 +2482,10 @@ bool Project::readMapTypes() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_map_types)}; const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types); fileWatcher.addPath(root + "/" + filename); - mapTypes = parser.readCDefineNames(filename, regexList); - if (mapTypes.isEmpty()) - logWarn(QString("Failed to read map type constants from %1").arg(filename)); + QString error; + this->mapTypes = parser.readCDefineNames(filename, regexList, &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read map type constants from '%1': %2").arg(filename).arg(error)); return true; } @@ -2480,9 +2493,10 @@ bool Project::readMapBattleScenes() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_battle_scenes)}; const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types); fileWatcher.addPath(root + "/" + filename); - mapBattleScenes = parser.readCDefineNames(filename, regexList); - if (mapBattleScenes.isEmpty()) - logWarn(QString("Failed to read map battle scene constants from %1").arg(filename)); + QString error; + this->mapBattleScenes = parser.readCDefineNames(filename, regexList, &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read map battle scene constants from '%1': %2").arg(filename).arg(error)); return true; } @@ -2490,9 +2504,10 @@ bool Project::readWeatherNames() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_weather)}; const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather); fileWatcher.addPath(root + "/" + filename); - weatherNames = parser.readCDefineNames(filename, regexList); - if (weatherNames.isEmpty()) - logWarn(QString("Failed to read weather constants from %1").arg(filename)); + QString error; + this->weatherNames = parser.readCDefineNames(filename, regexList, &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read weather constants from '%1': %2").arg(filename).arg(error)); return true; } @@ -2503,9 +2518,10 @@ bool Project::readCoordEventWeatherNames() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_coord_event_weather)}; const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather); fileWatcher.addPath(root + "/" + filename); - coordEventWeatherNames = parser.readCDefineNames(filename, regexList); - if (coordEventWeatherNames.isEmpty()) - logWarn(QString("Failed to read coord event weather constants from %1").arg(filename)); + QString error; + this->coordEventWeatherNames = parser.readCDefineNames(filename, regexList, &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read coord event weather constants from '%1': %2").arg(filename).arg(error)); return true; } @@ -2516,9 +2532,10 @@ bool Project::readSecretBaseIds() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_secret_bases)}; const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_secret_bases); fileWatcher.addPath(root + "/" + filename); - secretBaseIds = parser.readCDefineNames(filename, regexList); - if (secretBaseIds.isEmpty()) - logWarn(QString("Failed to read secret base id constants from '%1'").arg(filename)); + QString error; + this->secretBaseIds = parser.readCDefineNames(filename, regexList, &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read secret base id constants from '%1': %2").arg(filename).arg(error)); return true; } @@ -2526,9 +2543,10 @@ bool Project::readBgEventFacingDirections() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_sign_facing_directions)}; const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_event_bg); fileWatcher.addPath(root + "/" + filename); - bgEventFacingDirections = parser.readCDefineNames(filename, regexList); - if (bgEventFacingDirections.isEmpty()) - logWarn(QString("Failed to read bg event facing direction constants from %1").arg(filename)); + QString error; + this->bgEventFacingDirections = parser.readCDefineNames(filename, regexList, &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read bg event facing direction constants from '%1': %2").arg(filename).arg(error)); return true; } @@ -2536,9 +2554,10 @@ bool Project::readTrainerTypes() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_trainer_types)}; const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_trainer_types); fileWatcher.addPath(root + "/" + filename); - trainerTypes = parser.readCDefineNames(filename, regexList); - if (trainerTypes.isEmpty()) - logWarn(QString("Failed to read trainer type constants from %1").arg(filename)); + QString error; + this->trainerTypes = parser.readCDefineNames(filename, regexList, &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read trainer type constants from '%1': %2").arg(filename).arg(error)); return true; } @@ -2549,13 +2568,14 @@ bool Project::readMetatileBehaviors() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_behaviors)}; QString filename = projectConfig.getFilePath(ProjectFilePath::constants_metatile_behaviors); fileWatcher.addPath(root + "/" + filename); - QMap defines = parser.readCDefinesByRegex(filename, regexList); - if (defines.isEmpty()) { - // Not having any metatile behavior names is ok (their values will be displayed instead). - // If the user's metatiles can have nonzero values then warn them, as they likely want names. - if (projectConfig.metatileBehaviorMask) - logWarn(QString("Failed to read metatile behaviors from %1.").arg(filename)); - return true; + QString error; + QMap defines = parser.readCDefinesByRegex(filename, regexList, &error); + if (defines.isEmpty() && projectConfig.metatileBehaviorMask) { + // Not having any metatile behavior names is ok (their values will be displayed instead) + // but if the user's metatiles can have nonzero values then warn them, as they likely want names. + QString warning = QString("Failed to read metatile behaviors from '%1'").arg(filename); + if (!error.isEmpty()) warning += QString(": %1").arg(error); + logWarn(warning); } for (auto i = defines.cbegin(), end = defines.cend(); i != end; i++) { @@ -2571,9 +2591,10 @@ bool Project::readSongNames() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_music)}; const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_songs); fileWatcher.addPath(root + "/" + filename); - this->songNames = parser.readCDefineNames(filename, regexList); - if (this->songNames.isEmpty()) - logWarn(QString("Failed to read song names from %1.").arg(filename)); + QString error; + this->songNames = parser.readCDefineNames(filename, regexList, &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read song names from '%1': %2").arg(filename).arg(error)); // Song names don't have a very useful order (esp. if we include SE_* values), so sort them alphabetically. // The default song should be the first in the list, not the first alphabetically, so save that before sorting. @@ -2586,9 +2607,10 @@ bool Project::readObjEventGfxConstants() { const QStringList regexList = {projectConfig.getIdentifier(ProjectIdentifier::regex_obj_event_gfx)}; QString filename = projectConfig.getFilePath(ProjectFilePath::constants_obj_events); fileWatcher.addPath(root + "/" + filename); - this->gfxDefines = parser.readCDefinesByRegex(filename, regexList); - if (this->gfxDefines.isEmpty()) - logWarn(QString("Failed to read object event graphics constants from %1.").arg(filename)); + QString error; + this->gfxDefines = parser.readCDefinesByRegex(filename, regexList, &error); + if (!error.isEmpty()) + logWarn(QString("Failed to read object event graphics constants from '%1': %2").arg(filename).arg(error)); return true; } diff --git a/src/ui/prefab.cpp b/src/ui/prefab.cpp index 6a406072..bef6d9fe 100644 --- a/src/ui/prefab.cpp +++ b/src/ui/prefab.cpp @@ -27,8 +27,12 @@ void Prefab::loadPrefabs() { QJsonDocument prefabDoc; QString validPath = Project::getExistingFilepath(filepath); - if (validPath.isEmpty() || !parser.tryParseJsonFile(&prefabDoc, validPath)) { - logError(QString("Failed to read prefab data from %1").arg(filepath)); + if (validPath.isEmpty()) + return; + + QString error; + if (!parser.tryParseJsonFile(&prefabDoc, validPath, &error)) { + logError(QString("Failed to read prefab data from %1: %2").arg(filepath).arg(error)); return; } filepath = validPath; diff --git a/src/ui/regionmapeditor.cpp b/src/ui/regionmapeditor.cpp index 21b5c76d..94b7c8c6 100644 --- a/src/ui/regionmapeditor.cpp +++ b/src/ui/regionmapeditor.cpp @@ -120,26 +120,20 @@ bool RegionMapEditor::saveRegionMapEntries() { void buildEmeraldDefaults(poryjson::Json &json) { ParseUtil parser; QString emeraldDefault = parser.readTextFile(":/text/region_map_default_emerald.json"); - - QString err; - json = poryjson::Json::parse(emeraldDefault, err); + json = poryjson::Json::parse(emeraldDefault); } void buildRubyDefaults(poryjson::Json &json) { ParseUtil parser; QString emeraldDefault = parser.readTextFile(":/text/region_map_default_ruby.json"); - - QString err; - json = poryjson::Json::parse(emeraldDefault, err); + json = poryjson::Json::parse(emeraldDefault); } void buildFireredDefaults(poryjson::Json &json) { ParseUtil parser; QString fireredDefault = parser.readTextFile(":/text/region_map_default_firered.json"); - - QString err; - json = poryjson::Json::parse(fireredDefault, err); + json = poryjson::Json::parse(fireredDefault); } poryjson::Json RegionMapEditor::buildDefaultJson() { @@ -199,8 +193,7 @@ bool RegionMapEditor::buildConfigDialog() { poryjson::Json::object newJson; poryjson::Json::array mapArr; for (auto item : regionMapList->findItems("*", Qt::MatchWildcard)) { - QString err; - poryjson::Json itemJson = poryjson::Json::parse(item->data(Qt::UserRole).toString(), err); + poryjson::Json itemJson = poryjson::Json::parse(item->data(Qt::UserRole).toString()); mapArr.append(itemJson); } newJson["region_maps"] = mapArr; @@ -213,8 +206,7 @@ bool RegionMapEditor::buildConfigDialog() { connect(regionMapList, &QListWidget::itemDoubleClicked, [this, &rmConfigJsonUpdate, updateMapList, regionMapList](QListWidgetItem *item) { int itemIndex = regionMapList->row(item); - QString err; - poryjson::Json clickedJson = poryjson::Json::parse(item->data(Qt::UserRole).toString(), err); + poryjson::Json clickedJson = poryjson::Json::parse(item->data(Qt::UserRole).toString()); RegionMapPropertiesDialog dialog(this); dialog.setProject(this->project);