From 5722ecdf5ce0ecc4567482b8af34da75d4eb2223 Mon Sep 17 00:00:00 2001 From: USAMI Kenta Date: Thu, 19 Dec 2024 21:21:08 +0900 Subject: [PATCH] Support PHP 8.4 property-hooks --- lisp/php-mode.el | 4 +- tests/8.4/property-hooks.php | 33 +++++++ tests/8.4/property-hooks.php.faces | 146 +++++++++++++++++++++++++++++ tests/php-mode-test.el | 8 +- 4 files changed, 188 insertions(+), 3 deletions(-) create mode 100644 tests/8.4/property-hooks.php create mode 100644 tests/8.4/property-hooks.php.faces diff --git a/lisp/php-mode.el b/lisp/php-mode.el index 867a84fe..e1736b28 100644 --- a/lisp/php-mode.el +++ b/lisp/php-mode.el @@ -1519,7 +1519,9 @@ for \\[find-tag] (which see)." ;; Not operator (!) is defined in "before cc-mode" section above. ("\\(&&\\|||\\)" 1 'php-logical-op) ;; string interpolation ("$var, ${var}, {$var}") - (php-mode--string-interpolated-variable-font-lock-find 0 nil))) + (php-mode--string-interpolated-variable-font-lock-find 0 nil) + (,(rx symbol-start (group (or "get" "set")) (+ (syntax whitespace)) (or "{" "=>")) + 1 'php-builtin))) "Detailed highlighting for PHP Mode.") (defvar php-font-lock-keywords php-font-lock-keywords-3 diff --git a/tests/8.4/property-hooks.php b/tests/8.4/property-hooks.php new file mode 100644 index 00000000..aa50f965 --- /dev/null +++ b/tests/8.4/property-hooks.php @@ -0,0 +1,33 @@ + $this->firstName . ' ' . $this->lastName; + } + + // All write operations go through this hook, and the result is what is written. + // Read access happens normally. + public string $firstName { + set => ucfirst(strtolower($value)); + } + + // All write operations go through this hook, which has to write to the backing value itself. + // Read access happens normally. + public string $lastName { + set { + if (strlen($value) < 2) { + throw new \InvalidArgumentException('Too short'); + } + $this->lastName = $value; + } + } +} + +$p = new Person(); + +$p->firstName = 'peter'; +print $p->firstName; // Prints "Peter" +$p->lastName = 'Peterson'; +print $p->fullName; // Prints "Peter Peterson" diff --git a/tests/8.4/property-hooks.php.faces b/tests/8.4/property-hooks.php.faces new file mode 100644 index 00000000..89ec60a6 --- /dev/null +++ b/tests/8.4/property-hooks.php.faces @@ -0,0 +1,146 @@ +;; -*- mode: emacs-lisp -*- +(("" . php-comparison-op) + (" ") + ("$" . php-this-sigil) + ("this" . php-this) + ("->" . php-object-op) + ("firstName" . php-property-name) + (" . ") + ("' '" . php-string) + (" . ") + ("$" . php-this-sigil) + ("this" . php-this) + ("->" . php-object-op) + ("lastName" . php-property-name) + (";\n }\n\n ") + ("// " . font-lock-comment-delimiter-face) + ("All write operations go through this hook, and the result is what is written.\n" . font-lock-comment-face) + (" ") + ("// " . font-lock-comment-delimiter-face) + ("Read access happens normally.\n" . font-lock-comment-face) + (" ") + ("public" . php-keyword) + (" ") + ("string" . php-class) + (" ") + ("$" . php-variable-sigil) + ("firstName" . php-variable-name) + (" {\n ") + ("set" . php-builtin) + (" ") + ("=" . php-assignment-op) + (">" . php-comparison-op) + (" ") + ("ucfirst" . php-function-call-traditional) + ("(") + ("strtolower" . php-function-call-traditional) + ("(") + ("$" . php-variable-sigil) + ("value" . php-variable-name) + ("));\n }\n\n ") + ("// " . font-lock-comment-delimiter-face) + ("All write operations go through this hook, which has to write to the backing value itself.\n" . font-lock-comment-face) + (" ") + ("// " . font-lock-comment-delimiter-face) + ("Read access happens normally.\n" . font-lock-comment-face) + (" ") + ("public" . php-keyword) + (" ") + ("string" . php-class) + (" ") + ("$" . php-variable-sigil) + ("lastName" . php-variable-name) + (" {\n ") + ("set" . php-builtin) + (" {\n ") + ("if" . php-keyword) + (" (") + ("strlen" . php-function-call-traditional) + ("(") + ("$" . php-variable-sigil) + ("value" . php-variable-name) + (") ") + ("<" . php-comparison-op) + (" 2) {\n ") + ("throw" . php-keyword) + (" ") + ("new" . php-keyword) + (" ") + ("\\InvalidArgumentException" . font-lock-type-face) + ("(") + ("'Too short'" . php-string) + (");\n }\n ") + ("$" . php-this-sigil) + ("this" . php-this) + ("->" . php-object-op) + ("lastName" . php-property-name) + (" ") + ("=" . php-assignment-op) + (" ") + ("$" . php-variable-sigil) + ("value" . php-variable-name) + (";\n }\n }\n}\n\n") + ("$" . php-variable-sigil) + ("p" . php-variable-name) + (" ") + ("=" . php-assignment-op) + (" ") + ("new" . php-keyword) + (" ") + ("Person" . font-lock-type-face) + ("();\n\n") + ("$" . php-variable-sigil) + ("p" . php-variable-name) + ("->" . php-object-op) + ("firstName" . php-property-name) + (" ") + ("=" . php-assignment-op) + (" ") + ("'peter'" . php-string) + (";\n") + ("print" . php-keyword) + (" ") + ("$" . php-variable-sigil) + ("p" . php-variable-name) + ("->" . php-object-op) + ("firstName" . php-property-name) + ("; ") + ("// " . font-lock-comment-delimiter-face) + ("Prints \"Peter\"\n" . font-lock-comment-face) + ("$" . php-variable-sigil) + ("p" . php-variable-name) + ("->" . php-object-op) + ("lastName" . php-property-name) + (" ") + ("=" . php-assignment-op) + (" ") + ("'Peterson'" . php-string) + (";\n") + ("print" . php-keyword) + (" ") + ("$" . php-variable-sigil) + ("p" . php-variable-name) + ("->" . php-object-op) + ("fullName" . php-property-name) + ("; ") + ("// " . font-lock-comment-delimiter-face) + ("Prints \"Peter Peterson\"\n" . font-lock-comment-face)) diff --git a/tests/php-mode-test.el b/tests/php-mode-test.el index 9890e0c8..4d36579b 100644 --- a/tests/php-mode-test.el +++ b/tests/php-mode-test.el @@ -1,6 +1,6 @@ -;;; php-mode-test.el --- Tests for php-mode +;;; php-mode-test.el --- Tests for php-mode -*- lexical-binding: t -*- -;; Copyright (C) 2018-2019 Friends of Emacs-PHP development +;; Copyright (C) 2018-2024 Friends of Emacs-PHP development ;; Copyright (C) 2013 Daniel Hackney ;; 2014, 2015 Eric James Michael Ritz @@ -669,6 +669,10 @@ Meant for `php-mode-test-issue-503'." (with-php-mode-test ("8.1/enum.php" :faces t)) (with-php-mode-test ("8.1/readonly.php" :faces t))) +(ert-deftest php-mode-test-php84 () + "Test highlighting language constructs added in PHP 8.4." + (with-php-mode-test ("8.4/property-hooks.php" :faces t))) + (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))