@@ -166,11 +166,20 @@ have unexpected behaviors or performance implications."
166
166
" Lists identifiers prohibited from being added to @phpstan-ignore tags."
167
167
:type '(repeat string))
168
168
169
+ (defcustom phpstan-activate-editor-mode nil
170
+ " Controls how PHPStan's editor mode is activated."
171
+ :local t
172
+ :type '(choice (const :tag " Automatic (based on version)" nil )
173
+ (const :tag " Editor mode will be actively enabled, regardless of the PHPStan version." 'enabled )
174
+ (const :tag " Editor mode will be explicitly disabled." 'disabled )))
175
+
169
176
(defvar-local phpstan--use-xdebug-option nil )
170
177
171
178
(defvar-local phpstan--ignorable-errors '())
172
179
(defvar-local phpstan--dumped-types '())
173
180
181
+ (defvar phpstan-executable-versions-alist '())
182
+
174
183
;;;### autoload
175
184
(progn
176
185
(defvar-local phpstan-working-dir nil
@@ -479,7 +488,7 @@ it returns the value of `SOURCE' as it is."
479
488
((executable-find " phpstan" ) (list (executable-find " phpstan" )))
480
489
(t (error " PHPStan executable not found " )))))))
481
490
482
- (cl-defun phpstan-get-command-args (&key include-executable use-pro args format options config verbose )
491
+ (cl-defun phpstan-get-command-args (&key include-executable use-pro args format options config verbose editor )
483
492
" Return command line argument for PHPStan."
484
493
(let ((executable-and-args (phpstan-get-executable-and-args))
485
494
(config (or config (phpstan-normalize-path (phpstan-get-config-file))))
@@ -510,6 +519,15 @@ it returns the value of `SOURCE' as it is."
510
519
" --xdebug" ))
511
520
(list phpstan--use-xdebug-option))
512
521
(phpstan-use-xdebug-option (list " --xdebug" )))
522
+ (when editor
523
+ (let ((original-file (plist-get editor :original-file )))
524
+ (if (phpstan-editor-mode-available-p (car (phpstan-get-executable-and-args)))
525
+ (list " --tmp-file" (funcall (plist-get editor :temp-file ))
526
+ " --instead-of" original-file
527
+ " --" original-file)
528
+ (if (funcall (plist-get editor :analyze-original ) original-file)
529
+ (list " --" original-file)
530
+ (list " --" (funcall (plist-get editor :inplace )))))))
513
531
options
514
532
(and args (cons " --" args)))))
515
533
@@ -535,6 +553,37 @@ it returns the value of `SOURCE' as it is."
535
553
collect (cons (plist-get message :line )
536
554
(substring-no-properties msg (match-end 0 ))))))))
537
555
556
+ (defun phpstan-version (executable )
557
+ " Return the PHPStan version of EXECUTABLE."
558
+ (if-let* ((cached-entry (assoc executable phpstan-executable-versions-alist)))
559
+ (cdr cached-entry)
560
+ (let* ((version (thread-first
561
+ (mapconcat #'shell-quote-argument (list executable " --version" ) " " )
562
+ (shell-command-to-string )
563
+ (string-trim-right )
564
+ (split-string " " )
565
+ (last )
566
+ (car-safe ))))
567
+ (prog1 version
568
+ (push (cons executable version) phpstan-executable-versions-alist)))))
569
+
570
+ (defun phpstan-editor-mode-available-p (executable )
571
+ " Check if the specified PHPStan EXECUTABLE supports editor mode.
572
+
573
+ If a cached result for EXECUTABLE exists, it is returned directly.
574
+ Otherwise, this function attempts to determine support by retrieving
575
+ the PHPStan version using 'phpstan --version' command."
576
+ (pcase phpstan-activate-editor-mode
577
+ ('enabled t )
578
+ ('disabled nil )
579
+ ('nil
580
+ (let* ((version (phpstan-version executable)))
581
+ (if (string-match-p (eval-when-compile (regexp-quote " -dev@" )) version)
582
+ t
583
+ (pcase (elt version 0 )
584
+ (?1 (version<= " 1.12.27" version))
585
+ (?2 (version<= " 2.1.17" version))))))))
586
+
538
587
(defconst phpstan--re-ignore-tag
539
588
(eval-when-compile
540
589
(rx (* (syntax whitespace)) " //" (* (syntax whitespace))
0 commit comments