branch: externals/relint
commit b890b5ae5c78971efd62dcb0c0c33b982e0120ee
Author: Mattias Engdegård <[email protected]>
Commit: Mattias Engdegård <[email protected]>
Track mutation in push and lambda in phase 2
---
relint.el | 29 +++++++++++++++++++++++++++++
test/5.elisp | 14 ++++++++++++++
test/5.expected | 9 +++++++++
3 files changed, 52 insertions(+)
diff --git a/relint.el b/relint.el
index 9d2d6e8..65fbd2c 100644
--- a/relint.el
+++ b/relint.el
@@ -1201,6 +1201,20 @@ directly."
val)))))))
(setq args (cddr args))
(setq i (+ i 2)))))
+ (`(push ,expr ,(and (pred symbolp) name))
+ ;; Treat (push EXPR NAME) as (setq NAME (cons EXPR NAME)).
+ (relint--check-form-recursively-2 expr mutables file pos (cons 1 path))
+ (let ((local (assq name relint--locals)))
+ (when local
+ (setcdr local
+ (let ((old-val (cdr local)))
+ (and old-val
+ (memq name mutables)
+ (let ((val (catch 'relint-eval
+ (list (cons (relint--eval expr)
+ (car old-val))))))
+ (and (consp val)
+ val))))))))
(`(,(or 'if 'and 'or 'when 'unless) ,(and (pred consp) arg1) . ,rest)
;; Only first arg is executed unconditionally.
;; FIXME: A conditional in the tail position of its environment binding
@@ -1228,6 +1242,21 @@ directly."
(car body) argnames file pos (cons i path)))
(setq body (cdr body))
(setq i (1+ i))))))
+ (`(lambda ,(and (pred listp) arglist) . ,body)
+ ;; Create local bindings for formal arguments (with unknown values).
+ (let* ((argnames (mapcan (lambda (arg)
+ (and (symbolp arg)
+ (not (memq arg '(&optional &rest)))
+ (list arg)))
+ arglist))
+ (relint--locals (append (mapcar #'list argnames) relint--locals)))
+ (let ((i 2))
+ (while (consp body)
+ (when (consp (car body))
+ (relint--check-form-recursively-2
+ (car body) argnames file pos (cons i path)))
+ (setq body (cdr body))
+ (setq i (1+ i))))))
(_
(pcase form
(`(,(or 'looking-at 're-search-forward 're-search-backward
diff --git a/test/5.elisp b/test/5.elisp
index 406ef69..4d0e9b2 100644
--- a/test/5.elisp
+++ b/test/5.elisp
@@ -25,3 +25,17 @@
(z "M"))
(setq z "B")
(looking-at (concat x y z "]"))))
+
+(defun test-push (x)
+ (let ((x (list "a")))
+ (push "+" x)
+ (looking-at (string-join x))))
+
+(defun test-setq-defun (x)
+ (setq x "[CC]")
+ (looking-at x))
+
+(defun test-setq-lambda ()
+ (lambda (y)
+ (setq y "[DD]")
+ (looking-at y)))
diff --git a/test/5.expected b/test/5.expected
index 75c59ea..7bde92e 100644
--- a/test/5.expected
+++ b/test/5.expected
@@ -10,3 +10,12 @@
5.elisp:27:17: In call to looking-at: Duplicated `B' inside character
alternative (pos 2)
"[BB]"
..^
+5.elisp:32:17: In call to looking-at: Unescaped literal `+' (pos 0)
+ "+a"
+ ^
+5.elisp:36:15: In call to looking-at: Duplicated `C' inside character
alternative (pos 2)
+ "[CC]"
+ ..^
+5.elisp:41:17: In call to looking-at: Duplicated `D' inside character
alternative (pos 2)
+ "[DD]"
+ ..^