branch: externals/phpinspect
commit f5fe299c015f8b4b51f0635f82eaf5b9ac58da4d
Author: Hugo Thunnissen <de...@hugot.nl>
Commit: Hugo Thunnissen <de...@hugot.nl>

    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

Reply via email to