diff options
author | Nicolas Goaziou <mail@nicolasgoaziou.fr> | 2021-04-19 02:06:01 +0200 |
---|---|---|
committer | Nicolas Goaziou <mail@nicolasgoaziou.fr> | 2021-04-19 02:06:01 +0200 |
commit | 628bb4f324b664f4ef75f1d60406eca92ee5e7d3 (patch) | |
tree | d5bc8096a6a481b7c745893349601fa92b6510ad | |
parent | 772f7acb6511699c701eb7af8b3c42ac3195f5ca (diff) | |
download | org-mode-628bb4f324b664f4ef75f1d60406eca92ee5e7d3.tar.gz |
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.
-rw-r--r-- | lisp/org-lint.el | 81 | ||||
-rw-r--r-- | testing/lisp/test-org-lint.el | 6 |
2 files changed, 60 insertions, 27 deletions
diff --git a/lisp/org-lint.el b/lisp/org-lint.el index 94db816..87ab78b 100644 --- a/lisp/org-lint.el +++ b/lisp/org-lint.el @@ -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) diff --git a/testing/lisp/test-org-lint.el b/testing/lisp/test-org-lint.el index 800599e..e57993c 100644 --- a/testing/lisp/test-org-lint.el +++ b/testing/lisp/test-org-lint.el @@ -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 () |