diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index 978e7f1c3..823313264 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -645,7 +645,8 @@ static void test_tokenizer() { do_test(token.has_value()); do_test(token->type == token_type_t::error); do_test(token->error == tokenizer_error_t::closing_unopened_subshell); - do_test(token->error_offset == 4); + do_test(token->offset == 4); + do_test(token->error_offset == 0); } { @@ -4631,6 +4632,11 @@ static void test_highlighting() { {L"stuff", highlight_role_t::param}, }); + highlight_tests.push_back({ + {L"echo", highlight_role_t::command}, + {L")", highlight_role_t::error}, + }); + auto &vars = parser_t::principal_parser().vars(); // Verify variables and wildcards in commands using /bin/cat. vars.set(L"VARIABLE_IN_COMMAND", ENV_LOCAL, {L"a"}); diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index a7c3d1dfb..48e8315fd 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -184,31 +184,30 @@ tok_t tokenizer_t::read_string() { } else if (c == L')') { if (expecting.size() > 0 && expecting.back() == L'}') { return this->call_error(tokenizer_error_t::expected_bclose_found_pclose, - this->start, this->token_cursor, 1); + this->token_cursor, this->token_cursor, 1); } - switch (paran_offsets.size()) { - case 0: - return this->call_error(tokenizer_error_t::closing_unopened_subshell, - this->start, this->token_cursor, 1); - case 1: - mode &= ~(tok_modes::subshell); - default: - paran_offsets.pop_back(); + if (paran_offsets.empty()) { + return this->call_error(tokenizer_error_t::closing_unopened_subshell, + this->token_cursor, this->token_cursor, 1); + } + paran_offsets.pop_back(); + if (paran_offsets.empty()) { + mode &= ~(tok_modes::subshell); } expecting.pop_back(); } else if (c == L'}') { if (expecting.size() > 0 && expecting.back() == L')') { return this->call_error(tokenizer_error_t::expected_pclose_found_bclose, - this->start, this->token_cursor, 1); + this->token_cursor, this->token_cursor, 1); } - switch (brace_offsets.size()) { - case 0: - return this->call_error(tokenizer_error_t::closing_unopened_brace, - this->token_cursor, this->start + wcslen(this->start)); - case 1: - mode &= ~(tok_modes::curly_braces); - default: - brace_offsets.pop_back(); + if (brace_offsets.empty()) { + return this->call_error(tokenizer_error_t::closing_unopened_brace, + this->token_cursor, + this->token_cursor + wcslen(this->token_cursor)); + } + brace_offsets.pop_back(); + if (brace_offsets.empty()) { + mode &= ~(tok_modes::curly_braces); } expecting.pop_back(); } else if (c == L'[') {