diff --git a/lisp/php-mode.el b/lisp/php-mode.el index 1b88a8a7..7521cd17 100644 --- a/lisp/php-mode.el +++ b/lisp/php-mode.el @@ -318,6 +318,12 @@ In that case set to `NIL'." :tag "PHP Mode Enable Project Local Variable" :type 'boolean) +(defcustom php-mode-use-php7-syntax-table nil + "When set to `T', use a syntax table compatible with PHP 7." + :group 'php-mode + :tag "PHP Mode Enable Project Local Variable" + :type 'boolean) + (defconst php-mode-cc-vertion (eval-when-compile c-version)) @@ -979,18 +985,45 @@ this ^ lineup" (string-match "\\_<.+?\\_>" heredoc-start) (concat "^\\s-*\\(" (match-string 0 heredoc-start) "\\)\\W")) +(defvar php-syntax-propertize-functions + '(php-syntax-propertize-heredoc + php-syntax-propertize-hash-line-comment + php-syntax-propertize-quotes-in-comment) + "Syntax propertize functions for PHP script.") + (defun php-syntax-propertize-function (start end) "Apply propertize rules from START to END." - (goto-char start) + (dolist (propertizer php-syntax-propertize-functions) + (goto-char start) + (funcall propertizer start end))) + +(defun php-syntax-propertize-heredoc (_start end) + "Apply propertize Heredoc and Nowdoc from START to END." (while (and (< (point) end) (re-search-forward php-heredoc-start-re end t)) - (php-heredoc-syntax)) - (goto-char start) + (php-heredoc-syntax))) + +(defun php-syntax-propertize-quotes-in-comment (_start end) + "Apply propertize quotes (' and \") from START to END." (while (re-search-forward "['\"]" end t) (when (php-in-comment-p) (c-put-char-property (match-beginning 0) 'syntax-table (string-to-syntax "_"))))) +(defun php-syntax-propertize-hash-line-comment (_start end) + "Apply propertize # comment (without PHP8 Attributes) from START to END." + (unless php-mode-use-php7-syntax-table + (let (line-end in-last-line) + (while (and (< (point) (min end (point-max))) + (not in-last-line)) + (setq line-end (line-end-position)) + (when (and (search-forward "#" line-end t) + (not (php-in-string-or-comment-p)) + (not (looking-at "[[]"))) + (c-put-char-property (1- (point)) 'syntax-table (string-to-syntax "< b"))) + (move-beginning-of-line 2) + (setq in-last-line (>= line-end (point))))))) + (defun php-heredoc-syntax () "Mark the boundaries of searched heredoc." (goto-char (match-beginning 0)) @@ -1121,7 +1154,6 @@ After setting the stylevars run hooks according to STYLENAME (modify-syntax-entry ?_ "_" table) (modify-syntax-entry ?` "\"" table) (modify-syntax-entry ?\" "\"" table) - (modify-syntax-entry ?# "< b" table) (modify-syntax-entry ?\n "> b" table) (modify-syntax-entry ?$ "_" table) table)) @@ -1151,7 +1183,7 @@ After setting the stylevars run hooks according to STYLENAME (setq-local comment-start "// ") (setq-local comment-start-skip (eval-when-compile - (rx (group (or (: "#") + (rx (group (or (: "#" (not (any "["))) (: "/" (+ "/")) (: "/*"))) (* (syntax whitespace))))) @@ -1175,6 +1207,9 @@ After setting the stylevars run hooks according to STYLENAME ;; PHP vars are case-sensitive (setq case-fold-search t) + (when php-mode-use-php7-syntax-table + (modify-syntax-entry ?# "< b" php-mode-syntax-table)) + (when php-mode-enable-project-local-variable (add-hook 'hack-local-variables-hook #'php-mode-set-local-variable-delay t t)) diff --git a/tests/8.0/attribute/class.php b/tests/8.0/attribute/class.php new file mode 100644 index 00000000..4f2bf76e --- /dev/null +++ b/tests/8.0/attribute/class.php @@ -0,0 +1,22 @@ +> +#[ExampleAttribute] function f1() { } -<> -<> -<> +#[WithoutArgument] +#[SingleArgument(0)] +#[FewArguments('Hello', 'World')] function foo() {} -<><><> +#[WithoutArgument]#[SingleArgument(0)]#[FewArguments('Hello', 'World')] function bar() {} diff --git a/tests/8.0/attribute/function.php.faces b/tests/8.0/attribute/function.php.faces new file mode 100644 index 00000000..da2aea6c --- /dev/null +++ b/tests/8.0/attribute/function.php.faces @@ -0,0 +1,43 @@ +;; -*- mode: emacs-lisp -*- +(("