Skip to content

Commit

Permalink
Support PHP 8.4 property-hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
zonuexe committed Dec 19, 2024
1 parent 69e9c16 commit 5722ecd
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 3 deletions.
4 changes: 3 additions & 1 deletion lisp/php-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 33 additions & 0 deletions tests/8.4/property-hooks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

class Person
{
// A "virtual" property. It may not be set explicitly.
public string $fullName {
get => $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"
146 changes: 146 additions & 0 deletions tests/8.4/property-hooks.php.faces
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
;; -*- mode: emacs-lisp -*-
(("<?php" . php-php-tag)
("\n\n")
("class" . php-class-declaration)
(" ")
("Person" . font-lock-type-face)
("\n{\n ")
("// " . font-lock-comment-delimiter-face)
("A \"virtual\" property. It may not be set explicitly.\n" . font-lock-comment-face)
(" ")
("public" . php-keyword)
(" ")
("string" . php-class)
(" ")
("$" . php-variable-sigil)
("fullName" . php-variable-name)
(" {\n ")
("get" . php-builtin)
(" ")
("=" . php-assignment-op)
(">" . 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))
8 changes: 6 additions & 2 deletions tests/php-mode-test.el
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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))
Expand Down

0 comments on commit 5722ecd

Please sign in to comment.