Skip to content

Commit 8e3fb3b

Browse files
committed
Do not error normalizing a nil path under a container
`phpstan-get-command-args' starts with (config (or config (phpstan-normalize-path (phpstan-get-config-file)))) and `phpstan-get-config-file' returns nil when the project has no phpstan.neon and `phpstan-config-file' is unset. For a container executable `phpstan-normalize-path' then passed that nil to `replace-regexp-in-string', raising `(wrong-type-argument arrayp nil)'. The local case was unaffected, since it returns `(or source source-original)' without touching the path. So `M-x phpstan-analyze-project', `phpstan-analyze-this-file', flycheck, and flymake all errored under `(phpstan-executable . docker)' / `container' whenever the project had no config file -- which `phpstan-enable-on-no-config-file' explicitly allows (Composer autoload is enough to enable PHPStan). Guard `phpstan-normalize-path' at the source: a nil path falls through to the `(or source source-original)' branch instead of the container rewrite, so it returns nil (or the optional SOURCE fallback) rather than erroring. Fixing it in the one function protects every caller. With config nil the command line now simply omits `-c', which is correct.
1 parent 04a0c39 commit 8e3fb3b

3 files changed

Lines changed: 37 additions & 8 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ All notable changes of the `phpstan.el` are documented in this file using the [K
3737
* Fix editor mode detection asking the wrong program for its version. Only the first element of the command line was probed, which is the container runtime for `(phpstan-executable . docker)` / `container` and `php` for a PHAR without the executable bit — so `docker --version` and `php --version` were parsed as PHPStan versions (`d1c06ef`, `Technologies`) and editor mode was silently disabled for every setup except a directly executable `phpstan`.
3838
* `phpstan-version` and `phpstan-editor-mode-available-p` now take the whole command line, as returned by `phpstan-get-executable-and-args`. A bare string is still accepted. `phpstan-version` no longer merges STDERR into the version string, which a container runtime pollutes with its progress report.
3939
* Fix `declare-function` forms for `tramp` that quoted the function name and argument list (and misspelled `tramp` as `tamp`), so the byte compiler warned that `tramp-dissect-file-name` might not be defined at runtime.
40+
* Fix a container run erroring when the project has no configuration file. `phpstan-normalize-path` was handed the nil from `phpstan-get-config-file` and passed it to `replace-regexp-in-string`; it now returns nil for a nil path, so the command line simply omits `-c`.
4041

4142
### Removed
4243

‎phpstan.el‎

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -393,16 +393,19 @@ such a command line still needs project paths rewritten to its mount point."
393393
394394
If neither `phpstan-replace-path-prefix' nor a container executable is set,
395395
it returns the value of `SOURCE' as it is."
396-
(let ((root-directory (expand-file-name (php-project-get-root-dir)))
397-
(prefix
396+
(let ((prefix
398397
(or phpstan-replace-path-prefix
399398
(and (phpstan--container-executable-p) "/app"))))
400-
(if prefix
401-
(expand-file-name
402-
(replace-regexp-in-string (concat "\\`" (regexp-quote root-directory))
403-
""
404-
source-original t t)
405-
prefix)
399+
;; SOURCE-ORIGINAL is nil when there is no path to normalize, e.g. when
400+
;; `phpstan-get-config-file' finds no configuration. Fall through rather
401+
;; than passing nil to `replace-regexp-in-string', which would error.
402+
(if (and prefix source-original)
403+
(let ((root-directory (expand-file-name (php-project-get-root-dir))))
404+
(expand-file-name
405+
(replace-regexp-in-string (concat "\\`" (regexp-quote root-directory))
406+
""
407+
source-original t t)
408+
prefix))
406409
(or source source-original))))
407410

408411
(defun phpstan-get-level ()

‎test/phpstan-test.el‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,20 @@
122122
(phpstan-replace-path-prefix nil))
123123
(should (equal src (phpstan-normalize-path src))))))))
124124

125+
(ert-deftest phpstan-test-normalize-path-nil ()
126+
"A nil path yields nil rather than erroring, even under a container.
127+
`phpstan-get-config-file' returns nil when a project has no configuration,
128+
and a containerized run would otherwise pass that nil to
129+
`replace-regexp-in-string'."
130+
(cl-letf (((symbol-function 'php-project-get-root-dir) (lambda () "/proj/")))
131+
(let ((phpstan-replace-path-prefix nil))
132+
(dolist (exe '(docker container ("docker" "run" "img") nil "/bin/phpstan"))
133+
(let ((phpstan-executable exe))
134+
(should-not (phpstan-normalize-path nil))))
135+
;; The optional SOURCE fallback still applies when it is given.
136+
(let ((phpstan-executable 'docker))
137+
(should (equal "fallback" (phpstan-normalize-path nil "fallback")))))))
138+
125139
;;; Command line construction
126140

127141
(defmacro phpstan-test--with-stubbed-project (&rest body)
@@ -184,5 +198,16 @@ survive `expand-file-name' on every platform."
184198
(should (member (expand-file-name "phpstan.neon" "/app") args))
185199
(should-not (member (phpstan-get-config-file) args))))))
186200

201+
(ert-deftest phpstan-test-command-args-without-config-under-container ()
202+
"A container run with no configuration file must not error.
203+
`phpstan-get-config-file' returns nil then, and normalizing it used to
204+
error; the command line should simply omit the `-c' flag."
205+
(phpstan-test--with-stubbed-project
206+
(cl-letf (((symbol-function 'phpstan-get-config-file) (lambda () nil)))
207+
(let ((phpstan-executable 'docker))
208+
(let ((args (phpstan-get-command-args :include-executable t)))
209+
(should-not (member "-c" args))
210+
(should (member "analyze" args)))))))
211+
187212
(provide 'phpstan-test)
188213
;;; phpstan-test.el ends here

0 commit comments

Comments
 (0)