# phpinspect.el PHPInspect is a minor mode that provides code intelligence for PHP in Emacs. At its core is a PHP parser implemented in Emacs Lisp. PHPInspect comes with backends for `completion-at-point`, `company-mode` and `eldoc`. A backend for `xref` (which provides go-to-definition functionality) is planned to be implemented at a later date. The main documentation of the mode is in the docstring of the mode itself (`C-h f phpinspect-mode RET` to view, or read it in the source code of [phpinspect.el](phpinspect.el)). ## Projects and Finding Types By default, phpinspect will recognize composer projects and read their composer.json files for autoload information which is used to find files in which the types/classes/functions you use in your code are defined. It is also possible to add an "include directory" of files that should always be read and indexed for a certain project. To do this, open a file in a project and run `M-x phpinspect-project-add-include-dir`. You can also edit the list of include directories via `M-x customize-goup RET phpinspect RET`. ## Example Configuration If you already have a completion UI setup that is able to use `completion-at-point-functions` as completion source, you can basically just enable phpinspect-mode and you'll be good to go. An example of a basic mode hook configuration to get the most out of phpinspect is the following: ```elisp (defun my-php-personal-hook () ;; Shortcut to add use statements for classes you use. (define-key php-mode-map (kbd \"C-c u\") 'phpinspect-fix-imports) ;; Shortcuts to quickly search/open files of PHP classes. ;; You can make these local to php-mode, but making them global ;; like this makes them work in other modes/filetypes as well, which ;; can be handy when jumping between templates, config files and PHP code. (global-set-key (kbd \"C-c a\") 'phpinspect-find-class-file) (global-set-key (kbd \"C-c c\") 'phpinspect-find-own-class-file) ;; Enable phpinspect-mode (phpinspect-mode)) (add-hook 'php-mode-hook #'my-php-personal-hook) ``` ## Example config with company mode setup ```elisp ;;;###autoload (defun my-php-personal-hook () ;; It is important to enable `company-mode' before setting ;; the variables below. (company-mode) (setq-local company-minimum-prefix-length 0) (setq-local company-tooltip-align-annotations t) (setq-local company-idle-delay 0.1) (setq-local company-backends '(phpinspect-company-backend)) ;; Shortcut to add use statements for classes you use. (define-key php-mode-map (kbd "C-c u") 'phpinspect-fix-imports) ;; Shortcuts to quickly search/open files of PHP classes. (global-set-key (kbd "C-c a") 'phpinspect-find-class-file) (global-set-key (kbd "C-c c") 'phpinspect-find-own-class-file) (phpinspect-mode)) (add-hook 'php-mode-hook #'my-php-personal-hook) ``` ## Install from git ```bash git clone https://git.snorba.art/hugo/phpinspect.el ~/projects/phpinspect.el cd ~/projects/phpinspect.el make ``` ```elisp (add-to-list 'load-path "~/projects/phpinspect.el") (require 'phpinspect) ``` ## Compilation It is highly recommended to byte- or native compile phpinspect. Aside from the normal performance boost that this brings to most packages, it can reduce phpinspect's parsing time by up to 90%. It especially makes a difference when incrementally parsing edited buffers. For example: ### benchmarks/parse-file.el uncompiled on Ryzen 5 3600 (time in seconds): ``` Incremental parse (warmup): Elapsed time: 0.168390 (0.019751 in 1 GC’s) Incremental parse: Elapsed time: 0.143811 (0.000000 in 0 GC’s) Incremental parse (no edits): Elapsed time: 0.000284 (0.000000 in 0 GC’s) Incremental parse repeat (no edits): Elapsed time: 0.000241 (0.000000 in 0 GC’s) Incremental parse after buffer edit: Elapsed time: 0.012449 (0.000000 in 0 GC’s) Incremental parse after 2 more edits: Elapsed time: 0.015839 (0.000000 in 0 GC’s) Bare (no token reuse) parse (warmup): Elapsed time: 0.048996 (0.000000 in 0 GC’s) Bare (no token reuse) parse: Elapsed time: 0.052495 (0.000000 in 0 GC’s) ``` ### benchmarks/parse-file.el with native compilation on Ryzen 5 3600 (time in seconds): ``` Incremental parse (warmup): Elapsed time: 0.023432 (0.000000 in 0 GC’s) Incremental parse: Elapsed time: 0.018350 (0.000000 in 0 GC’s) Incremental parse (no edits): Elapsed time: 0.000076 (0.000000 in 0 GC’s) Incremental parse repeat (no edits): Elapsed time: 0.000058 (0.000000 in 0 GC’s) Incremental parse after buffer edit: Elapsed time: 0.001212 (0.000000 in 0 GC’s) Incremental parse after 2 more edits: Elapsed time: 0.001381 (0.000000 in 0 GC’s) Bare (no token reuse) parse (warmup): Elapsed time: 0.013874 (0.000000 in 0 GC’s) Bare (no token reuse) parse: Elapsed time: 0.013878 (0.000000 in 0 GC’s) ``` ## Development ### Building ```bash make ``` ### Running tests Tests are implemented using `ert`. You can run them in batch mode with the following command: ```bash make test # or: emacs -L ./ -batch -l ert -l ./test/phpinspect-test.el -f ert-run-tests-batch-and-exit ```