emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 0da7689b16: Don't freeze Emacs on colour codes in sccs-mode


From: Lars Ingebrigtsen
Subject: master 0da7689b16: Don't freeze Emacs on colour codes in sccs-mode
Date: Sun, 15 May 2022 08:13:33 -0400 (EDT)

branch: master
commit 0da7689b167dd92c0ac307122be0a742a10abfb4
Author: Lars Ingebrigtsen <larsi@gnus.org>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Don't freeze Emacs on colour codes in sccs-mode
    
    * lisp/textmodes/css-mode.el (css--font-lock-keywords): Don't
    freeze Emacs on #ffffff #ffffff, and be more strict in parsing
    selectors (bug#53203).
---
 lisp/textmodes/css-mode.el                         | 56 +++++++++++-------
 .../textmodes/css-mode-resources/css-selectors.txt | 56 ++++++++++++++++++
 .../css-mode-resources/scss-selectors.txt          |  6 ++
 test/lisp/textmodes/css-mode-tests.el              | 69 ++++++++++++++++++++++
 4 files changed, 166 insertions(+), 21 deletions(-)

diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index ef7debc4bd..99b4482dc5 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -928,6 +928,32 @@ cannot be completed sensibly: `custom-ident',
 (defface css-proprietary-property '((t :inherit (css-property italic)))
   "Face to use for vendor-specific properties.")
 
+(defun css--selector-regexp (sassy)
+  (concat
+   "\\(?:"
+   (if (not sassy)
+       "[-_%*#.>[:alnum:]]+"
+     ;; Same as for non-sassy except we do want to allow { and }
+     ;; chars in selectors in the case of #{$foo}
+     ;; variable interpolation!
+     (concat "\\(?:[-_%*#.>[:alnum:]]*" scss--hash-re
+             "\\|[-_%*#.>[:alnum:]]+\\)"))
+   ;; Even though pseudo-elements should be prefixed by ::, a
+   ;; single colon is accepted for backward compatibility.
+   "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids
+                                   css-pseudo-element-ids)
+                           t)
+   "\\|::" (regexp-opt css-pseudo-element-ids t) "\\)\\)?"
+   ;; Braces after selectors.
+   "\\(?:\\[[^]\n]+\\]\\)?"
+   ;; Parentheses after selectors.
+   "\\(?:([^)]+)\\)?"
+   ;; Main bit over.  But perhaps just [target]?
+   "\\|\\[[^]\n]+\\]"
+   ;; :root, ::marker and the like.
+   "\\|::?[[:alnum:]]+\\(?:([^)]+)\\)?"
+   "\\)"))
+
 (defun css--font-lock-keywords (&optional sassy)
   `((,(concat "!\\s-*" (regexp-opt css--bang-ids))
      (0 font-lock-builtin-face))
@@ -948,28 +974,16 @@ cannot be completed sensibly: `custom-ident',
     ;; selector between [...] should simply not be highlighted.
     (,(concat
        "^[ \t]*\\("
-       (if (not sassy)
-           ;; We don't allow / as first char, so as not to
-           ;; take a comment as the beginning of a selector.
-           "[^@/:{}() \t\n][^:{}()]*"
-         ;; Same as for non-sassy except we do want to allow { and }
-         ;; chars in selectors in the case of #{$foo}
-         ;; variable interpolation!
-         (concat "\\(?:" scss--hash-re
-                 "\\|[^@/:{}() \t\n#]\\)"
-                 "[^:{}()#]*\\(?:" scss--hash-re "[^:{}()#]*\\)*"))
-       ;; Even though pseudo-elements should be prefixed by ::, a
-       ;; single colon is accepted for backward compatibility.
-       "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids
-                                       css-pseudo-element-ids)
-                               t)
-       "\\|::" (regexp-opt css-pseudo-element-ids t) "\\)"
-       "\\(?:([^)]+)\\)?"
-       (if (not sassy)
-           "[^:{}()\n]*"
-         (concat "[^:{}()\n#]*\\(?:" scss--hash-re "[^:{}()\n#]*\\)*"))
+       ;; We have at least one selector.
+       (css--selector-regexp sassy)
+       ;; And then possibly more.
+       "\\(?:"
+       ;; Separators between selectors.
+       "[ \n\t,+~>]+"
+       (css--selector-regexp sassy)
        "\\)*"
-       "\\)\\(?:\n[ \t]*\\)*{")
+       ;; And then a brace.
+       "\\)[ \n\t]*{")
      (1 'css-selector keep))
     ;; In the above rule, we allow the open-brace to be on some subsequent
     ;; line.  This will only work if we properly mark the intervening text
diff --git a/test/lisp/textmodes/css-mode-resources/css-selectors.txt 
b/test/lisp/textmodes/css-mode-resources/css-selectors.txt
new file mode 100644
index 0000000000..5b3d990f27
--- /dev/null
+++ b/test/lisp/textmodes/css-mode-resources/css-selectors.txt
@@ -0,0 +1,56 @@
+#firstname
+*
+p
+p.intro
+div, p
+div p
+div > p
+div + p
+p ~ ul
+[target]
+[target=_blank]
+[title~=flower]
+[lang|=en]
+a[href^="https"]
+a[href$=".pdf"]
+a[href*="w3schools"]
+a:active
+p::after
+p::before
+input:checked
+input:default
+input:disabled
+p:empty
+input:enabled
+p:first-child
+p::first-letter
+p::first-line
+p:first-of-type
+input:focus
+:fullscreen
+a:hover
+input:in-range
+input:indeterminate
+input:invalid
+p:lang(it)
+p:last-child
+p:last-of-type
+a:link
+::marker
+:not(p)
+p:nth-child(2)
+p:nth-last-child(2)
+p:nth-last-of-type(2)
+p:nth-of-type(2)
+p:only-of-type
+p:only-child
+input:optional
+input:out-of-range
+input:read-only
+input:read-write
+input:required
+:root
+::selection
+#news:target
+input:valid
+a:visited
diff --git a/test/lisp/textmodes/css-mode-resources/scss-selectors.txt 
b/test/lisp/textmodes/css-mode-resources/scss-selectors.txt
new file mode 100644
index 0000000000..86e58110b7
--- /dev/null
+++ b/test/lisp/textmodes/css-mode-resources/scss-selectors.txt
@@ -0,0 +1,6 @@
+p.#{$name} var
+p.#{$name}:active var
+p.#{$name}::after var
+f.#{$bar}::after p::after
+p.#{$name} f.#{$bar} k.var #{$bar}  #{$bar}
+p.#{$name}
diff --git a/test/lisp/textmodes/css-mode-tests.el 
b/test/lisp/textmodes/css-mode-tests.el
index 0ae1593508..555a73c3bb 100644
--- a/test/lisp/textmodes/css-mode-tests.el
+++ b/test/lisp/textmodes/css-mode-tests.el
@@ -419,5 +419,74 @@
       (indent-region (point-min) (point-max))
       (should (equal (buffer-string) orig)))))
 
+(ert-deftest css-mode-test-selectors ()
+  (let ((selectors
+         (with-temp-buffer
+           (insert-file-contents (ert-resource-file "css-selectors.txt"))
+           (string-lines (buffer-string)))))
+    (with-suppressed-warnings ((interactive font-lock-debug-fontif))
+      (dolist (selector selectors)
+        (with-temp-buffer
+          (css-mode)
+          (insert selector " {\n}\n")
+          (font-lock-debug-fontify)
+          (goto-char (point-min))
+          (unless (eq (get-text-property (point) 'face)
+                      'css-selector)
+            (should-not (format "Didn't recognize %s as a selector"
+                                (buffer-substring-no-properties
+                                 (point) (line-end-position)))))))
+      ;; Test many selectors.
+      (dolist (selector selectors)
+        (with-temp-buffer
+          (css-mode)
+          (insert selector " ")
+          (dotimes (_ (random 5))
+            (insert (seq-random-elt '(" , " " > " " + "))
+                    (seq-random-elt selectors)))
+          (insert "{\n}\n")
+          (font-lock-debug-fontify)
+          (goto-char (point-min))
+          (unless (eq (get-text-property (point) 'face)
+                      'css-selector)
+            (should-not (format "Didn't recognize %s as a selector"
+                                (buffer-substring-no-properties
+                                 (point) (line-end-position)))))))
+      ;; Test wrong separators.
+      (dolist (selector selectors)
+        (with-temp-buffer
+          (css-mode)
+          (insert selector " ")
+          (dotimes (_ (1+ (random 5)))
+            (insert (seq-random-elt '("=" " @ "))
+                    (seq-random-elt selectors)))
+          (insert "{\n}\n")
+          (font-lock-debug-fontify)
+          (goto-char (point-min))
+          (when (eq (get-text-property (point) 'face)
+                    'css-selector)
+            (should-not (format "Recognized %s as a selector"
+                                (buffer-substring-no-properties
+                                 (point) (line-end-position))))))))))
+
+(ert-deftest scss-mode-test-selectors ()
+  (let ((selectors
+         (with-temp-buffer
+           (insert-file-contents (ert-resource-file "scss-selectors.txt"))
+           (string-lines (buffer-string)))))
+    (with-suppressed-warnings ((interactive font-lock-debug-fontif))
+      (dolist (selector selectors)
+        (with-temp-buffer
+          (scss-mode)
+          (insert selector " {\n}\n")
+          (font-lock-debug-fontify)
+          (goto-char (point-min))
+          (unless (eq (get-text-property (point) 'face)
+                      'css-selector)
+            (should-not (format "Didn't recognize %s as a selector"
+                                (buffer-substring-no-properties
+                                 (point) (line-end-position))))))))))
+
+
 (provide 'css-mode-tests)
 ;;; css-mode-tests.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]