From 0da56720a8379c7d839043220aadd59a554a41ca Mon Sep 17 00:00:00 2001 From: Joao Tavora Date: Sun, 5 May 2013 20:41:04 -0400 Subject: [PATCH] Closes #318: now checks for circular parenthood in snippet dirs --- yasnippet-tests.el | 16 ++++++++++++++++ yasnippet.el | 26 ++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/yasnippet-tests.el b/yasnippet-tests.el index 6d57d866b..4741a6d26 100644 --- a/yasnippet-tests.el +++ b/yasnippet-tests.el @@ -312,6 +312,22 @@ TODO: correct this bug!" (yas-reload-all) (yas--basic-jit-loading-1)))) +(ert-deftest loading-with-cyclic-parenthood () + "Test loading when cyclic parenthood is setup." + (yas-saving-variables + (yas-with-snippet-dirs '((".emacs.d/snippets" + ("c-mode" + (".yas-parents" . "cc-mode")) + ("cc-mode" + (".yas-parents" . "yet-another-c-mode")) + ("yet-another-c-mode" + (".yas-parents" . "c-mode")))) + (yas-reload-all) + (condition-case nil + (yas--all-parents 'c-mode) + (error + (ert-fail "cyclic parenthood test failed")))))) + (defun yas--basic-jit-loading-1 (&optional compile) (with-temp-buffer (should (= 4 (hash-table-count yas--scheduled-jit-loads))) diff --git a/yasnippet.el b/yasnippet.el index f799ad585..7e2eeee22 100644 --- a/yasnippet.el +++ b/yasnippet.el @@ -660,6 +660,11 @@ There might be additional parenting information stored in the `derived-mode-parent' property of some mode symbols, but that is not recorded here.") +(defvar yas--ancestors (make-hash-table) + "A hash table of mode symbols do lists of all parent mode symbols. + +A cache managed by `yas--all-parents'") + (defvar yas--direct-keymaps (list) "Keymap alist supporting direct snippet keybindings. @@ -1151,9 +1156,21 @@ conditions to filter out potential expansions." (defun yas--all-parents (mode) "Returns a list of all parent modes of MODE." - (let ((parents (gethash mode yas--parents))) - (append parents - (mapcan #'yas--all-parents parents)))) + (or (gethash mode yas--ancestors) + (let ((seen '())) + (labels ((yas--all-parents-1 + (m) + (cond ((memq m seen) + (yas--message 1 + "Cyclic parenthood: mode %s has already seen as a parent of mode %s" + m mode) + nil) + (t + (let* ((parents (gethash m yas--parents))) + (setq seen (append seen parents)) + (append parents (mapcan #'yas--all-parents-1 parents))))))) + (puthash mode (yas--all-parents-1 mode) + yas--ancestors))))) (defun yas--table-templates (table) (when table @@ -1866,6 +1883,7 @@ loading." ;; (setq yas--tables (make-hash-table)) (setq yas--parents (make-hash-table)) + (setq yas--ancestors (make-hash-table)) ;; Before killing `yas--menu-table' use its keys to cleanup the ;; mode menu parts of `yas--minor-mode-menu' (thus also cleaning @@ -2531,7 +2549,7 @@ neither do the elements of PARENTS." (buffer-substring-no-properties (point-min) (point-max)))))))) (when major-mode-sym - (cons major-mode-sym parents)))) + (cons major-mode-sym (remove major-mode-sym parents))))) (defvar yas--editing-template nil "Supporting variable for `yas-load-snippet-buffer' and `yas--visit-snippet'.") -- 2.39.2