diff options
Diffstat (limited to 'test/unit/helpers.moon')
-rw-r--r-- | test/unit/helpers.moon | 97 |
1 files changed, 81 insertions, 16 deletions
diff --git a/test/unit/helpers.moon b/test/unit/helpers.moon index 77d491a008..e84c569143 100644 --- a/test/unit/helpers.moon +++ b/test/unit/helpers.moon @@ -1,4 +1,19 @@ ffi = require 'ffi' +lpeg = require 'lpeg' +formatc = require 'test.unit.formatc' +Set = require 'test.unit.set' +Preprocess = require 'test.unit.preprocess' + +-- add some standard header locations +-- TODO(aktau, jszakmeister): optionally pass more header locations via env +Preprocess.add_to_include_path('./src') +Preprocess.add_to_include_path('./.deps/usr/include') +Preprocess.add_to_include_path('./build/config') + +if ffi.abi('32bit') + Preprocess.add_to_include_path('/opt/neovim-deps/32/include') +else + Preprocess.add_to_include_path('/opt/neovim-deps/include') -- load neovim shared library testlib = os.getenv 'NVIM_TEST_LIB' @@ -7,22 +22,72 @@ unless testlib libnvim = ffi.load testlib --- Luajit ffi parser doesn't understand preprocessor directives, so --- this helper function removes common directives before passing it the to ffi. --- It will return a pointer to the library table, emulating 'requires' -cimport = (path) -> - header_file = io.open path, 'rb' - - if not header_file - error "cannot find #{path}" - - header = header_file\read '*a' - header_file.close! - header = string.gsub header, '#include[^\n]*\n', '' - header = string.gsub header, '#ifndef[^\n]*\n', '' - header = string.gsub header, '#define[^\n]*\n', '' - header = string.gsub header, '#endif[^\n]*\n', '' - ffi.cdef header +trim = (s) -> + s\match'^%s*(.*%S)' or '' + +-- a Set that keeps around the lines we've already seen +export cdefs +if cdefs == nil + cdefs = Set! + +export imported +if imported == nil + imported = Set! + +-- some things are just too complex for the LuaJIT C parser to digest. We +-- usually don't need them anyway. +filter_complex_blocks = (body) -> + result = {} + for line in body\gmatch("[^\r\n]+") + -- remove all lines that contain Objective-C block syntax, the LuaJIT ffi + -- doesn't understand it. + if string.find(line, "(^)", 1, true) ~= nil + continue + if string.find(line, "_ISwupper", 1, true) ~= nil + continue + result[#result + 1] = line + table.concat(result, "\n") + +-- use this helper to import C files, you can pass multiple paths at once, +-- this helper will return the C namespace of the nvim library. +-- cimport = (path) -> +cimport = (...) -> + -- filter out paths we've already imported + paths = [path for path in *{...} when not imported\contains(path)] + for path in *paths + imported\add(path) + + if #paths == 0 + return libnvim + + -- preprocess the header + stream = Preprocess.preprocess_stream(unpack(paths)) + body = stream\read("*a") + stream\close! + + -- format it (so that the lines are "unique" statements), also filter out + -- Objective-C blocks + body = formatc(body) + body = filter_complex_blocks(body) + + -- add the formatted lines to a set + new_cdefs = Set! + for line in body\gmatch("[^\r\n]+") + new_cdefs\add(trim(line)) + + -- subtract the lines we've already imported from the new lines, then add + -- the new unique lines to the old lines (so they won't be imported again) + new_cdefs\diff(cdefs) + cdefs\union(new_cdefs) + + if new_cdefs\size! == 0 + -- if there's no new lines, just return + return libnvim + + -- request a sorted version of the new lines (same relative order as the + -- original preprocessed file) and feed that to the LuaJIT ffi + new_lines = new_cdefs\to_table! + ffi.cdef(table.concat(new_lines, "\n")) return libnvim |