1
0
mirror of https://github.com/janet-lang/janet synced 2026-05-22 05:12:14 +00:00

More tweaks for named arity linting.

Handle more edge cases where &named is combined with &opt
This commit is contained in:
Calvin Rose
2026-01-31 23:57:08 -06:00
parent 497e363401
commit d47f82713b
2 changed files with 21 additions and 4 deletions
+9 -4
View File
@@ -599,17 +599,22 @@ static JanetSlot janetc_call(JanetFopts opts, JanetSlot *slots, JanetSlot fun, c
fun.constant, min, min == 1 ? "" : "s", min_arity);
janetc_error(c, es);
}
if (structarg && ((min_arity - min) & 1)) {
if (structarg && (min_arity > f->def->arity) && ((min_arity - f->def->arity) & 1)) {
/* If we have an odd number of variadic arguments to a `&keys` function, that is almost certainly wrong. */
janetc_lintf(c, JANET_C_LINT_NORMAL,
"odd number of variadic arguments to `&keys` function %v", fun.constant);
if (namedarg) {
janetc_lintf(c, JANET_C_LINT_NORMAL,
"odd number of named arguments to `&named` function %v", fun.constant);
} else {
janetc_lintf(c, JANET_C_LINT_NORMAL,
"odd number of named arguments to `&keys` function %v", fun.constant);
}
}
if (namedarg && f->def->named_args_count > 0) {
/* For each argument passed in, check if it is one of the used named arguments
* by checking the list defined in the function def. If not, raise a normal compiler
* lint. We can also do a strict lint for _missing_ named arguments, although in many
* cases those are assumed to have some kind of default, or we have dynamic keys. */
int32_t first_arg_key_index = min + 1;
int32_t first_arg_key_index = f->def->arity + 1;
for (int32_t i = first_arg_key_index; i < janet_tuple_length(form); i += 2) {
Janet argkey = form[i];
/* Assumption: The first N constants of a function are its named argument keys. This
+12
View File
@@ -110,6 +110,9 @@
(defn fnamed2 [_a _b _c &named x y z] [x y z])
(defn fkeys2 [_a _b _c &keys ks] ks)
(defn fnamed3 [{:x x} &named a b c] [x a b c])
(defn fnamed4 [_y &opt _z &named a b c] [a b c])
(defn fnamed5 [&opt _z &named a b c] [a b c])
(defn g [x &opt y &named z] [x y z])
(defn check-good-compile
[code msg]
@@ -137,6 +140,15 @@
(check-lint-compile '(fkeys2 nil nil nil :a 1 :b) "keys 2 odd args")
(check-good-compile '(fnamed3 {:x 1} :a 1 :b 2 :c 3) "named 3 good")
(check-lint-compile '(fnamed3 {:x 1} :a 1 :b 2 :d 3) "named 3 lint")
(check-good-compile '(fnamed4 10 20 :a 1 :b 2 :c 3) "named 4 good")
(check-lint-compile '(fnamed4 10 20 :a 1 :b 2 :d 3) "named 4 lint")
(check-good-compile '(fnamed5 10 :a 1 :b 2 :c 3) "named 5 good")
(check-lint-compile '(fnamed5 10 :a 1 :b 2 :d 3) "named 5 lint")
(check-good-compile '(g 1) "g good 1")
(check-good-compile '(g 1 2) "g good 2")
(check-good-compile '(g 1 2 :z 10) "g good 3")
(check-lint-compile '(g 1 2 :z) "g lint 1")
(check-lint-compile '(g 1 2 :z 4 5) "g lint 2")
(end-suite)