diff options
author | Amaan Qureshi <amaanq12@gmail.com> | 2023-07-19 05:02:49 -0400 |
---|---|---|
committer | Lewis Russell <me@lewisr.dev> | 2023-08-31 13:33:40 +0100 |
commit | 845d5b8b64190e0e09a6a6dd97bdbc0e6f96eb02 (patch) | |
tree | 8c1116e6abe75c456f3a816cb633f76f7676016a /src/nvim/lua/treesitter.c | |
parent | 4afd33e69f4c4a061bcb51a5ed437163262f943c (diff) | |
download | rneovim-845d5b8b64190e0e09a6a6dd97bdbc0e6f96eb02.tar.gz rneovim-845d5b8b64190e0e09a6a6dd97bdbc0e6f96eb02.tar.bz2 rneovim-845d5b8b64190e0e09a6a6dd97bdbc0e6f96eb02.zip |
feat(treesitter): improve query error message
Diffstat (limited to 'src/nvim/lua/treesitter.c')
-rw-r--r-- | src/nvim/lua/treesitter.c | 80 |
1 files changed, 71 insertions, 9 deletions
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 49e920f748..48057b0c65 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -1543,8 +1543,9 @@ int tslua_parse_query(lua_State *L) TSQuery *query = ts_query_new(lang, src, (uint32_t)len, &error_offset, &error_type); if (!query) { - return luaL_error(L, "query: %s at position %d for language %s", - query_err_string(error_type), (int)error_offset, lang_name); + char err_msg[IOSIZE]; + query_err_string(src, (int)error_offset, error_type, err_msg, sizeof(err_msg)); + return luaL_error(L, "%s", err_msg); } TSQuery **ud = lua_newuserdata(L, sizeof(TSQuery *)); // [udata] @@ -1554,24 +1555,85 @@ int tslua_parse_query(lua_State *L) return 1; } -static const char *query_err_string(TSQueryError err) +static const char *query_err_to_string(TSQueryError error_type) { - switch (err) { + switch (error_type) { case TSQueryErrorSyntax: - return "invalid syntax"; + return "Invalid syntax:\n"; case TSQueryErrorNodeType: - return "invalid node type"; + return "Invalid node type "; case TSQueryErrorField: - return "invalid field"; + return "Invalid field name "; case TSQueryErrorCapture: - return "invalid capture"; + return "Invalid capture name "; case TSQueryErrorStructure: - return "invalid structure"; + return "Impossible pattern:\n"; default: return "error"; } } +static void query_err_string(const char *src, int error_offset, TSQueryError error_type, char *err, + size_t errlen) +{ + int line_start = 0; + int row = 0; + const char *error_line = NULL; + int error_line_len = 0; + + const char *end_str; + const char *src_tmp = src; + while ((end_str = strchr(src_tmp, '\n')) != NULL) { + int line_length = (int)(end_str - src_tmp) + 1; + int line_end = line_start + line_length; + if (line_end > error_offset) { + error_line = src_tmp; + error_line_len = line_length; + break; + } + line_start = line_end; + row++; + src_tmp += line_length; + } + + // Additional check for the last line + if (line_start <= error_offset) { + error_line = src_tmp; + error_line_len = (int)strlen(src_tmp); + } + + int column = error_offset - line_start; + + const char *type_msg = query_err_to_string(error_type); + snprintf(err, errlen, "Query error at %d:%d. %s", row + 1, column + 1, type_msg); + size_t offset = strlen(err); + errlen = errlen - offset; + err = err + offset; + + // Error types that report names + if (error_type == TSQueryErrorNodeType + || error_type == TSQueryErrorField + || error_type == TSQueryErrorCapture) { + const char *suffix = src + error_offset; + int suffix_len = 0; + char c = suffix[suffix_len]; + while (isalnum(c) || c == '_' || c == '-' || c == '.') { + c = suffix[++suffix_len]; + } + snprintf(err, errlen, "\"%.*s\":\n", suffix_len, suffix); + offset = strlen(err); + errlen = errlen - offset; + err = err + offset; + } + + if (!error_line) { + snprintf(err, errlen, "Unexpected EOF\n"); + return; + } + + snprintf(err, errlen, "%.*s\n%*s^\n", error_line_len, error_line, column, ""); +} + static TSQuery *query_check(lua_State *L, int index) { TSQuery **ud = luaL_checkudata(L, index, TS_META_QUERY); |