Skip to content

Commit c77eb10

Browse files
authored
Merge pull request #797 from emacs-php/feature/php84-property-hooks
Support PHP 8.4 property-hooks
2 parents 69e9c16 + 5722ecd commit c77eb10

File tree

4 files changed

+188
-3
lines changed

4 files changed

+188
-3
lines changed

lisp/php-mode.el

+3-1
Original file line numberDiff line numberDiff line change
@@ -1519,7 +1519,9 @@ for \\[find-tag] (which see)."
15191519
;; Not operator (!) is defined in "before cc-mode" section above.
15201520
("\\(&&\\|||\\)" 1 'php-logical-op)
15211521
;; string interpolation ("$var, ${var}, {$var}")
1522-
(php-mode--string-interpolated-variable-font-lock-find 0 nil)))
1522+
(php-mode--string-interpolated-variable-font-lock-find 0 nil)
1523+
(,(rx symbol-start (group (or "get" "set")) (+ (syntax whitespace)) (or "{" "=>"))
1524+
1 'php-builtin)))
15231525
"Detailed highlighting for PHP Mode.")
15241526

15251527
(defvar php-font-lock-keywords php-font-lock-keywords-3

tests/8.4/property-hooks.php

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
class Person
4+
{
5+
// A "virtual" property. It may not be set explicitly.
6+
public string $fullName {
7+
get => $this->firstName . ' ' . $this->lastName;
8+
}
9+
10+
// All write operations go through this hook, and the result is what is written.
11+
// Read access happens normally.
12+
public string $firstName {
13+
set => ucfirst(strtolower($value));
14+
}
15+
16+
// All write operations go through this hook, which has to write to the backing value itself.
17+
// Read access happens normally.
18+
public string $lastName {
19+
set {
20+
if (strlen($value) < 2) {
21+
throw new \InvalidArgumentException('Too short');
22+
}
23+
$this->lastName = $value;
24+
}
25+
}
26+
}
27+
28+
$p = new Person();
29+
30+
$p->firstName = 'peter';
31+
print $p->firstName; // Prints "Peter"
32+
$p->lastName = 'Peterson';
33+
print $p->fullName; // Prints "Peter Peterson"

tests/8.4/property-hooks.php.faces

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
;; -*- mode: emacs-lisp -*-
2+
(("<?php" . php-php-tag)
3+
("\n\n")
4+
("class" . php-class-declaration)
5+
(" ")
6+
("Person" . font-lock-type-face)
7+
("\n{\n ")
8+
("// " . font-lock-comment-delimiter-face)
9+
("A \"virtual\" property. It may not be set explicitly.\n" . font-lock-comment-face)
10+
(" ")
11+
("public" . php-keyword)
12+
(" ")
13+
("string" . php-class)
14+
(" ")
15+
("$" . php-variable-sigil)
16+
("fullName" . php-variable-name)
17+
(" {\n ")
18+
("get" . php-builtin)
19+
(" ")
20+
("=" . php-assignment-op)
21+
(">" . php-comparison-op)
22+
(" ")
23+
("$" . php-this-sigil)
24+
("this" . php-this)
25+
("->" . php-object-op)
26+
("firstName" . php-property-name)
27+
(" . ")
28+
("' '" . php-string)
29+
(" . ")
30+
("$" . php-this-sigil)
31+
("this" . php-this)
32+
("->" . php-object-op)
33+
("lastName" . php-property-name)
34+
(";\n }\n\n ")
35+
("// " . font-lock-comment-delimiter-face)
36+
("All write operations go through this hook, and the result is what is written.\n" . font-lock-comment-face)
37+
(" ")
38+
("// " . font-lock-comment-delimiter-face)
39+
("Read access happens normally.\n" . font-lock-comment-face)
40+
(" ")
41+
("public" . php-keyword)
42+
(" ")
43+
("string" . php-class)
44+
(" ")
45+
("$" . php-variable-sigil)
46+
("firstName" . php-variable-name)
47+
(" {\n ")
48+
("set" . php-builtin)
49+
(" ")
50+
("=" . php-assignment-op)
51+
(">" . php-comparison-op)
52+
(" ")
53+
("ucfirst" . php-function-call-traditional)
54+
("(")
55+
("strtolower" . php-function-call-traditional)
56+
("(")
57+
("$" . php-variable-sigil)
58+
("value" . php-variable-name)
59+
("));\n }\n\n ")
60+
("// " . font-lock-comment-delimiter-face)
61+
("All write operations go through this hook, which has to write to the backing value itself.\n" . font-lock-comment-face)
62+
(" ")
63+
("// " . font-lock-comment-delimiter-face)
64+
("Read access happens normally.\n" . font-lock-comment-face)
65+
(" ")
66+
("public" . php-keyword)
67+
(" ")
68+
("string" . php-class)
69+
(" ")
70+
("$" . php-variable-sigil)
71+
("lastName" . php-variable-name)
72+
(" {\n ")
73+
("set" . php-builtin)
74+
(" {\n ")
75+
("if" . php-keyword)
76+
(" (")
77+
("strlen" . php-function-call-traditional)
78+
("(")
79+
("$" . php-variable-sigil)
80+
("value" . php-variable-name)
81+
(") ")
82+
("<" . php-comparison-op)
83+
(" 2) {\n ")
84+
("throw" . php-keyword)
85+
(" ")
86+
("new" . php-keyword)
87+
(" ")
88+
("\\InvalidArgumentException" . font-lock-type-face)
89+
("(")
90+
("'Too short'" . php-string)
91+
(");\n }\n ")
92+
("$" . php-this-sigil)
93+
("this" . php-this)
94+
("->" . php-object-op)
95+
("lastName" . php-property-name)
96+
(" ")
97+
("=" . php-assignment-op)
98+
(" ")
99+
("$" . php-variable-sigil)
100+
("value" . php-variable-name)
101+
(";\n }\n }\n}\n\n")
102+
("$" . php-variable-sigil)
103+
("p" . php-variable-name)
104+
(" ")
105+
("=" . php-assignment-op)
106+
(" ")
107+
("new" . php-keyword)
108+
(" ")
109+
("Person" . font-lock-type-face)
110+
("();\n\n")
111+
("$" . php-variable-sigil)
112+
("p" . php-variable-name)
113+
("->" . php-object-op)
114+
("firstName" . php-property-name)
115+
(" ")
116+
("=" . php-assignment-op)
117+
(" ")
118+
("'peter'" . php-string)
119+
(";\n")
120+
("print" . php-keyword)
121+
(" ")
122+
("$" . php-variable-sigil)
123+
("p" . php-variable-name)
124+
("->" . php-object-op)
125+
("firstName" . php-property-name)
126+
("; ")
127+
("// " . font-lock-comment-delimiter-face)
128+
("Prints \"Peter\"\n" . font-lock-comment-face)
129+
("$" . php-variable-sigil)
130+
("p" . php-variable-name)
131+
("->" . php-object-op)
132+
("lastName" . php-property-name)
133+
(" ")
134+
("=" . php-assignment-op)
135+
(" ")
136+
("'Peterson'" . php-string)
137+
(";\n")
138+
("print" . php-keyword)
139+
(" ")
140+
("$" . php-variable-sigil)
141+
("p" . php-variable-name)
142+
("->" . php-object-op)
143+
("fullName" . php-property-name)
144+
("; ")
145+
("// " . font-lock-comment-delimiter-face)
146+
("Prints \"Peter Peterson\"\n" . font-lock-comment-face))

tests/php-mode-test.el

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
;;; php-mode-test.el --- Tests for php-mode
1+
;;; php-mode-test.el --- Tests for php-mode -*- lexical-binding: t -*-
22

3-
;; Copyright (C) 2018-2019 Friends of Emacs-PHP development
3+
;; Copyright (C) 2018-2024 Friends of Emacs-PHP development
44
;; Copyright (C) 2013 Daniel Hackney
55
;; 2014, 2015 Eric James Michael Ritz
66

@@ -669,6 +669,10 @@ Meant for `php-mode-test-issue-503'."
669669
(with-php-mode-test ("8.1/enum.php" :faces t))
670670
(with-php-mode-test ("8.1/readonly.php" :faces t)))
671671

672+
(ert-deftest php-mode-test-php84 ()
673+
"Test highlighting language constructs added in PHP 8.4."
674+
(with-php-mode-test ("8.4/property-hooks.php" :faces t)))
675+
672676
(ert-deftest php-mode-test-lang ()
673677
"Test highlighting for language constructs."
674678
(with-php-mode-test ("lang/class/anonymous-class.php" :indent t :magic t :faces t))

0 commit comments

Comments
 (0)