in src/checks/level0/qcolor-from-literal.cpp [60:124]
void run(const MatchFinder::MatchResult &result) override
{
auto *lt = result.Nodes.getNodeAs<StringLiteral>("myLiteral");
const Expr *replaceExpr = lt; // When QColor::fromString is used, we want to wrap the QColor constructor around it
bool isStaticFromString = false;
if (auto res = result.Nodes.getNodeAs<CallExpr>("methodCall"); res && res->getNumArgs() == 1) {
if (Expr *argExpr = const_cast<Expr *>(res->getArg(0))) {
lt = clazy::getFirstChildOfType<StringLiteral>(argExpr);
replaceExpr = res;
isStaticFromString = true;
}
}
if (!lt) {
return;
}
llvm::StringRef str = lt->getString();
if (!clazy::startsWith(str, "#")) {
return;
}
const bool singleDigit = isSingleDigitRgb(str);
const bool doubleDigit = isDoubleDigitRgb(str);
const bool doubleDigitA = isDoubleDigitRgba(str);
if (bool isAnyValidPattern = singleDigit || doubleDigit || doubleDigitA || isTripleDigitRgb(str) || isQuadrupleDigitRgb(str); !isAnyValidPattern) {
m_check->emitWarning(replaceExpr->getBeginLoc(), "Pattern length does not match any supported one by QColor, check the documentation");
return;
}
for (unsigned int i = 1; i < str.size(); ++i) {
if (!isxdigit(str[i])) {
m_check->emitWarning(replaceExpr->getBeginLoc(), "QColor pattern may only contain hexadecimal digits");
return;
}
}
if (singleDigit || doubleDigit || doubleDigitA) {
const int increment = singleDigit ? 1 : 2;
int endPos = 1;
int startPos = 1;
std::string aColor = doubleDigitA ? getHexValue(str, startPos, endPos, increment) : "";
std::string rColor = getHexValue(str, startPos, endPos, increment);
std::string gColor = getHexValue(str, startPos, endPos, increment);
std::string bColor = getHexValue(str, startPos, endPos, increment);
std::string fixit;
std::string message;
if (doubleDigitA) {
const static std::string sep = ", ";
fixit = prefixHex(rColor) + sep + prefixHex(gColor) + sep + prefixHex(bColor) + sep + prefixHex(aColor);
message = "The QColor ctor taking ints is cheaper than one taking string literals";
} else {
fixit = "0x" + twoDigit(rColor) + twoDigit(gColor) + twoDigit(bColor);
message = "The QColor ctor taking RGB int value is cheaper than one taking string literals";
}
if (isStaticFromString) {
fixit = "QColor(" + fixit + ")";
}
m_check->emitWarning(replaceExpr->getBeginLoc(), message, {clang::FixItHint::CreateReplacement(replaceExpr->getSourceRange(), fixit)});
} else {
// triple or quadruple digit RGBA
m_check->emitWarning(replaceExpr->getBeginLoc(), "The QColor ctor taking QRgba64 is cheaper than one taking string literals");
}
}