branch: externals/phpinspect
commit f5fe299c015f8b4b51f0635f82eaf5b9ac58da4d
Author: Hugo Thunnissen <[email protected]>
Commit: Hugo Thunnissen <[email protected]>
Make functions that access the filesystem configurable and add test
Add test for `phpinspect-resolve-type-from-context'
---
phpinspect.el | 53 +++++++++++++++++++++++++---------
test/phpinspect-test.el | 75 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 114 insertions(+), 14 deletions(-)
diff --git a/phpinspect.el b/phpinspect.el
index 8b362cae2d..5ebf68cad7 100644
--- a/phpinspect.el
+++ b/phpinspect.el
@@ -46,6 +46,15 @@
"In-memory nested key-value store used for caching by
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
'("composer.json" "composer.lock" ".git" ".svn" ".hg")
"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."
(unless resolvecontext
(setq resolvecontext (phpinspect--make-resolvecontext
- :project-root (phpinspect--get-project-root))))
+ :project-root (phpinspect-project-root))))
(let ((last-token (car (last token)))
(last-encountered-token (car
@@ -1109,7 +1118,7 @@ accompanied by all of its enclosing tokens."
(defun phpinspect-parse-file (file)
(with-temp-buffer
- (insert-file-contents-literally file)
+ (phpinspect-insert-file-contents file)
(phpinspect-parse-current-buffer)))
(defun phpinspect-parse-current-buffer ()
@@ -1117,6 +1126,11 @@ accompanied by all of its enclosing tokens."
(current-buffer)
(point-max)))
+(defun phpinspect-parse-string (string)
+ (with-temp-buffer
+ (insert string)
+ (phpinspect-parse-current-buffer)))
+
(defun phpinspect--split-list (predicate list)
(seq-reduce (let ((current-sublist))
(lambda (result elt)
@@ -1785,7 +1799,7 @@ namespace if not provided"
(defun phpinspect--get-or-create-index-for-class-file (class-fqn)
(phpinspect--log "Getting or creating index for %s" class-fqn)
(phpinspect-get-or-create-cached-project-class
- (phpinspect--get-project-root)
+ (phpinspect-project-root)
class-fqn))
(defun phpinspect-index-file (file-name)
@@ -1799,7 +1813,7 @@ namespace if not provided"
(or
existing-index
(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)))
(new-index))
@@ -1889,7 +1903,7 @@ users will have to use \\[phpinspect-purge-cache]."
(setq phpinspect--buffer-index (phpinspect--index-current-buffer))
(dolist (class (alist-get 'classes phpinspect--buffer-index))
(when class
- (phpinspect-cache-project-class (phpinspect--get-project-root)
+ (phpinspect-cache-project-class (phpinspect-project-root)
(cdr class))))))
(defun phpinspect--disable-mode ()
@@ -2340,7 +2354,7 @@ hierarchy as long as no matching files are found. See
also
phpinspect-project-root-file-list)
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.
If a found project root has a parent directory called \"vendor\",
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 "/")
(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
;;;###autoload
(defun phpinspect-fix-uses-interactive ()
"Add missing use statements to the currently visited PHP file."
(interactive)
- (let ((project-root (phpinspect--get-project-root)))
+ (let ((project-root (phpinspect-project-root)))
(when project-root
(save-buffer)
(let* ((phpinspect-json (shell-command-to-string
@@ -2417,12 +2435,16 @@ level of START-FILE in stead of `default-directory`."
(forward-line -1)
(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)
(unless fqn-file
(setq fqn-file "uses"))
(with-temp-buffer
- (insert-file-contents-literally
- (concat (phpinspect--get-project-root) "/.cache/phpinspect/" fqn-file))
+ (phpinspect-insert-file-contents
+ (concat (phpinspect-project-root) "/.cache/phpinspect/" fqn-file))
(split-string (buffer-string) (char-to-string ?\n))))
;;;###autoload
@@ -2434,7 +2456,7 @@ available FQNs in a project. This may require
`phpinspect-index-current-project' to have run once for the
project directory before it can be used."
(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)
"`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
located in \"vendor\" folder."
(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)
"Retrieve filepath to CLASS definition file.
@@ -2454,7 +2479,7 @@ before the search is executed."
(when (eq index-new 'index-new)
(with-temp-buffer
(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
(phpinspect--log "dir: %s" default-directory)
(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
the project root."
(interactive)
- (let* ((default-directory (phpinspect--get-project-root)))
+ (let* ((default-directory (phpinspect-project-root)))
(with-current-buffer (get-buffer-create "**phpinspect-index**")
(goto-char (point-max))
(make-process
diff --git a/test/phpinspect-test.el b/test/phpinspect-test.el
index ebb21ec0e2..338a3c7159 100644
--- a/test/phpinspect-test.el
+++ b/test/phpinspect-test.el
@@ -237,6 +237,81 @@
(functions))))
(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)
;;; phpinspect-test.el ends here