aboutsummaryrefslogtreecommitdiffstats
path: root/admin
diff options
context:
space:
mode:
authorGlenn Morris2012-02-11 14:16:10 -0800
committerGlenn Morris2012-02-11 14:16:10 -0800
commit584745030f2fc93f4f473c5d3dfb36ebe92851a1 (patch)
treeeadea19d06537f7a277a87dd7199b4c13f4c285d /admin
parent2bed3f0483e55e4fe5a4efa40e15e89b63536ed0 (diff)
downloademacs-584745030f2fc93f4f473c5d3dfb36ebe92851a1.tar.gz
emacs-584745030f2fc93f4f473c5d3dfb36ebe92851a1.zip
Add some admin stuff to check for defcustoms missing version tags
* admin/admin.el (cusver-find-files, cusver-scan, cusver-goto-xref) (cusver-check): New functions.
Diffstat (limited to 'admin')
-rw-r--r--admin/ChangeLog5
-rw-r--r--admin/admin.el123
2 files changed, 128 insertions, 0 deletions
diff --git a/admin/ChangeLog b/admin/ChangeLog
index 2178df6caf0..cc734d1393c 100644
--- a/admin/ChangeLog
+++ b/admin/ChangeLog
@@ -1,3 +1,8 @@
12012-02-11 Glenn Morris <rgm@gnu.org>
2
3 * admin.el (cusver-find-files, cusver-scan, cusver-goto-xref)
4 (cusver-check): New functions.
5
12012-01-19 Glenn Morris <rgm@gnu.org> 62012-01-19 Glenn Morris <rgm@gnu.org>
2 7
3 * bzrmerge.el (bzrmerge-missing): Allow a definitive "no" answer to the 8 * bzrmerge.el (bzrmerge-missing): Allow a definitive "no" answer to the
diff --git a/admin/admin.el b/admin/admin.el
index 2ca838fdff9..27b2b3ab648 100644
--- a/admin/admin.el
+++ b/admin/admin.el
@@ -442,6 +442,129 @@ Also generate PostScript output in PS-DEST."
442 (setq done t)))) 442 (setq done t))))
443 (forward-line 1)))) 443 (forward-line 1))))
444 444
445
446;; Stuff to check new defcustoms got :version tags.
447;; Adapted from check-declare.el.
448
449(defun cusver-find-files (root &optional old)
450 "Find .el files beneath directory ROOT that contain defcustoms.
451If optional OLD is non-nil, also include defvars."
452 (process-lines find-program root
453 "-name" "*.el"
454 "-exec" grep-program
455 "-l" "-E" (format "^[ \\t]*\\(def%s"
456 (if old "(custom|var)"
457 "custom"
458 ))
459 "{}" "+"))
460
461;; TODO if a defgroup with a version tag, apply to all customs in that
462;; group (eg for new files).
463(defun cusver-scan (file &optional old)
464 "Scan FILE for `defcustom' calls.
465Return a list with elements of the form (VAR . VER),
466This means that FILE contains a defcustom for variable VAR, with
467a :version tag having value VER (may be nil).
468If optional argument OLD is non-nil, also scan for defvars."
469 (let ((m (format "Scanning %s..." file))
470 (re (format "^[ \t]*\\((def%s\\)[ \t\n]"
471 (if old "\\(?:custom\\|var\\)" "custom")))
472 alist var ver)
473 (message "%s" m)
474 (with-temp-buffer
475 (insert-file-contents file)
476 ;; FIXME we could theoretically be inside a string.
477 (while (re-search-forward re nil t)
478 (goto-char (match-beginning 1))
479 (if (and (setq form (ignore-errors (read (current-buffer))))
480 (setq var (car-safe (cdr-safe form)))
481 ;; Exclude macros, eg (defcustom ,varname ...).
482 (symbolp var))
483 (setq ver (car (cdr-safe (memq :version form)))
484 alist (cons (cons var ver) alist))
485 (if form (message "Malformed defcustom: `%s'" form)))))
486 (message "%sdone" m)
487 alist))
488
489(define-button-type 'cusver-xref 'action #'cusver-goto-xref)
490
491(defun cusver-goto-xref (button)
492 "Jump to a lisp file for the BUTTON at point."
493 (let ((file (button-get button 'file))
494 (var (button-get button 'var)))
495 (if (not (file-readable-p file))
496 (message "Cannot read `%s'" file)
497 (with-current-buffer (find-file-noselect file)
498 (goto-char (point-min))
499 (or (re-search-forward (format "^[ \t]*(defcustom[ \t]*%s" var) nil t)
500 (message "Unable to locate defcustom"))
501 (pop-to-buffer (current-buffer))))))
502
503;; You should probably at least do a grep over the old directory
504;; to check the results of this look sensible. Eg cus-start if
505;; something moved from C to Lisp.
506;; TODO handle renamed things with aliases to the old names.
507;; What to do about new files? Does everything in there need a :version,
508;; or eg just the defgroup?
509(defun cusver-check (newdir olddir)
510 "Check that defcustoms have :version tags where needed.
511NEWDIR is the current lisp/ directory, OLDDIR is that from the previous
512release. A defcustom that is only in NEWDIR should have a :version
513tag. We exclude cases where a defvar exists in OLDDIR, since
514just converting a defvar to a defcustom does not require a :version bump.
515
516Note that a :version tag should also be added if the value of a defcustom
517changes (in a non-trivial way). This function does not check for that."
518 (interactive "DNew Lisp directory: \nDOld Lisp directory: ")
519 (or (file-directory-p (setq newdir (expand-file-name newdir)))
520 (error "Directory `%s' not found" newdir))
521 (or (file-directory-p (setq olddir (expand-file-name olddir)))
522 (error "Directory `%s' not found" olddir))
523 (let* ((newfiles (progn (message "Finding new files with defcustoms...")
524 (cusver-find-files newdir)))
525 (oldfiles (progn (message "Finding old files with defcustoms...")
526 (cusver-find-files olddir t)))
527 (newcus (progn (message "Reading new defcustoms...")
528 (mapcar
529 (lambda (file)
530 (cons file (cusver-scan file))) newfiles)))
531 oldcus result thisfile)
532 (message "Reading old defcustoms...")
533 (dolist (file oldfiles)
534 (setq oldcus (append oldcus (cusver-scan file t))))
535 ;; newcus has elements (FILE (VAR VER) ... ).
536 ;; oldcus just (VAR . VER).
537 (message "Checking for version tags...")
538 (dolist (new newcus)
539 (setq file (car new)
540 thisfile
541 (let (missing var)
542 (dolist (cons (cdr new))
543 (or (cdr cons)
544 (assq (setq var (car cons)) oldcus)
545 (push var missing)))
546 (if missing
547 (cons file missing))))
548 (if thisfile
549 (setq result (cons thisfile result))))
550 (message "Checking for version tags... done")
551 (if (not result)
552 (message "No missing :version tags")
553 (pop-to-buffer "*cusver*")
554 (erase-buffer)
555 (insert "These defcustoms might be missing :version tags:\n\n")
556 (dolist (elem result)
557 (let* ((str (file-relative-name (car elem) newdir))
558 (strlen (length str)))
559 (dolist (var (cdr elem))
560 (insert (format "%s: %s\n" str var))
561 (make-text-button (+ (line-beginning-position 0) strlen 2)
562 (line-end-position 0)
563 'file (car elem)
564 'var var
565 'help-echo "Mouse-2: visit this definition"
566 :type 'cusver-xref)))))))
567
445(provide 'admin) 568(provide 'admin)
446 569
447;;; admin.el ends here 570;;; admin.el ends here