diff --git a/src/ast.cpp b/src/ast.cpp index 6e8c8357f..106b35939 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -182,6 +182,16 @@ class token_stream_t { assert(token.length <= SOURCE_OFFSET_INVALID); result.source_length = static_cast(token.length); + + if (token.error != tokenizer_error_t::none) { + auto subtoken_offset = static_cast(token.error_offset_within_token); + // Skip invalid tokens that have a zero length, especially if they are at EOF. + if (subtoken_offset < result.source_length) { + result.source_start += subtoken_offset; + result.source_length -= subtoken_offset; + } + } + return result; } diff --git a/tests/checks/syntax-error-location.fish b/tests/checks/syntax-error-location.fish index 22e281170..bf5c9a9ce 100644 --- a/tests/checks/syntax-error-location.fish +++ b/tests/checks/syntax-error-location.fish @@ -22,3 +22,13 @@ echo ' # CHECK: # CHECK: <(true one)> # CHECK: <^> + +$fish -c 'echo "unfinished "(subshell' 2>| string replace -r '.*' '<$0>' +# CHECK: +# CHECK: +# CHECK: < ^> + +$fish -c 'echo "unfinished "$(subshell' 2>| string replace -r '.*' '<$0>' +# CHECK: +# CHECK: +# CHECK: < ^>