Skip to content

Commit dddd1bc

Browse files
authored
Merge pull request #27 from emacs-php/feature/flymake-phpstan
Add flymake-phpstan feature
2 parents a1c30ca + d3a7a51 commit dddd1bc

File tree

3 files changed

+115
-2
lines changed

3 files changed

+115
-2
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
EMACS ?= emacs
22
CASK ?= cask
3-
ELS = phpstan.el flycheck-phpstan.el
3+
ELS = phpstan.el flycheck-phpstan.el flymake-phpstan.el
44
AUTOLOADS = phpstan-autoloads.el
55
ELCS = $(ELS:.el=.elc)
66

README.org

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ Emacs interface to [[https://github.com/phpstan/phpstan][PHPStan]], includes che
2424
#+END_SRC
2525

2626
*** For Flymake user
27-
The function for flymake will be implemented soon. You do not have to depend on flycheck.
27+
#+BEGIN_SRC emacs-lisp
28+
(add-hook 'php-mode-hook #'flymake-phpstan-turn-on)
29+
#+END_SRC
30+
2831
*** Using Docker (phpstan/docker-image)
2932
Install [[https://www.docker.com/get-started][Docker]] and [[https://hub.docker.com/r/phpstan/phpstan][phpstan/phpstan image]].
3033

flymake-phpstan.el

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
;;; flymake-phpstan.el --- Flymake backend for PHP using PHPStan -*- lexical-binding: t; -*-
2+
3+
;; Copyright (C) 2020 Friends of Emacs-PHP development
4+
5+
;; Author: USAMI Kenta <tadsan@zonu.me>
6+
;; Created: 31 Mar 2020
7+
;; Version: 0.4.0
8+
;; Keywords: tools, php
9+
;; Homepage: https://github.com/emacs-php/phpstan.el
10+
;; Package-Requires: ((emacs "26.1") (phpstan "0.3.3"))
11+
12+
;; This program is free software; you can redistribute it and/or modify
13+
;; it under the terms of the GNU General Public License as published by
14+
;; the Free Software Foundation, either version 3 of the License, or
15+
;; (at your option) any later version.
16+
17+
;; This program is distributed in the hope that it will be useful,
18+
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
;; GNU General Public License for more details.
21+
22+
;; You should have received a copy of the GNU General Public License
23+
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
24+
25+
;;; Commentary:
26+
27+
;; Flymake backend for PHP using PHPStan (PHP Static Analysis Tool).
28+
;;
29+
;; Put the following into your .emacs file (~/.emacs.d/init.el)
30+
;;
31+
;; (add-hook 'php-mode-hook #'flymake-phpstan-turn-on)
32+
;;
33+
;; For Lisp maintainers: see [GNU Flymake manual - 2.2.2 An annotated example backend]
34+
;; https://www.gnu.org/software/emacs/manual/html_node/flymake/An-annotated-example-backend.html
35+
36+
;;; Code:
37+
(require 'flymake)
38+
(require 'phpstan)
39+
40+
(defgroup flymake-phpstan nil
41+
"Flymake backend for PHP using PHPStan."
42+
:group 'flymake
43+
:group 'phpstan)
44+
45+
(defcustom flymake-phpstan-disable-c-mode-hooks t
46+
"When T, disable `flymake-diagnostic-functions' for `c-mode'."
47+
:group 'flymake-phpstan)
48+
49+
(defvar-local flymake-phpstan--proc nil)
50+
51+
(defun flymake-phpstan-make-process (root command-args report-fn source)
52+
"Make PHPStan process by ROOT, COMMAND-ARGS, REPORT-FN and SOURCE."
53+
(let ((default-directory root))
54+
(make-process
55+
:name "flymake-phpstan" :noquery t :connection-type 'pipe
56+
:buffer (generate-new-buffer " *Flymake-PHPStan*")
57+
:command command-args
58+
:sentinel
59+
(lambda (proc _event)
60+
(case (process-status proc))
61+
((exit)
62+
(unwind-protect
63+
(when (with-current-buffer source (eq proc flymake-phpstan--proc))
64+
(with-current-buffer (process-buffer proc)
65+
(goto-char (point-min))
66+
(cl-loop
67+
while (search-forward-regexp
68+
(eval-when-compile
69+
(rx line-start (1+ (not (any ":"))) ":"
70+
(group-n 1 (one-or-more digit)) ":"
71+
(group-n 2 (one-or-more not-newline)) line-end))
72+
nil t)
73+
for msg = (match-string 2)
74+
for (beg . end) = (flymake-diag-region
75+
source
76+
(string-to-number (match-string 1)))
77+
for type = :warning
78+
collect (flymake-make-diagnostic source beg end type msg)
79+
into diags
80+
finally (funcall report-fn diags)))
81+
(flymake-log :warning "Canceling obsolete check %s" proc))
82+
(kill-buffer (process-buffer proc))))
83+
(user-error "PHPStan error")))))
84+
85+
(defun flymake-phpstan (report-fn &rest _ignored-args)
86+
"Flymake backend for PHPStan report using REPORT-FN."
87+
(let ((command-args (phpstan-get-command-args)))
88+
(unless (car command-args)
89+
(user-error "Cannot find a phpstan executtable command"))
90+
(when (process-live-p flymake-phpstan--proc)
91+
(kill-process flymake-phpstan--proc))
92+
(let ((source (current-buffer)))
93+
(save-restriction
94+
(widen)
95+
(setq flymake-phpstan--proc (flymake-phpstan-make-process (php-project-root) command-args report-fn source))
96+
(process-send-region flymake-phpstan--proc (point-min) (point-max))
97+
(process-send-eof flymake-phpstan--proc)))))
98+
99+
(defun flymake-phpstan-turn-on ()
100+
"Enable flymake-phpstan as buffer-local Flymake backend."
101+
(interactive)
102+
(let ((enabled (or phpstan-working-dir (phpstan-get-config-file))))
103+
(when enabled
104+
(flymake-mode 1)
105+
(when flymake-phpstan-disable-c-mode-hooks
106+
(remove-hook 'flymake-diagnostic-functions 'flymake-cc t))
107+
(add-hook 'flymake-diagnostic-functions #'flymake-phpstan nil t))))
108+
109+
(provide 'flymake-phpstan)
110+
;;; flymake-phpstan.el ends here

0 commit comments

Comments
 (0)