// Find uses of OUString in conditional expressions that could be rewritten as std::u16string_view, // as in // // s += (b ? OUString("xy") : OUString(z");
namespace
{ // Like Expr::IgnoreImplicit, but for an ImplicitCastExpr skips to getSubExprAsWritten (so skips a // CXXConstructExpr where Expr::IgnoreImplicit would stop):
Expr const* ignoreImplicit(Expr const* expr)
{ for (auto e = expr;;)
{ if (autoconst e1 = dyn_cast<ImplicitCastExpr>(e))
{
e = e1->getSubExprAsWritten();
} elseif (autoconst e2 = dyn_cast<FullExpr>(e))
{
e = e2->getSubExpr();
} elseif (autoconst e3 = dyn_cast<MaterializeTemporaryExpr>(e))
{
e = e3->getSubExpr();
} elseif (autoconst e4 = dyn_cast<CXXBindTemporaryExpr>(e))
{
e = e4->getSubExpr();
} else
{ return e;
}
}
}
class ConditionalString final : public loplugin::FilteringPlugin<ConditionalString>
{ public: explicit ConditionalString(loplugin::InstantiationData const& data)
: FilteringPlugin(data)
{
}
bool VisitCallExpr(CallExpr const* expr)
{ if (ignoreLocation(expr))
{ returntrue;
} autoconst fn = expr->getDirectCallee(); if (fn == nullptr)
{ returntrue;
} //TODO: Instead of a hardcoded list of functions, check that `fn` has overloads taking // OUString and std::u16string_view, respectively (and operator + is even more complicated // than that, going via ToStringHelper<std::u16string_view> specialization; the getNumArgs // checks for the various functions are meant to guard against the unlikely case that the // affected parameters get defaulted in the future; overloaded operators cannot generally // have defaulted parameters):
loplugin::DeclCheck const dc(fn); if (dc.Operator(OO_Equal).Class("OUString").Namespace("rtl").GlobalNamespace())
{
assert(fn->getNumParams() == 1); if (isa<CXXOperatorCallExpr>(expr))
{
assert(expr->getNumArgs() == 2);
check(expr->getArg(1));
} else
{
assert(expr->getNumArgs() == 1);
check(expr->getArg(0));
} returntrue;
} if (dc.Operator(OO_PlusEqual).Class("OUString").Namespace("rtl").GlobalNamespace())
{
assert(fn->getNumParams() == 1); if (isa<CXXOperatorCallExpr>(expr))
{
assert(expr->getNumArgs() == 2);
check(expr->getArg(1));
} else
{
assert(expr->getNumArgs() == 1);
check(expr->getArg(0));
} returntrue;
} if (dc.Function("reverseCompareTo").Class("OUString").Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 1)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} returntrue;
} if (dc.Function("equalsIgnoreAsciiCase")
.Class("OUString")
.Namespace("rtl")
.GlobalNamespace()
&& fn->getNumParams() == 1)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} returntrue;
} if (dc.Function("match").Class("OUString").Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 2)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} returntrue;
} if (dc.Function("matchIgnoreAsciiCase").Class("OUString").Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 2)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} returntrue;
} if (dc.Function("startsWith").Class("OUString").Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 2)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} returntrue;
} if (dc.Function("startsWithIgnoreAsciiCase")
.Class("OUString")
.Namespace("rtl")
.GlobalNamespace()
&& fn->getNumParams() == 2)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} returntrue;
} if (dc.Function("endsWith").Class("OUString").Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 2)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} returntrue;
} if (dc.Function("endsWithIgnoreAsciiCase")
.Class("OUString")
.Namespace("rtl")
.GlobalNamespace()
&& fn->getNumParams() == 2)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} returntrue;
} if (dc.Operator(OO_EqualEqual)
.Namespace("rtl")
.GlobalNamespace()) //TODO: more precicse check
{
assert(fn->getNumParams() == 2);
assert(expr->getNumArgs() == 2);
check(expr->getArg(0));
check(expr->getArg(1)); returntrue;
} if (dc.Operator(OO_ExclaimEqual)
.Namespace("rtl")
.GlobalNamespace()) //TODO: more precicse check
{
assert(fn->getNumParams() == 2);
assert(expr->getNumArgs() == 2);
check(expr->getArg(0));
check(expr->getArg(1)); returntrue;
} if (dc.Operator(OO_Less).Namespace("rtl").GlobalNamespace()) //TODO: more precicse check
{
assert(fn->getNumParams() == 2);
assert(expr->getNumArgs() == 2);
check(expr->getArg(0));
check(expr->getArg(1)); returntrue;
} if (dc.Operator(OO_LessEqual)
.Namespace("rtl")
.GlobalNamespace()) //TODO: more precicse check
{
assert(fn->getNumParams() == 2);
assert(expr->getNumArgs() == 2);
check(expr->getArg(0));
check(expr->getArg(1)); returntrue;
} if (dc.Operator(OO_Greater).Namespace("rtl").GlobalNamespace()) //TODO: more precicse check
{
assert(fn->getNumParams() == 2);
assert(expr->getNumArgs() == 2);
check(expr->getArg(0));
check(expr->getArg(1)); returntrue;
} if (dc.Operator(OO_GreaterEqual)
.Namespace("rtl")
.GlobalNamespace()) //TODO: more precicse check
{
assert(fn->getNumParams() == 2);
assert(expr->getNumArgs() == 2);
check(expr->getArg(0));
check(expr->getArg(1)); returntrue;
} if (dc.Function("indexOf").Class("OUString").Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 2)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} returntrue;
} if (dc.Function("lastIndexOf").Class("OUString").Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 1)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} returntrue;
} if (dc.Function("replaceFirst").Class("OUString").Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 3)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} if (expr->getNumArgs() >= 2)
{
check(expr->getArg(1));
} returntrue;
} if (dc.Function("replaceAll").Class("OUString").Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 2)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} if (expr->getNumArgs() >= 2)
{
check(expr->getArg(1));
} returntrue;
} if (dc.Operator(OO_Plus).Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 2) //TODO: more precicse check
{
assert(expr->getNumArgs() == 2);
check(expr->getArg(0));
check(expr->getArg(1)); returntrue;
} if (dc.Operator(OO_Equal).Class("OUStringBuffer").Namespace("rtl").GlobalNamespace())
{
assert(fn->getNumParams() == 1); if (isa<CXXOperatorCallExpr>(expr))
{
assert(expr->getNumArgs() == 2);
check(expr->getArg(1));
} else
{
assert(expr->getNumArgs() == 1);
check(expr->getArg(0));
} returntrue;
} if (dc.Function("append").Class("OUStringBuffer").Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 1)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} returntrue;
} if (dc.Function("insert").Class("OUStringBuffer").Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 2)
{ if (expr->getNumArgs() >= 2)
{
check(expr->getArg(1));
} returntrue;
} if (dc.Function("indexOf").Class("OUStringBuffer").Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 2)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} returntrue;
} if (dc.Function("lastIndexOf").Class("OUStringBuffer").Namespace("rtl").GlobalNamespace()
&& fn->getNumParams() == 1)
{ if (expr->getNumArgs() >= 1)
{
check(expr->getArg(0));
} returntrue;
} returntrue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.