diff --git a/tools/clang-tidy-plugin/CMakeLists.txt b/tools/clang-tidy-plugin/CMakeLists.txt index 9a591396e67e1..969b8617c79b8 100644 --- a/tools/clang-tidy-plugin/CMakeLists.txt +++ b/tools/clang-tidy-plugin/CMakeLists.txt @@ -17,6 +17,7 @@ add_library( TestFilenameCheck.cpp TextStyleCheck.cpp TranslatorCommentsCheck.cpp + UseLocalizedSortingCheck.cpp UseNamedPointConstantsCheck.cpp UsePointApisCheck.cpp UsePointArithmeticCheck.cpp diff --git a/tools/clang-tidy-plugin/CataTidyModule.cpp b/tools/clang-tidy-plugin/CataTidyModule.cpp index 8b8dd43e321a7..cd8666dcc28c6 100644 --- a/tools/clang-tidy-plugin/CataTidyModule.cpp +++ b/tools/clang-tidy-plugin/CataTidyModule.cpp @@ -12,6 +12,7 @@ #include "TestFilenameCheck.h" #include "TextStyleCheck.h" #include "TranslatorCommentsCheck.h" +#include "UseLocalizedSortingCheck.h" #include "UseNamedPointConstantsCheck.h" #include "UsePointApisCheck.h" #include "UsePointArithmeticCheck.h" @@ -39,6 +40,7 @@ class CataModule : public ClangTidyModule CheckFactories.registerCheck( "cata-test-filename" ); CheckFactories.registerCheck( "cata-text-style" ); CheckFactories.registerCheck( "cata-translator-comments" ); + CheckFactories.registerCheck( "cata-use-localized-sorting" ); CheckFactories.registerCheck( "cata-use-named-point-constants" ); CheckFactories.registerCheck( "cata-use-point-apis" ); diff --git a/tools/clang-tidy-plugin/UseLocalizedSortingCheck.cpp b/tools/clang-tidy-plugin/UseLocalizedSortingCheck.cpp new file mode 100644 index 0000000000000..e579cc425338e --- /dev/null +++ b/tools/clang-tidy-plugin/UseLocalizedSortingCheck.cpp @@ -0,0 +1,82 @@ +#include "UseLocalizedSortingCheck.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Utils.h" +#include "clang/Basic/OperatorKinds.h" + +using namespace clang::ast_matchers; + +namespace clang +{ +namespace tidy +{ +namespace cata +{ + +void UseLocalizedSortingCheck::registerMatchers( MatchFinder *Finder ) +{ + Finder->addMatcher( + cxxOperatorCallExpr( + hasArgument( + 0, + expr( + hasType( + qualType( + anyOf( asString( "const std::string" ), asString( "std::string" ) ) + ).bind( "arg0Type" ) + ) + ).bind( "arg0Expr" ) + ), + hasOverloadedOperatorName( "<" ) + ).bind( "call" ), + this + ); +} + +static void CheckCall( UseLocalizedSortingCheck &Check, const MatchFinder::MatchResult &Result ) +{ + const CXXOperatorCallExpr *Call = Result.Nodes.getNodeAs( "call" ); + const QualType *Arg0Type = Result.Nodes.getNodeAs( "arg0Type" ); + const Expr *Arg0Expr = Result.Nodes.getNodeAs( "arg0Expr" ); + if( !Call || !Arg0Type || !Arg0Expr ) { + return; + } + + StringRef Arg0Text = getText( Result, Arg0Expr ); + if( Arg0Text.endswith( "id" ) ) { + return; + } + + Check.diag( Call->getBeginLoc(), + "Raw comparison of %0. For UI purposes please use localized_compare from " + "translations.h." ) << *Arg0Type; +} + +void UseLocalizedSortingCheck::check( const MatchFinder::MatchResult &Result ) +{ + CheckCall( *this, Result ); +} + +} // namespace cata +} // namespace tidy +} // namespace clang diff --git a/tools/clang-tidy-plugin/UseLocalizedSortingCheck.h b/tools/clang-tidy-plugin/UseLocalizedSortingCheck.h new file mode 100644 index 0000000000000..29586eba5e37e --- /dev/null +++ b/tools/clang-tidy-plugin/UseLocalizedSortingCheck.h @@ -0,0 +1,32 @@ +#ifndef CATA_TOOLS_CLANG_TIDY_PLUGIN_USELOCALIZEDSORTINGCHECK_H +#define CATA_TOOLS_CLANG_TIDY_PLUGIN_USELOCALIZEDSORTINGCHECK_H + +#include +#include + +#include "ClangTidy.h" + +namespace clang +{ + +namespace tidy +{ +class ClangTidyContext; + +namespace cata +{ + +class UseLocalizedSortingCheck : public ClangTidyCheck +{ + public: + UseLocalizedSortingCheck( StringRef Name, ClangTidyContext *Context ) + : ClangTidyCheck( Name, Context ) {} + void registerMatchers( ast_matchers::MatchFinder *Finder ) override; + void check( const ast_matchers::MatchFinder::MatchResult &Result ) override; +}; + +} // namespace cata +} // namespace tidy +} // namespace clang + +#endif // CATA_TOOLS_CLANG_TIDY_PLUGIN_USELOCALIZEDSORTINGCHECK_H diff --git a/tools/clang-tidy-plugin/test/use-localized-sorting.cpp b/tools/clang-tidy-plugin/test/use-localized-sorting.cpp new file mode 100644 index 0000000000000..bdc23d552bd0a --- /dev/null +++ b/tools/clang-tidy-plugin/test/use-localized-sorting.cpp @@ -0,0 +1,41 @@ +// RUN: %check_clang_tidy %s cata-use-localized-sorting %t -- -plugins=%cata_plugin -- -isystem %cata_include + +namespace std +{ + +template +struct allocator; + +template +class char_traits; + +template < + class CharT, + class Traits = std::char_traits, + class Allocator = std::allocator + > class basic_string; + +typedef basic_string string; + +template +bool operator<( const std::basic_string &lhs, + const std::basic_string &rhs ) noexcept; + +} + +class NonString +{ +}; + +bool operator<( const NonString &, const NonString &rhs ) noexcept; + +bool f0( const std::string &l, const std::string &r ) +{ + return l < r; + // CHECK-MESSAGES: warning: Raw comparison of 'const std::string' (aka 'const basic_string'). For UI purposes please use localized_compare from translations.h. [cata-use-localized-sorting] +} + +bool f1( const NonString &l, const NonString &r ) +{ + return l < r; +}