(defvar change-match-data-calling (regexp-opt '("(search-forward " "(search-backward " "(word-search-forward " "(word-search-backward " "(re-search-forward " "(re-search-backward " "(string-match " "(looking-at " "(looking-back " "(search-spaces-regexp " "(posix-search-forward " "(posix-search-backward " "(posix-looking-at " "(posix-string-match " "(set-match-data "))) (defvar defun-form (regexp-opt '("(defun " "(define-minor-mode " "(define-derived-mode "))) (defun find-possible-wrong-match-defuns-in-buffer (buffer) (let (possible-wrong-functions) (catch 'skip-this-file (with-current-buffer buffer (goto-char (point-min)) ;; Find a calling. (while (re-search-forward change-match-data-calling nil t) (let ((valid t) func-name) (catch 'not-a-defun (condition-case nil (progn (let ((last-pos (point))) (mark-defun) (unless (looking-at (concat "\n" defun-form)) (goto-char last-pos) (throw 'not-a-defun t))) (setq func-name (save-excursion (down-list) (forward-sexp) (skip-syntax-forward " ") (buffer-substring-no-properties (point) (save-excursion (forward-sexp) (point))))) (save-restriction (narrow-to-region (region-beginning) (region-end)) ;; Check each calling. (while (and valid (re-search-forward change-match-data-calling nil t)) (save-excursion (backward-up-list) (catch 'found-save-match-data (condition-case nil (while t (backward-up-list) (if (looking-at "(save-match-data") (throw 'found-save-match-data t))) (error (setq valid nil)))))) (unless valid (setq possible-wrong-functions (cons func-name possible-wrong-functions)) (while (re-search-forward change-match-data-calling nil t) nil)))) (error (throw 'skip-this-file t)))))))) possible-wrong-functions)) (defun find-possible-wrong-match-defuns-in-file (file) (when (file-exists-p file) (let* ((buffer (find-file-noselect file)) (possible-wrong-functions (find-possible-wrong-match-defuns-in-buffer buffer))) (kill-buffer buffer) (cons file possible-wrong-functions)))) (defun find-possible-wrong-match-defuns-in-dir (dir) (when (file-exists-p dir) (let (functions-list) (dolist (file (directory-files dir)) (when (not (or (string= file ".") (string= file "..") (string-match "elc$" file))) (let* ((fullname (concat dir (if (not (string-match "/$" dir)) "/" "") file)) (isdir (car (file-attributes fullname))) functions sub-functions-list) (if isdir (progn (setq sub-functions-list (find-possible-wrong-match-defuns-in-dir fullname)) (when sub-functions-list (setq functions-list (append sub-functions-list functions-list)))) (setq functions (find-possible-wrong-match-defuns-in-file fullname)) (if (> (length functions) 1) (setq functions-list (cons functions functions-list))))))) functions-list))) (defun list-possible-wrong-match-defuns-in-dir (dir) (interactive "DDirectory: ") (let ((functions-list (find-possible-wrong-match-defuns-in-dir dir)) (buffer (get-buffer-create "*possible wrong match defuns*"))) (with-current-buffer buffer (dolist (functions functions-list) (insert "In " (car functions) ":\n") (dolist (function (cdr functions)) (insert "\t" function "\n")) (insert "\n"))) (delete-other-windows) (split-window-vertically) (other-window 1) (switch-to-buffer buffer) (goto-char (point-min))))