summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Gutov <dgutov@yandex.ru>2016-03-07 02:58:49 +0200
committerDmitry Gutov <dgutov@yandex.ru>2016-03-07 05:07:34 +0200
commit6e63b3e997e1ac2fa9b58f0d2edeca3cd83628f2 (patch)
tree80fe9ca13285f52d56c6c2a677001fe36d5ad884
parent066f3bc3f3d024b2e10ee11e09ae6aaa1003bbda (diff)
downloademacs-6e63b3e.tar.gz
Guard against nested percent literals
* lisp/progmodes/ruby-mode.el (ruby-syntax-propertize-percent-literal): Don't check the syntax status. (ruby-syntax-propertize): Check it here. And also guard against being in a larger percent literal. * test/automated/ruby-mode-tests.el (ruby-no-nested-percent-literals): New test.
-rw-r--r--lisp/progmodes/ruby-mode.el61
-rw-r--r--test/automated/ruby-mode-tests.el8
2 files changed, 39 insertions, 30 deletions
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index fa94992ab79..1395828cff9 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -1901,7 +1901,10 @@ It will be properly highlighted even when the call omits parens.")
(ruby-syntax-propertize-heredoc end))))
;; Handle percent literals: %w(), %q{}, etc.
((concat "\\(?:^\\|[[ \t\n<+(,=]\\)" ruby-percent-literal-beg-re)
- (1 (prog1 "|" (ruby-syntax-propertize-percent-literal end)))))
+ (1 (unless (nth 8 (save-excursion (syntax-ppss (match-beginning 1))))
+ ;; Not inside a string, a comment, or a percent literal.
+ (ruby-syntax-propertize-percent-literal end)
+ (string-to-syntax "|")))))
(point) end)))
(define-obsolete-function-alias
@@ -1944,35 +1947,33 @@ It will be properly highlighted even when the call omits parens.")
(defun ruby-syntax-propertize-percent-literal (limit)
(goto-char (match-beginning 2))
- ;; Not inside a simple string or comment.
- (when (eq t (nth 3 (syntax-ppss)))
- (let* ((op (char-after))
- (ops (char-to-string op))
- (cl (or (cdr (aref (syntax-table) op))
- (cdr (assoc op '((?< . ?>))))))
- parse-sexp-lookup-properties)
- (save-excursion
- (condition-case nil
- (progn
- (if cl ; Paired delimiters.
- ;; Delimiter pairs of the same kind can be nested
- ;; inside the literal, as long as they are balanced.
- ;; Create syntax table that ignores other characters.
- (with-syntax-table (make-char-table 'syntax-table nil)
- (modify-syntax-entry op (concat "(" (char-to-string cl)))
- (modify-syntax-entry cl (concat ")" ops))
- (modify-syntax-entry ?\\ "\\")
- (save-restriction
- (narrow-to-region (point) limit)
- (forward-list))) ; skip to the paired character
- ;; Single character delimiter.
- (re-search-forward (concat "[^\\]\\(?:\\\\\\\\\\)*"
- (regexp-quote ops)) limit nil))
- ;; Found the closing delimiter.
- (put-text-property (1- (point)) (point) 'syntax-table
- (string-to-syntax "|")))
- ;; Unclosed literal, do nothing.
- ((scan-error search-failed)))))))
+ (let* ((op (char-after))
+ (ops (char-to-string op))
+ (cl (or (cdr (aref (syntax-table) op))
+ (cdr (assoc op '((?< . ?>))))))
+ parse-sexp-lookup-properties)
+ (save-excursion
+ (condition-case nil
+ (progn
+ (if cl ; Paired delimiters.
+ ;; Delimiter pairs of the same kind can be nested
+ ;; inside the literal, as long as they are balanced.
+ ;; Create syntax table that ignores other characters.
+ (with-syntax-table (make-char-table 'syntax-table nil)
+ (modify-syntax-entry op (concat "(" (char-to-string cl)))
+ (modify-syntax-entry cl (concat ")" ops))
+ (modify-syntax-entry ?\\ "\\")
+ (save-restriction
+ (narrow-to-region (point) limit)
+ (forward-list))) ; skip to the paired character
+ ;; Single character delimiter.
+ (re-search-forward (concat "[^\\]\\(?:\\\\\\\\\\)*"
+ (regexp-quote ops)) limit nil))
+ ;; Found the closing delimiter.
+ (put-text-property (1- (point)) (point) 'syntax-table
+ (string-to-syntax "|")))
+ ;; Unclosed literal, do nothing.
+ ((scan-error search-failed))))))
(defun ruby-syntax-propertize-expansion ()
;; Save the match data to a text property, for font-locking later.
diff --git a/test/automated/ruby-mode-tests.el b/test/automated/ruby-mode-tests.el
index da8d77c5157..7073f7a04e2 100644
--- a/test/automated/ruby-mode-tests.el
+++ b/test/automated/ruby-mode-tests.el
@@ -461,6 +461,14 @@ VALUES-PLIST is a list with alternating index and value elements."
(ruby-assert-face "%S{foo}" 4 nil)
(ruby-assert-face "%R{foo}" 4 nil))
+(ert-deftest ruby-no-nested-percent-literals ()
+ (ruby-with-temp-buffer "a = %w[b %()]"
+ (syntax-propertize (point))
+ (should (null (nth 8 (syntax-ppss))))
+ (should (eq t (nth 3 (syntax-ppss (1- (point-max))))))
+ (search-backward "[")
+ (should (eq t (nth 3 (syntax-ppss))))))
+
(ert-deftest ruby-add-log-current-method-examples ()
(let ((pairs '(("foo" . "#foo")
("C.foo" . ".foo")