branch: elpa/php-mode
commit c3cc4c999e5427d7a0ec9fba5531c998707570c1
Author: USAMI Kenta <[email protected]>
Commit: USAMI Kenta <[email protected]>

    Add php-pipe-op face for the PHP 8.5 pipe operator
    
    The pipe operator came out half-fontified.  No rule matched `|>', so
    the comparison-operator matcher -- whose `[<>]=?' alternative claims a
    bare `>' -- took the second character and left the first one plain:
    
        '|' -> nil
        '>' -> php-comparison-op
    
    Give it a face of its own.  php-pipe-op inherits php-operator like the
    rest of the operator faces, and its rule sits ahead of the comparison
    operators so it wins the `>'.
    
    The rule is deliberately narrow (`|>' only), so nothing else moves:
    `||', `>=', `>', `===', `<=>', `=>' and a bare `|' all keep the faces
    they had.  A test pins that down alongside the pipe itself.
    
    See https://www.php.net/releases/8.5/en.php
---
 lisp/php-face.el       |  5 +++++
 lisp/php-mode.el       |  5 +++++
 tests/php-mode-test.el | 30 ++++++++++++++++++++++++++++++
 3 files changed, 40 insertions(+)

diff --git a/lisp/php-face.el b/lisp/php-face.el
index 15395fb269..85aa38dd39 100644
--- a/lisp/php-face.el
+++ b/lisp/php-face.el
@@ -126,6 +126,11 @@
   "PHP Mode face used to object operators (->)."
   :tag "PHP Object Op")
 
+(defface php-pipe-op '((t (:inherit php-operator)))
+  "PHP Mode face used to the pipe operator (|>).
+The operator was added in PHP 8.5."
+  :tag "PHP Pipe Op")
+
 (defface php-paamayim-nekudotayim '((t ()))
   "PHP Mode face used to highlight scope resolution operators (::).
 The operator is also knows as \"Paamayim Nekudotayim\"."
diff --git a/lisp/php-mode.el b/lisp/php-mode.el
index 4b050d2449..4fd23b2912 100644
--- a/lisp/php-mode.el
+++ b/lisp/php-mode.el
@@ -1518,6 +1518,11 @@ for \\[find-tag] (which see)."
      ;; Assignment operators (=, +=, ...)
      ("\\([^=<!>]+?\\([\-+./%]?=\\)[^=<!]+?\\)" 2 'php-assignment-op)
 
+     ;; Pipe operator (|>) --- PHP 8.5.  Must precede the comparison
+     ;; operators, whose `[<>]=?' alternative would otherwise claim the
+     ;; `>' and leave the `|' unfontified.
+     ("\\(|>\\)" 1 'php-pipe-op)
+
      ;; Comparison operators (==, ===, >=, ...)
      ("\\([!=]=\\{1,2\\}[>]?\\|[<>]=?\\)" 1 'php-comparison-op)
 
diff --git a/tests/php-mode-test.el b/tests/php-mode-test.el
index 09a33754f2..1d5ef11ffb 100644
--- a/tests/php-mode-test.el
+++ b/tests/php-mode-test.el
@@ -803,6 +803,36 @@ path; sending those to an HTML mode would take most PHP 
files away from
   "Test highlighting language constructs added in PHP 8.4."
   (with-php-mode-test ("8.4/property-hooks.php" :faces t)))
 
+(defun php-mode-test--faces-of (code token)
+  "Return the list of faces on TOKEN's characters after fontifying CODE."
+  (with-temp-buffer
+    (insert code)
+    (php-mode)
+    (font-lock-ensure)
+    (goto-char (point-min))
+    (should (search-forward token nil t))
+    (let ((start (- (point) (length token))))
+      (mapcar (lambda (i) (get-text-property (+ start i) 'face))
+              (number-sequence 0 (1- (length token)))))))
+
+(ert-deftest php-mode-test-php85-pipe-op ()
+  "The PHP 8.5 pipe operator is fontified as `php-pipe-op'.
+
+Both characters must get the face.  The comparison-operator matcher
+claims a bare `>', so without a rule of its own `|>' came out
+half-fontified: the `|' plain and the `>' as `php-comparison-op'."
+  (should (equal '(php-pipe-op php-pipe-op)
+                 (php-mode-test--faces-of "<?php\n$slug = $title |> 
trim(...);\n" "|>")))
+  ;; Operators that the new rule must not steal from.
+  (dolist (probe '(("<?php\n$a = $b || $c;\n"    "||"  (php-logical-op 
php-logical-op))
+                   ("<?php\n$a = $b >= $c;\n"    ">="  (php-comparison-op 
php-comparison-op))
+                   ("<?php\n$a = $b > $c;\n"     ">"   (php-comparison-op))
+                   ("<?php\n$a = $b <=> $c;\n"   "<=>" (php-comparison-op 
php-comparison-op php-comparison-op))
+                   ("<?php\n$a = $b | $c;\n"     "|"   (nil))))
+    (cl-destructuring-bind (code token expected) probe
+      (should (equal (cons token expected)
+                     (cons token (php-mode-test--faces-of code token)))))))
+
 (ert-deftest php-mode-test-lang ()
   "Test highlighting for language constructs."
   (with-php-mode-test ("lang/class/anonymous-class.php" :indent t :magic t 
:faces t))

Reply via email to