mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 17:24:23 +00:00
Add support for PHP 8.5 in 'php-ts-mode.el'
* lisp/progmodes/php-ts-mode.el: Doc string update. (php-ts-mode--language-source-alist): PHP grammar update. (php-ts-mode-find-sibling-rules): Doc string fix. (php-ts-mode--parent-html-heuristic): Handled the case where there is no HTML between two blocks of PHP code. (php-ts-mode--array-element-heuristic): Fix typo. (php-ts-mode--pipe-heuristic): New function that handle PHP's new pipe operator. (php-ts-mode--indent-styles): Removed commented code. More accurate indentation of ‘member_call_expression’. Use of new function to handle pipe operator indentation. New rule for indenting ‘property_hook_list’. (php-ts-mode--test-yield-from-p): New predicate to check whether the 'yield from' keyword is supported by the PHP grammar. (php-ts-mode--test-pipe-p): New predicate to check whether the ‘pipe’ operator is supported by the PHP grammar. (php-ts-mode--keywords): Use the new predicate 'php-ts-mode--test-yield-from-p'. Now it is a var instead of a const. (php-ts-mode--operators): Use the new predicate 'php-ts-mode--test-pipe-p'. Now it is a var instead of a const. (php-ts-mode--font-lock-settings): New rules for 'nullsafe_member_access_expression', 'callable' primitive type. New rule for the 'php_end_tag' if supported by the grammar. More precise rules for 'scoped_call_expression' and 'member_call_expression'. (php-ts-mode--inferior-php-process): Removed this unnecessary variable. (inferior-php-ts-mode-startup): Removed the use of 'php-ts-mode--inferior-php-process'. (php-ts-mode-inferior--write-history): Removed the use of 'php-ts-mode--inferior-php-process'. (Bug#79339)
This commit is contained in:
parent
d02181e39f
commit
abfd8a454a
1 changed files with 105 additions and 63 deletions
|
|
@ -30,7 +30,7 @@
|
|||
;; - tree-sitter-jsdoc: v0.23.2
|
||||
;; - tree-sitter-javascript: v0.23.1-2-g108b2d4
|
||||
;; - tree-sitter-html: v0.23.2-1-gd9219ad
|
||||
;; - tree-sitter-php: v0.23.12
|
||||
;; - tree-sitter-php: v0.24.2
|
||||
;;
|
||||
;; We try our best to make builtin modes work with latest grammar
|
||||
;; versions, so a more recent grammar has a good chance to work too.
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
;;; Install treesitter language parsers
|
||||
(defvar php-ts-mode--language-source-alist
|
||||
'((php "https://github.com/tree-sitter/tree-sitter-php"
|
||||
:commit "f7cf7348737d8cff1b13407a0bfedce02ee7b046"
|
||||
:commit "5b5627faaa290d89eb3d01b9bf47c3bb9e797dea"
|
||||
:source-dir "php/src")
|
||||
(phpdoc "https://github.com/claytonrcarter/tree-sitter-phpdoc"
|
||||
:commit "03bb10330704b0b371b044e937d5cc7cd40b4999"))
|
||||
|
|
@ -238,8 +238,8 @@ Useful for testing code against multiple simultaneous requests."
|
|||
(defcustom php-ts-mode-find-sibling-rules
|
||||
(list (list (rx "src/" (group (+ not-newline) "/") (group (+ (not "/"))) ".php") "tests/\\1\\2Test.php")
|
||||
(list (rx "tests/" (group (+ not-newline) "/") (group (+ (not "/"))) "Test.php") "src/\\1\\2.php"))
|
||||
"Rules for finding sibling files. See `find-sibling-rules' for the
|
||||
form of the value.
|
||||
"Rules for finding sibling files.
|
||||
See `find-sibling-rules' for the form of the value.
|
||||
As a default, the rules try to find the corresponding test of the
|
||||
current source file and vice versa. Source files are assumed to be in
|
||||
src/, and tests of in tests/. Many frameworks have a folder
|
||||
|
|
@ -587,7 +587,11 @@ the current line."
|
|||
((eq php-ts-mode-html-relative-indent 'ignore) (line-beginning-position))
|
||||
((search-backward "</html>" (treesit-node-start parent) t 1) (line-beginning-position))
|
||||
((null node) (apply (alist-get 'prev-sibling treesit-simple-indent-presets) node parent bol nil))
|
||||
(t (when-let* ((html-node (treesit-search-forward node "text" t))
|
||||
(t (when-let* ((html-node (treesit-search-forward
|
||||
node
|
||||
(lambda (node)
|
||||
(equal (treesit-node-type node) "text"))
|
||||
t))
|
||||
(end-html (treesit-node-end html-node)))
|
||||
(goto-char end-html)
|
||||
;; go to the start of the last tag
|
||||
|
|
@ -622,7 +626,7 @@ characters of the current line."
|
|||
(defun php-ts-mode--anchor-first-sibling (_node parent _bol &rest _)
|
||||
"Return the start of the first child of a sibling of PARENT.
|
||||
|
||||
If the fist sibling of PARENT and the first child of the sibling are
|
||||
If the first sibling of PARENT and the first child of the sibling are
|
||||
on the same line return the start position of the first child of the
|
||||
sibling. Otherwise return the start of the first sibling.
|
||||
PARENT is NODE's parent, BOL is the beginning of non-whitespace
|
||||
|
|
@ -663,12 +667,27 @@ characters of the current line."
|
|||
(treesit-node-prev-sibling prev-sibling)))))
|
||||
(treesit-node-start prev-sibling)))
|
||||
|
||||
(defun php-ts-mode--pipe-heuristic (node parent _bol &rest _)
|
||||
"Return the start of the previous pipe to the current pipe NODE.
|
||||
Otherwise return the beginning of line of the previous non pipe NODE.
|
||||
|
||||
PARENT is NODE's parent, BOL is the beginning of non-whitespace
|
||||
characters of the current line."
|
||||
(save-excursion
|
||||
(let* ((parent-start (treesit-node-start parent))
|
||||
(node-start (treesit-node-start node))
|
||||
(bound (progn
|
||||
(goto-char parent-start)
|
||||
(beginning-of-line 1)
|
||||
(point))))
|
||||
(goto-char node-start)
|
||||
(let ((previous-pipe (search-backward "|>" bound t nil)))
|
||||
(or previous-pipe (+ bound php-ts-mode-indent-offset))))))
|
||||
|
||||
(defun php-ts-mode--indent-styles ()
|
||||
"Indent rules supported by `php-ts-mode'."
|
||||
(let ((common
|
||||
`(;; Handle indentation relatives to HTML.
|
||||
;; ((parent-is "program") php-ts-mode--parent-html-heuristic 0)
|
||||
;; ((parent-is "text_interpolation") php-ts-mode--parent-html-heuristic 0)
|
||||
((or (parent-is "program")
|
||||
(parent-is "text_interpolation"))
|
||||
php-ts-mode--parent-html-heuristic 0)
|
||||
|
|
@ -709,12 +728,14 @@ characters of the current line."
|
|||
(parent-is "use_list"))
|
||||
parent-bol php-ts-mode-indent-offset)
|
||||
((parent-is "function_definition") parent-bol 0)
|
||||
((parent-is "member_call_expression") first-sibling php-ts-mode-indent-offset)
|
||||
((parent-is "member_call_expression") parent-bol php-ts-mode-indent-offset)
|
||||
((parent-is "conditional_expression") parent-bol php-ts-mode-indent-offset)
|
||||
((parent-is "assignment_expression") parent-bol php-ts-mode-indent-offset)
|
||||
((parent-is "array_creation_expression") parent-bol php-ts-mode-indent-offset)
|
||||
((parent-is "attribute_group") parent-bol php-ts-mode-indent-offset)
|
||||
((parent-is "parenthesized_expression") first-sibling 1)
|
||||
|
||||
((node-is "|>") php-ts-mode--pipe-heuristic 0)
|
||||
((parent-is "binary_expression") parent 0)
|
||||
((or (parent-is "arguments")
|
||||
(parent-is "formal_parameters"))
|
||||
|
|
@ -742,6 +763,7 @@ characters of the current line."
|
|||
((parent-is "declaration_list") column-0 php-ts-mode-indent-offset)
|
||||
|
||||
((parent-is "initializer_list") parent-bol php-ts-mode-indent-offset)
|
||||
((parent-is "property_hook_list") parent-bol php-ts-mode-indent-offset)
|
||||
|
||||
;; Statement in {} blocks.
|
||||
((or (and (or (parent-is "compound_statement")
|
||||
|
|
@ -827,24 +849,66 @@ characters of the current line."
|
|||
|
||||
;;; Font-lock
|
||||
|
||||
(defconst php-ts-mode--keywords
|
||||
'("abstract" "and" "array" "as" "break" "callable" "case" "catch"
|
||||
"class" "clone" "const" "continue" "declare" "default" "do" "echo"
|
||||
"else" "elseif" "enddeclare" "endfor" "endforeach" "endif"
|
||||
"endswitch" "endwhile" "enum" "exit" "extends" "final" "finally" "fn"
|
||||
"for" "foreach" "from" "function" "global" "goto" "if" "implements"
|
||||
"include" "include_once" "instanceof" "insteadof" "interface"
|
||||
"list" "match" "namespace" "new" "null" "or" "print" "private"
|
||||
"protected" "public" "readonly" "require" "require_once" "return"
|
||||
"static" "switch" "throw" "trait" "try" "unset" "use" "while" "xor"
|
||||
"yield")
|
||||
(defun php-ts-mode--test-namespace-name-as-prefix-p ()
|
||||
"Return t if namespace_name_as_prefix is a named node, nil otherwise."
|
||||
(treesit-query-valid-p 'php "(namespace_name_as_prefix)"))
|
||||
|
||||
(defun php-ts-mode--test-namespace-aliasing-clause-p ()
|
||||
"Return t if namespace_aliasing_clause is a named node, nil otherwise."
|
||||
(treesit-query-valid-p 'php "(namespace_aliasing_clause)"))
|
||||
|
||||
(defun php-ts-mode--test-namespace-use-group-clause-p ()
|
||||
"Return t if namespace_use_group_clause is a named node, nil otherwise."
|
||||
(treesit-query-valid-p 'php "(namespace_use_group_clause)"))
|
||||
|
||||
(defun php-ts-mode--test-visibility-modifier-operation-p ()
|
||||
"Return t if (visibility_modifier (operation)) is defined, nil otherwise."
|
||||
(treesit-query-valid-p 'php "(visibility_modifier (operation))"))
|
||||
|
||||
(defun php-ts-mode--test-property-hook-p ()
|
||||
"Return t if property_hook is a named node, nil otherwise."
|
||||
(treesit-query-valid-p 'php "(property_hook)"))
|
||||
|
||||
(defun php-ts-mode--test-relative-name-p ()
|
||||
"Return t if relative_name is a named node, nil otherwise."
|
||||
(treesit-query-valid-p 'php "(relative_name)"))
|
||||
|
||||
(defun php-ts-mode--test-php-end-tag-p ()
|
||||
"Return t if php_end_tag is a named node, nil otherwise."
|
||||
(treesit-query-valid-p 'php "(php_end_tag)"))
|
||||
|
||||
(defun php-ts-mode--test-yield-from-p ()
|
||||
"Return t if the keyword `yield from' is defined, nil otherwise."
|
||||
(treesit-query-valid-p 'php '("yield from")))
|
||||
|
||||
(defun php-ts-mode--test-pipe-p ()
|
||||
"Return t if the operator '|>' is defined, nil otherwise."
|
||||
(treesit-query-valid-p 'php '("|>")))
|
||||
|
||||
(defvar php-ts-mode--keywords
|
||||
(when (treesit-available-p)
|
||||
(append
|
||||
'("abstract" "and" "array" "as" "break" "case" "catch"
|
||||
"class" "clone" "const" "continue" "declare" "default" "do" "echo"
|
||||
"else" "elseif" "enddeclare" "endfor" "endforeach" "endif"
|
||||
"endswitch" "endwhile" "enum" "exit" "extends" "final" "finally" "fn"
|
||||
"for" "foreach" "function" "global" "goto" "if" "implements"
|
||||
"include" "include_once" "instanceof" "insteadof" "interface"
|
||||
"list" "match" "namespace" "new" "null" "or" "print" "private"
|
||||
"protected" "public" "readonly" "require" "require_once" "return"
|
||||
"static" "switch" "throw" "trait" "try" "unset" "use" "while" "xor"
|
||||
"yield")
|
||||
(if (php-ts-mode--test-yield-from-p) '("yield from") '("from"))))
|
||||
"PHP keywords for tree-sitter font-locking.")
|
||||
|
||||
(defconst php-ts-mode--operators
|
||||
'("--" "**=" "*=" "/=" "%=" "+=" "-=" ".=" "<<=" ">>=" "&=" "^="
|
||||
"|=" "??" "??=" "||" "&&" "|" "^" "&" "==" "!=" "<>" "===" "!=="
|
||||
"<" ">" "<=" ">=" "<=>" "<<" ">>" "+" "-" "." "*" "**" "/" "%"
|
||||
"->" "?->" "...")
|
||||
(defvar php-ts-mode--operators
|
||||
(when (treesit-available-p)
|
||||
(append
|
||||
'("--" "**=" "*=" "/=" "%=" "+=" "-=" ".=" "<<=" ">>=" "&=" "^="
|
||||
"|=" "??" "??=" "||" "&&" "|" "^" "&" "==" "!=" "<>" "===" "!=="
|
||||
"<" ">" "<=" ">=" "<=>" "<<" ">>" "+" "-" "." "*" "**" "/" "%"
|
||||
"->" "?->" "...")
|
||||
(when (php-ts-mode--test-pipe-p) '("|>"))))
|
||||
"PHP operators for tree-sitter font-locking.")
|
||||
|
||||
(defconst php-ts-mode--predefined-constant
|
||||
|
|
@ -890,30 +954,6 @@ characters of the current line."
|
|||
("::" . ?∷))
|
||||
"Value for `prettify-symbols-alist' in `php-ts-mode'.")
|
||||
|
||||
(defun php-ts-mode--test-namespace-name-as-prefix-p ()
|
||||
"Return t if namespace_name_as_prefix is a named node, nil otherwise."
|
||||
(treesit-query-valid-p 'php "(namespace_name_as_prefix)"))
|
||||
|
||||
(defun php-ts-mode--test-namespace-aliasing-clause-p ()
|
||||
"Return t if namespace_aliasing_clause is a named node, nil otherwise."
|
||||
(treesit-query-valid-p 'php "(namespace_aliasing_clause)"))
|
||||
|
||||
(defun php-ts-mode--test-namespace-use-group-clause-p ()
|
||||
"Return t if namespace_use_group_clause is a named node, nil otherwise."
|
||||
(treesit-query-valid-p 'php "(namespace_use_group_clause)"))
|
||||
|
||||
(defun php-ts-mode--test-visibility-modifier-operation-p ()
|
||||
"Return t if (visibility_modifier (operation)) is defined, nil otherwise."
|
||||
(treesit-query-valid-p 'php "(visibility_modifier (operation))"))
|
||||
|
||||
(defun php-ts-mode--test-property-hook-p ()
|
||||
"Return t if property_hook is a named node, nil otherwise."
|
||||
(treesit-query-valid-p 'php "(property_hook)"))
|
||||
|
||||
(defun php-ts-mode--test-relative-name-p ()
|
||||
"Return t if relative_name is a named node, nil otherwise."
|
||||
(treesit-query-valid-p 'php "(relative_name)"))
|
||||
|
||||
(defun php-ts-mode--font-lock-settings ()
|
||||
"Tree-sitter font-lock settings."
|
||||
(treesit-font-lock-rules
|
||||
|
|
@ -974,6 +1014,7 @@ characters of the current line."
|
|||
name: (_) @font-lock-variable-name-face)
|
||||
(scoped_property_access_expression
|
||||
scope: (name) @font-lock-constant-face)
|
||||
(nullsafe_member_access_expression (name) @font-lock-variable-name-face)
|
||||
(error_suppression_expression (name) @font-lock-property-name-face))
|
||||
|
||||
:language 'php
|
||||
|
|
@ -1002,6 +1043,8 @@ characters of the current line."
|
|||
(union_type) @font-lock-type-face
|
||||
(bottom_type) @font-lock-type-face
|
||||
(primitive_type) @font-lock-type-face
|
||||
((primitive_type) @font-lock-keyword-face
|
||||
(:equal "callable" @font-lock-keyword-face))
|
||||
(cast_type) @font-lock-type-face
|
||||
(named_type) @font-lock-type-face
|
||||
(optional_type) @font-lock-type-face)
|
||||
|
|
@ -1010,7 +1053,9 @@ characters of the current line."
|
|||
:feature 'definition
|
||||
:override t
|
||||
`((php_tag) @font-lock-preprocessor-face
|
||||
("?>") @font-lock-preprocessor-face
|
||||
,@(if (php-ts-mode--test-php-end-tag-p)
|
||||
'((php_end_tag) @font-lock-preprocessor-face)
|
||||
'(("?>") @font-lock-preprocessor-face))
|
||||
;; Highlights identifiers in declarations.
|
||||
(class_declaration
|
||||
name: (_) @font-lock-type-face)
|
||||
|
|
@ -1067,9 +1112,9 @@ characters of the current line."
|
|||
'((function_call_expression
|
||||
function: (name) @font-lock-function-call-face)
|
||||
(scoped_call_expression
|
||||
name: (_) @font-lock-function-call-face)
|
||||
name: (name) @font-lock-function-call-face)
|
||||
(member_call_expression
|
||||
name: (_) @font-lock-function-call-face)
|
||||
name: (name) @font-lock-function-call-face)
|
||||
(nullsafe_member_call_expression
|
||||
name: (_) @font-lock-function-call-face))
|
||||
|
||||
|
|
@ -1792,9 +1837,6 @@ The optional TYPE can be the symbol \"port\", \"hostname\", \"document-root\",
|
|||
|
||||
;;; Inferior PHP process.
|
||||
|
||||
(defvar php-ts-mode--inferior-php-process nil
|
||||
"The PHP inferior process associated to `php-ts-mode-inferior-php-buffer'.")
|
||||
|
||||
;;;###autoload
|
||||
(defun run-php (&optional cmd config)
|
||||
"Run an PHP interpreter as a inferior process.
|
||||
|
|
@ -1829,8 +1871,7 @@ Optional CONFIG, if supplied, is the php.ini file to use."
|
|||
"Start an inferior PHP process with command CMD and init file CONFIG.
|
||||
CMD is the command to run. Optional CONFIG, if supplied, is the php.ini
|
||||
file to use."
|
||||
(setq-local php-ts-mode--inferior-php-process
|
||||
(apply #'make-comint-in-buffer
|
||||
(apply #'make-comint-in-buffer
|
||||
(string-replace "*" "" php-ts-mode-inferior-php-buffer)
|
||||
php-ts-mode-inferior-php-buffer
|
||||
cmd
|
||||
|
|
@ -1840,7 +1881,7 @@ file to use."
|
|||
(list
|
||||
(when config
|
||||
(format "-c %s" config))
|
||||
"-a"))))
|
||||
"-a")))
|
||||
(add-hook 'comint-preoutput-filter-functions
|
||||
(lambda (string)
|
||||
(let ((prompt (concat php-ts-mode--inferior-prompt " ")))
|
||||
|
|
@ -1865,7 +1906,7 @@ file to use."
|
|||
nil t)
|
||||
(when php-ts-mode-inferior-history
|
||||
(set-process-sentinel
|
||||
(get-buffer-process php-ts-mode-inferior-php-buffer)
|
||||
(get-buffer-process php-ts-mode-inferior-php-buffer)
|
||||
'php-ts-mode-inferior--write-history)))
|
||||
|
||||
;; taken and adapted from lua-ts-mode
|
||||
|
|
@ -1880,14 +1921,15 @@ file to use."
|
|||
(defun php-ts-mode-send-region (beg end)
|
||||
"Send region between BEG and END to the inferior PHP process."
|
||||
(interactive "r")
|
||||
(if (buffer-live-p php-ts-mode--inferior-php-process)
|
||||
(if-let* ((php-process
|
||||
(get-buffer-process php-ts-mode-inferior-php-buffer)))
|
||||
(progn
|
||||
(php-ts-mode-show-process-buffer)
|
||||
(comint-send-string php-ts-mode--inferior-php-process "\n")
|
||||
(comint-send-string php-process "\n")
|
||||
(comint-send-string
|
||||
php-ts-mode--inferior-php-process
|
||||
php-process
|
||||
(buffer-substring-no-properties beg end))
|
||||
(comint-send-string php-ts-mode--inferior-php-process "\n"))
|
||||
(comint-send-string php-process "\n"))
|
||||
(message "Invoke run-php first!")))
|
||||
|
||||
(defun php-ts-mode-send-buffer ()
|
||||
|
|
|
|||
Loading…
Reference in a new issue