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}
|
{:indeterminate nil &as result}
|
||||||
(case (?. (navigate.getmetadata server result) :fnl/arglist)
|
(case (?. (navigate.getmetadata server result) :fnl/arglist)
|
||||||
signature
|
signature
|
||||||
(let [number-of-args (- (length ast)
|
(let [number-of-args (- (length ast) 1)
|
||||||
(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
|
|
||||||
passes-extra-args (and (not= 1 (length ast))
|
passes-extra-args (and (not= 1 (length ast))
|
||||||
(not (special? (. ast 1)))
|
(not (special? (. ast 1)))
|
||||||
(not (. file.macro-calls ast))
|
(not (. file.macro-calls ast))
|
||||||
(possibly-multival? (. ast (length 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
|
||||||
;; exception: (/ a b) only needs 1 argument
|
;; exception: (/ a b) only needs 1 argument
|
||||||
min-params (if (= result (docs.get-builtin server :-)) 1
|
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
|
;; exception: fn only needs one argument
|
||||||
(= result (docs.get-builtin server :fn)) 1
|
(= result (docs.get-builtin server :fn)) 1
|
||||||
(= result (docs.get-builtin server :collect)) 2
|
(= 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)
|
(if (and (< number-of-args min-params)
|
||||||
(not passes-extra-args))
|
(not passes-extra-args))
|
||||||
{:range (message.ast->range server file ast)
|
{: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})))))})
|
:severity message.severity.WARN})))))})
|
||||||
|
|
||||||
(add-lint :too-many-arguments
|
(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}
|
{:indeterminate nil &as result}
|
||||||
(case (?. (navigate.getmetadata server result) :fnl/arglist)
|
(case (?. (navigate.getmetadata server result) :fnl/arglist)
|
||||||
signature
|
signature
|
||||||
(let [number-of-args (- (length ast)
|
(let [number-of-args (- (length ast) 1)
|
||||||
(if (and (sym? (. ast 1))
|
infinite-params? (accumulate [vararg nil
|
||||||
(string.find (tostring (. ast 1)) ".:"))
|
_ arg (ipairs signature)
|
||||||
0 ; method call; the head counts as an argument
|
&until vararg]
|
||||||
1)) ; function call; the head doesn't count as an argument
|
(let [s (tostring arg)]
|
||||||
(infinite-params?) (accumulate [vararg nil
|
(or (= s "...") (= s "&"))))
|
||||||
_ arg (ipairs signature)
|
|
||||||
&until vararg]
|
|
||||||
(let [s (tostring arg)]
|
|
||||||
(or (= s "...") (= s "&"))))
|
|
||||||
;; exception: (table.insert table item) can take a third argument
|
;; exception: (table.insert table item) can take a third argument
|
||||||
max-params (if (= result (. (docs.get-global server :table) :fields :insert))
|
max-params (if (= result (. (docs.get-global server :table) :fields :insert))
|
||||||
3
|
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)
|
(if (and (< max-params number-of-args)
|
||||||
(not infinite-params?))
|
(not infinite-params?))
|
||||||
{:range (message.ast->range server file ast)
|
(let [range-of-call (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)
|
first-bad-argument (. ast (+ 1 max-params))
|
||||||
:severity message.severity.WARN})))))})
|
?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
|
(add-lint :duplicate-table-keys
|
||||||
{:what-it-does
|
{:what-it-does
|
||||||
|
|||||||
@ -306,16 +306,23 @@
|
|||||||
;; methods
|
;; methods
|
||||||
(let [add-opts #{:main.fnl $ :flsproject.fnl "{:lints {:not-enough-arguments true}}"}]
|
(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)")
|
(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)"))
|
||||||
(assert-ok (add-opts "(fn foo [a b c ?d ?e] (print a b c ?d ?e))\n(foo 1 2 3 4 5)"))
|
(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)")
|
(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))"))
|
(assert-ok (add-opts "(let [f :hi] (f:byte))"))
|
||||||
(check (add-opts "(let [f :hi] (f:sub))")
|
(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))")
|
(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 "(let [foo 10] (fn [] foo))"))
|
||||||
(assert-ok (add-opts "(fn [])"))
|
(assert-ok (add-opts "(fn [])"))
|
||||||
nil))
|
nil))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user