aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2017-03-15 17:46:07 +0100
committerGitHub <noreply@github.com>2017-03-15 17:46:07 +0100
commitf4b8dbeeb21ca65c5cd19fa361c5588349c0a1e0 (patch)
tree183cfb73ac950194b70c37a1b89aeb57028cec6d
parentec4e84210b87965e7110b061a321c7ec8a359d47 (diff)
parent7d28489a338e7112c0c7dc5e5a131ba8dcd1b3d2 (diff)
downloadrneovim-f4b8dbeeb21ca65c5cd19fa361c5588349c0a1e0.tar.gz
rneovim-f4b8dbeeb21ca65c5cd19fa361c5588349c0a1e0.tar.bz2
rneovim-f4b8dbeeb21ca65c5cd19fa361c5588349c0a1e0.zip
Merge pull request #5540 from bfredl/api_since
allow specify api since field and more api compatibility checks
-rw-r--r--CMakeLists.txt4
-rw-r--r--scripts/gendispatch.lua13
-rwxr-xr-xscripts/release.sh9
-rw-r--r--src/nvim/api/buffer.c17
-rw-r--r--src/nvim/api/tabpage.c7
-rw-r--r--src/nvim/api/ui.c8
-rw-r--r--src/nvim/api/vim.c42
-rw-r--r--src/nvim/api/window.c16
-rw-r--r--src/nvim/func_attr.h1
-rw-r--r--test/functional/api/version_spec.lua134
-rw-r--r--test/functional/fixtures/api_level_1.mpackbin0 -> 16695 bytes
11 files changed, 206 insertions, 45 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2fd5209396..1a058f2bff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -68,9 +68,9 @@ set(NVIM_VERSION_PATCH 0)
set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
# API level
-set(NVIM_API_LEVEL 1) # Bump this after any API change.
+set(NVIM_API_LEVEL 2) # Bump this after any API change.
set(NVIM_API_LEVEL_COMPAT 0) # Adjust this after a _breaking_ API change.
-set(NVIM_API_PRERELEASE false)
+set(NVIM_API_PRERELEASE true)
file(TO_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/.git FORCED_GIT_DIR)
include(GetGitRevisionDescription)
diff --git a/scripts/gendispatch.lua b/scripts/gendispatch.lua
index 397ccc9aaf..45a4f4a4de 100644
--- a/scripts/gendispatch.lua
+++ b/scripts/gendispatch.lua
@@ -9,7 +9,8 @@ C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg
any = P(1) -- (consume one character)
letter = R('az', 'AZ') + S('_$')
-alpha = letter + R('09')
+num = R('09')
+alpha = letter + num
nl = P('\r\n') + P('\n')
not_nl = any - nl
ws = S(' \t') + nl
@@ -35,6 +36,7 @@ c_proto = Ct(
Cg(c_type, 'return_type') * Cg(c_id, 'name') *
fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') *
Cg(Cc(false), 'async') *
+ (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) *
(fill * Cg((P('FUNC_API_ASYNC') * Cc(true)), 'async') ^ -1) *
(fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) *
(fill * Cg((P('FUNC_API_NOEVAL') * Cc(true)), 'noeval') ^ -1) *
@@ -52,6 +54,7 @@ package.path = nvimsrcdir .. '/?.lua;' .. package.path
-- names of all headers relative to the source root (for inclusion in the
-- generated file)
headers = {}
+
-- output h file with generated dispatch functions
dispatch_outputf = arg[#arg-2]
-- output h file with packed metadata
@@ -114,9 +117,11 @@ local deprecated_aliases = require("api.dispatch_deprecated")
for i,f in ipairs(shallowcopy(functions)) do
local ismethod = false
if startswith(f.name, "nvim_") then
- -- TODO(bfredl) after 0.1.6 allow method definitions
- -- to specify the since and deprecated_since field
- f.since = 1
+ if f.since == nil then
+ print("Function "..f.name.." lacks since field.\n")
+ os.exit(1)
+ end
+ f.since = tonumber(f.since)
if startswith(f.name, "nvim_buf_") then
ismethod = true
elseif startswith(f.name, "nvim_win_") then
diff --git a/scripts/release.sh b/scripts/release.sh
index 93f9fa3d35..dac5e9b177 100755
--- a/scripts/release.sh
+++ b/scripts/release.sh
@@ -31,6 +31,8 @@ __VERSION_MINOR=$(grep 'set(NVIM_VERSION_MINOR' CMakeLists.txt\
__VERSION_PATCH=$(grep 'set(NVIM_VERSION_PATCH' CMakeLists.txt\
|$__sed 's/.*NVIM_VERSION_PATCH ([[:digit:]]).*/\1/')
__VERSION="${__VERSION_MAJOR}.${__VERSION_MINOR}.${__VERSION_PATCH}"
+__API_LEVEL=$(grep 'set(NVIM_API_LEVEL ' CMakeLists.txt\
+ |$__sed 's/.*NVIM_API_LEVEL ([[:digit:]]).*/\1/')
{ [ -z "$__VERSION_MAJOR" ] || [ -z "$__VERSION_MINOR" ] || [ -z "$__VERSION_PATCH" ]; } \
&& { echo "ERROR: version parse failed: '${__VERSION}'"; exit 1; }
__RELEASE_MSG="NVIM v${__VERSION}
@@ -47,7 +49,12 @@ __BUMP_MSG="version bump"
echo "Most recent tag: ${__LAST_TAG}"
echo "Release version: ${__VERSION}"
$__sed -i.bk 's/(NVIM_VERSION_PRERELEASE) "-dev"/\1 ""/' CMakeLists.txt
-$__sed -i.bk 's/(NVIM_API_PRERELEASE) true/\1 false/' CMakeLists.txt
+if grep '(NVIM_API_PRERELEASE true)' CMakeLists.txt > /dev/null; then
+ $__sed -i.bk 's/(NVIM_API_PRERELEASE) true/\1 false/' CMakeLists.txt
+ cp build/funcs_data.mpack test/functional/fixtures/api_level_$__API_LEVEL.mpack
+ git add test/functional/fixtures/api_level_$__API_LEVEL.mpack
+fi
+
echo "Building changelog since ${__LAST_TAG}..."
__CHANGELOG="$(./scripts/git-log-pretty-since.sh "$__LAST_TAG" 'vim-patch:\S')"
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index c7e535228a..b75a2c7211 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -32,6 +32,7 @@
/// @param[out] err Error details, if any
/// @return Line count
Integer nvim_buf_line_count(Buffer buffer, Error *err)
+ FUNC_API_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -132,7 +133,6 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
return nvim_buf_get_lines(0, buffer, start , end, false, err);
}
-
/// Retrieves a line range from the buffer
///
/// Indexing is zero-based, end-exclusive. Negative indices are interpreted
@@ -154,6 +154,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id,
Integer end,
Boolean strict_indexing,
Error *err)
+ FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -266,6 +267,7 @@ void nvim_buf_set_lines(uint64_t channel_id,
Boolean strict_indexing,
ArrayOf(String) replacement, // NOLINT
Error *err)
+ FUNC_API_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -416,6 +418,7 @@ end:
/// @param[out] err Error details, if any
/// @return Variable value
Object nvim_buf_get_var(Buffer buffer, String name, Error *err)
+ FUNC_API_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -432,6 +435,7 @@ Object nvim_buf_get_var(Buffer buffer, String name, Error *err)
///
/// @return `b:changedtick` value.
Integer nvim_buf_get_changedtick(Buffer buffer, Error *err)
+ FUNC_API_SINCE(2)
{
const buf_T *const buf = find_buffer_by_handle(buffer, err);
@@ -449,6 +453,7 @@ Integer nvim_buf_get_changedtick(Buffer buffer, Error *err)
/// @param value Variable value
/// @param[out] err Error details, if any
void nvim_buf_set_var(Buffer buffer, String name, Object value, Error *err)
+ FUNC_API_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -465,6 +470,7 @@ void nvim_buf_set_var(Buffer buffer, String name, Object value, Error *err)
/// @param name Variable name
/// @param[out] err Error details, if any
void nvim_buf_del_var(Buffer buffer, String name, Error *err)
+ FUNC_API_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -525,6 +531,7 @@ Object buffer_del_var(Buffer buffer, String name, Error *err)
/// @param[out] err Error details, if any
/// @return Option value
Object nvim_buf_get_option(Buffer buffer, String name, Error *err)
+ FUNC_API_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -543,6 +550,7 @@ Object nvim_buf_get_option(Buffer buffer, String name, Error *err)
/// @param value Option value
/// @param[out] err Error details, if any
void nvim_buf_set_option(Buffer buffer, String name, Object value, Error *err)
+ FUNC_API_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -559,6 +567,7 @@ void nvim_buf_set_option(Buffer buffer, String name, Object value, Error *err)
/// @param[out] err Error details, if any
/// @return Buffer number
Integer nvim_buf_get_number(Buffer buffer, Error *err)
+ FUNC_API_SINCE(1)
{
Integer rv = 0;
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -576,6 +585,7 @@ Integer nvim_buf_get_number(Buffer buffer, Error *err)
/// @param[out] err Error details, if any
/// @return Buffer name
String nvim_buf_get_name(Buffer buffer, Error *err)
+ FUNC_API_SINCE(1)
{
String rv = STRING_INIT;
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -593,6 +603,7 @@ String nvim_buf_get_name(Buffer buffer, Error *err)
/// @param name Buffer name
/// @param[out] err Error details, if any
void nvim_buf_set_name(Buffer buffer, String name, Error *err)
+ FUNC_API_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -622,6 +633,7 @@ void nvim_buf_set_name(Buffer buffer, String name, Error *err)
/// @param buffer Buffer handle
/// @return true if the buffer is valid, false otherwise
Boolean nvim_buf_is_valid(Buffer buffer)
+ FUNC_API_SINCE(1)
{
Error stub = ERROR_INIT;
return find_buffer_by_handle(buffer, &stub) != NULL;
@@ -653,6 +665,7 @@ void buffer_insert(Buffer buffer,
/// @param[out] err Error details, if any
/// @return (row, col) tuple
ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err)
+ FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -727,6 +740,7 @@ Integer nvim_buf_add_highlight(Buffer buffer,
Integer col_start,
Integer col_end,
Error *err)
+ FUNC_API_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
@@ -767,6 +781,7 @@ void nvim_buf_clear_highlight(Buffer buffer,
Integer line_start,
Integer line_end,
Error *err)
+ FUNC_API_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c
index d24250d032..0f0c33f621 100644
--- a/src/nvim/api/tabpage.c
+++ b/src/nvim/api/tabpage.c
@@ -15,6 +15,7 @@
/// @param[out] err Error details, if any
/// @return List of windows in `tabpage`
ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err)
+ FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -44,6 +45,7 @@ ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err)
/// @param[out] err Error details, if any
/// @return Variable value
Object nvim_tabpage_get_var(Tabpage tabpage, String name, Error *err)
+ FUNC_API_SINCE(1)
{
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -64,6 +66,7 @@ void nvim_tabpage_set_var(Tabpage tabpage,
String name,
Object value,
Error *err)
+ FUNC_API_SINCE(1)
{
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -80,6 +83,7 @@ void nvim_tabpage_set_var(Tabpage tabpage,
/// @param name Variable name
/// @param[out] err Error details, if any
void nvim_tabpage_del_var(Tabpage tabpage, String name, Error *err)
+ FUNC_API_SINCE(1)
{
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -138,6 +142,7 @@ Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
/// @param[out] err Error details, if any
/// @return Window handle
Window nvim_tabpage_get_win(Tabpage tabpage, Error *err)
+ FUNC_API_SINCE(1)
{
Window rv = 0;
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -165,6 +170,7 @@ Window nvim_tabpage_get_win(Tabpage tabpage, Error *err)
/// @param[out] err Error details, if any
/// @return Tabpage number
Integer nvim_tabpage_get_number(Tabpage tabpage, Error *err)
+ FUNC_API_SINCE(1)
{
Integer rv = 0;
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -181,6 +187,7 @@ Integer nvim_tabpage_get_number(Tabpage tabpage, Error *err)
/// @param tabpage Tabpage handle
/// @return true if the tabpage is valid, false otherwise
Boolean nvim_tabpage_is_valid(Tabpage tabpage)
+ FUNC_API_SINCE(1)
{
Error stub = ERROR_INIT;
return find_tab_by_handle(tabpage, &stub) != NULL;
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 9178538110..625bcc6b4b 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -48,7 +48,7 @@ void remote_ui_disconnect(uint64_t channel_id)
void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
Dictionary options, Error *err)
- FUNC_API_NOEVAL
+ FUNC_API_SINCE(1) FUNC_API_NOEVAL
{
if (pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(err, Exception, _("UI already attached for channel"));
@@ -118,7 +118,7 @@ void ui_attach(uint64_t channel_id, Integer width, Integer height,
}
void nvim_ui_detach(uint64_t channel_id, Error *err)
- FUNC_API_NOEVAL
+ FUNC_API_SINCE(1) FUNC_API_NOEVAL
{
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(err, Exception, _("UI is not attached for channel"));
@@ -130,7 +130,7 @@ void nvim_ui_detach(uint64_t channel_id, Error *err)
void nvim_ui_try_resize(uint64_t channel_id, Integer width,
Integer height, Error *err)
- FUNC_API_NOEVAL
+ FUNC_API_SINCE(1) FUNC_API_NOEVAL
{
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(err, Exception, _("UI is not attached for channel"));
@@ -151,7 +151,7 @@ void nvim_ui_try_resize(uint64_t channel_id, Integer width,
void nvim_ui_set_option(uint64_t channel_id, String name,
Object value, Error *error)
- FUNC_API_NOEVAL
+ FUNC_API_SINCE(1) FUNC_API_NOEVAL
{
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(error, Exception, _("UI is not attached for channel"));
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index bf11795d9e..413456c615 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -39,6 +39,7 @@
/// @param command Ex-command string
/// @param[out] err Error details (including actual VimL error), if any
void nvim_command(String command, Error *err)
+ FUNC_API_SINCE(1)
{
// Run the command
try_start();
@@ -56,6 +57,7 @@ void nvim_command(String command, Error *err)
/// @see feedkeys()
/// @see vim_strsave_escape_csi
void nvim_feedkeys(String keys, String mode, Boolean escape_csi)
+ FUNC_API_SINCE(1)
{
bool remap = true;
bool insert = false;
@@ -122,7 +124,7 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi)
/// @return Number of bytes actually written (can be fewer than
/// requested if the buffer becomes full).
Integer nvim_input(String keys)
- FUNC_API_ASYNC
+ FUNC_API_SINCE(1) FUNC_API_ASYNC
{
return (Integer)input_enqueue(keys);
}
@@ -133,6 +135,7 @@ Integer nvim_input(String keys)
/// @see cpoptions
String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt,
Boolean special)
+ FUNC_API_SINCE(1)
{
if (str.size == 0) {
// Empty string
@@ -152,6 +155,7 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt,
}
String nvim_command_output(String str, Error *err)
+ FUNC_API_SINCE(1)
{
do_cmdline_cmd("redir => v:command_output");
nvim_command(str, err);
@@ -172,6 +176,7 @@ String nvim_command_output(String str, Error *err)
/// @param[out] err Error details, if any
/// @return Evaluation result or expanded object
Object nvim_eval(String expr, Error *err)
+ FUNC_API_SINCE(1)
{
Object rv = OBJECT_INIT;
// Evaluate the expression
@@ -200,6 +205,7 @@ Object nvim_eval(String expr, Error *err)
/// @param[out] err Error details, if any
/// @return Result of the function call
Object nvim_call_function(String fname, Array args, Error *err)
+ FUNC_API_SINCE(1)
{
Object rv = OBJECT_INIT;
if (args.size > MAX_FUNC_ARGS) {
@@ -248,6 +254,7 @@ free_vim_args:
/// @param[out] err Error details, if any
/// @return Number of cells
Integer nvim_strwidth(String str, Error *err)
+ FUNC_API_SINCE(1)
{
if (str.size > INT_MAX) {
api_set_error(err, Validation, _("String length is too high"));
@@ -261,6 +268,7 @@ Integer nvim_strwidth(String str, Error *err)
///
/// @return List of paths
ArrayOf(String) nvim_list_runtime_paths(void)
+ FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
uint8_t *rtp = p_rtp;
@@ -302,6 +310,7 @@ ArrayOf(String) nvim_list_runtime_paths(void)
/// @param dir Directory path
/// @param[out] err Error details, if any
void nvim_set_current_dir(String dir, Error *err)
+ FUNC_API_SINCE(1)
{
if (dir.size >= MAXPATHL) {
api_set_error(err, Validation, _("Directory string is too long"));
@@ -330,6 +339,7 @@ void nvim_set_current_dir(String dir, Error *err)
/// @param[out] err Error details, if any
/// @return Current line string
String nvim_get_current_line(Error *err)
+ FUNC_API_SINCE(1)
{
return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, err);
}
@@ -339,6 +349,7 @@ String nvim_get_current_line(Error *err)
/// @param line Line contents
/// @param[out] err Error details, if any
void nvim_set_current_line(String line, Error *err)
+ FUNC_API_SINCE(1)
{
buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, err);
}
@@ -347,6 +358,7 @@ void nvim_set_current_line(String line, Error *err)
///
/// @param[out] err Error details, if any
void nvim_del_current_line(Error *err)
+ FUNC_API_SINCE(1)
{
buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, err);
}
@@ -357,6 +369,7 @@ void nvim_del_current_line(Error *err)
/// @param[out] err Error details, if any
/// @return Variable value
Object nvim_get_var(String name, Error *err)
+ FUNC_API_SINCE(1)
{
return dict_get_value(&globvardict, name, err);
}
@@ -367,6 +380,7 @@ Object nvim_get_var(String name, Error *err)
/// @param value Variable value
/// @param[out] err Error details, if any
void nvim_set_var(String name, Object value, Error *err)
+ FUNC_API_SINCE(1)
{
dict_set_var(&globvardict, name, value, false, false, err);
}
@@ -376,6 +390,7 @@ void nvim_set_var(String name, Object value, Error *err)
/// @param name Variable name
/// @param[out] err Error details, if any
void nvim_del_var(String name, Error *err)
+ FUNC_API_SINCE(1)
{
dict_set_var(&globvardict, name, NIL, true, false, err);
}
@@ -414,6 +429,7 @@ Object vim_del_var(String name, Error *err)
/// @param[out] err Error details, if any
/// @return Variable value
Object nvim_get_vvar(String name, Error *err)
+ FUNC_API_SINCE(1)
{
return dict_get_value(&vimvardict, name, err);
}
@@ -424,6 +440,7 @@ Object nvim_get_vvar(String name, Error *err)
/// @param[out] err Error details, if any
/// @return Option value
Object nvim_get_option(String name, Error *err)
+ FUNC_API_SINCE(1)
{
return get_option_from(NULL, SREQ_GLOBAL, name, err);
}
@@ -434,6 +451,7 @@ Object nvim_get_option(String name, Error *err)
/// @param value New option value
/// @param[out] err Error details, if any
void nvim_set_option(String name, Object value, Error *err)
+ FUNC_API_SINCE(1)
{
set_option_to(NULL, SREQ_GLOBAL, name, value, err);
}
@@ -442,6 +460,7 @@ void nvim_set_option(String name, Object value, Error *err)
///
/// @param str Message
void nvim_out_write(String str)
+ FUNC_API_SINCE(1)
{
write_msg(str, false);
}
@@ -450,6 +469,7 @@ void nvim_out_write(String str)
///
/// @param str Message
void nvim_err_write(String str)
+ FUNC_API_SINCE(1)
{
write_msg(str, true);
}
@@ -460,6 +480,7 @@ void nvim_err_write(String str)
/// @param str Message
/// @see nvim_err_write()
void nvim_err_writeln(String str)
+ FUNC_API_SINCE(1)
{
nvim_err_write(str);
nvim_err_write((String) { .data = "\n", .size = 1 });
@@ -469,6 +490,7 @@ void nvim_err_writeln(String str)
///
/// @return List of buffer handles
ArrayOf(Buffer) nvim_list_bufs(void)
+ FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
@@ -490,6 +512,7 @@ ArrayOf(Buffer) nvim_list_bufs(void)
///
/// @return Buffer handle
Buffer nvim_get_current_buf(void)
+ FUNC_API_SINCE(1)
{
return curbuf->handle;
}
@@ -499,6 +522,7 @@ Buffer nvim_get_current_buf(void)
/// @param id Buffer handle
/// @param[out] err Error details, if any
void nvim_set_current_buf(Buffer buffer, Error *err)
+ FUNC_API_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -520,6 +544,7 @@ void nvim_set_current_buf(Buffer buffer, Error *err)
///
/// @return List of window handles
ArrayOf(Window) nvim_list_wins(void)
+ FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
@@ -541,6 +566,7 @@ ArrayOf(Window) nvim_list_wins(void)
///
/// @return Window handle
Window nvim_get_current_win(void)
+ FUNC_API_SINCE(1)
{
return curwin->handle;
}
@@ -549,6 +575,7 @@ Window nvim_get_current_win(void)
///
/// @param handle Window handle
void nvim_set_current_win(Window window, Error *err)
+ FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -570,6 +597,7 @@ void nvim_set_current_win(Window window, Error *err)
///
/// @return List of tabpage handles
ArrayOf(Tabpage) nvim_list_tabpages(void)
+ FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
@@ -591,6 +619,7 @@ ArrayOf(Tabpage) nvim_list_tabpages(void)
///
/// @return Tabpage handle
Tabpage nvim_get_current_tabpage(void)
+ FUNC_API_SINCE(1)
{
return curtab->handle;
}
@@ -600,6 +629,7 @@ Tabpage nvim_get_current_tabpage(void)
/// @param handle Tabpage handle
/// @param[out] err Error details, if any
void nvim_set_current_tabpage(Tabpage tabpage, Error *err)
+ FUNC_API_SINCE(1)
{
tabpage_T *tp = find_tab_by_handle(tabpage, err);
@@ -622,7 +652,7 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err)
/// @param channel_id Channel id (passed automatically by the dispatcher)
/// @param event Event type string
void nvim_subscribe(uint64_t channel_id, String event)
- FUNC_API_NOEVAL
+ FUNC_API_SINCE(1) FUNC_API_NOEVAL
{
size_t length = (event.size < METHOD_MAXLEN ? event.size : METHOD_MAXLEN);
char e[METHOD_MAXLEN + 1];
@@ -636,7 +666,7 @@ void nvim_subscribe(uint64_t channel_id, String event)
/// @param channel_id Channel id (passed automatically by the dispatcher)
/// @param event Event type string
void nvim_unsubscribe(uint64_t channel_id, String event)
- FUNC_API_NOEVAL
+ FUNC_API_SINCE(1) FUNC_API_NOEVAL
{
size_t length = (event.size < METHOD_MAXLEN ?
event.size :
@@ -648,11 +678,13 @@ void nvim_unsubscribe(uint64_t channel_id, String event)
}
Integer nvim_get_color_by_name(String name)
+ FUNC_API_SINCE(1)
{
return name_to_color((uint8_t *)name.data);
}
Dictionary nvim_get_color_map(void)
+ FUNC_API_SINCE(1)
{
Dictionary colors = ARRAY_DICT_INIT;
@@ -665,7 +697,7 @@ Dictionary nvim_get_color_map(void)
Array nvim_get_api_info(uint64_t channel_id)
- FUNC_API_ASYNC FUNC_API_NOEVAL
+ FUNC_API_SINCE(1) FUNC_API_ASYNC FUNC_API_NOEVAL
{
Array rv = ARRAY_DICT_INIT;
@@ -698,7 +730,7 @@ Array nvim_get_api_info(uint64_t channel_id)
/// which resulted in an error, the error type and the error message. If an
/// error ocurred, the values from all preceding calls will still be returned.
Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err)
- FUNC_API_NOEVAL
+ FUNC_API_SINCE(1) FUNC_API_NOEVAL
{
Array rv = ARRAY_DICT_INIT;
Array results = ARRAY_DICT_INIT;
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index 13294e6bf2..3c564ada99 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -19,6 +19,7 @@
/// @param[out] err Error details, if any
/// @return Buffer handle
Buffer nvim_win_get_buf(Window window, Error *err)
+ FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -35,6 +36,7 @@ Buffer nvim_win_get_buf(Window window, Error *err)
/// @param[out] err Error details, if any
/// @return (row, col) tuple
ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Error *err)
+ FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
win_T *win = find_window_by_handle(window, err);
@@ -53,6 +55,7 @@ ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Error *err)
/// @param pos (row, col) tuple representing the new position
/// @param[out] err Error details, if any
void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err)
+ FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -99,6 +102,7 @@ void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err)
/// @param[out] err Error details, if any
/// @return Height as a count of rows
Integer nvim_win_get_height(Window window, Error *err)
+ FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -116,6 +120,7 @@ Integer nvim_win_get_height(Window window, Error *err)
/// @param height Height as a count of rows
/// @param[out] err Error details, if any
void nvim_win_set_height(Window window, Integer height, Error *err)
+ FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -142,6 +147,7 @@ void nvim_win_set_height(Window window, Integer height, Error *err)
/// @param[out] err Error details, if any
/// @return Width as a count of columns
Integer nvim_win_get_width(Window window, Error *err)
+ FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -159,6 +165,7 @@ Integer nvim_win_get_width(Window window, Error *err)
/// @param width Width as a count of columns
/// @param[out] err Error details, if any
void nvim_win_set_width(Window window, Integer width, Error *err)
+ FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -186,6 +193,7 @@ void nvim_win_set_width(Window window, Integer width, Error *err)
/// @param[out] err Error details, if any
/// @return Variable value
Object nvim_win_get_var(Window window, String name, Error *err)
+ FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -203,6 +211,7 @@ Object nvim_win_get_var(Window window, String name, Error *err)
/// @param value Variable value
/// @param[out] err Error details, if any
void nvim_win_set_var(Window window, String name, Object value, Error *err)
+ FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -219,6 +228,7 @@ void nvim_win_set_var(Window window, String name, Object value, Error *err)
/// @param name Variable name
/// @param[out] err Error details, if any
void nvim_win_del_var(Window window, String name, Error *err)
+ FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -278,6 +288,7 @@ Object window_del_var(Window window, String name, Error *err)
/// @param[out] err Error details, if any
/// @return Option value
Object nvim_win_get_option(Window window, String name, Error *err)
+ FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -296,6 +307,7 @@ Object nvim_win_get_option(Window window, String name, Error *err)
/// @param value Option value
/// @param[out] err Error details, if any
void nvim_win_set_option(Window window, String name, Object value, Error *err)
+ FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -312,6 +324,7 @@ void nvim_win_set_option(Window window, String name, Object value, Error *err)
/// @param[out] err Error details, if any
/// @return (row, col) tuple with the window position
ArrayOf(Integer, 2) nvim_win_get_position(Window window, Error *err)
+ FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
win_T *win = find_window_by_handle(window, err);
@@ -330,6 +343,7 @@ ArrayOf(Integer, 2) nvim_win_get_position(Window window, Error *err)
/// @param[out] err Error details, if any
/// @return Tabpage that contains the window
Tabpage nvim_win_get_tabpage(Window window, Error *err)
+ FUNC_API_SINCE(1)
{
Tabpage rv = 0;
win_T *win = find_window_by_handle(window, err);
@@ -347,6 +361,7 @@ Tabpage nvim_win_get_tabpage(Window window, Error *err)
/// @param[out] err Error details, if any
/// @return Window number
Integer nvim_win_get_number(Window window, Error *err)
+ FUNC_API_SINCE(1)
{
int rv = 0;
win_T *win = find_window_by_handle(window, err);
@@ -366,6 +381,7 @@ Integer nvim_win_get_number(Window window, Error *err)
/// @param window Window handle
/// @return true if the window is valid, false otherwise
Boolean nvim_win_is_valid(Window window)
+ FUNC_API_SINCE(1)
{
Error stub = ERROR_INIT;
return find_window_by_handle(window, &stub) != NULL;
diff --git a/src/nvim/func_attr.h b/src/nvim/func_attr.h
index d98fe5b22b..18410445e1 100644
--- a/src/nvim/func_attr.h
+++ b/src/nvim/func_attr.h
@@ -186,6 +186,7 @@
# define FUNC_API_ASYNC
# define FUNC_API_NOEXPORT
# define FUNC_API_NOEVAL
+# define FUNC_API_SINCE(X)
# define FUNC_ATTR_MALLOC REAL_FATTR_MALLOC
# define FUNC_ATTR_ALLOC_SIZE(x) REAL_FATTR_ALLOC_SIZE(x)
# define FUNC_ATTR_ALLOC_SIZE_PROD(x, y) REAL_FATTR_ALLOC_SIZE_PROD(x, y)
diff --git a/test/functional/api/version_spec.lua b/test/functional/api/version_spec.lua
index 3efd00ddbe..d23f058f69 100644
--- a/test/functional/api/version_spec.lua
+++ b/test/functional/api/version_spec.lua
@@ -4,26 +4,16 @@ local clear, funcs, eq = helpers.clear, helpers.funcs, helpers.eq
local function read_mpack_file(fname)
local fd = io.open(fname, 'rb')
+ if fd == nil then
+ return nil
+ end
+
local data = fd:read('*a')
fd:close()
local unpack = mpack.Unpacker()
return unpack(data)
end
--- Remove metadata that is not essential to backwards-compatibility.
-local function remove_function_metadata(fspec)
- fspec['can_fail'] = nil
- fspec['async'] = nil
- fspec['method'] = nil
- fspec['since'] = nil
- fspec['deprecated_since'] = nil
- fspec['receives_channel_id'] = nil
- for idx, _ in ipairs(fspec['parameters']) do
- fspec['parameters'][idx][2] = '' -- Remove parameter name.
- end
- return fspec
-end
-
describe("api_info()['version']", function()
before_each(clear)
@@ -49,23 +39,111 @@ describe("api_info()['version']", function()
eq(0, funcs.has("nvim-"..major.."."..(minor + 1).."."..patch))
eq(0, funcs.has("nvim-"..(major + 1).."."..minor.."."..patch))
end)
+end)
+
+
+describe("api functions", function()
+ before_each(clear)
+
+ local function func_table(metadata)
+ local functions = {}
+ for _,f in ipairs(metadata.functions) do
+ functions[f.name] = f
+ end
+ return functions
+ end
+
+ -- Remove metadata that is not essential to backwards-compatibility.
+ local function filter_function_metadata(f)
+ f.deprecated_since = nil
+ for idx, _ in ipairs(f.parameters) do
+ f.parameters[idx][2] = '' -- Remove parameter name.
+ end
+
+ if string.sub(f.name, 1, 4) ~= "nvim" then
+ f.method = nil
+ end
+ return f
+ end
- it("api_compatible level is valid", function()
- local api = helpers.call('api_info')
- local compat = api['version']['api_compatible']
- local path = 'test/functional/fixtures/api_level_'
- ..tostring(compat)..'.mpack'
-
- -- Verify that the current API function signatures match those of the API
- -- level for which we claim compatibility.
- local old_api = read_mpack_file(path)
- for _, fn_old in ipairs(old_api['functions']) do
- for _, fn_new in ipairs(api['functions']) do
- if fn_old['name'] == fn_new['name'] then
- eq(remove_function_metadata(fn_old),
- remove_function_metadata(fn_new))
+ -- Level 0 represents methods from 0.1.5 and earlier, when 'since' was not
+ -- yet defined, and metadata was not filtered of internal keys like 'async'.
+ local function clean_level_0(metadata)
+ for _, f in ipairs(metadata.functions) do
+ f.can_fail = nil
+ f.async = nil
+ f.receives_channel_id = nil
+ f.since = 0
+ end
+ end
+
+ it("are compatible with old metadata or have new level", function()
+ local api = helpers.call('api_info')
+ local compat = api.version.api_compatible
+ local api_level = api.version.api_level
+ local stable
+ if api.version.api_prerelease then
+ stable = api_level-1
+ else
+ stable = api_level
+ end
+
+ local funcs_new = func_table(api)
+ local funcs_compat = {}
+ for level = compat, stable do
+ local path = ('test/functional/fixtures/api_level_'..
+ tostring(level)..'.mpack')
+ local old_api = read_mpack_file(path)
+ if old_api == nil then
+ local errstr = "missing metadata fixture for stable level "..level..". "
+ if level == api_level and not api.version.api_prerelease then
+ errstr = (errstr.."If NVIM_API_CURRENT was bumped, "..
+ "don't forget to set NVIM_API_PRERELEASE to true.")
+ end
+ error(errstr)
+ end
+
+ if level == 0 then
+ clean_level_0(old_api)
+ end
+
+ for _,f in ipairs(old_api.functions) do
+ if funcs_new[f.name] == nil then
+ if f.since >= compat then
+ error('function '..f.name..' was removed but exists in level '..
+ f.since..' which nvim should be compatible with')
+ end
+ else
+ eq(filter_function_metadata(f),
+ filter_function_metadata(funcs_new[f.name]))
+ end
+ end
+
+ funcs_compat[level] = func_table(old_api)
+ end
+
+ for _,f in ipairs(api.functions) do
+ if f.since <= stable then
+ local f_old = funcs_compat[f.since][f.name]
+ if f_old == nil then
+ if string.sub(f.name, 1, 4) == "nvim" then
+ local errstr = ("function "..f.name.." has too low since value. "..
+ "For new functions set it to "..(stable+1)..".")
+ if not api.version.api_prerelease then
+ errstr = (errstr.." Also bump NVIM_API_CURRENT and set "..
+ "NVIM_API_PRERELEASE to true in CMakeLists.txt.")
+ end
+ error(errstr)
+ else
+ error("function name '"..f.name.."' doesn't begin with 'nvim_'")
+ end
end
+ elseif f.since > api_level then
+ error("function "..f.name.." has since value > api_level. "..
+ "Please bump NVIM_API_CURRENT and set "..
+ "NVIM_API_PRERELEASE to true in CMakeLists.txt.")
end
end
end)
+
end)
diff --git a/test/functional/fixtures/api_level_1.mpack b/test/functional/fixtures/api_level_1.mpack
new file mode 100644
index 0000000000..66ea9c2e5d
--- /dev/null
+++ b/test/functional/fixtures/api_level_1.mpack
Binary files differ