emacs-elpa-diffs
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]