Fix #4706: don't replace ampersands when loading from plain text (#4734)

* Fix #4706: Exit linting early if a card with the exact name is found first

* Remove ampersand conversion

* put back

* Update tests

* Format

* don't use qsizetype

---------

Co-authored-by: ebbit1q <ebbit1q@gmail.com>
This commit is contained in:
Zach H 2023-01-29 15:37:28 -08:00 committed by GitHub
parent 42d1d66d9b
commit 4c290aec57
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 28 additions and 24 deletions

View file

@ -289,7 +289,7 @@ QString DeckLoader::getCardZoneFromName(QString cardName, QString currentZoneNam
return currentZoneName;
}
QString DeckLoader::getCompleteCardName(const QString cardName) const
QString DeckLoader::getCompleteCardName(const QString &cardName) const
{
if (db) {
CardInfoPtr temp = db->guessCard(cardName);

View file

@ -58,7 +58,7 @@ protected:
QList<DecklistCardNode *> cards,
bool addComments = true);
virtual QString getCardZoneFromName(QString cardName, QString currentZoneName);
virtual QString getCompleteCardName(const QString cardName) const;
virtual QString getCompleteCardName(const QString &cardName) const;
};
#endif

View file

@ -488,34 +488,33 @@ bool DeckList::saveToFile_Native(QIODevice *device)
bool DeckList::loadFromStream_Plain(QTextStream &in)
{
const QRegularExpression reCardLine("^\\s*[\\w\\[\\(\\{].*$", QRegularExpression::UseUnicodePropertiesOption);
const QRegularExpression reCardLine(R"(^\s*[\w\[\(\{].*$)", QRegularExpression::UseUnicodePropertiesOption);
const QRegularExpression reEmpty("^\\s*$");
const QRegularExpression reComment("[\\w\\[\\(\\{].*$", QRegularExpression::UseUnicodePropertiesOption);
const QRegularExpression reComment(R"([\w\[\(\{].*$)", QRegularExpression::UseUnicodePropertiesOption);
const QRegularExpression reSBMark("^\\s*sb:\\s*(.+)", QRegularExpression::CaseInsensitiveOption);
const QRegularExpression reSBComment("^sideboard\\b.*$", QRegularExpression::CaseInsensitiveOption);
const QRegularExpression reDeckComment("^((main)?deck(list)?|mainboard)\\b",
QRegularExpression::CaseInsensitiveOption);
// simplified matches
const QRegularExpression reMultiplier("^[xX\\(\\[]*(\\d+)[xX\\*\\)\\]]* ?(.+)");
const QRegularExpression reBrace(" ?[\\[\\{][^\\]\\}]*[\\]\\}] ?"); // not nested
const QRegularExpression reRoundBrace("^\\([^\\)]*\\) ?"); // () are only matched at start of string
const QRegularExpression reDigitBrace(" ?\\(\\d*\\) ?"); // () are matched if containing digits
const QRegularExpression reBraceDigit(
" ?\\([\\dA-Z]+\\) *\\d+$"); // () are matched if containing setcode then a number
const QRegularExpression reMultiplier(R"(^[xX\(\[]*(\d+)[xX\*\)\]]* ?(.+))");
const QRegularExpression reBrace(R"( ?[\[\{][^\]\}]*[\]\}] ?)"); // not nested
const QRegularExpression reRoundBrace(R"(^\([^\)]*\) ?)"); // () are only matched at start of string
const QRegularExpression reDigitBrace(R"( ?\(\d*\) ?)"); // () are matched if containing digits
// () are matched if containing setcode then a number
const QRegularExpression reBraceDigit(R"( ?\([\dA-Z]+\) *\d+$)");
const QHash<QRegularExpression, QString> differences{{QRegularExpression(""), QString("'")},
{QRegularExpression("Æ"), QString("Ae")},
{QRegularExpression("æ"), QString("ae")},
{QRegularExpression(" ?[|/]+ ?"), QString(" // ")},
{QRegularExpression("(?<![A-Z]) ?& ?"), QString(" // ")}};
{QRegularExpression(" ?[|/]+ ?"), QString(" // ")}};
cleanList();
QStringList inputs = in.readAll().trimmed().split('\n');
int max_line = inputs.size();
auto inputs = in.readAll().trimmed().split('\n');
auto max_line = inputs.size();
// start at the first empty line before the first cardline
int deckStart = inputs.indexOf(reCardLine);
auto deckStart = inputs.indexOf(reCardLine);
if (deckStart == -1) { // there are no cards?
if (inputs.indexOf(reComment) == -1) {
return false; // input is empty
@ -537,7 +536,7 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
if (sBStart == -1) {
sBStart = max_line;
}
int nextCard = inputs.indexOf(reCardLine, sBStart + 1);
auto nextCard = inputs.indexOf(reCardLine, sBStart + 1);
if (inputs.indexOf(reEmpty, nextCard + 1) != -1) {
sBStart = max_line; // if there is another empty line all cards are mainboard
}
@ -549,7 +548,7 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
// parse name and comments
while (index < deckStart) {
const QString current = inputs.at(index++);
const auto &current = inputs.at(index++);
if (!current.contains(reEmpty)) {
match = reComment.match(current);
name = match.captured();
@ -557,7 +556,7 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
}
}
while (index < deckStart) {
const QString current = inputs.at(index++);
const auto &current = inputs.at(index++);
if (!current.contains(reEmpty)) {
match = reComment.match(current);
comments += match.captured() + '\n';
@ -631,7 +630,7 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
return true;
}
InnerDecklistNode *DeckList::getZoneObjFromName(const QString zoneName)
InnerDecklistNode *DeckList::getZoneObjFromName(const QString &zoneName)
{
for (int i = 0; i < root->size(); i++) {
auto *node = dynamic_cast<InnerDecklistNode *>(root->at(i));

View file

@ -178,14 +178,14 @@ private:
QMap<QString, SideboardPlan *> sideboardPlans;
InnerDecklistNode *root;
void getCardListHelper(InnerDecklistNode *node, QSet<QString> &result) const;
InnerDecklistNode *getZoneObjFromName(QString zoneName);
InnerDecklistNode *getZoneObjFromName(const QString &zoneName);
protected:
virtual QString getCardZoneFromName(const QString /*cardName*/, QString currentZoneName)
{
return currentZoneName;
};
virtual QString getCompleteCardName(const QString cardName) const
virtual QString getCompleteCardName(const QString &cardName) const
{
return cardName;
};

View file

@ -127,9 +127,10 @@ TEST(LoadingFromClipboardTest, EdgeCaseTesting)
//(test) Æ | / (3)
// Mainboard (10 cards)
// Mainboard (11 cards)
Æther Adept
2x Fire & Ice
2x Fire // Ice
1 Minsc & Boo, Timeless Heroes
3 Pain/Suffering
4X [B] Forest (3)
@ -145,7 +146,11 @@ TEST(LoadingFromClipboardTest, EdgeCaseTesting)
)");
Result result("DeckName", "Comment 1\n\nComment [two]\n(test) Æ | / (3)",
{{"Aether Adept", 1}, {"Fire // Ice", 2}, {"Pain // Suffering", 3}, {"Forest", 4}},
{{"Aether Adept", 1},
{"Fire // Ice", 2},
{"Minsc & Boo, Timeless Heroes", 1},
{"Pain // Suffering", 3},
{"Forest", 4}},
{{"Nature's Resurgence", 5}, {"Gaea's Skyfolk", 6}, {"B.F.M. (Big Furry Monster)", 7}});
testDeck(clipboard, result);
}