aboutsummaryrefslogtreecommitdiff
path: root/test/unit/helpers.moon
diff options
context:
space:
mode:
Diffstat (limited to 'test/unit/helpers.moon')
-rw-r--r--test/unit/helpers.moon97
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