mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #11757 from bfredl/treesitter_runtime
treesitter: add standard search path for parsers + bundle c parser properly
This commit is contained in:
commit
120a4c8e25
16
ci/build.ps1
16
ci/build.ps1
@ -123,22 +123,6 @@ if (-not $NoTests) {
|
||||
npm.cmd install -g neovim
|
||||
Get-Command -CommandType Application neovim-node-host.cmd
|
||||
npm.cmd link neovim
|
||||
|
||||
|
||||
$env:TREE_SITTER_DIR = $env:USERPROFILE + "\tree-sitter-build"
|
||||
mkdir "$env:TREE_SITTER_DIR\bin"
|
||||
|
||||
$xbits = if ($bits -eq '32') {'x86'} else {'x64'}
|
||||
Invoke-WebRequest -UseBasicParsing -Uri "https://github.com/tree-sitter/tree-sitter/releases/download/0.15.9/tree-sitter-windows-$xbits.gz" -OutFile tree-sitter.exe.gz
|
||||
C:\msys64\usr\bin\gzip -d tree-sitter.exe.gz
|
||||
|
||||
Invoke-WebRequest -UseBasicParsing -Uri "https://codeload.github.com/tree-sitter/tree-sitter-c/zip/v0.15.2" -OutFile tree_sitter_c.zip
|
||||
Expand-Archive .\tree_sitter_c.zip -DestinationPath .
|
||||
cd tree-sitter-c-0.15.2
|
||||
..\tree-sitter.exe test
|
||||
if (-Not (Test-Path -PathType Leaf "$env:TREE_SITTER_DIR\bin\c.dll")) {
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
if ($compiler -eq 'MSVC') {
|
||||
|
@ -27,29 +27,5 @@ nvm use 10
|
||||
npm install -g neovim
|
||||
npm link neovim
|
||||
|
||||
echo "Install tree-sitter npm package"
|
||||
|
||||
# FIXME
|
||||
# https://github.com/tree-sitter/tree-sitter/commit/e14e285a1087264a8c74a7c62fcaecc49db9d904
|
||||
# If queries added to tree-sitter-c, we can use latest tree-sitter-cli
|
||||
npm install -g tree-sitter-cli@v0.15.9
|
||||
|
||||
echo "Install tree-sitter c parser"
|
||||
curl "https://codeload.github.com/tree-sitter/tree-sitter-c/tar.gz/v0.15.2" -o tree_sitter_c.tar.gz
|
||||
tar xf tree_sitter_c.tar.gz
|
||||
cd tree-sitter-c-0.15.2
|
||||
export TREE_SITTER_DIR=$HOME/tree-sitter-build/
|
||||
mkdir -p "$TREE_SITTER_DIR/bin"
|
||||
|
||||
if [[ "$BUILD_32BIT" != "ON" ]]; then
|
||||
# builds c parser in $HOME/tree-sitter-build/bin/c.(so|dylib)
|
||||
tree-sitter test
|
||||
else
|
||||
# no tree-sitter binary for 32bit linux, so fake it (no tree-sitter unit tests)
|
||||
cd src/
|
||||
gcc -m32 -o "$TREE_SITTER_DIR/bin/c.so" -shared parser.c -I.
|
||||
fi
|
||||
test -f "$TREE_SITTER_DIR/bin/c.so"
|
||||
|
||||
sudo cpanm -n Neovim::Ext || cat "$HOME/.cpanm/build.log"
|
||||
perl -W -e 'use Neovim::Ext; print $Neovim::Ext::VERSION'
|
||||
|
@ -19,7 +19,7 @@ exit_suite --continue
|
||||
|
||||
source ~/.nvm/nvm.sh
|
||||
nvm use 10
|
||||
export TREE_SITTER_DIR=$HOME/tree-sitter-build/
|
||||
|
||||
|
||||
enter_suite tests
|
||||
|
||||
|
@ -3,5 +3,6 @@
|
||||
#include "${PROJECT_SOURCE_DIR}/src/nvim/vim.h"
|
||||
char *default_vim_dir = "${CMAKE_INSTALL_FULL_DATAROOTDIR}/nvim";
|
||||
char *default_vimruntime_dir = "";
|
||||
char *default_lib_dir = "${CMAKE_INSTALL_FULL_LIBDIR}/nvim";
|
||||
char_u *compiled_user = (char_u *)"${USERNAME}";
|
||||
char_u *compiled_sys = (char_u *)"${HOSTNAME}";
|
||||
|
@ -494,10 +494,12 @@ VIM.TREESITTER *lua-treesitter*
|
||||
Nvim integrates the tree-sitter library for incremental parsing of buffers.
|
||||
|
||||
Currently Nvim does not provide the tree-sitter parsers, instead these must
|
||||
be built separately, for instance using the tree-sitter utility.
|
||||
The parser is loaded into nvim using >
|
||||
be built separately, for instance using the tree-sitter utility. The only
|
||||
exception is a C parser being included in official builds for testing
|
||||
purposes. Parsers are searched for as `parser/{lang}.*` in any 'runtimepath'
|
||||
directory. A parser can also be loaded manually using a full path: >
|
||||
|
||||
vim.treesitter.add_language("/path/to/c_parser.so", "c")
|
||||
vim.treesitter.require_language("python", "/path/to/python.so")
|
||||
|
||||
<Create a parser for a buffer and a given language (if another plugin uses the
|
||||
same buffer/language combination, it will be safely reused). Use >
|
||||
|
@ -31,8 +31,6 @@ function Parser:_on_lines(bufnr, _, start_row, old_stop_row, stop_row, old_byte_
|
||||
end
|
||||
|
||||
local M = {
|
||||
add_language=vim._ts_add_language,
|
||||
inspect_language=vim._ts_inspect_language,
|
||||
parse_query = vim._ts_parse_query,
|
||||
}
|
||||
|
||||
@ -45,12 +43,34 @@ setmetatable(M, {
|
||||
end
|
||||
})
|
||||
|
||||
function M.create_parser(bufnr, ft, id)
|
||||
function M.require_language(lang, path)
|
||||
if vim._ts_has_language(lang) then
|
||||
return true
|
||||
end
|
||||
if path == nil then
|
||||
local fname = 'parser/' .. lang .. '.*'
|
||||
local paths = a.nvim_get_runtime_file(fname, false)
|
||||
if #paths == 0 then
|
||||
-- TODO(bfredl): help tag?
|
||||
error("no parser for '"..lang.."' language")
|
||||
end
|
||||
path = paths[1]
|
||||
end
|
||||
vim._ts_add_language(path, lang)
|
||||
end
|
||||
|
||||
function M.inspect_language(lang)
|
||||
M.require_language(lang)
|
||||
return vim._ts_inspect_language(lang)
|
||||
end
|
||||
|
||||
function M.create_parser(bufnr, lang, id)
|
||||
M.require_language(lang)
|
||||
if bufnr == 0 then
|
||||
bufnr = a.nvim_get_current_buf()
|
||||
end
|
||||
local self = setmetatable({bufnr=bufnr, lang=ft, valid=false}, Parser)
|
||||
self._parser = vim._create_ts_parser(ft)
|
||||
local self = setmetatable({bufnr=bufnr, lang=lang, valid=false}, Parser)
|
||||
self._parser = vim._create_ts_parser(lang)
|
||||
self.change_cbs = {}
|
||||
self:parse()
|
||||
-- TODO(bfredl): use weakref to self, so that the parser is free'd is no plugin is
|
||||
@ -94,6 +114,7 @@ local Query = {}
|
||||
Query.__index = Query
|
||||
|
||||
function M.parse_query(lang, query)
|
||||
M.require_language(lang)
|
||||
local self = setmetatable({}, Query)
|
||||
self.query = vim._ts_parse_query(lang, query)
|
||||
self.info = self.query:inspect()
|
||||
|
@ -270,6 +270,8 @@ _line_length = 80
|
||||
# This is set by --extensions flag.
|
||||
_valid_extensions = set(['c', 'h'])
|
||||
|
||||
_RE_COMMENTLINE = re.compile(r'^\s*//')
|
||||
|
||||
|
||||
def ParseNolintSuppressions(filename, raw_line, linenum, error):
|
||||
"""Updates the global list of error-suppressions.
|
||||
@ -1358,7 +1360,9 @@ def CheckForOldStyleComments(filename, line, linenum, error):
|
||||
linenum: The number of the line to check.
|
||||
error: The function to call with any errors found.
|
||||
"""
|
||||
if line.find('/*') >= 0 and line[-1] != '\\':
|
||||
# hack: allow /* inside comment line. Could be extended to allow them inside
|
||||
# any // comment.
|
||||
if line.find('/*') >= 0 and line[-1] != '\\' and not _RE_COMMENTLINE.match(line):
|
||||
error(filename, linenum, 'readability/old_style_comment', 5,
|
||||
'/*-style comment found, it should be replaced with //-style. '
|
||||
'/*-style comments are only allowed inside macros. '
|
||||
|
@ -546,6 +546,11 @@ else()
|
||||
endif()
|
||||
set_target_properties(nvim_runtime_deps PROPERTIES FOLDER deps)
|
||||
|
||||
file(COPY ${DEPS_PREFIX}/lib/nvim/parser DESTINATION ${PROJECT_BINARY_DIR}/lib/nvim/)
|
||||
install(DIRECTORY ${PROJECT_BINARY_DIR}/lib/nvim/
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/nvim/
|
||||
USE_SOURCE_PERMISSIONS)
|
||||
|
||||
add_library(
|
||||
libnvim
|
||||
STATIC
|
||||
|
@ -703,6 +703,40 @@ ArrayOf(String) nvim_list_runtime_paths(void)
|
||||
return rv;
|
||||
}
|
||||
|
||||
/// Find files in runtime directories
|
||||
///
|
||||
/// 'name' can contain wildcards. For example
|
||||
/// nvim_get_runtime_file("colors/*.vim", true) will return all color
|
||||
/// scheme files.
|
||||
///
|
||||
/// It is not an error to not find any files. An empty array is returned then.
|
||||
///
|
||||
/// @param name pattern of files to search for
|
||||
/// @param all whether to return all matches or only the first
|
||||
/// @return list of absolute paths to the found files
|
||||
ArrayOf(String) nvim_get_runtime_file(String name, Boolean all)
|
||||
FUNC_API_SINCE(7)
|
||||
{
|
||||
Array rv = ARRAY_DICT_INIT;
|
||||
if (!name.data) {
|
||||
return rv;
|
||||
}
|
||||
int flags = DIP_START | (all ? DIP_ALL : 0);
|
||||
do_in_runtimepath((char_u *)name.data, flags, find_runtime_cb, &rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void find_runtime_cb(char_u *fname, void *cookie)
|
||||
{
|
||||
Array *rv = (Array *)cookie;
|
||||
ADD(*rv, STRING_OBJ(cstr_to_string((char *)fname)));
|
||||
}
|
||||
|
||||
String nvim__get_lib_dir(void)
|
||||
{
|
||||
return cstr_as_string(get_lib_dir());
|
||||
}
|
||||
|
||||
/// Changes the global working directory.
|
||||
///
|
||||
/// @param dir Directory path
|
||||
|
@ -833,6 +833,7 @@ enum {
|
||||
#ifdef HAVE_PATHDEF
|
||||
extern char *default_vim_dir;
|
||||
extern char *default_vimruntime_dir;
|
||||
extern char *default_lib_dir;
|
||||
extern char_u *compiled_user;
|
||||
extern char_u *compiled_sys;
|
||||
#endif
|
||||
|
@ -1025,9 +1025,12 @@ static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
lua_pushcfunction(lstate, create_tslua_parser);
|
||||
lua_setfield(lstate, -2, "_create_ts_parser");
|
||||
|
||||
lua_pushcfunction(lstate, tslua_register_lang);
|
||||
lua_pushcfunction(lstate, tslua_add_language);
|
||||
lua_setfield(lstate, -2, "_ts_add_language");
|
||||
|
||||
lua_pushcfunction(lstate, tslua_has_language);
|
||||
lua_setfield(lstate, -2, "_ts_has_language");
|
||||
|
||||
lua_pushcfunction(lstate, tslua_inspect_lang);
|
||||
lua_setfield(lstate, -2, "_ts_inspect_language");
|
||||
|
||||
|
@ -119,7 +119,14 @@ void tslua_init(lua_State *L)
|
||||
build_meta(L, "treesitter_querycursor", querycursor_meta);
|
||||
}
|
||||
|
||||
int tslua_register_lang(lua_State *L)
|
||||
int tslua_has_language(lua_State *L)
|
||||
{
|
||||
const char *lang_name = luaL_checkstring(L, 1);
|
||||
lua_pushboolean(L, pmap_has(cstr_t)(langs, lang_name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tslua_add_language(lua_State *L)
|
||||
{
|
||||
if (lua_gettop(L) < 2 || !lua_isstring(L, 1) || !lua_isstring(L, 2)) {
|
||||
return luaL_error(L, "string expected");
|
||||
|
@ -498,6 +498,24 @@ static inline char *add_dir(char *dest, const char *const dir,
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *get_lib_dir(void)
|
||||
{
|
||||
// TODO(bfredl): too fragile? Ideally default_lib_dir would be made empty
|
||||
// in an appimage build
|
||||
if (strlen(default_lib_dir) != 0
|
||||
&& os_isdir((const char_u *)default_lib_dir)) {
|
||||
return xstrdup(default_lib_dir);
|
||||
}
|
||||
|
||||
// Find library path relative to the nvim binary: ../lib/nvim/
|
||||
char exe_name[MAXPATHL];
|
||||
vim_get_prefix_from_exepath(exe_name);
|
||||
if (append_path(exe_name, "lib" _PATHSEPSTR "nvim", MAXPATHL) == OK) {
|
||||
return xstrdup(exe_name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Sets &runtimepath to default value.
|
||||
///
|
||||
/// Windows: Uses "…/nvim-data" for kXDGDataHome to avoid storing
|
||||
@ -508,6 +526,7 @@ static void set_runtimepath_default(void)
|
||||
char *const data_home = stdpaths_get_xdg_var(kXDGDataHome);
|
||||
char *const config_home = stdpaths_get_xdg_var(kXDGConfigHome);
|
||||
char *const vimruntime = vim_getenv("VIMRUNTIME");
|
||||
char *const libdir = get_lib_dir();
|
||||
char *const data_dirs = stdpaths_get_xdg_var(kXDGDataDirs);
|
||||
char *const config_dirs = stdpaths_get_xdg_var(kXDGConfigDirs);
|
||||
#define SITE_SIZE (sizeof("site") - 1)
|
||||
@ -515,6 +534,7 @@ static void set_runtimepath_default(void)
|
||||
size_t data_len = 0;
|
||||
size_t config_len = 0;
|
||||
size_t vimruntime_len = 0;
|
||||
size_t libdir_len = 0;
|
||||
if (data_home != NULL) {
|
||||
data_len = strlen(data_home);
|
||||
if (data_len != 0) {
|
||||
@ -544,6 +564,12 @@ static void set_runtimepath_default(void)
|
||||
rtp_size += vimruntime_len + memcnt(vimruntime, ',', vimruntime_len) + 1;
|
||||
}
|
||||
}
|
||||
if (libdir != NULL) {
|
||||
libdir_len = strlen(libdir);
|
||||
if (libdir_len != 0) {
|
||||
rtp_size += libdir_len + memcnt(libdir, ',', libdir_len) + 1;
|
||||
}
|
||||
}
|
||||
rtp_size += compute_double_colon_len(data_dirs, NVIM_SIZE + 1 + SITE_SIZE + 1,
|
||||
AFTER_SIZE + 1);
|
||||
rtp_size += compute_double_colon_len(config_dirs, NVIM_SIZE + 1,
|
||||
@ -562,6 +588,7 @@ static void set_runtimepath_default(void)
|
||||
true);
|
||||
rtp_cur = add_dir(rtp_cur, vimruntime, vimruntime_len, kXDGNone,
|
||||
NULL, 0, NULL, 0);
|
||||
rtp_cur = add_dir(rtp_cur, libdir, libdir_len, kXDGNone, NULL, 0, NULL, 0);
|
||||
rtp_cur = add_colon_dirs(rtp_cur, data_dirs, "site", SITE_SIZE,
|
||||
"after", AFTER_SIZE, false);
|
||||
rtp_cur = add_dir(rtp_cur, data_home, data_len, kXDGDataHome,
|
||||
@ -583,6 +610,7 @@ static void set_runtimepath_default(void)
|
||||
xfree(data_home);
|
||||
xfree(config_home);
|
||||
xfree(vimruntime);
|
||||
xfree(libdir);
|
||||
}
|
||||
|
||||
#undef NVIM_SIZE
|
||||
|
@ -847,6 +847,20 @@ const void *vim_env_iter_rev(const char delim,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @param[out] exe_name should be at least MAXPATHL in size
|
||||
void vim_get_prefix_from_exepath(char *exe_name)
|
||||
{
|
||||
// TODO(bfredl): param could have been written as "char exe_name[MAXPATHL]"
|
||||
// but c_grammar.lua does not recognize it (yet).
|
||||
xstrlcpy(exe_name, (char *)get_vim_var_str(VV_PROGPATH),
|
||||
MAXPATHL * sizeof(*exe_name));
|
||||
char *path_end = (char *)path_tail_with_sep((char_u *)exe_name);
|
||||
*path_end = '\0'; // remove the trailing "nvim.exe"
|
||||
path_end = (char *)path_tail((char_u *)exe_name);
|
||||
*path_end = '\0'; // remove the trailing "bin/"
|
||||
}
|
||||
|
||||
/// Vim getenv() wrapper with special handling of $HOME, $VIM, $VIMRUNTIME,
|
||||
/// allowing the user to override the Nvim runtime directory at runtime.
|
||||
/// Result must be freed by the caller.
|
||||
@ -902,12 +916,7 @@ char *vim_getenv(const char *name)
|
||||
char exe_name[MAXPATHL];
|
||||
// Find runtime path relative to the nvim binary: ../share/nvim/runtime
|
||||
if (vim_path == NULL) {
|
||||
xstrlcpy(exe_name, (char *)get_vim_var_str(VV_PROGPATH),
|
||||
sizeof(exe_name));
|
||||
char *path_end = (char *)path_tail_with_sep((char_u *)exe_name);
|
||||
*path_end = '\0'; // remove the trailing "nvim.exe"
|
||||
path_end = (char *)path_tail((char_u *)exe_name);
|
||||
*path_end = '\0'; // remove the trailing "bin/"
|
||||
vim_get_prefix_from_exepath(exe_name);
|
||||
if (append_path(
|
||||
exe_name,
|
||||
"share" _PATHSEPSTR "nvim" _PATHSEPSTR "runtime" _PATHSEPSTR,
|
||||
|
@ -23,6 +23,7 @@ local pcall_err = helpers.pcall_err
|
||||
local format_string = helpers.format_string
|
||||
local intchar2lua = helpers.intchar2lua
|
||||
local mergedicts_copy = helpers.mergedicts_copy
|
||||
local endswith = helpers.endswith
|
||||
|
||||
describe('API', function()
|
||||
before_each(clear)
|
||||
@ -1853,4 +1854,27 @@ describe('API', function()
|
||||
command('silent! call nvim_create_buf(0, 1)')
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('nvim_get_runtime_file', function()
|
||||
it('works', function()
|
||||
eq({}, meths.get_runtime_file("bork.borkbork", false))
|
||||
eq({}, meths.get_runtime_file("bork.borkbork", true))
|
||||
eq(1, #meths.get_runtime_file("autoload/msgpack.vim", false))
|
||||
eq(1, #meths.get_runtime_file("autoload/msgpack.vim", true))
|
||||
local val = meths.get_runtime_file("autoload/remote/*.vim", true)
|
||||
eq(2, #val)
|
||||
local p = helpers.alter_slashes
|
||||
if endswith(val[1], "define.vim") then
|
||||
ok(endswith(val[1], p("autoload/remote/define.vim")))
|
||||
ok(endswith(val[2], p("autoload/remote/host.vim")))
|
||||
else
|
||||
ok(endswith(val[1], p("autoload/remote/host.vim")))
|
||||
ok(endswith(val[2], p("autoload/remote/define.vim")))
|
||||
end
|
||||
val = meths.get_runtime_file("autoload/remote/*.vim", false)
|
||||
eq(1, #val)
|
||||
ok(endswith(val[1], p("autoload/remote/define.vim"))
|
||||
or endswith(val[1], p("autoload/remote/host.vim")))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
@ -6,7 +6,6 @@ local clear = helpers.clear
|
||||
local eq = helpers.eq
|
||||
local insert = helpers.insert
|
||||
local exec_lua = helpers.exec_lua
|
||||
local iswin = helpers.iswin
|
||||
local feed = helpers.feed
|
||||
local pcall_err = helpers.pcall_err
|
||||
local matches = helpers.matches
|
||||
@ -16,37 +15,35 @@ before_each(clear)
|
||||
describe('treesitter API', function()
|
||||
-- error tests not requiring a parser library
|
||||
it('handles missing language', function()
|
||||
eq('Error executing lua: .../treesitter.lua: no such language: borklang',
|
||||
eq("Error executing lua: .../treesitter.lua: no parser for 'borklang' language",
|
||||
pcall_err(exec_lua, "parser = vim.treesitter.create_parser(0, 'borklang')"))
|
||||
|
||||
-- actual message depends on platform
|
||||
matches('Error executing lua: Failed to load parser: uv_dlopen: .+',
|
||||
pcall_err(exec_lua, "parser = vim.treesitter.add_language('borkbork.so', 'borklang')"))
|
||||
matches("Error executing lua: Failed to load parser: uv_dlopen: .+",
|
||||
pcall_err(exec_lua, "parser = vim.treesitter.require_language('borklang', 'borkbork.so')"))
|
||||
|
||||
eq('Error executing lua: [string "<nvim>"]:1: no such language: borklang',
|
||||
eq("Error executing lua: .../treesitter.lua: no parser for 'borklang' language",
|
||||
pcall_err(exec_lua, "parser = vim.treesitter.inspect_language('borklang')"))
|
||||
end)
|
||||
|
||||
end)
|
||||
|
||||
describe('treesitter API with C parser', function()
|
||||
local ts_path = os.getenv("TREE_SITTER_DIR")
|
||||
|
||||
-- The tests after this requires an actual parser
|
||||
if ts_path == nil then
|
||||
it("works", function() pending("TREE_SITTER_PATH not set, skipping treesitter parser tests") end)
|
||||
return
|
||||
local function check_parser()
|
||||
local status, msg = unpack(exec_lua([[ return {pcall(vim.treesitter.require_language, 'c')} ]]))
|
||||
if not status then
|
||||
if helpers.isCI() then
|
||||
error("treesitter C parser not found, required on CI: " .. msg)
|
||||
else
|
||||
pending('no C parser, skipping')
|
||||
end
|
||||
end
|
||||
return status
|
||||
end
|
||||
|
||||
before_each(function()
|
||||
local path = ts_path .. '/bin/c'..(iswin() and '.dll' or '.so')
|
||||
exec_lua([[
|
||||
local path = ...
|
||||
vim.treesitter.add_language(path,'c')
|
||||
]], path)
|
||||
end)
|
||||
|
||||
it('parses buffer', function()
|
||||
if not check_parser() then return end
|
||||
|
||||
insert([[
|
||||
int main() {
|
||||
int x = 3;
|
||||
@ -138,6 +135,8 @@ void ui_refresh(void)
|
||||
]]
|
||||
|
||||
it('support query and iter by capture', function()
|
||||
if not check_parser() then return end
|
||||
|
||||
insert(test_text)
|
||||
|
||||
local res = exec_lua([[
|
||||
@ -167,6 +166,8 @@ void ui_refresh(void)
|
||||
end)
|
||||
|
||||
it('support query and iter by match', function()
|
||||
if not check_parser() then return end
|
||||
|
||||
insert(test_text)
|
||||
|
||||
local res = exec_lua([[
|
||||
@ -198,6 +199,8 @@ void ui_refresh(void)
|
||||
end)
|
||||
|
||||
it('supports highlighting', function()
|
||||
if not check_parser() then return end
|
||||
|
||||
local hl_text = [[
|
||||
/// Schedule Lua callback on main loop's event queue
|
||||
static int nlua_schedule(lua_State *const lstate)
|
||||
@ -357,41 +360,43 @@ static int nlua_schedule(lua_State *const lstate)
|
||||
end)
|
||||
|
||||
it('inspects language', function()
|
||||
local keys, fields, symbols = unpack(exec_lua([[
|
||||
local lang = vim.treesitter.inspect_language('c')
|
||||
local keys, symbols = {}, {}
|
||||
for k,_ in pairs(lang) do
|
||||
keys[k] = true
|
||||
end
|
||||
if not check_parser() then return end
|
||||
|
||||
-- symbols array can have "holes" and is thus not a valid msgpack array
|
||||
-- but we don't care about the numbers here (checked in the parser test)
|
||||
for _, v in pairs(lang.symbols) do
|
||||
table.insert(symbols, v)
|
||||
end
|
||||
return {keys, lang.fields, symbols}
|
||||
]]))
|
||||
|
||||
eq({fields=true, symbols=true}, keys)
|
||||
|
||||
local fset = {}
|
||||
for _,f in pairs(fields) do
|
||||
eq("string", type(f))
|
||||
fset[f] = true
|
||||
local keys, fields, symbols = unpack(exec_lua([[
|
||||
local lang = vim.treesitter.inspect_language('c')
|
||||
local keys, symbols = {}, {}
|
||||
for k,_ in pairs(lang) do
|
||||
keys[k] = true
|
||||
end
|
||||
eq(true, fset["directive"])
|
||||
eq(true, fset["initializer"])
|
||||
|
||||
local has_named, has_anonymous
|
||||
for _,s in pairs(symbols) do
|
||||
eq("string", type(s[1]))
|
||||
eq("boolean", type(s[2]))
|
||||
if s[1] == "for_statement" and s[2] == true then
|
||||
has_named = true
|
||||
elseif s[1] == "|=" and s[2] == false then
|
||||
has_anonymous = true
|
||||
end
|
||||
-- symbols array can have "holes" and is thus not a valid msgpack array
|
||||
-- but we don't care about the numbers here (checked in the parser test)
|
||||
for _, v in pairs(lang.symbols) do
|
||||
table.insert(symbols, v)
|
||||
end
|
||||
eq({true,true}, {has_named,has_anonymous})
|
||||
return {keys, lang.fields, symbols}
|
||||
]]))
|
||||
|
||||
eq({fields=true, symbols=true}, keys)
|
||||
|
||||
local fset = {}
|
||||
for _,f in pairs(fields) do
|
||||
eq("string", type(f))
|
||||
fset[f] = true
|
||||
end
|
||||
eq(true, fset["directive"])
|
||||
eq(true, fset["initializer"])
|
||||
|
||||
local has_named, has_anonymous
|
||||
for _,s in pairs(symbols) do
|
||||
eq("string", type(s[1]))
|
||||
eq("boolean", type(s[2]))
|
||||
if s[1] == "for_statement" and s[2] == true then
|
||||
has_named = true
|
||||
elseif s[1] == "|=" and s[2] == false then
|
||||
has_anonymous = true
|
||||
end
|
||||
end
|
||||
eq({true,true}, {has_named,has_anonymous})
|
||||
end)
|
||||
end)
|
||||
|
@ -293,6 +293,14 @@ describe('XDG-based defaults', function()
|
||||
-- TODO(jkeyes): tests below fail on win32 because of path separator.
|
||||
if helpers.pending_win32(pending) then return end
|
||||
|
||||
local function vimruntime_and_libdir()
|
||||
local vimruntime = eval('$VIMRUNTIME')
|
||||
-- libdir is hard to calculate reliably across various ci platforms
|
||||
-- local libdir = string.gsub(vimruntime, "share/nvim/runtime$", "lib/nvim")
|
||||
local libdir = meths._get_lib_dir()
|
||||
return vimruntime, libdir
|
||||
end
|
||||
|
||||
describe('with too long XDG variables', function()
|
||||
before_each(function()
|
||||
clear({env={
|
||||
@ -308,6 +316,8 @@ describe('XDG-based defaults', function()
|
||||
end)
|
||||
|
||||
it('are correctly set', function()
|
||||
local vimruntime, libdir = vimruntime_and_libdir()
|
||||
|
||||
eq((('/x'):rep(4096) .. '/nvim'
|
||||
.. ',' .. ('/a'):rep(2048) .. '/nvim'
|
||||
.. ',' .. ('/b'):rep(2048) .. '/nvim'
|
||||
@ -316,7 +326,8 @@ describe('XDG-based defaults', function()
|
||||
.. ',' .. ('/A'):rep(2048) .. '/nvim/site'
|
||||
.. ',' .. ('/B'):rep(2048) .. '/nvim/site'
|
||||
.. (',' .. '/C/nvim/site'):rep(512)
|
||||
.. ',' .. eval('$VIMRUNTIME')
|
||||
.. ',' .. vimruntime
|
||||
.. ',' .. libdir
|
||||
.. (',' .. '/C/nvim/site/after'):rep(512)
|
||||
.. ',' .. ('/B'):rep(2048) .. '/nvim/site/after'
|
||||
.. ',' .. ('/A'):rep(2048) .. '/nvim/site/after'
|
||||
@ -339,7 +350,8 @@ describe('XDG-based defaults', function()
|
||||
.. ',' .. ('/A'):rep(2048) .. '/nvim/site'
|
||||
.. ',' .. ('/B'):rep(2048) .. '/nvim/site'
|
||||
.. (',' .. '/C/nvim/site'):rep(512)
|
||||
.. ',' .. eval('$VIMRUNTIME')
|
||||
.. ',' .. vimruntime
|
||||
.. ',' .. libdir
|
||||
.. (',' .. '/C/nvim/site/after'):rep(512)
|
||||
.. ',' .. ('/B'):rep(2048) .. '/nvim/site/after'
|
||||
.. ',' .. ('/A'):rep(2048) .. '/nvim/site/after'
|
||||
@ -368,11 +380,13 @@ describe('XDG-based defaults', function()
|
||||
end)
|
||||
|
||||
it('are not expanded', function()
|
||||
local vimruntime, libdir = vimruntime_and_libdir()
|
||||
eq(('$XDG_DATA_HOME/nvim'
|
||||
.. ',$XDG_DATA_DIRS/nvim'
|
||||
.. ',$XDG_CONFIG_HOME/nvim/site'
|
||||
.. ',$XDG_CONFIG_DIRS/nvim/site'
|
||||
.. ',' .. eval('$VIMRUNTIME')
|
||||
.. ',' .. vimruntime
|
||||
.. ',' .. libdir
|
||||
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
|
||||
.. ',$XDG_CONFIG_HOME/nvim/site/after'
|
||||
.. ',$XDG_DATA_DIRS/nvim/after'
|
||||
@ -387,7 +401,8 @@ describe('XDG-based defaults', function()
|
||||
.. ',$XDG_DATA_DIRS/nvim'
|
||||
.. ',$XDG_CONFIG_HOME/nvim/site'
|
||||
.. ',$XDG_CONFIG_DIRS/nvim/site'
|
||||
.. ',' .. eval('$VIMRUNTIME')
|
||||
.. ',' .. vimruntime
|
||||
.. ',' .. libdir
|
||||
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
|
||||
.. ',$XDG_CONFIG_HOME/nvim/site/after'
|
||||
.. ',$XDG_DATA_DIRS/nvim/after'
|
||||
@ -402,7 +417,8 @@ describe('XDG-based defaults', function()
|
||||
.. ',$XDG_DATA_DIRS/nvim'
|
||||
.. ',$XDG_CONFIG_HOME/nvim/site'
|
||||
.. ',$XDG_CONFIG_DIRS/nvim/site'
|
||||
.. ',' .. eval('$VIMRUNTIME')
|
||||
.. ',' .. vimruntime
|
||||
.. ',' .. libdir
|
||||
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
|
||||
.. ',$XDG_CONFIG_HOME/nvim/site/after'
|
||||
.. ',$XDG_DATA_DIRS/nvim/after'
|
||||
@ -426,13 +442,15 @@ describe('XDG-based defaults', function()
|
||||
end)
|
||||
|
||||
it('are escaped properly', function()
|
||||
local vimruntime, libdir = vimruntime_and_libdir()
|
||||
eq(('\\, \\, \\,/nvim'
|
||||
.. ',\\,-\\,-\\,/nvim'
|
||||
.. ',-\\,-\\,-/nvim'
|
||||
.. ',\\,=\\,=\\,/nvim/site'
|
||||
.. ',\\,≡\\,≡\\,/nvim/site'
|
||||
.. ',≡\\,≡\\,≡/nvim/site'
|
||||
.. ',' .. eval('$VIMRUNTIME')
|
||||
.. ',' .. vimruntime
|
||||
.. ',' .. libdir
|
||||
.. ',≡\\,≡\\,≡/nvim/site/after'
|
||||
.. ',\\,≡\\,≡\\,/nvim/site/after'
|
||||
.. ',\\,=\\,=\\,/nvim/site/after'
|
||||
@ -451,7 +469,8 @@ describe('XDG-based defaults', function()
|
||||
.. ',\\,=\\,=\\,/nvim/site'
|
||||
.. ',\\,≡\\,≡\\,/nvim/site'
|
||||
.. ',≡\\,≡\\,≡/nvim/site'
|
||||
.. ',' .. eval('$VIMRUNTIME')
|
||||
.. ',' .. vimruntime
|
||||
.. ',' .. libdir
|
||||
.. ',≡\\,≡\\,≡/nvim/site/after'
|
||||
.. ',\\,≡\\,≡\\,/nvim/site/after'
|
||||
.. ',\\,=\\,=\\,/nvim/site/after'
|
||||
|
8
third-party/CMakeLists.txt
vendored
8
third-party/CMakeLists.txt
vendored
@ -42,6 +42,7 @@ option(USE_BUNDLED_LUV "Use the bundled version of luv." ${USE_BUNDLED})
|
||||
#XXX(tarruda): Lua is only used for debugging the functional test client, no
|
||||
# build it unless explicitly requested
|
||||
option(USE_BUNDLED_LUA "Use the bundled version of lua." OFF)
|
||||
option(USE_BUNDLED_TS_PARSERS "Use the bundled treesitter parsers." ${USE_BUNDLED})
|
||||
|
||||
if(USE_BUNDLED AND MSVC)
|
||||
option(USE_BUNDLED_GETTEXT "Use the bundled version of gettext." ON)
|
||||
@ -199,6 +200,9 @@ set(LIBICONV_SHA256 ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc891
|
||||
set(UTF8PROC_URL https://github.com/JuliaStrings/utf8proc/archive/v2.2.0.tar.gz)
|
||||
set(UTF8PROC_SHA256 3f8fd1dbdb057ee5ba584a539d5cd1b3952141c0338557cb0bdf8cb9cfed5dbf)
|
||||
|
||||
set(TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/6002fcd.tar.gz)
|
||||
set(TREESITTER_C_SHA256 46f8d44fa886d9ddb92571bb6fa8b175992c8758eca749cb1217464e512b6e97)
|
||||
|
||||
if(USE_BUNDLED_UNIBILIUM)
|
||||
include(BuildUnibilium)
|
||||
endif()
|
||||
@ -254,6 +258,10 @@ if(USE_BUNDLED_UTF8PROC)
|
||||
include(BuildUtf8proc)
|
||||
endif()
|
||||
|
||||
if(USE_BUNDLED_TS_PARSERS)
|
||||
include(BuildTreesitterParsers)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
include(GetBinaryDeps)
|
||||
|
||||
|
28
third-party/cmake/BuildTreesitterParsers.cmake
vendored
Normal file
28
third-party/cmake/BuildTreesitterParsers.cmake
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
ExternalProject_Add(treesitter-c
|
||||
PREFIX ${DEPS_BUILD_DIR}
|
||||
URL ${TREESITER_C_URL}
|
||||
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/treesitter-c
|
||||
DOWNLOAD_COMMAND ${CMAKE_COMMAND}
|
||||
-DPREFIX=${DEPS_BUILD_DIR}
|
||||
-DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/treesitter-c
|
||||
-DURL=${TREESITTER_C_URL}
|
||||
-DEXPECTED_SHA256=${TREESITTER_C_SHA256}
|
||||
-DTARGET=treesitter-c
|
||||
-DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/TreesitterParserCMakeLists.txt
|
||||
${DEPS_BUILD_DIR}/src/treesitter-c/CMakeLists.txt
|
||||
COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/treesitter-c/CMakeLists.txt
|
||||
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
|
||||
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
|
||||
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
|
||||
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
|
||||
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
|
||||
# Pass toolchain
|
||||
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
|
||||
-DPARSERLANG=c
|
||||
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE})
|
19
third-party/cmake/TreesitterParserCMakeLists.txt
vendored
Normal file
19
third-party/cmake/TreesitterParserCMakeLists.txt
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
# some parsers have c++ scanner, problem?
|
||||
project(parser C) # CXX
|
||||
|
||||
add_library(parser
|
||||
MODULE
|
||||
src/parser.c
|
||||
)
|
||||
set_target_properties(
|
||||
parser
|
||||
PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
OUTPUT_NAME ${PARSERLANG}
|
||||
PREFIX ""
|
||||
)
|
||||
|
||||
include_directories(src)
|
||||
|
||||
install(TARGETS parser LIBRARY DESTINATION lib/nvim/parser)
|
Loading…
Reference in New Issue
Block a user