mirror of
https://git.savannah.gnu.org/git/emacs/org-mode.git
synced 2024-09-29 22:37:47 +00:00
lint: Improve checks for internal macros
* lisp/org-lint.el (org-lint-invalid-macro-argument-and-template): Add arity checks for internal macros. * testing/lisp/test-org-lint.el (test-org-lint/invalid-macro-argument-and-template): Add tests.
This commit is contained in:
parent
772f7acb65
commit
628bb4f324
|
@ -687,15 +687,42 @@ Use \"export %s\" instead"
|
|||
reports))
|
||||
|
||||
(defun org-lint-invalid-macro-argument-and-template (ast)
|
||||
(let ((extract-placeholders
|
||||
(lambda (template)
|
||||
(let ((start 0)
|
||||
args)
|
||||
(while (string-match "\\$\\([1-9][0-9]*\\)" template start)
|
||||
(setf start (match-end 0))
|
||||
(push (string-to-number (match-string 1 template)) args))
|
||||
(sort (org-uniquify args) #'<))))
|
||||
reports)
|
||||
(let* ((reports nil)
|
||||
(extract-placeholders
|
||||
(lambda (template)
|
||||
(let ((start 0)
|
||||
args)
|
||||
(while (string-match "\\$\\([1-9][0-9]*\\)" template start)
|
||||
(setf start (match-end 0))
|
||||
(push (string-to-number (match-string 1 template)) args))
|
||||
(sort (org-uniquify args) #'<))))
|
||||
(check-arity
|
||||
(lambda (arity macro)
|
||||
(let* ((name (org-element-property :key macro))
|
||||
(pos (org-element-property :begin macro))
|
||||
(args (org-element-property :args macro))
|
||||
(l (length args)))
|
||||
(cond
|
||||
((< l (1- (car arity)))
|
||||
(push (list pos (format "Missing arguments in macro %S" name))
|
||||
reports))
|
||||
((< l (car arity))
|
||||
(push (list pos (format "Missing argument in macro %S" name))
|
||||
reports))
|
||||
((> l (1+ (cdr arity)))
|
||||
(push (let ((spurious-args (nthcdr (cdr arity) args)))
|
||||
(list pos
|
||||
(format "Spurious arguments in macro %S: %s"
|
||||
name
|
||||
(mapconcat #'org-trim spurious-args ", "))))
|
||||
reports))
|
||||
((> l (cdr arity))
|
||||
(push (list pos
|
||||
(format "Spurious argument in macro %S: %s"
|
||||
name
|
||||
(org-last args)))
|
||||
reports))
|
||||
(t nil))))))
|
||||
;; Check arguments for macro templates.
|
||||
(org-element-map ast 'keyword
|
||||
(lambda (k)
|
||||
|
@ -730,31 +757,31 @@ Use \"export %s\" instead"
|
|||
(org-element-map ast 'macro
|
||||
(lambda (macro)
|
||||
(let* ((name (org-element-property :key macro))
|
||||
(args (org-element-property :args macro))
|
||||
(template (cdr (assoc-string name templates t))))
|
||||
(pcase template
|
||||
(`nil
|
||||
(push (list (org-element-property :begin macro)
|
||||
(format "Undefined macro %S" name))
|
||||
reports))
|
||||
((pred functionp) nil) ;ignore it
|
||||
((guard (string= name "keyword"))
|
||||
(funcall check-arity '(1 . 1) macro))
|
||||
((guard (string= name "modification-time"))
|
||||
(funcall check-arity '(1 . 2) macro))
|
||||
((guard (string= name "n"))
|
||||
(funcall check-arity '(0 . 2) macro))
|
||||
((guard (string= name "property"))
|
||||
(funcall check-arity '(1 . 2) macro))
|
||||
((guard (string= name "time"))
|
||||
(funcall check-arity '(1 . 1) macro))
|
||||
((pred functionp)) ;ignore (eval ...) templates
|
||||
(_
|
||||
(let ((arg-numbers (funcall extract-placeholders template)))
|
||||
(when arg-numbers
|
||||
(let ((spurious-args
|
||||
(nthcdr (apply #'max arg-numbers)
|
||||
(org-element-property :args macro))))
|
||||
(when spurious-args
|
||||
(push
|
||||
(list (org-element-property :begin macro)
|
||||
(pcase spurious-args
|
||||
(`(,arg)
|
||||
(format "Unused argument in macro %S: %s"
|
||||
name arg))
|
||||
(args
|
||||
(format "Unused arguments in macro %S: %s"
|
||||
name
|
||||
(mapconcat #'org-trim args ", ")))))
|
||||
reports)))))))))))
|
||||
(let* ((arg-numbers (funcall extract-placeholders template))
|
||||
(arity (if (null arg-numbers)
|
||||
'(0 . 0)
|
||||
(let ((m (apply #'max arg-numbers)))
|
||||
(cons m m)))))
|
||||
(funcall check-arity arity macro))))))))
|
||||
reports))
|
||||
|
||||
(defun org-lint-undefined-footnote-reference (ast)
|
||||
|
|
|
@ -339,6 +339,12 @@ This is not a node property
|
|||
(should-not
|
||||
(org-test-with-temp-text
|
||||
"#+macro: valid $1 $2\n{{{valid(1, 2)}}}"
|
||||
(org-lint '(invalid-macro-argument-and-template))))
|
||||
(should
|
||||
(org-test-with-temp-text "{{{keyword}}}"
|
||||
(org-lint '(invalid-macro-argument-and-template))))
|
||||
(should
|
||||
(org-test-with-temp-text "{{{keyword(one, too many)}}}"
|
||||
(org-lint '(invalid-macro-argument-and-template)))))
|
||||
|
||||
(ert-deftest test-org-lint/undefined-footnote-reference ()
|
||||
|
|
Loading…
Reference in a new issue