[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/php-mode 56e5b67c06 7/9: Merge pull request #718 from emac
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/php-mode 56e5b67c06 7/9: Merge pull request #718 from emacs-php/feature/flymake-diagnostic-functions |
Date: |
Sat, 5 Nov 2022 19:59:06 -0400 (EDT) |
branch: elpa/php-mode
commit 56e5b67c069d071a948af72abb206e2d736bbf44
Merge: f5c4016bb6 a8a62f39ed
Author: USAMI Kenta <tadsan@pixiv.com>
Commit: GitHub <noreply@github.com>
Merge pull request #718 from emacs-php/feature/flymake-diagnostic-functions
New feature: php-flymake
---
CHANGELOG.md | 6 +++
Makefile | 2 +-
lisp/php-flymake.el | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++
lisp/php-mode.el | 43 ++++++++++++----
lisp/php.el | 8 ++-
5 files changed, 184 insertions(+), 15 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3276c010e6..c4ba92416d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@ All notable changes of the PHP Mode 1.19.1 release series are
documented in this
* **New feature: `php-complete`**
* Add `php-complete-complete-function` to autocomplete function names
([#708])
+ * **New feature: `php-flymake`**
+ * Add `php-flymake` as a flymake backend compatible with Emacs 26 and above
([#718])
* Supports PHPDoc tags and types for static analysis tools ([#710], [#715],
[#716], [#717], thanks to [@takeokunn])
* Please refer to the article below
* PHPStan: [PHPDoc
Types](https://phpstan.org/writing-php-code/phpdoc-types)
@@ -15,6 +17,7 @@ All notable changes of the PHP Mode 1.19.1 release series are
documented in this
* Psalm: [Atomic Type
Reference](https://psalm.dev/docs/annotating_code/type_syntax/atomic_types/)
* Psalm: [Supported
Annotations](https://psalm.dev/docs/annotating_code/supported_annotations/)
* Psalm: [Template
Annotations](https://psalm.dev/docs/annotating_code/templated_annotations/)
+ * Add `php-mode-replace-flymake-diag-function` custom variable and default
activated it ([#718])
### Changed
@@ -24,11 +27,13 @@ All notable changes of the PHP Mode 1.19.1 release series
are documented in this
* Make `php-mode-version` function include a Git tag and revision ([#713])
* Like `"1.23.4-56-xxxxxx"` for example.
* Change `php-phpdoc-type-keywords` to `php-phpdoc-type-names` to avoid
confusion ([#717])
+ * Make `php-flymake-php-init` append to `flymake-allowed-file-name-masks`
only in legacy Flymake ([#718])
### Deprecated
* Make obsolete `php-mode-version-number` contstant variable ([#712])
* `(php-mode-version :as-number t)` is provided for use cases comparing as
versions, but generally SHOULD NOT be dependent on the PHP Mode version.
+ * Make obsolete `php-mode-disable-c-mode-hook` customize variable ([#718])
### Fixed
@@ -44,6 +49,7 @@ All notable changes of the PHP Mode 1.19.1 release series are
documented in this
[#715]: https://github.com/emacs-php/php-mode/pull/715
[#716]: https://github.com/emacs-php/php-mode/pull/716
[#717]: https://github.com/emacs-php/php-mode/pull/717
+[#718]: https://github.com/emacs-php/php-mode/pull/718
## [1.24.1] - 2022-10-08
diff --git a/Makefile b/Makefile
index 97922d2a50..45dc5c44bf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
EMACS ?= emacs
CASK ?= cask
-ELS = lisp/php.el lisp/php-align.el lisp/php-complete.el lisp/php-defs.el
lisp/php-face.el lisp/php-project.el lisp/php-local-manual.el lisp/php-mode.el
lisp/php-mode-debug.el
+ELS = lisp/php.el lisp/php-align.el lisp/php-complete.el lisp/php-defs.el
lisp/php-face.el lisp/php-flymake.el lisp/php-project.el
lisp/php-local-manual.el lisp/php-mode.el lisp/php-mode-debug.el
AUTOLOADS = php-mode-autoloads.el
ELCS = $(ELS:.el=.elc)
diff --git a/lisp/php-flymake.el b/lisp/php-flymake.el
new file mode 100644
index 0000000000..3c71e1a7bb
--- /dev/null
+++ b/lisp/php-flymake.el
@@ -0,0 +1,140 @@
+;;; php-flymake.el --- Flymake backend for PHP -*- lexical-binding: t;
-*-
+
+;; Copyright (C) 2022 Friends of Emacs-PHP development
+
+;; Author: USAMI Kenta <tadsan@zonu.me>
+;; Created: 5 Mar 2022
+;; Version: 1.24.1
+;; Keywords: tools, languages, php
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Flymake backend for PHP.
+
+;;; Code:
+(require 'flymake)
+(require 'cl-lib)
+(eval-when-compile
+ (require 'pcase)
+ (require 'rx))
+
+(defgroup php-flymake nil
+ "Flymake backend for PHP."
+ :tag "PHP Flymake"
+ :group 'php)
+
+(defcustom php-flymake-executable-command-args nil
+ "List of command and arguments for `php -l'."
+ :group 'php-flymake
+ :type '(repeat string)
+ :safe (lambda (v) (and (listp v) (cl-every v #'stringp))))
+
+(defconst php-flymake--diaggnostics-pattern
+ (eval-when-compile
+ (rx bol (? "PHP ")
+ (group (or "Parse" "Fatal")) ;; 1: type, not used
+ " error:" (+ (syntax whitespace))
+ (group (+? any)) ;; 2: msg
+ " in " (group (+? any)) ;; 3: file, not used
+ " on line " (group (+ num)) ;; 4: line
+ eol)))
+
+(defvar-local php-flymake--proc nil)
+
+;;;###autoload
+(defun php-flymake (report-fn &rest args)
+ "Flymake backend for PHP syntax check.
+
+See `flymake-diagnostic-functions' about REPORT-FN and ARGS parameters."
+ (setq-local flymake-proc-allowed-file-name-masks nil)
+ (when (process-live-p php-flymake--proc)
+ (if (plist-get args :interactive)
+ (user-error "There's already a Flymake process running in this buffer")
+ (kill-process php-flymake--proc)))
+ (save-restriction
+ (widen)
+ (cl-multiple-value-bind (use-stdin skip) (php-flymake--buffer-status)
+ (unless skip
+ (setq php-flymake--proc (php-flymake--make-process report-fn
buffer-file-name (current-buffer) use-stdin))
+ (when use-stdin
+ (process-send-region php-flymake--proc (point-min) (point-max)))
+ (process-send-eof php-flymake--proc)))))
+
+(defun php-flymake--buffer-status ()
+ "Return buffer status about \"use STDIN\" and \"Skip diagnostic\"."
+ (let* ((use-stdin (or (null buffer-file-name)
+ (buffer-modified-p (current-buffer))
+ (file-remote-p buffer-file-name)))
+ (skip (and (not use-stdin)
+ (save-excursion (goto-char (point-min)) (looking-at-p
"#!")))))
+ (cl-values use-stdin skip)))
+
+(defun php-flymake--diagnostics (locus source)
+ "Parse output of `php -l' command in SOURCE buffer. LOCUS means filename."
+ (unless (eval-when-compile (and (fboundp 'flymake-make-diagnostic)
+ (fboundp 'flymake-diag-region)))
+ (error "`php-flymake' requires Emacs 26.1 or later"))
+ (cl-loop
+ while (search-forward-regexp php-flymake--diaggnostics-pattern nil t)
+ for msg = (match-string 2)
+ for line = (string-to-number (match-string 4))
+ for diag = (or (pcase-let ((`(,beg . ,end)
+ (flymake-diag-region source line)))
+ (flymake-make-diagnostic source beg end :error msg))
+ (flymake-make-diagnostic locus (cons line nil) nil :error
msg))
+ return (list diag)))
+
+(defun php-flymake--build-command-line (file)
+ "Return the command line for `php -l' FILE."
+ (let* ((command-args (or php-flymake-executable-command-args
+ (list (or (bound-and-true-p php-executable)
"php"))))
+ (cmd (car-safe command-args))
+ (default-directory (expand-file-name "~")))
+ (unless (or (file-executable-p cmd)
+ (executable-find cmd))
+ (user-error "`%s' is not valid command" cmd))
+ (nconc command-args
+ (list "-d" "display_errors=0")
+ (when file (list "-f" file))
+ (list "-l"))))
+
+(defun php-flymake--make-process (report-fn locus source use-stdin)
+ "Make PHP process for syntax check SOURCE buffer.
+
+See `flymake-diagnostic-functions' about REPORT-FN parameter.
+See `flymake-make-diagnostic' about LOCUS parameter."
+ (make-process
+ :name "php-flymake"
+ :buffer (generate-new-buffer "*flymake-php-flymake*")
+ :command (php-flymake--build-command-line (unless use-stdin locus))
+ :noquery t :connection-type 'pipe
+ :sentinel
+ (lambda (p _ev)
+ (unwind-protect
+ (when (and (eq 'exit (process-status p))
+ (with-current-buffer source (eq p php-flymake--proc)))
+ (with-current-buffer (process-buffer p)
+ (goto-char (point-min))
+ (funcall report-fn
+ (if (zerop (process-exit-status p))
+ nil
+ (php-flymake--diagnostics locus source)))))
+ (unless (process-live-p p)
+ ;; (display-buffer (process-buffer p)) ; uncomment to debug
+ (kill-buffer (process-buffer p)))))))
+
+(provide 'php-flymake)
+;;; php-flymake.el ends here
diff --git a/lisp/php-mode.el b/lisp/php-mode.el
index 6843b3a720..d7603131dd 100644
--- a/lisp/php-mode.el
+++ b/lisp/php-mode.el
@@ -81,6 +81,8 @@
(eval-when-compile
(require 'rx)
(require 'cl-lib)
+ (require 'flymake)
+ (require 'php-flymake)
(require 'regexp-opt)
(defvar add-log-current-defun-header-regexp)
(defvar add-log-current-defun-function)
@@ -179,6 +181,15 @@ Turning this on will open it whenever `php-mode' is
loaded."
:tag "PHP Mode Page Delimiter"
:type 'regexp)
+(defcustom php-mode-replace-flymake-diag-function
+ (eval-when-compile (when (boundp 'flymake-diagnostic-functions)
+ #'php-flymake))
+ "Flymake function to replace, if NIL do not replace."
+ :group 'php-mode
+ :tag "PHP Mode Replace Flymake Diag Function"
+ :type '(choice 'function
+ (const :tag "Disable to replace" nil)))
+
(define-obsolete-variable-alias 'php-do-not-use-semantic-imenu
'php-mode-do-not-use-semantic-imenu "1.20.0")
(defcustom php-mode-do-not-use-semantic-imenu t
"Customize `imenu-create-index-function' for `php-mode'.
@@ -301,6 +312,7 @@ In that case set to `NIL'."
:group 'php-mode
:tag "PHP Mode Disable C Mode Hook"
:type 'boolean)
+(make-obsolete-variable 'php-mode-disable-c-mode-hook nil "1.24.2")
(defcustom php-mode-enable-project-local-variable t
"When set to `T', apply project local variable to buffer local variable."
@@ -1147,6 +1159,14 @@ After setting the stylevars run hooks according to
STYLENAME
(php-project-apply-local-variables)
(remove-hook 'hack-local-variables-hook #'php-mode-set-local-variable-delay))
+(defun php-mode-neutralize-cc-mode-effect ()
+ "Reset PHP-irrelevant variables set by Cc Mode initialization."
+ (setq-local c-mode-hook nil)
+ (setq-local java-mode-hook nil)
+ (when (eval-when-compile (boundp 'flymake-diagnostic-functions))
+ (remove-hook 'flymake-diagnostic-functions 'flymake-cc t))
+ t)
+
(defvar php-mode-syntax-table
(let ((table (make-syntax-table)))
(c-populate-syntax-table table)
@@ -1173,9 +1193,12 @@ After setting the stylevars run hooks according to
STYLENAME
"Please run `M-x package-reinstall php-mode' command."
"Please byte recompile PHP Mode files.")))
- (when php-mode-disable-c-mode-hook
- (setq-local c-mode-hook nil)
- (setq-local java-mode-hook nil))
+ (if php-mode-disable-c-mode-hook
+ (php-mode-neutralize-cc-mode-effect)
+ (display-warning 'php-mode
+ "`php-mode-disable-c-mode-hook' will be removed. Do not
depends on this variable."
+ :warning))
+
(c-initialize-cc-mode t)
(c-init-language-vars php-mode)
(c-common-init 'php-mode)
@@ -1249,6 +1272,10 @@ After setting the stylevars run hooks according to
STYLENAME
(setq-local add-log-current-defun-function nil)
(setq-local add-log-current-defun-header-regexp
php-beginning-of-defun-regexp)
+ (when (and (eval-when-compile (boundp 'flymake-diagnostic-functions))
+ php-mode-replace-flymake-diag-function)
+ (add-hook 'flymake-diagnostic-functions
php-mode-replace-flymake-diag-function nil t))
+
(when (fboundp 'c-looking-at-or-maybe-in-bracelist)
(advice-add #'c-looking-at-or-maybe-in-bracelist
:override 'php-c-looking-at-or-maybe-in-bracelist '(local)))
@@ -1515,12 +1542,10 @@ for \\[find-tag] (which see)."
(defvar php-font-lock-keywords php-font-lock-keywords-3
"Default expressions to highlight in PHP Mode.")
-(add-to-list
- (eval-when-compile
- (if (boundp 'flymake-proc-allowed-file-name-masks)
- 'flymake-proc-allowed-file-name-masks
- 'flymake-allowed-file-name-masks))
- '("\\.php[345s]?\\'" php-flymake-php-init))
+(eval-when-compile
+ (unless (boundp 'flymake-proc-allowed-file-name-masks)
+ (add-to-list 'flymake-allowed-file-name-masks
+ '("\\.php[345s]?\\'" php-flymake-php-init))))
(defun php-send-region (start end)
diff --git a/lisp/php.el b/lisp/php.el
index 3a79a97ac3..ce70b279fb 100644
--- a/lisp/php.el
+++ b/lisp/php.el
@@ -550,11 +550,9 @@ The order is reversed by calling as follows:
This is an alternative function of `flymake-php-init'.
Look at the `php-executable' variable instead of the constant \"php\" command."
- (let* ((init (funcall (eval-when-compile
- (if (fboundp 'flymake-proc-php-init)
- 'flymake-proc-php-init
- 'flymake-php-init)))))
- (list php-executable (cdr init))))
+ (let ((init (with-no-warnings (flymake-php-init))))
+ (setf (car init) php-executable)
+ init))
(defconst php-re-detect-html-tag-aggressive
(eval-when-compile
- [nongnu] elpa/php-mode updated (f5c4016bb6 -> 2bc4db007c), ELPA Syncer, 2022/11/05
- [nongnu] elpa/php-mode 683211c088 2/9: Remove 'flymake-cc from flymake-diagnostic-functions, ELPA Syncer, 2022/11/05
- [nongnu] elpa/php-mode dc67eaecf1 3/9: Add php-flymake.el, ELPA Syncer, 2022/11/05
- [nongnu] elpa/php-mode a8a62f39ed 6/9: Make append to flymake-allowed-file-name-masks only in legacy, ELPA Syncer, 2022/11/05
- [nongnu] elpa/php-mode 56e5b67c06 7/9: Merge pull request #718 from emacs-php/feature/flymake-diagnostic-functions,
ELPA Syncer <=
- [nongnu] elpa/php-mode 2bc4db007c 9/9: Merge pull request #719 from emacs-php/feature/always-disable-c-auto-align-backslashe, ELPA Syncer, 2022/11/05
- [nongnu] elpa/php-mode 0902894e21 4/9: Add php-mode-replace-flymake-diag-function, ELPA Syncer, 2022/11/05
- [nongnu] elpa/php-mode 330070dc01 5/9: Fix php-flymake-php-init for legacy flymake, ELPA Syncer, 2022/11/05
- [nongnu] elpa/php-mode 0260bd288a 1/9: Make obsolete php-mode-disable-c-mode-hook variable, ELPA Syncer, 2022/11/05
- [nongnu] elpa/php-mode 7bcc9d64e9 8/9: Remove php-mode-disable-c-auto-align-backslashes and always disabled, ELPA Syncer, 2022/11/05