1 // RUN: %check_clang_tidy %s cata-json-translation-input %t -- -plugins=%cata_plugin --
2 
3 // check_clang_tidy uses -nostdinc++, so we add dummy declaration of std::string here
4 namespace std
5 {
6 template<class CharT, class Traits = void, class Allocator = void>
7 class basic_string
8 {
9     public:
10         basic_string();
11         basic_string( const CharT * );
12         CharT *c_str();
13         const CharT *c_str() const;
14 };
15 using string = basic_string<char>;
16 string operator+( const string &, const string & );
17 } // namespace std
18 
19 // check_clang_tidy uses -nostdinc++, so we add dummy translation interface here instead of including translations.h
20 std::string _( const std::string & );
21 std::string gettext( const std::string & );
22 std::string pgettext( const std::string &, const std::string & );
23 std::string ngettext( const std::string &, const std::string &, int );
24 std::string npgettext( const std::string &, const std::string &, const std::string &, int );
25 
26 class translation
27 {
28     public:
29         static translation to_translation( const std::string & );
30         static translation to_translation( const std::string &, const std::string & );
31         static translation pl_translation( const std::string &, const std::string & );
32         static translation pl_translation( const std::string &, const std::string &, const std::string & );
33         static translation no_translation( const std::string & );
34 };
35 
36 translation to_translation( const std::string & );
37 translation to_translation( const std::string &, const std::string & );
38 translation pl_translation( const std::string &, const std::string & );
39 translation pl_translation( const std::string &, const std::string &, const std::string & );
40 translation no_translation( const std::string & );
41 
42 // dummy json interface
43 class JsonArray
44 {
45     public:
46         std::string next_string();
47 };
48 
49 class JsonObject
50 {
51     public:
52         std::string get_string( const std::string & );
53         JsonArray get_array( const std::string & );
54         template<class T>
55         bool read( const std::string &name, T &t, bool throw_on_error = true );
56 };
57 
58 class JsonIn
59 {
60     public:
61         JsonObject get_object();
62 };
63 
64 class foo
65 {
66     public:
67         std::string name;
68         std::string double_name;
69         std::string nickname;
70         translation msg;
71         translation more_msg;
72         translation moar_msg;
73         translation endless_msg;
74         translation desc;
75         std::string whatever;
76 };
77 
78 // <translation function>( ... <json input object>.<method>(...) ... )
deserialize(foo & bar,JsonIn & jin)79 static void deserialize( foo &bar, JsonIn &jin )
80 {
81     JsonObject jo = jin.get_object();
82     bar.name = _( jo.get_string( "name" ) );
83     // CHECK-MESSAGES: [[@LINE-1]]:16: warning: immediately translating a value read from json causes translation updating issues.  Consider reading into a translation object instead.
84     // CHECK-MESSAGES: [[@LINE-2]]:19: note: value read from json
85 
86     JsonArray ja = jo.get_array( "double_name" );
87     bar.double_name = std::string( _( ja.next_string() ) ) + pgettext( "blah",
88                       // CHECK-MESSAGES: [[@LINE-1]]:36: warning: immediately translating a value read from json causes translation updating issues.  Consider reading into a translation object instead.
89                       // CHECK-MESSAGES: [[@LINE-2]]:39: note: value read from json
90                       // CHECK-MESSAGES: [[@LINE-3]]:62: warning: immediately translating a value read from json causes translation updating issues.  Consider reading into a translation object instead.
91                       std::string( ja.next_string() ) );
92     // CHECK-MESSAGES: [[@LINE-1]]:36: note: value read from json
93 
94     // ok, not reading from json
95     bar.nickname = _( "blah" );
96 
97     bar.msg = to_translation( jo.get_string( "message" ) );
98     // CHECK-MESSAGES: [[@LINE-1]]:15: warning: read translation directly instead of constructing it from json strings to ensure consistent format in json.
99     // CHECK-MESSAGES: [[@LINE-2]]:31: note: string read from json
100 
101     bar.more_msg = pl_translation( jo.get_string( "message" ), "foo" );
102     // CHECK-MESSAGES: [[@LINE-1]]:20: warning: read translation directly instead of constructing it from json strings to ensure consistent format in json.
103     // CHECK-MESSAGES: [[@LINE-2]]:36: note: string read from json
104 
105     bar.moar_msg = translation::to_translation( jo.get_string( "more_message" ) );
106     // CHECK-MESSAGES: [[@LINE-1]]:20: warning: read translation directly instead of constructing it from json strings to ensure consistent format in json.
107     // CHECK-MESSAGES: [[@LINE-2]]:49: note: string read from json
108 
109     // ok, reading translation directly
110     jo.read( "endless_msg", bar.endless_msg );
111 
112     // ok, using no_translation to avoid re-translating generated string
113     bar.desc = no_translation( jo.get_string( "generated_desc" ) );
114 
115     std::string duh;
116     // ok, not reading from json
117     bar.whatever = _( duh.c_str() );
118 }
119