Make functions that access the filesystem configurable and add test

Add test for `phpinspect-resolve-type-from-context'
WIP
Hugo Thunnissen 3 years ago
parent a6bb09b2b3
commit f5fe299c01

@ -46,6 +46,15 @@
"In-memory nested key-value store used for caching by "In-memory nested key-value store used for caching by
phpinspect") phpinspect")
(defvar phpinspect-insert-file-contents-function #'insert-file-contents-literally
"Function that phpinspect uses to insert file contents into a buffer.")
(defvar phpinspect-project-root-function #'phpinspect--find-project-root
"Function that phpinspect uses to find the root directory of a project.")
(defvar phpinspect-class-filepath-function #'phpinspect-get-class-filepath
"Function that phpinspect uses to find the filepath of a class by its FQN.")
(defvar phpinspect-project-root-file-list (defvar phpinspect-project-root-file-list
'("composer.json" "composer.lock" ".git" ".svn" ".hg") '("composer.json" "composer.lock" ".git" ".svn" ".hg")
"List of files that could indicate a project root directory.") "List of files that could indicate a project root directory.")
@ -963,7 +972,7 @@ statement of the innermost incomplete token as subject
accompanied by all of its enclosing tokens." accompanied by all of its enclosing tokens."
(unless resolvecontext (unless resolvecontext
(setq resolvecontext (phpinspect--make-resolvecontext (setq resolvecontext (phpinspect--make-resolvecontext
:project-root (phpinspect--get-project-root)))) :project-root (phpinspect-project-root))))
(let ((last-token (car (last token))) (let ((last-token (car (last token)))
(last-encountered-token (car (last-encountered-token (car
@ -1109,7 +1118,7 @@ accompanied by all of its enclosing tokens."
(defun phpinspect-parse-file (file) (defun phpinspect-parse-file (file)
(with-temp-buffer (with-temp-buffer
(insert-file-contents-literally file) (phpinspect-insert-file-contents file)
(phpinspect-parse-current-buffer))) (phpinspect-parse-current-buffer)))
(defun phpinspect-parse-current-buffer () (defun phpinspect-parse-current-buffer ()
@ -1117,6 +1126,11 @@ accompanied by all of its enclosing tokens."
(current-buffer) (current-buffer)
(point-max))) (point-max)))
(defun phpinspect-parse-string (string)
(with-temp-buffer
(insert string)
(phpinspect-parse-current-buffer)))
(defun phpinspect--split-list (predicate list) (defun phpinspect--split-list (predicate list)
(seq-reduce (let ((current-sublist)) (seq-reduce (let ((current-sublist))
(lambda (result elt) (lambda (result elt)
@ -1785,7 +1799,7 @@ namespace if not provided"
(defun phpinspect--get-or-create-index-for-class-file (class-fqn) (defun phpinspect--get-or-create-index-for-class-file (class-fqn)
(phpinspect--log "Getting or creating index for %s" class-fqn) (phpinspect--log "Getting or creating index for %s" class-fqn)
(phpinspect-get-or-create-cached-project-class (phpinspect-get-or-create-cached-project-class
(phpinspect--get-project-root) (phpinspect-project-root)
class-fqn)) class-fqn))
(defun phpinspect-index-file (file-name) (defun phpinspect-index-file (file-name)
@ -1799,7 +1813,7 @@ namespace if not provided"
(or (or
existing-index existing-index
(progn (progn
(let* ((class-file (phpinspect-get-class-filepath class-fqn)) (let* ((class-file (phpinspect-class-filepath class-fqn))
(visited-buffer (when class-file (find-buffer-visiting class-file))) (visited-buffer (when class-file (find-buffer-visiting class-file)))
(new-index)) (new-index))
@ -1889,7 +1903,7 @@ users will have to use \\[phpinspect-purge-cache]."
(setq phpinspect--buffer-index (phpinspect--index-current-buffer)) (setq phpinspect--buffer-index (phpinspect--index-current-buffer))
(dolist (class (alist-get 'classes phpinspect--buffer-index)) (dolist (class (alist-get 'classes phpinspect--buffer-index))
(when class (when class
(phpinspect-cache-project-class (phpinspect--get-project-root) (phpinspect-cache-project-class (phpinspect-project-root)
(cdr class)))))) (cdr class))))))
(defun phpinspect--disable-mode () (defun phpinspect--disable-mode ()
@ -2340,7 +2354,7 @@ hierarchy as long as no matching files are found. See also
phpinspect-project-root-file-list) phpinspect-project-root-file-list)
dominating-file)) dominating-file))
(defun phpinspect--get-project-root (&optional start-file) (defun phpinspect--find-project-root (&optional start-file)
"(Attempt to) Find the root directory of the visited PHP project. "(Attempt to) Find the root directory of the visited PHP project.
If a found project root has a parent directory called \"vendor\", If a found project root has a parent directory called \"vendor\",
the search continues upwards. See also the search continues upwards. See also
@ -2363,14 +2377,18 @@ level of START-FILE in stead of `default-directory`."
"/"))) "/")))
(when (not (or (string= parent-without-vendor "/") (when (not (or (string= parent-without-vendor "/")
(string= parent-without-vendor ""))) (string= parent-without-vendor "")))
(phpinspect--get-project-root parent-without-vendor)))))))) (phpinspect--find-project-root parent-without-vendor))))))))
(defsubst phpinspect-project-root (&rest args)
"Call `phpinspect-project-root-function' with ARGS as arguments."
(apply phpinspect-project-root-function args))
;; Use statements ;; Use statements
;;;###autoload ;;;###autoload
(defun phpinspect-fix-uses-interactive () (defun phpinspect-fix-uses-interactive ()
"Add missing use statements to the currently visited PHP file." "Add missing use statements to the currently visited PHP file."
(interactive) (interactive)
(let ((project-root (phpinspect--get-project-root))) (let ((project-root (phpinspect-project-root)))
(when project-root (when project-root
(save-buffer) (save-buffer)
(let* ((phpinspect-json (shell-command-to-string (let* ((phpinspect-json (shell-command-to-string
@ -2417,12 +2435,16 @@ level of START-FILE in stead of `default-directory`."
(forward-line -1) (forward-line -1)
(phpinspect-goto-first-line-no-comment-up))) (phpinspect-goto-first-line-no-comment-up)))
(defsubst phpinspect-insert-file-contents (&rest args)
"Call `phpinspect-insert-file-contents-function' with ARGS as arguments."
(apply phpinspect-insert-file-contents-function args))
(defun phpinspect-get-all-fqns (&optional fqn-file) (defun phpinspect-get-all-fqns (&optional fqn-file)
(unless fqn-file (unless fqn-file
(setq fqn-file "uses")) (setq fqn-file "uses"))
(with-temp-buffer (with-temp-buffer
(insert-file-contents-literally (phpinspect-insert-file-contents
(concat (phpinspect--get-project-root) "/.cache/phpinspect/" fqn-file)) (concat (phpinspect-project-root) "/.cache/phpinspect/" fqn-file))
(split-string (buffer-string) (char-to-string ?\n)))) (split-string (buffer-string) (char-to-string ?\n))))
;;;###autoload ;;;###autoload
@ -2434,7 +2456,7 @@ available FQNs in a project. This may require
`phpinspect-index-current-project' to have run once for the `phpinspect-index-current-project' to have run once for the
project directory before it can be used." project directory before it can be used."
(interactive (list (completing-read "Class: " (phpinspect-get-all-fqns)))) (interactive (list (completing-read "Class: " (phpinspect-get-all-fqns))))
(find-file (phpinspect-get-class-filepath fqn))) (find-file (phpinspect-class-filepath fqn)))
(defun phpinspect-find-own-class-file (fqn) (defun phpinspect-find-own-class-file (fqn)
"`phpinspect-find-class-file', but for non-vendored classes. "`phpinspect-find-class-file', but for non-vendored classes.
@ -2443,8 +2465,11 @@ When called interactively, presents the user with a list of
available FQNs for classes in the current project, which aren't available FQNs for classes in the current project, which aren't
located in \"vendor\" folder." located in \"vendor\" folder."
(interactive (list (completing-read "Class: " (phpinspect-get-all-fqns "uses_own")))) (interactive (list (completing-read "Class: " (phpinspect-get-all-fqns "uses_own"))))
(find-file (phpinspect-get-class-filepath fqn))) (find-file (phpinspect-class-filepath fqn)))
(defsubst phpinspect-class-filepath (fqn)
"Call `phpinspect-class-filepath-function' with FQN as argument."
(funcall phpinspect-class-filepath-function fqn))
(defun phpinspect-get-class-filepath (class &optional index-new) (defun phpinspect-get-class-filepath (class &optional index-new)
"Retrieve filepath to CLASS definition file. "Retrieve filepath to CLASS definition file.
@ -2454,7 +2479,7 @@ before the search is executed."
(when (eq index-new 'index-new) (when (eq index-new 'index-new)
(with-temp-buffer (with-temp-buffer
(call-process phpinspect-index-executable nil (current-buffer) nil "index" "--new"))) (call-process phpinspect-index-executable nil (current-buffer) nil "index" "--new")))
(let* ((default-directory (phpinspect--get-project-root)) (let* ((default-directory (phpinspect-project-root))
(result (with-temp-buffer (result (with-temp-buffer
(phpinspect--log "dir: %s" default-directory) (phpinspect--log "dir: %s" default-directory)
(phpinspect--log "class: %s" (string-remove-prefix "\\" class)) (phpinspect--log "class: %s" (string-remove-prefix "\\" class))
@ -2489,7 +2514,7 @@ before the search is executed."
Index is stored in files in the .cache directory of Index is stored in files in the .cache directory of
the project root." the project root."
(interactive) (interactive)
(let* ((default-directory (phpinspect--get-project-root))) (let* ((default-directory (phpinspect-project-root)))
(with-current-buffer (get-buffer-create "**phpinspect-index**") (with-current-buffer (get-buffer-create "**phpinspect-index**")
(goto-char (point-max)) (goto-char (point-max))
(make-process (make-process

@ -237,6 +237,81 @@
(functions)))) (functions))))
(should (equal expected-index index)))) (should (equal expected-index index))))
(ert-deftest phpinspect-resolve-type-from-context ()
(let* ((token-tree (phpinspect-parse-string "
namespace Amazing;
class FluffBall
{
private $fluffer;
public function __construct(Fluffer $fluffer)
{
$this->fluffer = $fluffer;
}
public function beFluffy(): void
{
$ball = $this->fluffer;
if ($ball) {
if(isset($ball->fluff()->poof->upFluff->"))
(fluffer "
namespace Amazing;
use Vendor\\FluffLib\\Fluff;
class Fluffer
{
public function fluff(): Fluff
{
}
}")
(vendor-fluff "
namespace Vendor\\FluffLib;
class Fluff
{
/**
* @var FlufferUpper
*/
public $poof;
}")
(vendor-fluffer-upper "
namespace Vendor\\FluffLib;
class FlufferUpper
{
public $upFluff;
public function __construct(DoubleFluffer $upFluff)
{
$this->upFluff = $upFluff;
}
}")
(phpinspect-project-root-function (lambda () "phpinspect-test"))
(phpinspect-class-filepath-function
(lambda (fqn)
(pcase fqn
("\\Amazing\\Fluffer" "fluffer")
("\\Vendor\\FluffLib\\Fluff" "vendor-fluff")
("\\Vendor\\FluffLib\\FlufferUpper" "vendor-fluffer-upper")
(_ (ert-fail (format "Unexpected class FQN filepath was requested: %s" fqn))))))
(phpinspect-insert-file-contents-function
(lambda (filepath)
(pcase filepath
("fluffer" (insert fluffer))
("vendor-fluff" (insert vendor-fluff))
("vendor-fluffer-upper" (insert vendor-fluffer-upper))
(_ (ert-fail (format "Unexpected filepath was requested: %s" filepath))))))
(context (phpinspect--get-resolvecontext token-tree)))
(phpinspect-purge-cache)
(phpinspect-cache-project-class
(phpinspect-project-root)
(cdar (alist-get 'classes (cdr (phpinspect--index-tokens token-tree)))))
(should (equal "\\Vendor\\FluffLib\\DoubleFluffer"
(phpinspect-resolve-type-from-context
context
(phpinspect--make-type-resolver-for-resolvecontext
context))))))
(provide 'phpinspect-test) (provide 'phpinspect-test)
;;; phpinspect-test.el ends here ;;; phpinspect-test.el ends here

Loading…
Cancel
Save