From 46a87a5d2bac598fed0870f0d3c926087f95d30f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Feb 2023 05:19:04 -0500 Subject: refactor(api): VALIDATE macros #22187 Problem: - API validation involves too much boilerplate. - API validation errors are not consistently worded. Solution: Introduce some macros. Currently these are clumsy, but they at least help with consistency and avoid some nesting. --- src/nvim/api/private/validate.h | 69 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/nvim/api/private/validate.h (limited to 'src/nvim/api/private/validate.h') diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h new file mode 100644 index 0000000000..8448b416be --- /dev/null +++ b/src/nvim/api/private/validate.h @@ -0,0 +1,69 @@ +#ifndef NVIM_API_PRIVATE_VALIDATE_H +#define NVIM_API_PRIVATE_VALIDATE_H + +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" + +#define VALIDATE_INT(cond, name, val_, code) \ + do { \ + if (!(cond)) { \ + api_set_error(err, kErrorTypeValidation, "Invalid " name ": %" PRId64, val_); \ + code; \ + } \ + } while (0) + +#define VALIDATE_S(cond, name, val_, code) \ + do { \ + if (!(cond)) { \ + if (strequal(val_, "")) { \ + api_set_error(err, kErrorTypeValidation, "Invalid " name); \ + } else { \ + api_set_error(err, kErrorTypeValidation, "Invalid " name ": '%s'", val_); \ + } \ + code; \ + } \ + } while (0) + +#define VALIDATE_R(cond, name, code) \ + do { \ + if (!(cond)) { \ + api_set_error(err, kErrorTypeValidation, "'" name "' is required"); \ + code; \ + } \ + } while (0) + +#define VALIDATE_EXP(cond, name, expected, actual, code) \ + do { \ + if (!(cond)) { \ + api_set_error(err, kErrorTypeValidation, "Invalid " name ": expected %s, got %s", \ + expected, actual); \ + code; \ + } \ + } while (0) + +#define VALIDATE_T(name, expected_t, actual_t, code) \ + do { \ + if (expected_t != actual_t) { \ + api_set_error(err, kErrorTypeValidation, "Invalid %s: expected %s, got %s", \ + name, api_typename(expected_t), api_typename(actual_t)); \ + code; \ + } \ + } while (0) + +#define VALIDATE(cond, msg_, code) \ + do { \ + if (!(cond)) { \ + api_set_error(err, kErrorTypeValidation, "%s", msg_); \ + code; \ + } \ + } while (0) + +#define VALIDATE_FMT(cond, fmt_, msg_, code) \ + do { \ + if (!(cond)) { \ + api_set_error(err, kErrorTypeValidation, fmt_, msg_); \ + code; \ + } \ + } while (0) + +#endif // NVIM_API_PRIVATE_VALIDATE_H -- cgit From ff3d04b75b4a9314815c37d53ebc4d035a043335 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Feb 2023 08:07:38 -0500 Subject: refactor(api): VALIDATE macros #22256 - VALIDATE() takes a format string - deduplicate check_string_array - VALIDATE_RANGE - validate UI args --- src/nvim/api/private/validate.h | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'src/nvim/api/private/validate.h') diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h index 8448b416be..4a1b99408e 100644 --- a/src/nvim/api/private/validate.h +++ b/src/nvim/api/private/validate.h @@ -24,19 +24,11 @@ } \ } while (0) -#define VALIDATE_R(cond, name, code) \ - do { \ - if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, "'" name "' is required"); \ - code; \ - } \ - } while (0) - #define VALIDATE_EXP(cond, name, expected, actual, code) \ do { \ if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, "Invalid " name ": expected %s, got %s", \ - expected, actual); \ + api_set_error(err, kErrorTypeValidation, "Invalid %s: expected %s, got %s", \ + name, expected, actual); \ code; \ } \ } while (0) @@ -50,20 +42,27 @@ } \ } while (0) -#define VALIDATE(cond, msg_, code) \ +#define VALIDATE(cond, fmt_, fmt_arg1, code) \ do { \ if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, "%s", msg_); \ + api_set_error(err, kErrorTypeValidation, fmt_, fmt_arg1); \ code; \ } \ } while (0) -#define VALIDATE_FMT(cond, fmt_, msg_, code) \ +#define VALIDATE_RANGE(cond, name, code) \ do { \ if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, fmt_, msg_); \ + api_set_error(err, kErrorTypeValidation, "Invalid '%s': out of range", name); \ code; \ } \ } while (0) +#define VALIDATE_R(cond, name, code) \ + VALIDATE(cond, "Required: '%s'", name, code); + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/private/validate.h.generated.h" +#endif + #endif // NVIM_API_PRIVATE_VALIDATE_H -- cgit From 556f8646c01d1751cf39fe4df9c622899dceab9d Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Feb 2023 14:19:28 -0500 Subject: refactor(api): consistent VALIDATE messages #22262 Problem: Validation messages are not consistently formatted. - Parameter names sometimes are NOT quoted. - Descriptive names (non-parameters) sometimes ARE quoted. Solution: Always quote the `name` value passed to a VALIDATE macro _unless_ the value has whitespace. --- src/nvim/api/private/validate.h | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) (limited to 'src/nvim/api/private/validate.h') diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h index 4a1b99408e..469fed0f83 100644 --- a/src/nvim/api/private/validate.h +++ b/src/nvim/api/private/validate.h @@ -4,48 +4,42 @@ #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" -#define VALIDATE_INT(cond, name, val_, code) \ +#define VALIDATE(cond, fmt_, fmt_arg1, code) \ do { \ if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, "Invalid " name ": %" PRId64, val_); \ + api_set_error(err, kErrorTypeValidation, fmt_, fmt_arg1); \ code; \ } \ } while (0) -#define VALIDATE_S(cond, name, val_, code) \ +#define VALIDATE_INT(cond, name, val_, code) \ do { \ if (!(cond)) { \ - if (strequal(val_, "")) { \ - api_set_error(err, kErrorTypeValidation, "Invalid " name); \ - } else { \ - api_set_error(err, kErrorTypeValidation, "Invalid " name ": '%s'", val_); \ - } \ + api_err_invalid(err, name, NULL, val_, false); \ code; \ } \ } while (0) -#define VALIDATE_EXP(cond, name, expected, actual, code) \ +#define VALIDATE_S(cond, name, val_, code) \ do { \ if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, "Invalid %s: expected %s, got %s", \ - name, expected, actual); \ + api_err_invalid(err, name, val_, 0, true); \ code; \ } \ } while (0) -#define VALIDATE_T(name, expected_t, actual_t, code) \ +#define VALIDATE_EXP(cond, name, expected, actual, code) \ do { \ - if (expected_t != actual_t) { \ - api_set_error(err, kErrorTypeValidation, "Invalid %s: expected %s, got %s", \ - name, api_typename(expected_t), api_typename(actual_t)); \ + if (!(cond)) { \ + api_err_exp(err, name, expected, actual); \ code; \ } \ } while (0) -#define VALIDATE(cond, fmt_, fmt_arg1, code) \ +#define VALIDATE_T(name, expected_t, actual_t, code) \ do { \ - if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, fmt_, fmt_arg1); \ + if (expected_t != actual_t) { \ + api_err_exp(err, name, api_typename(expected_t), api_typename(actual_t)); \ code; \ } \ } while (0) @@ -53,7 +47,7 @@ #define VALIDATE_RANGE(cond, name, code) \ do { \ if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, "Invalid '%s': out of range", name); \ + api_err_invalid(err, name, "out of range", 0, false); \ code; \ } \ } while (0) -- cgit From 09b3432eaff3abcadb56d61b6f247f992b80b63f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 16 Feb 2023 10:07:18 -0500 Subject: fix(api): allow empty Lua table for nested dicts #22268 Problem: The Lua-API bridge allows Dict params to be empty Lua (list) tables at the function-signature level. But not for _nested_ Dicts, because they are not modeled: https://github.com/neovim/neovim/blob/fae754073289566051433fae74ec65783f9e7a6a/src/nvim/api/keysets.lua#L184 Some API functions like nvim_cmd check for kObjectTypeDictionary and don't handle the case of empty Lua tables (treated as "Array"). Solution: Introduce VALIDATE_T_DICT and use it in places where kObjectTypeDictionary was being checked directly. fixes #21005 --- src/nvim/api/private/validate.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src/nvim/api/private/validate.h') diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h index 469fed0f83..91a92c2762 100644 --- a/src/nvim/api/private/validate.h +++ b/src/nvim/api/private/validate.h @@ -38,12 +38,35 @@ #define VALIDATE_T(name, expected_t, actual_t, code) \ do { \ + STATIC_ASSERT(expected_t != kObjectTypeDictionary, "use VALIDATE_T_DICT"); \ if (expected_t != actual_t) { \ api_err_exp(err, name, api_typename(expected_t), api_typename(actual_t)); \ code; \ } \ } while (0) +/// Checks that `obj_` has type `expected_t`. +#define VALIDATE_T2(obj_, expected_t, code) \ + do { \ + STATIC_ASSERT(expected_t != kObjectTypeDictionary, "use VALIDATE_T_DICT"); \ + if ((obj_).type != expected_t) { \ + api_err_exp(err, STR(obj_), api_typename(expected_t), api_typename((obj_).type)); \ + code; \ + } \ + } while (0) + +/// Checks that `obj_` has Dict type. Also allows empty Array in a Lua context. +#define VALIDATE_T_DICT(name, obj_, code) \ + do { \ + if ((obj_).type != kObjectTypeDictionary \ + && !(channel_id == LUA_INTERNAL_CALL \ + && (obj_).type == kObjectTypeArray \ + && (obj_).data.array.size == 0)) { \ + api_err_exp(err, name, api_typename(kObjectTypeDictionary), api_typename((obj_).type)); \ + code; \ + } \ + } while (0) + #define VALIDATE_RANGE(cond, name, code) \ do { \ if (!(cond)) { \ -- cgit From 0f42aa1f2a860ce6d72a825b397fe09c875613b5 Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 6 Apr 2023 10:03:37 +0200 Subject: fix(highlight): use winhl=Foo:Bar even when Bar is empty fixes #22906 --- src/nvim/api/private/validate.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/nvim/api/private/validate.h') diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h index 91a92c2762..a3e77ea838 100644 --- a/src/nvim/api/private/validate.h +++ b/src/nvim/api/private/validate.h @@ -67,6 +67,15 @@ } \ } while (0) +/// Checks that actual_t is either the correct handle type or a type erased handle (integer) +#define VALIDATE_T_HANDLE(name, expected_t, actual_t, code) \ + do { \ + if (expected_t != actual_t && kObjectTypeInteger != actual_t) { \ + api_err_exp(err, name, api_typename(expected_t), api_typename(actual_t)); \ + code; \ + } \ + } while (0) + #define VALIDATE_RANGE(cond, name, code) \ do { \ if (!(cond)) { \ -- cgit From cf8b2c0e74fd5e723b0c15c2ce84e6900fd322d3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 30 Sep 2023 12:05:28 +0800 Subject: build(iwyu): add a few more _defs.h mappings (#25435) --- src/nvim/api/private/validate.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/nvim/api/private/validate.h') diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h index a3e77ea838..089b8d2f9c 100644 --- a/src/nvim/api/private/validate.h +++ b/src/nvim/api/private/validate.h @@ -1,8 +1,13 @@ #ifndef NVIM_API_PRIVATE_VALIDATE_H #define NVIM_API_PRIVATE_VALIDATE_H +#include +#include + #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/assert.h" +#include "nvim/macros.h" #define VALIDATE(cond, fmt_, fmt_arg1, code) \ do { \ -- cgit From 4f8941c1a5f1ef6caa410feeb52e343db22763ce Mon Sep 17 00:00:00 2001 From: dundargoc Date: Fri, 10 Nov 2023 12:23:42 +0100 Subject: refactor: replace manual header guards with #pragma once It is less error-prone than manually defining header guards. Pretty much all compilers support it even if it's not part of the C standard. --- src/nvim/api/private/validate.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/nvim/api/private/validate.h') diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h index 089b8d2f9c..29ca6242f3 100644 --- a/src/nvim/api/private/validate.h +++ b/src/nvim/api/private/validate.h @@ -1,5 +1,4 @@ -#ifndef NVIM_API_PRIVATE_VALIDATE_H -#define NVIM_API_PRIVATE_VALIDATE_H +#pragma once #include #include @@ -95,5 +94,3 @@ #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/private/validate.h.generated.h" #endif - -#endif // NVIM_API_PRIVATE_VALIDATE_H -- cgit From 79b6ff28ad1204fbb4199b9092f5c578d88cb28e Mon Sep 17 00:00:00 2001 From: dundargoc Date: Tue, 28 Nov 2023 20:31:00 +0100 Subject: refactor: fix headers with IWYU --- src/nvim/api/private/validate.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/api/private/validate.h') diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h index 29ca6242f3..d1c977cd6e 100644 --- a/src/nvim/api/private/validate.h +++ b/src/nvim/api/private/validate.h @@ -5,8 +5,8 @@ #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" -#include "nvim/assert.h" -#include "nvim/macros.h" +#include "nvim/assert_defs.h" +#include "nvim/macros_defs.h" #define VALIDATE(cond, fmt_, fmt_arg1, code) \ do { \ -- cgit