From 561f199505d13fb03641a389ce00d5d8e339e809 Mon Sep 17 00:00:00 2001 From: XeroOl Date: Fri, 11 Jul 2025 23:36:05 -0500 Subject: [PATCH] hardcode in some argument counting exceptions --- flsproject.fnl | 1 + src/fennel-ls/lint.fnl | 25 ++++++++++++++++++------- test/lint.fnl | 13 ++++++++++++- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/flsproject.fnl b/flsproject.fnl index 24381e7..d143b88 100644 --- a/flsproject.fnl +++ b/flsproject.fnl @@ -1,2 +1,3 @@ {:lua-version "intersection" + :lints {:mismatched-argument-count true} :fennel-path "./?.fnl;./?/init.fnl;src/?.fnl;src/?/init.fnl;deps/?.fnl;deps/?/init.fnl"} diff --git a/src/fennel-ls/lint.fnl b/src/fennel-ls/lint.fnl index abf1831..ca47ace 100644 --- a/src/fennel-ls/lint.fnl +++ b/src/fennel-ls/lint.fnl @@ -9,6 +9,7 @@ the `file.diagnostics` field, filling it with diagnostics." (local message (require :fennel-ls.message)) (local utils (require :fennel-ls.utils)) (local navigate (require :fennel-ls.navigate)) +(local docs (require :fennel-ls.docs)) (local dkjson (require :dkjson)) (local lints {:definition [] @@ -295,9 +296,10 @@ the `file.diagnostics` field, filling it with diagnostics." {:indeterminate nil &as result} (case (?. (navigate.getmetadata server result) :fnl/arglist) signature - (let [number-of-args (- (length ast) 1) + (let [number-of-args (- (length ast) (if (and (sym? (. ast 1)) (string.find (tostring (. ast 1)) ".:")) + 0 1)) passes-extra-args (and (not= 1 (length ast)) (possibly-multival? (. ast (length ast)))) - (number-of-params accepts-extra-params) (faccumulate [(last-required-argument vararg) nil + (min-params infinite-params?) (faccumulate [(last-required-argument vararg) nil i (length signature) 1 -1] (let [s (tostring (. signature i)) m (or (= s "...") (= s "&"))] @@ -309,14 +311,23 @@ the `file.diagnostics` field, filling it with diagnostics." (not= (string.sub s 1 1) "?") i) (or vararg m)))) - number-of-params (or number-of-params 0)] - (if (and (< number-of-args number-of-params) (not passes-extra-args)) + ;; exception: (- a b) only needs 1 argument + ;; exception: (/ a b) only needs 1 argument + min-params (if (= result (docs.get-builtin server :-)) 1 + (= result (docs.get-builtin server :/)) 1 + ;; exception: fn only needs one argument + ;; TODO Fennel 1.5.4+ has `fn`'s arglist fixed. + (= result (docs.get-builtin server :fn)) 1 + (or min-params 0)) + ;; exception: (table.insert table item) can take a third argument + max-params (if (= result (. (docs.get-global server :table) :fields :insert)) 3 (length signature))] + (if (and (< number-of-args min-params) (not passes-extra-args)) {:range (message.ast->range server file ast) - :message (.. "not enough args. my analysis of the signature says you need at least " number-of-params " arguments but I only see " number-of-args) + :message (.. "not enough args. my analysis of the signature says you need at least " min-params " arguments but I only see " number-of-args) :severity message.severity.WARN} - (and (< (length signature) number-of-args) (not accepts-extra-params)) + (and (< max-params number-of-args) (not infinite-params?)) {:range (message.ast->range server file ast) - :message (.. "too many args. my analysis of the signature says we ignore any arguments past " number-of-params " arguments but you've provided " number-of-args) + :message (.. "too many args. my analysis of the signature says we ignore any arguments past " min-params " arguments but you've provided " number-of-args) :severity message.severity.WARN})))))}) (local lint-mt {:__tojson (fn [{: self} state] (dkjson.encode self state)) diff --git a/test/lint.fnl b/test/lint.fnl index 4310a81..93ea25e 100644 --- a/test/lint.fnl +++ b/test/lint.fnl @@ -305,6 +305,16 @@ :end {:character 21 :line 0}}}]) nil) +(fn test-arg-count [] + ;; methods + (assert-ok {:main.fnl "(let [f :hi] (f:byte))" + :flsproject.fnl "{:lints {:mismatched-argument-count true}}"}) + (assert-ok {:main.fnl "(let [foo 10] (fn [] foo))" + :flsproject.fnl "{:lints {:mismatched-argument-count true}}"}) + (assert-ok {:main.fnl "(fn [])" + :flsproject.fnl "{:lints {:mismatched-argument-count true}}"}) + nil) + ;; TODO lints: ;; duplicate keys in kv table ;; (tset ) --> (set (. )) (might be wanted for compat?) @@ -330,4 +340,5 @@ : test-unpack-in-middle : test-op-with-no-arguments : test-empty-let - : test-decreasing-comparison} + : test-decreasing-comparison + : test-arg-count}