Re-enable the : lint, but with better checks

This commit is contained in:
XeroOl 2023-11-26 12:38:20 -06:00
parent d74c6fbdc0
commit b861812b24
4 changed files with 52 additions and 12 deletions

View File

@ -59,8 +59,9 @@ later by fennel-ls.language to answer requests from the client."
diagnostics {} ; [diagnostic]
references {} ; symbol -> references
scopes {} ; ast -> scope
require-calls {} ; ast -> boolean (does this ast start with the symbol `require)
calls {}]; array of all lists
calls {} ; all calls in the macro-expanded code -> true
lexical {} ; all lists and tables in the original source
require-calls {}] ; the keys are all the calls that start with `require
(λ find-definition [name ?scope]
(when ?scope
@ -206,7 +207,7 @@ later by fennel-ls.language to answer requests from the client."
(tset scopes ast scope))
(λ call [ast scope]
(tset calls ast (. ast 1))
(tset calls ast true)
(tset scopes ast scope)
;; Most calls aren't interesting, but here's the list of the ones that are:
(case ast
@ -308,6 +309,16 @@ later by fennel-ls.language to answer requests from the client."
ast (icollect [ok ast parser &until (not ok)] ast)]
(λ collect-everything [ast result]
(when (or (table? ast) (list? ast))
(tset result ast true)
(each [k v (iter ast)]
(collect-everything k result)
(collect-everything v result))))
(collect-everything ast lexical)
;; This is bad; we mutate fennel.macro-path
(let [old-macro-path fennel.macro-path]
@ -322,6 +333,7 @@ later by fennel-ls.language to answer requests from the client."
(set file.ast ast)
(set file.calls calls)
(set file.lexical lexical)
(set file.scope scope)
(set file.scopes scopes)
(set file.definitions definitions)

View File

@ -16,7 +16,7 @@ Goes through a file and mutates the `file.diagnostics` field, filling it with di
:message (.. "unused definition: " (tostring symbol))
:severity message.severity.WARN
:code 301
:codeDescription "warning error"})))
:codeDescription "I don't know"})))
(λ unknown-module-field [self file]
"any multisym whose definition can't be found through a (require) call"
@ -26,7 +26,7 @@ Goes through a file and mutates the `file.diagnostics` field, filling it with di
item (language.search self file symbol [] opts)]
(if (and (not item) opts.searched-through-require)
{:range (message.ast->range self file symbol)
:message (.. "unknown field " (tostring symbol))
:message (.. "unknown field: " (tostring symbol))
:severity message.severity.WARN
:code 302
:codeDescription "field checking I guess"})))))
@ -34,14 +34,18 @@ Goes through a file and mutates the `file.diagnostics` field, filling it with di
(λ unnecessary-method [self file]
(icollect [[colon receiver method &as call] (pairs file.calls)
&into file.diagnostics]
(if (and (= (fennel.sym ":") colon)
(if (and (fennel.sym? colon ":")
(fennel.sym? receiver)
(= :string (type method)))
(. file.lexical call)
(= :string (type method))
(not (method:find "^[0-9]"))
;; questions: #
(not (method:find "[^!$%*+-/0-9<=>?A-Z\\^_a-z|\128-\255]")))
(case (message.ast->range self file call)
range {: range
:message "unnecessary : call; use multisym"
:message (.. "unnecessary : call: use (" (tostring receiver) ":" method ")")
:severity message.severity.WARN
:code 302
:code 303
:codeDescription "unnecessary colon"}))))
(λ check [self file]

View File

@ -96,7 +96,7 @@ in the \"self\" object."
:version (option "lua54")
:checks {:unused-definition (option true)
:unknown-module-field (option true)
:unnecessary-method (option false)}})
:unnecessary-method (option true)}})
(λ make-configuration [?c]
(make-configuration-from-template default-configuration ?c))

View File

@ -104,14 +104,38 @@
(let [self (create-client)]
(match (self:open-file! filename "(let [x :haha] (: x :find :a))")
[{:params {: diagnostics}}]
(is (find [i v (ipairs diagnostics)]
(is (find [_ v (ipairs diagnostics)]
(match v
{:message "unnecessary : call; use multisym"
{:message "unnecessary : call: use (x:find)"
:code 303
:range {:start {:character 15 :line 0}
:end {:character 29 :line 0}}}
v)))
_ (error "did not match"))))
(it "doesn't warn when using the : special when macros are involved"
(let [self (create-client)]
(match (self:open-file! filename "(let [x :haha y :find] (-> x (: y :a))
(let [x :haha] (-> x (: :find :a))")
[{:params {: diagnostics}}]
(is.nil (find [_ v (ipairs diagnostics)]
(match v
{:code 303
:range _}
v)))
_ (error "did not match"))))
(it "doesn't warn when using the : special when the string isn't valid"
(let [self (create-client)]
(match (self:open-file! filename "(let [x :haha] (: x \"bar baz\"))")
[{:params {: diagnostics}}]
(is.nil (find [_ v (ipairs diagnostics)]
(match v
{:code 303
:range _}
v)))
_ (error "did not match"))))
(it "warns if a var is written but not read"
(let [self (create-client)
responses (self:open-file! filename "(var x 1) (set x 2) (set [x] [3])")]