better messages for not-enough-arguments and too-many-arguments
This commit is contained in:
parent
284a760224
commit
319a2ddf10
@ -623,24 +623,11 @@ You can read more about how to add lints in docs/linting.md"
|
||||
{:indeterminate nil &as result}
|
||||
(case (?. (navigate.getmetadata server result) :fnl/arglist)
|
||||
signature
|
||||
(let [number-of-args (- (length ast)
|
||||
(if (and (sym? (. ast 1))
|
||||
(string.find (tostring (. ast 1)) ".:"))
|
||||
0 ; method call; the head counts as an argument
|
||||
1)) ; function call; the head doesn't count as an argument
|
||||
(let [number-of-args (- (length ast) 1)
|
||||
passes-extra-args (and (not= 1 (length ast))
|
||||
(not (special? (. ast 1)))
|
||||
(not (. file.macro-calls ast))
|
||||
(possibly-multival? (. ast (length ast))))
|
||||
min-params (accumulate [last-required-argument nil
|
||||
i arg (ipairs signature)
|
||||
&until (let [s (tostring arg)]
|
||||
(or (= s "...")
|
||||
(= s "&")))]
|
||||
(let [first-char (string.sub (tostring arg) 1 1)]
|
||||
(if (and (not= first-char "?") (not= first-char "_"))
|
||||
i
|
||||
last-required-argument)))
|
||||
;; exception: (- a b) only needs 1 argument
|
||||
;; exception: (/ a b) only needs 1 argument
|
||||
min-params (if (= result (docs.get-builtin server :-)) 1
|
||||
@ -649,11 +636,23 @@ You can read more about how to add lints in docs/linting.md"
|
||||
;; exception: fn only needs one argument
|
||||
(= result (docs.get-builtin server :fn)) 1
|
||||
(= result (docs.get-builtin server :collect)) 2
|
||||
(or min-params 0))]
|
||||
(or (accumulate [last-required-param nil
|
||||
i arg (ipairs signature)
|
||||
&until (let [s (tostring arg)]
|
||||
(or (= s "...")
|
||||
(= s "&")))]
|
||||
(let [first-char (string.sub (tostring arg) 1 1)]
|
||||
(if (and (not= first-char "?") (not= first-char "_"))
|
||||
i
|
||||
last-required-param)))
|
||||
0))
|
||||
method-call? (and (sym? (. ast 1))
|
||||
(string.find (tostring (. ast 1)) ".:"))
|
||||
min-params (- min-params (if method-call? 1 0))]
|
||||
(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 " min-params " arguments but I only see " number-of-args)
|
||||
:message (.. (view (. ast 1)) " expects at least " min-params " argument(s); found " number-of-args)
|
||||
:severity message.severity.WARN})))))})
|
||||
|
||||
(add-lint :too-many-arguments
|
||||
@ -690,25 +689,33 @@ You can read more about how to add lints in docs/linting.md"
|
||||
{:indeterminate nil &as result}
|
||||
(case (?. (navigate.getmetadata server result) :fnl/arglist)
|
||||
signature
|
||||
(let [number-of-args (- (length ast)
|
||||
(if (and (sym? (. ast 1))
|
||||
(string.find (tostring (. ast 1)) ".:"))
|
||||
0 ; method call; the head counts as an argument
|
||||
1)) ; function call; the head doesn't count as an argument
|
||||
(infinite-params?) (accumulate [vararg nil
|
||||
_ arg (ipairs signature)
|
||||
&until vararg]
|
||||
(let [s (tostring arg)]
|
||||
(or (= s "...") (= s "&"))))
|
||||
(let [number-of-args (- (length ast) 1)
|
||||
infinite-params? (accumulate [vararg nil
|
||||
_ arg (ipairs signature)
|
||||
&until vararg]
|
||||
(let [s (tostring arg)]
|
||||
(or (= s "...") (= s "&"))))
|
||||
;; exception: (table.insert table item) can take a third argument
|
||||
max-params (if (= result (. (docs.get-global server :table) :fields :insert))
|
||||
3
|
||||
(length signature))]
|
||||
(length signature))
|
||||
method-call? (and (sym? (. ast 1))
|
||||
(string.find (tostring (. ast 1)) ".:"))
|
||||
max-params (- max-params (if method-call? 1 0))]
|
||||
|
||||
(if (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 " max-params " arguments but you've provided " number-of-args)
|
||||
:severity message.severity.WARN})))))})
|
||||
(let [range-of-call (message.ast->range server file ast)
|
||||
first-bad-argument (. ast (+ 1 max-params))
|
||||
?range-of-first-bad-argument (message.ast->range server file first-bad-argument)
|
||||
range {:start (or (?. ?range-of-first-bad-argument :start) range-of-call.start)
|
||||
:end range-of-call.end}]
|
||||
{: range
|
||||
:message (if (= max-params -1)
|
||||
;; this is when you call a 0 argument function using a `:`
|
||||
(.. (: (view (. ast 1)) :gsub ":" ".") " expects 0 arguments; found 1")
|
||||
(.. (view (. ast 1)) " expects at most " max-params " argument(s); found " number-of-args))
|
||||
:severity message.severity.WARN}))))))})
|
||||
|
||||
(add-lint :duplicate-table-keys
|
||||
{:what-it-does
|
||||
|
||||
@ -306,16 +306,23 @@
|
||||
;; methods
|
||||
(let [add-opts #{:main.fnl $ :flsproject.fnl "{:lints {:not-enough-arguments true}}"}]
|
||||
(check (add-opts "(fn foo [a b c ?d ?e] (print a b c ?d ?e))\n(foo 1 2)")
|
||||
[{:code :not-enough-arguments}])
|
||||
[{:code :not-enough-arguments
|
||||
:message "foo expects at least 3 argument(s); found 2"}])
|
||||
(assert-ok (add-opts "(fn foo [a b c ?d ?e] (print a b c ?d ?e))\n(foo 1 2 3)"))
|
||||
(assert-ok (add-opts "(fn foo [a b c ?d ?e] (print a b c ?d ?e))\n(foo 1 2 3 4 5)"))
|
||||
(check (add-opts "(fn foo [a b c ?d ?e] (print a b c ?d ?e))\n(foo 1 2 3 4 5 6)")
|
||||
[{:code :too-many-arguments}])
|
||||
[{:code :too-many-arguments
|
||||
:message "foo expects at most 5 argument(s); found 6"}])
|
||||
(assert-ok (add-opts "(let [f :hi] (f:byte))"))
|
||||
(check (add-opts "(let [f :hi] (f:sub))")
|
||||
[{:code :not-enough-arguments}])
|
||||
[{:code :not-enough-arguments
|
||||
:message "f:sub expects at least 1 argument(s); found 0"}])
|
||||
(check (add-opts "(let [f :hi] (f:sub 1 2 3))")
|
||||
[{:code :too-many-arguments}])
|
||||
[{:code :too-many-arguments
|
||||
:message "f:sub expects at most 2 argument(s); found 3"}])
|
||||
(check (add-opts "(let [obj {:field (fn foo [])}] (obj:field))")
|
||||
[{:code :too-many-arguments
|
||||
:message "obj.field expects 0 arguments; found 1"}])
|
||||
(assert-ok (add-opts "(let [foo 10] (fn [] foo))"))
|
||||
(assert-ok (add-opts "(fn [])"))
|
||||
nil))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user