The unnecessary tset lint was assuming a single key, but it was
triggering for calls with multiple nested keys, causing the quickfix
action to drop all elements after the fourth argument, which was assumed
to be the value.
Now it's been updated to handle nested calls of any depth.
---
src/fennel-ls/lint.fnl | 21 +++++++++++++++++----
test/code-action.fnl | 27 ++++++++++++++++++---------
test/init.fnl | 1 +
test/lint.fnl | 5 +++--
4 files changed, 39 insertions(+), 15 deletions(-)
diff --git a/src/fennel-ls/lint.fnl b/src/fennel-ls/lint.fnl
index 168d202..1af180f 100644
--- a/src/fennel-ls/lint.fnl
+++ b/src/fennel-ls/lint.fnl
@@ -87,9 +87,24 @@ the `file.diagnostics` field, filling it with diagnostics."
:codeDescription "unnecessary-method"}))))
(λ unnecessary-tset [server file head call]
+ (λ all-syms? [call start end]
+ (faccumulate [syms true
+ i start end]
+ (and syms
+ (could-be-rewritten-as-sym? (. call i)))))
+
+ (λ make-new-text [call]
+ (.. (faccumulate [text "(set "
+ i 2 (- (length call) 2)]
+ (.. text (tostring (. call i)) "."))
+ (tostring (. call (- (length call) 1)))
+ " "
+ (view (. call (length call)))
+ ")"))
+
(if (and (sym? head :tset)
(sym? (. call 2))
- (could-be-rewritten-as-sym? (. call 3))
+ (all-syms? call 3 (- (length call) 1))
(. file.lexical call))
(diagnostic {:range (message.ast->range server file call)
:message (.. "unnecessary " (tostring head))
@@ -97,9 +112,7 @@ the `file.diagnostics` field, filling it with diagnostics."
:code 309
:codeDescription "unnecessary-tset"}
#[{:range (message.ast->range server file call)
- :newText (string.format "(set %s.%s %s)"
- (tostring (. call 2)) (. call 3)
- (view (. call 4)))}])))
+ :newText (make-new-text call)}])))
(λ unnecessary-do-values [server file head call]
(if (and (or (sym? head :do) (sym? head :values))
diff --git a/test/code-action.fnl b/test/code-action.fnl
index c376f9b..94f277c 100644
--- a/test/code-action.fnl
+++ b/test/code-action.fnl
@@ -42,14 +42,23 @@
"Prefix with _ to silence warning"
"(local _x 10)"))
-; (fn test-fix-method-function []
-; (check "(local x {})
-; (fn x:y [a b c]
-; (print client a b c))"
-; "TO-BE-NAMED"
-; "(local x {})
-; (fn x.y [client a b c]
-; (print client a b c))"))
+(fn test-unnecessary-tset []
+ (check "==(tset state :mouse 496)=="
+ "Replace with set"
+ "(set state.mouse 496)")
+
+ (check "==(tset state :mouse :cursor 496)=="
+ "Replace with set"
+ "(set state.mouse.cursor 496)")
+
+ (check "==(tset state :mouse :cursor {:x 4 :y 7})=="
+ "Replace with set"
+ "(set state.mouse.cursor {:x 4 :y 7})")
+
+ (check "==(tset state :mouse :cursor :x 496)=="
+ "Replace with set"
+ "(set state.mouse.cursor.x 496)"))
{: test-fix-op-no-arguments
- : test-fix-unused-definition}
+ : test-fix-unused-definition
+ : test-unnecessary-tset}
diff --git a/test/init.fnl b/test/init.fnl
index 38183ca..c4fcac0 100644
--- a/test/init.fnl
+++ b/test/init.fnl
@@ -22,6 +22,7 @@
:test.completion
:test.references
:test.document-highlight
+ :test.signature-help
:test.lint
:test.code-action
:test.rename
diff --git a/test/lint.fnl b/test/lint.fnl
index 8512e2c..1d11eb1 100644
--- a/test/lint.fnl
+++ b/test/lint.fnl
@@ -185,6 +185,7 @@
:message "unnecessary tset"
:range {:start {:character 15 :line 0}
:end {:character 32 :line 0}}}])
+ (check "(local tbl {}) (tset tbl :key :nested 9)" [{:code 309}])
;; Lint only triggers on keys that can be written as a sym
(check "(local tbl {}) (tset tbl \"hello-world\" 249)" [{:code 309}])
(assert-ok "(local tbl {}) (tset tbl \"01234567\" 249)")
@@ -274,5 +275,5 @@
: test-unset-var
: test-match-should-case
: test-unpack-into-op
- : test-unpack-in-middle
- }
+ : test-unpack-in-middle}
+
--
2.39.5 (Apple Git-154)
Michele Campeotto <micampe@micampe.it> writes:
> The unnecessary tset lint was assuming a single key, but it was
> triggering for calls with multiple nested keys, causing the quickfix
> action to drop all elements after the fourth argument, which was assumed
> to be the value.
Great catch; thanks! Glad to see the thorough tests.
-Phil