diff options
| author | Glenn Morris | 2012-02-11 14:16:10 -0800 |
|---|---|---|
| committer | Glenn Morris | 2012-02-11 14:16:10 -0800 |
| commit | 584745030f2fc93f4f473c5d3dfb36ebe92851a1 (patch) | |
| tree | eadea19d06537f7a277a87dd7199b4c13f4c285d /admin | |
| parent | 2bed3f0483e55e4fe5a4efa40e15e89b63536ed0 (diff) | |
| download | emacs-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/ChangeLog | 5 | ||||
| -rw-r--r-- | admin/admin.el | 123 |
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 @@ | |||
| 1 | 2012-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 | |||
| 1 | 2012-01-19 Glenn Morris <rgm@gnu.org> | 6 | 2012-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. | ||
| 451 | If 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. | ||
| 465 | Return a list with elements of the form (VAR . VER), | ||
| 466 | This means that FILE contains a defcustom for variable VAR, with | ||
| 467 | a :version tag having value VER (may be nil). | ||
| 468 | If 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. | ||
| 511 | NEWDIR is the current lisp/ directory, OLDDIR is that from the previous | ||
| 512 | release. A defcustom that is only in NEWDIR should have a :version | ||
| 513 | tag. We exclude cases where a defvar exists in OLDDIR, since | ||
| 514 | just converting a defvar to a defcustom does not require a :version bump. | ||
| 515 | |||
| 516 | Note that a :version tag should also be added if the value of a defcustom | ||
| 517 | changes (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 |