@@ -242,7 +242,9 @@ static void CompileCommand(noex::string& err_msg,
242242 splitted_cmd_json.SetArray ();
243243
244244 bool store_ids = false ;
245- const char * cmd = sub_definition[" command" ].GetString ();
245+ tuwjson::Value& cmd_json = sub_definition[" command" ];
246+ noex::string cmd_pos = cmd_json.GetLineColumnStr ();
247+ const char * cmd = cmd_json.GetString ();
246248 while (*cmd != ' \0 ' ) {
247249 noex::string token = SubstrToChar (cmd, ' %' );
248250 if (store_ids) {
@@ -263,52 +265,32 @@ static void CompileCommand(noex::string& err_msg,
263265 tuwjson::Value& components = sub_definition[" components" ];
264266 tuwjson::Value cmd_int_ids;
265267 cmd_int_ids.SetArray ();
266- noex::string cmd_str;
267268 int comp_size = static_cast <int >(comp_ids.size ());
268269 int non_id_comp = 0 ;
269270 for (int i = 0 ; i < static_cast <int >(cmd_ids.size ()); i++) {
270- cmd_str += splitted_cmd[i];
271271 const noex::string& id = cmd_ids[i];
272272 int j;
273273 if (id == CMD_TOKEN_PERCENT) {
274274 j = CMD_ID_PERCENT;
275- cmd_str.push_back (' %' );
276275 } else if (id == CMD_TOKEN_CURRENT_DIR) {
277276 j = CMD_ID_CURRENT_DIR;
278- cmd_str += id;
279277 } else if (id == CMD_TOKEN_HOME_DIR) {
280278 j = CMD_ID_HOME_DIR;
281- cmd_str += id;
282279 } else {
283280 for (j = 0 ; j < comp_size; j++)
284281 if (id == comp_ids[j]) break ;
285282 if (j == comp_size) {
286- while (non_id_comp < comp_size) {
287- int type_int = components[non_id_comp][" type_int" ].GetInt ();
288- if (type_int != COMP_STATIC_TEXT
289- && type_int != COMP_EMPTY
290- && comp_ids[non_id_comp].empty ())
291- break ;
292- non_id_comp++;
293- }
294- j = non_id_comp;
295- non_id_comp++;
283+ err_msg = noex::concat_cstr (
284+ " There is undefined id \" " , id.c_str (), " \" in the command." ) + cmd_pos;
285+ return ;
296286 }
297287 }
298- if (j < comp_size) {
299- tuwjson::Value n;
300- n.SetInt (j);
301- cmd_int_ids.MoveAndPush (n);
302- }
303- if (j >= comp_size)
304- cmd_str += " __comp???__" ;
305- else if (j >= 0 )
306- cmd_str += noex::concat_cstr (" __comp" , noex::to_string (j).c_str (), " __" );
288+ tuwjson::Value n;
289+ n.SetInt (j);
290+ cmd_int_ids.MoveAndPush (n);
307291 }
308- if (cmd_ids.size () < splitted_cmd.size ())
309- cmd_str += splitted_cmd.back ();
310292
311- // Check if the command requires more arguments or ignores some arguments .
293+ // Find unused IDs .
312294 for (int j = 0 ; j < comp_size; j++) {
313295 tuwjson::Value& v = components[j];
314296 int type_int = v[" type_int" ].GetInt ();
@@ -321,25 +303,14 @@ static void CompileCommand(noex::string& err_msg,
321303 break ;
322304 }
323305 if (!found) {
324- if (comp_ids[j].empty () || !v.HasMember (" id" )) {
325- err_msg = noex::concat_cstr (" [\" components\" ][" , noex::to_string (j).c_str (), " ]" )
326- + v.GetLineColumnStr () + " is unused in the command; " + cmd_str;
327- } else {
328- tuwjson::Value& vid = v[" id" ];
329- err_msg = noex::concat_cstr (" component id \" " , vid.GetString (), " \" " )
330- + vid.GetLineColumnStr () + " is unused in the command; " + cmd_str;
331- }
306+ tuwjson::Value& vid = v[" id" ];
307+ err_msg = noex::concat_cstr (" component id \" " , vid.GetString (), " \" " )
308+ + noex::concat_cstr (
309+ vid.GetLineColumnStr ().c_str (),
310+ " is unused in the command." , cmd_pos.c_str ());
332311 return ;
333312 }
334313 }
335- if (non_id_comp > comp_size) {
336- err_msg =
337- " The command requires more components for arguments; " + cmd_str;
338- return ;
339- }
340- tuwjson::Value v;
341- v.SetString (cmd_str);
342- sub_definition[" command_str" ].MoveFrom (v);
343314 sub_definition[" command_ids" ].MoveFrom (cmd_int_ids);
344315}
345316
@@ -443,14 +414,9 @@ void CheckSubDefinition(noex::string& err_msg, tuwjson::Value& sub_definition,
443414 const char * type_str = type_ptr->GetString ();
444415 int type = ComptypeToInt (type_str);
445416
446- // TODO: throw an error for missing ids.
447- if (type != COMP_STATIC_TEXT && !c.HasMember (" id" )) {
448- PrintFmt (
449- " [CheckDefinition] DeprecationWarning: "
450- " \" id\" is missing in [\" components\" ][%zu]%s."
451- " Support for components without \" id\" will be removed in a future version.\n " ,
452- comp_ids.size (), c.GetLineColumnStr ().c_str ());
453- }
417+ tuwjson::Value* id_ptr = CheckJsonType (
418+ err_msg, c, " id" , JsonType::STRING, " component" , type == COMP_STATIC_TEXT);
419+ if (!err_msg.empty ()) return ;
454420
455421 c[" type_int" ].SetInt (type);
456422 CorrectKey (c, " item" , " items" );
@@ -549,7 +515,6 @@ void CheckSubDefinition(noex::string& err_msg, tuwjson::Value& sub_definition,
549515 CheckJsonType (err_msg, c, " add_quotes" , JsonType::BOOLEAN);
550516 CorrectKey (c, " empty_message" , " placeholder" );
551517 CheckJsonType (err_msg, c, " placeholder" , JsonType::STRING);
552- CheckJsonType (err_msg, c, " id" , JsonType::STRING);
553518 CheckJsonType (err_msg, c, " tooltip" , JsonType::STRING);
554519
555520 CheckJsonType (err_msg, c, " optional" , JsonType::BOOLEAN);
@@ -571,16 +536,22 @@ void CheckSubDefinition(noex::string& err_msg, tuwjson::Value& sub_definition,
571536 }
572537 }
573538
574- const char * id = GetString (c, " id " , " " );
575- if (c. HasMember ( " id " )) {
576- noex::string linecol = c[ " id " ]. GetLineColumnStr ();
539+ if (id_ptr != nullptr ) {
540+ const char * id = id_ptr-> GetString ();
541+ noex::string linecol = id_ptr-> GetLineColumnStr ();
577542 if (id[0 ] == ' \0 ' ) {
578543 err_msg = " \" id\" should NOT be an empty string."
579544 + linecol;
580545 } else if (id[0 ] == ' _' ) {
581546 err_msg = " \" id\" should NOT start with '_'."
582547 + linecol;
583548 }
549+ if (type == COMP_STATIC_TEXT) {
550+ id_ptr->SetString (" " );
551+ PrintFmt (
552+ " [CheckDefinition] Warning: static text should not have ID. %s\n " ,
553+ linecol.c_str ());
554+ }
584555 if (!ignore) {
585556 for (const noex::string& str : comp_ids) {
586557 if (id == str) {
@@ -590,26 +561,25 @@ void CheckSubDefinition(noex::string& err_msg, tuwjson::Value& sub_definition,
590561 }
591562 }
592563 }
593- } else {
594- uint32_t hash = Fnv1Hash32 (c[" label" ].GetString ());
595- c[" id" ].SetString (" _" + noex::to_string (hash));
596564 }
597565 if (!err_msg.empty ()) return ;
598566
599567 if (ignore) {
600568 comp_ids.emplace_back (" " );
601569 c[" type_int" ].SetInt (COMP_EMPTY);
570+ } else if (type == COMP_STATIC_TEXT) {
571+ comp_ids.emplace_back (" " );
602572 } else {
603- comp_ids.emplace_back (id );
573+ comp_ids.emplace_back (id_ptr-> GetString () );
604574 }
605575 }
606576
607577 // Overwrite ["command"] with ["command_'os'"] if exists.
608578 const char * command_os_key = " command_" TUW_CONSTANTS_OS;
609579 json_ptr = CheckJsonType (err_msg, sub_definition, command_os_key, JsonType::STRING);
610580 if (err_msg.empty () && json_ptr) {
611- const char * command_os = json_ptr-> GetString ();
612- sub_definition[" command" ].SetString (command_os );
581+ // Note: CopyFrom() can overwrite m_line_count and m_column for error messages.
582+ sub_definition[" command" ].CopyFrom (*json_ptr );
613583 }
614584
615585 // check sub_definition["command"] and convert it to more useful format.
0 commit comments