Skip to content

Commit b7dfa65

Browse files
authored
Merge pull request #647 from emacs-php/feature/support-php8-syntax-table
Support PHP8 syntax table for supporting #[Attributes]
2 parents c526aa0 + 8044ded commit b7dfa65

File tree

9 files changed

+231
-11
lines changed

9 files changed

+231
-11
lines changed

lisp/php-mode.el

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,12 @@ In that case set to `NIL'."
318318
:tag "PHP Mode Enable Project Local Variable"
319319
:type 'boolean)
320320

321+
(defcustom php-mode-use-php7-syntax-table nil
322+
"When set to `T', use a syntax table compatible with PHP 7."
323+
:group 'php-mode
324+
:tag "PHP Mode Enable Project Local Variable"
325+
:type 'boolean)
326+
321327
(defconst php-mode-cc-vertion
322328
(eval-when-compile c-version))
323329

@@ -979,18 +985,45 @@ this ^ lineup"
979985
(string-match "\\_<.+?\\_>" heredoc-start)
980986
(concat "^\\s-*\\(" (match-string 0 heredoc-start) "\\)\\W"))
981987

988+
(defvar php-syntax-propertize-functions
989+
'(php-syntax-propertize-heredoc
990+
php-syntax-propertize-hash-line-comment
991+
php-syntax-propertize-quotes-in-comment)
992+
"Syntax propertize functions for PHP script.")
993+
982994
(defun php-syntax-propertize-function (start end)
983995
"Apply propertize rules from START to END."
984-
(goto-char start)
996+
(dolist (propertizer php-syntax-propertize-functions)
997+
(goto-char start)
998+
(funcall propertizer start end)))
999+
1000+
(defun php-syntax-propertize-heredoc (_start end)
1001+
"Apply propertize Heredoc and Nowdoc from START to END."
9851002
(while (and (< (point) end)
9861003
(re-search-forward php-heredoc-start-re end t))
987-
(php-heredoc-syntax))
988-
(goto-char start)
1004+
(php-heredoc-syntax)))
1005+
1006+
(defun php-syntax-propertize-quotes-in-comment (_start end)
1007+
"Apply propertize quotes (' and \") from START to END."
9891008
(while (re-search-forward "['\"]" end t)
9901009
(when (php-in-comment-p)
9911010
(c-put-char-property (match-beginning 0)
9921011
'syntax-table (string-to-syntax "_")))))
9931012

1013+
(defun php-syntax-propertize-hash-line-comment (_start end)
1014+
"Apply propertize # comment (without PHP8 Attributes) from START to END."
1015+
(unless php-mode-use-php7-syntax-table
1016+
(let (line-end in-last-line)
1017+
(while (and (< (point) (min end (point-max)))
1018+
(not in-last-line))
1019+
(setq line-end (line-end-position))
1020+
(when (and (search-forward "#" line-end t)
1021+
(not (php-in-string-or-comment-p))
1022+
(not (looking-at "[[]")))
1023+
(c-put-char-property (1- (point)) 'syntax-table (string-to-syntax "< b")))
1024+
(move-beginning-of-line 2)
1025+
(setq in-last-line (>= line-end (point)))))))
1026+
9941027
(defun php-heredoc-syntax ()
9951028
"Mark the boundaries of searched heredoc."
9961029
(goto-char (match-beginning 0))
@@ -1121,7 +1154,6 @@ After setting the stylevars run hooks according to STYLENAME
11211154
(modify-syntax-entry ?_ "_" table)
11221155
(modify-syntax-entry ?` "\"" table)
11231156
(modify-syntax-entry ?\" "\"" table)
1124-
(modify-syntax-entry ?# "< b" table)
11251157
(modify-syntax-entry ?\n "> b" table)
11261158
(modify-syntax-entry ?$ "_" table)
11271159
table))
@@ -1151,7 +1183,7 @@ After setting the stylevars run hooks according to STYLENAME
11511183
(setq-local comment-start "// ")
11521184
(setq-local comment-start-skip
11531185
(eval-when-compile
1154-
(rx (group (or (: "#")
1186+
(rx (group (or (: "#" (not (any "[")))
11551187
(: "/" (+ "/"))
11561188
(: "/*")))
11571189
(* (syntax whitespace)))))
@@ -1175,6 +1207,9 @@ After setting the stylevars run hooks according to STYLENAME
11751207
;; PHP vars are case-sensitive
11761208
(setq case-fold-search t)
11771209

1210+
(when php-mode-use-php7-syntax-table
1211+
(modify-syntax-entry ?# "< b" php-mode-syntax-table))
1212+
11781213
(when php-mode-enable-project-local-variable
11791214
(add-hook 'hack-local-variables-hook #'php-mode-set-local-variable-delay t t))
11801215

tests/8.0/attribute/class.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
# Comment
4+
5+
#[ExampleAttribute]
6+
#[Attr1, Attr2]
7+
class Klass
8+
{
9+
#[ExampleAttribute]
10+
function f1() { }
11+
12+
#[WithoutArgument]
13+
#[SingleArgument(0)]
14+
#[FewArguments('Hello', 'World')]
15+
function foo() {}
16+
17+
#[WithoutArgument] #[SingleArgument(0)] #[FewArguments('Hello', 'World')]
18+
function bar() {}
19+
20+
#[Attr2("foo"), Attr2("bar")]
21+
function buz() {}
22+
}

tests/8.0/attribute/class.php.faces

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
;; -*- mode: emacs-lisp -*-
2+
(("<?php" . php-php-tag)
3+
("
4+
5+
")
6+
("# " . font-lock-comment-delimiter-face)
7+
("Comment
8+
" . font-lock-comment-face)
9+
("
10+
#[ExampleAttribute]
11+
#[Attr1, Attr2]
12+
")
13+
("class" . php-class-declaration)
14+
(" ")
15+
("Klass" . font-lock-type-face)
16+
("
17+
{
18+
#[ExampleAttribute]
19+
")
20+
("function" . php-keyword)
21+
(" ")
22+
("f1" . php-function-name)
23+
("() { }
24+
25+
#[WithoutArgument]
26+
#[")
27+
("SingleArgument" . php-function-call)
28+
("(0)]
29+
#[")
30+
("FewArguments" . php-function-call)
31+
("(")
32+
("'Hello'" . php-string)
33+
(", ")
34+
("'World'" . php-string)
35+
(")]
36+
")
37+
("function" . php-keyword)
38+
(" ")
39+
("foo" . php-function-name)
40+
("() {}
41+
42+
#[WithoutArgument] #[")
43+
("SingleArgument" . php-function-call)
44+
("(0)] #[")
45+
("FewArguments" . php-function-call)
46+
("(")
47+
("'Hello'" . php-string)
48+
(", ")
49+
("'World'" . php-string)
50+
(")]
51+
")
52+
("function" . php-keyword)
53+
(" ")
54+
("bar" . php-function-name)
55+
("() {}
56+
57+
#[")
58+
("Attr2" . php-function-call)
59+
("(")
60+
("\"foo\"" . php-string)
61+
("), ")
62+
("Attr2" . php-function-call)
63+
("(")
64+
("\"bar\"" . php-string)
65+
(")]
66+
")
67+
("function" . php-keyword)
68+
(" ")
69+
("buz" . php-function-name)
70+
("() {}
71+
}
72+
"))

tests/8.0/attribute/function.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
<?php
22

3-
<<ExampleAttribute>>
3+
#[ExampleAttribute]
44
function f1() { }
55

6-
<<WithoutArgument>>
7-
<<SingleArgument(0)>>
8-
<<FewArguments('Hello', 'World')>>
6+
#[WithoutArgument]
7+
#[SingleArgument(0)]
8+
#[FewArguments('Hello', 'World')]
99
function foo() {}
1010

11-
<<WithoutArgument>><<SingleArgument(0)>><<FewArguments('Hello', 'World')>>
11+
#[WithoutArgument]#[SingleArgument(0)]#[FewArguments('Hello', 'World')]
1212
function bar() {}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
;; -*- mode: emacs-lisp -*-
2+
(("<?php" . php-php-tag)
3+
("
4+
5+
#[ExampleAttribute]
6+
")
7+
("function" . php-keyword)
8+
(" ")
9+
("f1" . php-function-name)
10+
("() { }
11+
12+
#[WithoutArgument]
13+
#[")
14+
("SingleArgument" . php-function-call)
15+
("(0)]
16+
#[")
17+
("FewArguments" . php-function-call)
18+
("(")
19+
("'Hello'" . php-string)
20+
(", ")
21+
("'World'" . php-string)
22+
(")]
23+
")
24+
("function" . php-keyword)
25+
(" ")
26+
("foo" . php-function-name)
27+
("() {}
28+
29+
#[WithoutArgument]#[")
30+
("SingleArgument" . php-function-call)
31+
("(0)]#[")
32+
("FewArguments" . php-function-call)
33+
("(")
34+
("'Hello'" . php-string)
35+
(", ")
36+
("'World'" . php-string)
37+
(")]
38+
")
39+
("function" . php-keyword)
40+
(" ")
41+
("bar" . php-function-name)
42+
("() {}
43+
"))

tests/8.0/attribute/function2.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
#[
4+
Deprecated
5+
]
6+
function f($arg1,
7+
#[Deprecated] $arg2){}
8+
#Deprecated
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
;; -*- mode: emacs-lisp -*-
2+
(("<?php" . php-php-tag)
3+
("
4+
5+
#[
6+
Deprecated
7+
]
8+
")
9+
("function" . php-keyword)
10+
(" ")
11+
("f" . php-function-name)
12+
("(")
13+
("$" . php-variable-sigil)
14+
("arg1" . php-variable-name)
15+
(",
16+
#[Deprecated] ")
17+
("$" . php-variable-sigil)
18+
("arg2" . php-variable-name)
19+
("){}
20+
")
21+
("#D" . font-lock-comment-delimiter-face)
22+
("eprecated
23+
" . font-lock-comment-face))

tests/8.1/enum.php.faces

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,4 @@
8282
};
8383
}
8484
}
85-
"))
85+
"))

tests/php-mode-test.el

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,12 @@ Meant for `php-mode-test-issue-503'."
654654
(with-php-mode-test ("7.4/arrow-function.php" :faces t))
655655
(with-php-mode-test ("7.4/typed-property.php" :faces t)))
656656

657+
(ert-deftest php-mode-test-php80 ()
658+
"Test highlighting language constructs added in PHP 8.0."
659+
(with-php-mode-test ("8.0/attribute/class.php" :faces t))
660+
(with-php-mode-test ("8.0/attribute/function.php" :faces t))
661+
(with-php-mode-test ("8.0/attribute/function2.php" :faces t)))
662+
657663
(ert-deftest php-mode-test-php81 ()
658664
"Test highlighting language constructs added in PHP 8.1."
659665
(with-php-mode-test ("8.1/enum.php" :faces t)))
@@ -678,4 +684,15 @@ Meant for `php-mode-test-issue-503'."
678684
(with-php-mode-test ("lang/errorcontrol.php" :faces t))
679685
(with-php-mode-test ("lang/magical-constants/echo.php" :faces t)))
680686

687+
;; For developers: How to make .faces list file.
688+
;;
689+
;; 1. Press `M-x eval-buffer' in this file bufffer.
690+
;; 2. Copy follows code snippet:
691+
;; (setq x (php-mode-test--buffer-face-list (current-buffer)))
692+
;; 3. Visit target buffer of testing PHP file.
693+
;; 4. Press `M-:' (or `M-x eval-expression') and yank killed the code snippet.
694+
;; 5. Press `M-x ielm' and input `x' and RET key.
695+
;; 6. Kill output list and yank list to .faces file.
696+
;; 7. Execute `make test' in shell.
697+
681698
;;; php-mode-test.el ends here

0 commit comments

Comments
 (0)