Restore display order for unevaluated defines

This commit is contained in:
GriffinR 2024-08-28 15:38:41 -04:00
parent 4b0d30fbc4
commit 869d0c7dec
2 changed files with 51 additions and 56 deletions

View file

@ -54,9 +54,9 @@ public:
QString readCIncbin(const QString &text, const QString &label); QString readCIncbin(const QString &text, const QString &label);
QMap<QString, QString> readCIncbinMulti(const QString &filepath); QMap<QString, QString> readCIncbinMulti(const QString &filepath);
QStringList readCIncbinArray(const QString &filename, const QString &label); QStringList readCIncbinArray(const QString &filename, const QString &label);
QMap<QString, int> readCDefinesByPrefix(const QString &filename, QStringList searchText); QMap<QString, int> readCDefinesByPrefix(const QString &filename, const QStringList &searchText);
QMap<QString, int> readCDefinesByName(const QString &filename, QStringList names); QMap<QString, int> readCDefinesByName(const QString &filename, const QStringList &names);
QStringList readCDefineNames(const QString&, QStringList searchText); QStringList readCDefineNames(const QString&, const QStringList &searchText);
QMap<QString, QHash<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString> = { }); QMap<QString, QHash<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString> = { });
QList<QStringList> getLabelMacros(const QList<QStringList>&, const QString&); QList<QStringList> getLabelMacros(const QList<QStringList>&, const QString&);
QStringList getLabelValues(const QList<QStringList>&, const QString&); QStringList getLabelValues(const QList<QStringList>&, const QString&);
@ -97,9 +97,14 @@ private:
void recordErrors(const QStringList &errors); void recordErrors(const QStringList &errors);
void logRecordedErrors(); void logRecordedErrors();
QString createErrorMessage(const QString &message, const QString &expression); QString createErrorMessage(const QString &message, const QString &expression);
QMap<QString, QString> readCDefineExpressions(const QString &filename);
QMap<QString,QString> filterCDefineExpressions(const QMap<QString,QString> &allExpressions, QStringList searchText, bool fullMatch); struct ParsedDefines {
QMap<QString, int> evaluateCDefines(const QString &filename, const QStringList &searchText, bool fullMatch); QMap<QString,QString> expressions; // Map of all define names->expressions encountered
QStringList filteredNames; // Define names matching the search text in the order they were encountered in the file
};
ParsedDefines readCDefines(const QString &filename, const QStringList &filterList, bool fullMatch);
QMap<QString, int> evaluateCDefines(const QString &filename, const QStringList &filterList, bool fullMatch);
bool defineNameMatchesFilter(const QString &name, const QStringList &filterList, bool fullMatch);
static const QRegularExpression re_incScriptLabel; static const QRegularExpression re_incScriptLabel;
static const QRegularExpression re_globalIncScriptLabel; static const QRegularExpression re_globalIncScriptLabel;

View file

@ -15,7 +15,7 @@ const QRegularExpression ParseUtil::re_poryScriptLabel("\\b(script)(\\((global|l
const QRegularExpression ParseUtil::re_globalPoryScriptLabel("\\b(script)(\\((global)\\))?\\s*\\b(?<label>[\\w_][\\w\\d_]*)"); const QRegularExpression ParseUtil::re_globalPoryScriptLabel("\\b(script)(\\((global)\\))?\\s*\\b(?<label>[\\w_][\\w\\d_]*)");
const QRegularExpression ParseUtil::re_poryRawSection("\\b(raw)\\s*`(?<raw_script>[^`]*)"); const QRegularExpression ParseUtil::re_poryRawSection("\\b(raw)\\s*`(?<raw_script>[^`]*)");
static const QMap<QString, int> defaultDefineValues = { static const QMap<QString, int> globalDefineValues = {
{"FALSE", 0}, {"FALSE", 0},
{"TRUE", 1}, {"TRUE", 1},
{"SCHAR_MIN", SCHAR_MIN}, {"SCHAR_MIN", SCHAR_MIN},
@ -369,14 +369,23 @@ QStringList ParseUtil::readCIncbinArray(const QString &filename, const QString &
return paths; return paths;
} }
// Open the file and return all the names and expressions defined by #define or enum bool ParseUtil::defineNameMatchesFilter(const QString &name, const QStringList &filterList, bool fullMatch) {
QMap<QString,QString> ParseUtil::readCDefineExpressions(const QString &filename) for (auto filter : filterList) {
{ if (fullMatch) {
QMap<QString, QString> expressions; if (name == filter) return true;
} else {
if (name.startsWith(filter) || QRegularExpression(filter).match(name).hasMatch()) return true;
}
}
return false;
}
ParseUtil::ParsedDefines ParseUtil::readCDefines(const QString &filename, const QStringList &filterList, bool fullMatch) {
ParsedDefines result;
this->file = filename; this->file = filename;
if (this->file.isEmpty()) { if (this->file.isEmpty()) {
return expressions; return result;
} }
QString filepath = this->root + "/" + this->file; QString filepath = this->root + "/" + this->file;
@ -384,7 +393,7 @@ QMap<QString,QString> ParseUtil::readCDefineExpressions(const QString &filename)
if (this->text.isNull()) { if (this->text.isNull()) {
logError(QString("Failed to read C defines file: '%1'").arg(filepath)); logError(QString("Failed to read C defines file: '%1'").arg(filepath));
return expressions; return result;
} }
static const QRegularExpression re_extraChars("(//.*)|(\\/+\\*+[^*]*\\*+\\/+)"); static const QRegularExpression re_extraChars("(//.*)|(\\/+\\*+[^*]*\\*+\\/+)");
@ -393,7 +402,7 @@ QMap<QString,QString> ParseUtil::readCDefineExpressions(const QString &filename)
this->text.replace(re_extraSpaces, ""); this->text.replace(re_extraSpaces, "");
if (this->text.isEmpty()) if (this->text.isEmpty())
return expressions; return result;
// Capture either the name and value of a #define, or everything between the braces of 'enum { }' // Capture either the name and value of a #define, or everything between the braces of 'enum { }'
static const QRegularExpression re("#define\\s+(?<defineName>\\w+)[\\s\\n][^\\S\\n]*(?<defineValue>.+)?" static const QRegularExpression re("#define\\s+(?<defineName>\\w+)[\\s\\n][^\\S\\n]*(?<defineValue>.+)?"
@ -411,6 +420,7 @@ QMap<QString,QString> ParseUtil::readCDefineExpressions(const QString &filename)
QRegularExpressionMatchIterator elementIter = re_enumElement.globalMatch(enumBody); QRegularExpressionMatchIterator elementIter = re_enumElement.globalMatch(enumBody);
while (elementIter.hasNext()) { while (elementIter.hasNext()) {
QRegularExpressionMatch elementMatch = elementIter.next(); QRegularExpressionMatch elementMatch = elementIter.next();
const QString name = elementMatch.captured("name");
QString expression = elementMatch.captured("expression"); QString expression = elementMatch.captured("expression");
if (expression.isEmpty()) { if (expression.isEmpty()) {
// enum values may use tokens that we don't know how to evaluate yet. // enum values may use tokens that we don't know how to evaluate yet.
@ -421,74 +431,54 @@ QMap<QString,QString> ParseUtil::readCDefineExpressions(const QString &filename)
baseExpression = expression; baseExpression = expression;
baseNum = 1; baseNum = 1;
} }
expressions.insert(elementMatch.captured("name"), expression); result.expressions.insert(name, expression);
if (defineNameMatchesFilter(name, filterList, fullMatch))
result.filteredNames.append(name);
} }
} else { } else {
// Encountered a #define // Encountered a #define
expressions.insert(match.captured("defineName"), match.captured("defineValue")); const QString name = match.captured("defineName");
result.expressions.insert(name, match.captured("defineValue"));
if (defineNameMatchesFilter(name, filterList, fullMatch))
result.filteredNames.append(name);
} }
} }
return result;
return expressions;
}
// Given a map of define names->expressions, returns a map of define names->expressions where all the names match searchText.
// If 'fullMatch' is true, 'searchText' is a list of exact define names to match.
// If 'fullMatch' is false, 'searchText' is a list of prefixes or regexes of define names to match.
QMap<QString,QString> ParseUtil::filterCDefineExpressions(const QMap<QString,QString> &allExpressions, QStringList searchText, bool fullMatch) {
QMap<QString,QString> filteredExpressions;
searchText.removeDuplicates();
for (auto i = allExpressions.cbegin(), end = allExpressions.cend(); i != end; i++) {
const QString name = i.key();
for (auto s : searchText) {
if ((fullMatch && name == s) || (!fullMatch && (name.startsWith(s) || QRegularExpression(s).match(name).hasMatch()))) {
filteredExpressions.insert(name, i.value());
break;
}
}
}
return filteredExpressions;
} }
// 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). // 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<QString, int> ParseUtil::evaluateCDefines(const QString &filename, const QStringList &searchText, bool fullMatch) { QMap<QString, int> ParseUtil::evaluateCDefines(const QString &filename, const QStringList &filterList, bool fullMatch) {
QMap<QString, int> filteredValues; ParsedDefines defines = readCDefines(filename, filterList, fullMatch);
QMap<QString, int> allValues = defaultDefineValues;
QMap<QString, QString> allExpressions = this->readCDefineExpressions(filename);
if (allExpressions.isEmpty())
return filteredValues;
QMap<QString, QString> filteredExpressions = this->filterCDefineExpressions(allExpressions, searchText, fullMatch);
// Evaluate defines // Evaluate defines
QMap<QString, int> filteredValues;
QMap<QString, int> allValues = globalDefineValues;
this->errorMap.clear(); this->errorMap.clear();
while (!filteredExpressions.isEmpty()) { while (!defines.filteredNames.isEmpty()) {
const QString name = filteredExpressions.firstKey(); const QString name = defines.filteredNames.takeFirst();
const QString expression = filteredExpressions.take(name); const QString expression = defines.expressions.take(name);
if (expression == " ") continue; if (expression == " ") continue;
this->curDefine = name; this->curDefine = name;
filteredValues.insert(name, evaluateDefine(name, expression, &allValues, &allExpressions)); filteredValues.insert(name, evaluateDefine(name, expression, &allValues, &defines.expressions));
logRecordedErrors(); // Only log errors for defines that Porymap is looking for logRecordedErrors(); // Only log errors for defines that Porymap is looking for
} }
return filteredValues; return filteredValues;
} }
// Find and evaluate an unknown list of defines with a known name prefix. // Find and evaluate an unknown list of defines with a known name prefix.
QMap<QString, int> ParseUtil::readCDefinesByPrefix(const QString &filename, QStringList searchText) { QMap<QString, int> ParseUtil::readCDefinesByPrefix(const QString &filename, const QStringList &filterList) {
return this->evaluateCDefines(filename, searchText, false); return evaluateCDefines(filename, filterList, false);
} }
// Find and evaluate a specific set of defines with known names. // Find and evaluate a specific set of defines with known names.
QMap<QString, int> ParseUtil::readCDefinesByName(const QString &filename, QStringList names) { QMap<QString, int> ParseUtil::readCDefinesByName(const QString &filename, const QStringList &names) {
return this->evaluateCDefines(filename, names, true); return evaluateCDefines(filename, names, true);
} }
// Similar to readCDefinesByPrefix, but for cases where we only need to show a list of define names. // Similar to readCDefinesByPrefix, 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). // We can skip evaluating any expressions (and by extension skip reporting any errors from this process).
QStringList ParseUtil::readCDefineNames(const QString &filename, QStringList searchText) { QStringList ParseUtil::readCDefineNames(const QString &filename, const QStringList &filterList) {
// TODO: These will now be alphabetical. Is that ok? return readCDefines(filename, filterList, false).filteredNames;
return this->filterCDefineExpressions(this->readCDefineExpressions(filename), searchText, false).keys();
} }
QStringList ParseUtil::readCArray(const QString &filename, const QString &label) { QStringList ParseUtil::readCArray(const QString &filename, const QString &label) {