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

    Implement basic support for function indexation and include dirs
    
    Does not yet include support for imported namespaced functions
---
 phpinspect-cache.el      |   3 +-
 phpinspect-completion.el |  15 +++++++
 phpinspect-eldoc.el      |  21 ++++++++-
 phpinspect-index.el      | 113 +++++++++++++++++++++++++++++++----------------
 phpinspect-pipeline.el   |   1 +
 phpinspect-project.el    |  78 +++++++++++++++++++++++++++++---
 phpinspect-suggest.el    |   5 +++
 phpinspect-type.el       |   8 ++--
 phpinspect-util.el       |  11 ++---
 phpinspect-worker.el     |  68 ++++++++++++++++++++--------
 phpinspect.el            |  12 +++--
 test/test-index.el       |  50 +++++++++++++++++++++
 12 files changed, 306 insertions(+), 79 deletions(-)

diff --git a/phpinspect-cache.el b/phpinspect-cache.el
index d3920e3e60..cdf89ee124 100644
--- a/phpinspect-cache.el
+++ b/phpinspect-cache.el
@@ -68,7 +68,8 @@ then returned."
                              (phpinspect--cache-projects cache)))
       (let ((autoloader (phpinspect-make-autoloader :project project)))
         (setf (phpinspect-project-autoload project) autoloader)
-        (phpinspect-autoloader-refresh autoloader)))
+        (phpinspect-autoloader-refresh autoloader)
+        (phpinspect-project-enqueue-include-dirs project)))
     project))
 
 (provide 'phpinspect-cache)
diff --git a/phpinspect-completion.el b/phpinspect-completion.el
index 3048d3c7a2..2ffdd49299 100644
--- a/phpinspect-completion.el
+++ b/phpinspect-completion.el
@@ -144,8 +144,22 @@ and CONTEXT. All strategies must implement this method.")
    (rctx phpinspect--resolvecontext))
   (phpinspect-suggest-attributes-at-point rctx 'static))
 
+(cl-defstruct (phpinspect-comp-word (:constructor phpinspect-make-comp-word))
+  "Comletion strategy for bare words")
+
+(cl-defmethod phpinspect-comp-strategy-supports
+  ((_strat phpinspect-comp-word) (_q phpinspect-completion-query)
+   (rctx phpinspect--resolvecontext))
+  (phpinspect-word-p (car (last (phpinspect--resolvecontext-subject rctx)))))
+
+(cl-defmethod phpinspect-comp-strategy-execute
+  ((_strat phpinspect-comp-word) (_q phpinspect-completion-query)
+   (rctx phpinspect--resolvecontext))
+  (phpinspect-suggest-functions rctx))
+
 (defvar phpinspect-completion-strategies (list (phpinspect-make-comp-attribute)
                                                (phpinspect-make-comp-sigil)
+                                               (phpinspect-make-comp-word)
                                                
(phpinspect-make-comp-static-attribute))
   "List of completion strategies that phpinspect can use.")
 
@@ -198,4 +212,5 @@ Returns list of `phpinspect--completion'."
                             phpinspect--null-type)))
    :kind 'variable))
 
+
 (provide 'phpinspect-completion)
diff --git a/phpinspect-eldoc.el b/phpinspect-eldoc.el
index 515ac985a9..225746c285 100644
--- a/phpinspect-eldoc.el
+++ b/phpinspect-eldoc.el
@@ -178,7 +178,26 @@ be implemented for return values of 
`phpinspect-eld-strategy-execute'")
                              (phpinspect--class-get-static-method class 
method-name-sym)
                            (phpinspect--class-get-method class 
method-name-sym)))))
           (when method
-            (phpinspect-make-function-doc :fn method :arg-pos arg-pos))))))))
+            (phpinspect-make-function-doc :fn method :arg-pos arg-pos))))
+       ((setq match-result (phpinspect--match-sequence (last statement 2)
+                             :f (phpinspect-meta-wrap-token-pred 
#'phpinspect-word-p)
+                             :f (phpinspect-meta-wrap-token-pred 
#'phpinspect-list-p)))
+        (phpinspect--log "Eldoc context is a function call")
+
+        (setq arg-list (car (last match-result))
+              arg-pos (seq-reduce
+                       (lambda (count meta)
+                         (if (phpinspect-comma-p (phpinspect-meta-token meta))
+                             (+ count 1)
+                           count))
+                       (phpinspect-meta-find-children-before arg-list 
(phpinspect-eldoc-query-point q)) 0))
+
+        (let ((func (phpinspect-project-get-function
+                     (phpinspect--resolvecontext-project rctx)
+                     (phpinspect-intern-name (cadr (phpinspect-meta-token (car 
match-result)))))))
+          (phpinspect--log "Got past that")
+          (when func
+            (phpinspect-make-function-doc :fn func :arg-pos arg-pos))))))))
 
 (cl-defmethod phpinspect-eldoc-string ((var phpinspect--variable))
   (concat (truncate-string-to-width
diff --git a/phpinspect-index.el b/phpinspect-index.el
index 5c61be5f75..d76b2d5899 100644
--- a/phpinspect-index.el
+++ b/phpinspect-index.el
@@ -59,7 +59,7 @@ of TYPE, if available."
   (or (not type)
       (phpinspect--type= type phpinspect--object-type)))
 
-(defun phpinspect--index-function-from-scope (type-resolver scope 
comment-before &optional add-used-types)
+(defun phpinspect--index-function-from-scope (type-resolver scope 
comment-before &optional add-used-types namespace)
   "Index a function inside SCOPE token using phpdoc metadata in COMMENT-BEFORE.
 
 If ADD-USED-TYPES is set, it must be a function and will be
@@ -104,7 +104,7 @@ function (think \"new\" statements, return types etc.)."
 
     (phpinspect--make-function
      :scope `(,(car scope))
-     :name (cadadr (cdr declaration))
+     :name (concat (if namespace (concat namespace "\\") "") (cadadr (cdr 
declaration)))
      :return-type (or type phpinspect--null-type)
      :arguments (phpinspect--index-function-arg-list
                  type-resolver
@@ -384,25 +384,54 @@ NAMESPACE will be assumed the root namespace if not 
provided"
   (mapcar #'phpinspect--use-to-type uses))
 
 (defun phpinspect--index-namespace (namespace type-resolver-factory 
location-resolver)
-  (phpinspect--index-classes-in-tokens
-   (phpinspect--uses-to-types (seq-filter #'phpinspect-use-p namespace))
-   namespace
-   type-resolver-factory location-resolver (cadadr namespace)))
+  (let* (used-types
+         (index
+          `((classes . ,(phpinspect--index-classes-in-tokens
+                         (phpinspect--uses-to-types (seq-filter 
#'phpinspect-use-p namespace))
+                         namespace
+                         type-resolver-factory location-resolver (cadadr 
namespace)))
+            (functions . ,(phpinspect--index-functions-in-tokens
+                           namespace
+                           type-resolver-factory
+                           (phpinspect--uses-to-types (seq-filter 
#'phpinspect-use-p namespace))
+                           (cadadr namespace)
+                           (lambda (types) (setq used-types (nconc used-types 
types))))))))
+
+    (push `(used-types . ,used-types) index)))
 
 (defun phpinspect--index-namespaces
     (namespaces type-resolver-factory location-resolver &optional indexed)
   (if namespaces
-      (progn
-        (push (phpinspect--index-namespace (pop namespaces)
-                                           type-resolver-factory
-                                           location-resolver)
-              indexed)
-        (phpinspect--index-namespaces namespaces type-resolver-factory
-                                      location-resolver indexed))
-    (apply #'append (nreverse indexed))))
-
-(defun phpinspect--index-functions (&rest _args)
-  "TODO: implement function indexation. This is a stub function.")
+      (let ((namespace-index
+             (phpinspect--index-namespace
+              (pop namespaces) type-resolver-factory location-resolver)))
+
+        (if indexed
+            (progn
+              (nconc (alist-get 'used-types indexed)
+                     (alist-get 'used-types namespace-index))
+              (nconc (alist-get 'classes indexed)
+                     (alist-get 'classes namespace-index))
+              (nconc (alist-get 'functions indexed)
+                     (alist-get 'functions namespace-index)))
+          (setq indexed namespace-index))
+        (phpinspect--index-namespaces
+         namespaces type-resolver-factory location-resolver indexed))
+    indexed))
+
+(defun phpinspect--index-functions-in-tokens (tokens type-resolver-factory 
&optional imports namespace add-used-types)
+  "TODO: implement function indexation. This is a stub function."
+  (let ((type-resolver (funcall type-resolver-factory imports nil namespace))
+        comment-before functions)
+    (dolist (token tokens)
+      (cond ((phpinspect-comment-p token)
+             (setq comment-before token))
+            ((phpinspect-function-p token)
+             (push (phpinspect--index-function-from-scope
+                    type-resolver `(:public ,token) comment-before 
add-used-types
+                    namespace)
+                   functions))))
+    functions))
 
 (defun phpinspect--find-used-types-in-tokens (tokens)
   "Find usage of the \"new\" keyword in TOKENS.
@@ -438,27 +467,35 @@ Return value is a list of the types that are \"newed\"."
 
 (defun phpinspect--index-tokens (tokens &optional type-resolver-factory 
location-resolver)
   "Index TOKENS as returned by `phpinspect--parse-current-buffer`."
-  (unless type-resolver-factory
-    (setq type-resolver-factory #'phpinspect--make-type-resolver))
-
-  (unless location-resolver
-    (setq location-resolver (lambda (_) (list 0 0))))
-
-  (let ((imports (phpinspect--uses-to-types (seq-filter #'phpinspect-use-p 
tokens))))
-    `(phpinspect--root-index
-      (imports . ,imports)
-      ,(append
-        (append '(classes)
-                (phpinspect--index-namespaces (seq-filter 
#'phpinspect-namespace-p tokens)
-                                              type-resolver-factory
-                                              location-resolver)
-                (phpinspect--index-classes-in-tokens
-                 imports tokens type-resolver-factory location-resolver)))
-      ,(append '(used-types)
-               (phpinspect--find-used-types-in-tokens tokens))
-      (functions))
-    ;; TODO: Implement function indexation
-    ))
+  (or
+   (condition-case err
+       (progn
+         (unless type-resolver-factory
+           (setq type-resolver-factory #'phpinspect--make-type-resolver))
+
+         (unless location-resolver
+           (setq location-resolver (lambda (_) (list 0 0))))
+
+         (let* ((imports (phpinspect--uses-to-types (seq-filter 
#'phpinspect-use-p tokens)))
+                (namespace-index
+                 (phpinspect--index-namespaces (seq-filter 
#'phpinspect-namespace-p tokens)
+                                               type-resolver-factory
+                                               location-resolver)))
+           `(phpinspect--root-index
+             (imports . ,imports)
+             (classes ,@(append
+                         (alist-get 'classes namespace-index)
+                         (phpinspect--index-classes-in-tokens
+                          imports tokens type-resolver-factory 
location-resolver)))
+             (used-types ,@(append
+                            (alist-get 'used-types namespace-index)
+                            (phpinspect--find-used-types-in-tokens tokens)))
+             (functions . ,(append
+                            (alist-get 'functions namespace-index)
+                            (phpinspect--index-functions-in-tokens
+                             tokens type-resolver-factory imports))))))
+     (t (phpinspect--log "phpinspect--index-tokens failed: %s" err) nil))
+   '(phpinspect--root-index)))
 
 (defun phpinspect-get-or-create-cached-project-class (project-root class-fqn)
   (when project-root
diff --git a/phpinspect-pipeline.el b/phpinspect-pipeline.el
index a55b944e0a..021a730feb 100644
--- a/phpinspect-pipeline.el
+++ b/phpinspect-pipeline.el
@@ -191,6 +191,7 @@ user input.")
                           (setq ,continue-running nil))
                         (phpinspect-pipeline--enqueue ,out-queue ,outgoing)))
                   (phpinspect-pipeline-incoming)
+                  (quit)
                   (t (phpinspect--log "Pipeline thread errored: %s" err)
                      (setq ,end (phpinspect-make-pipeline-end :thread 
(current-thread) :error err))
                      (setq ,continue-running nil)
diff --git a/phpinspect-project.el b/phpinspect-project.el
index f45f2c9268..ef7e328db8 100644
--- a/phpinspect-project.el
+++ b/phpinspect-project.el
@@ -46,11 +46,16 @@ serious performance hits. Enable at your own risk (:")
   phpinspect--buffer-project)
 
 (cl-defstruct (phpinspect-project (:constructor phpinspect--make-project))
-  (class-index (make-hash-table :test 'eq :size 100 :rehash-size 40)
+  (class-index (make-hash-table :test 'eq :size 100 :rehash-size 1.5)
                :type hash-table
                :documentation
                "A `hash-table` that contains all of the currently
 indexed classes in the project")
+  (function-index (make-hash-table :test 'eq :size 100 :rehash-size 2.0)
+                  :type hash-table
+                  :documentation
+                  "A hash able that contains all of the currently indexed 
functions
+in the project")
   (fs nil
       :type phpinspect-fs
       :documentation
@@ -115,9 +120,11 @@ indexed by the absolute paths of the files they're 
watching."))
                 (not (or (phpinspect--class-initial-index class))))
         (when (not class)
           (setq class (phpinspect-project-create-class project type)))
-        (phpinspect--log "Adding unpresent class %s to index queue" type)
-        (phpinspect-worker-enqueue (phpinspect-project-worker project)
-                                   (phpinspect-make-index-task project 
type))))))
+        (unless (or (phpinspect--type= phpinspect--null-type type)
+                    (phpinspect--type-is-native type))
+          (phpinspect--log "Adding unpresent class %s to index queue" type)
+          (phpinspect-worker-enqueue (phpinspect-project-worker project)
+                                     (phpinspect-make-index-task project 
type)))))))
 
 (cl-defmethod phpinspect-project-add-class-attribute-types-to-index-queue
   ((project phpinspect-project) (class phpinspect--class))
@@ -135,8 +142,29 @@ indexed by the absolute paths of the files they're 
watching."))
   ((project phpinspect-project) (index (head phpinspect--root-index)) 
&optional index-imports)
   (when index-imports
     (phpinspect-project-enqueue-imports project (alist-get 'imports (cdr 
index))))
+
   (dolist (indexed-class (alist-get 'classes (cdr index)))
-    (phpinspect-project-add-class project (cdr indexed-class) index-imports)))
+    (phpinspect-project-add-class project (cdr indexed-class) index-imports))
+
+  (dolist (func (alist-get 'functions (cdr index)))
+    (phpinspect-project-set-function project func)))
+
+(cl-defmethod phpinspect-project-set-function
+  ((project phpinspect-project) (func phpinspect--function))
+  (puthash (phpinspect--function-name-symbol func) func
+           (phpinspect-project-function-index project)))
+
+(cl-defmethod phpinspect-project-get-function
+  ((project phpinspect-project) (name symbol))
+  (gethash name (phpinspect-project-function-index project)))
+
+(cl-defmethod phpinspect-project-get-functions ((project phpinspect-project))
+  (let ((funcs))
+    (maphash
+     (lambda (_name func) (push func funcs))
+     (phpinspect-project-function-index project))
+
+    funcs))
 
 (cl-defmethod phpinspect-project-enqueue-imports
   ((project phpinspect-project) imports)
@@ -237,5 +265,45 @@ before the search is executed."
 (cl-defmethod phpinspect-project-add-file-index ((project phpinspect-project) 
(filename string))
   (phpinspect-project-add-index project (phpinspect-project-index-file project 
filename)))
 
+(defun phpinspect-project-enqueue-include-dirs (project)
+  (interactive (list (phpinspect--cache-get-project-create
+                      (phpinspect--get-or-create-global-cache)
+                      (phpinspect-current-project-root))))
+  (let ((dirs (alist-get 'include-dirs
+                         (alist-get (phpinspect-project-root project)
+                                    phpinspect-projects
+                                    nil nil #'string=))))
+    (dolist (dir dirs)
+      (message "enqueueing dir %s" dir)
+      (phpinspect-worker-enqueue
+       (phpinspect-project-worker project)
+       (phpinspect-make-index-dir-task :dir dir :project project)))))
+
+(defgroup phpinspect '((phpinspect-projects custom-variable))
+  "PHPInspect Configuration")
+
+(defcustom phpinspect-projects nil
+  "PHPInspect Projects."
+  :type '(alist :key-type string
+                :value-type (alist :key-type symbol
+                                   :options ((include-dirs (repeat string))))))
+
+(defun phpinspect-project-add-include-dir (dir)
+  "Configure DIR as an include dir for the current project."
+  (interactive (list (read-directory-name "Include Directory: ")))
+  (custom-set-variables '(phpinspect-projects))
+  (let ((existing
+         (alist-get (phpinspect-current-project-root) phpinspect-projects nil 
#'string=)))
+    (if existing
+        (push dir (alist-get 'include-dirs existing))
+      (push `(,(phpinspect-current-project-root) . ((include-dirs . (,dir)))) 
phpinspect-projects)))
+
+  (customize-save-variable 'phpinspect-projects phpinspect-projects)
+
+  (phpinspect-project-enqueue-include-dirs 
(phpinspect--cache-get-project-create
+                                            
(phpinspect--get-or-create-global-cache)
+                                            
(phpinspect-current-project-root))))
+
+
 (provide 'phpinspect-project)
 ;;; phpinspect-project.el ends here
diff --git a/phpinspect-suggest.el b/phpinspect-suggest.el
index 6851de075c..98c8fd6463 100644
--- a/phpinspect-suggest.el
+++ b/phpinspect-suggest.el
@@ -30,6 +30,11 @@
 (require 'phpinspect-project)
 (require 'phpinspect-class)
 
+(defun phpinspect-suggest-functions (rctx)
+  (let* ((project (phpinspect--resolvecontext-project rctx))
+         (word (cadr (car (last (phpinspect--resolvecontext-subject rctx))))))
+    (phpinspect-project-get-functions project)))
+
 (defun phpinspect-suggest-variables-at-point (resolvecontext)
   (phpinspect--log "Suggesting variables at point")
   (let ((variables))
diff --git a/phpinspect-type.el b/phpinspect-type.el
index 32409b31e3..8fc60064fa 100644
--- a/phpinspect-type.el
+++ b/phpinspect-type.el
@@ -172,10 +172,10 @@ NAMESPACE may be nil, or a string with a namespace FQN."
 (defun phpinspect--make-type-resolver (types &optional token-tree namespace)
   "Little wrapper closure to pass around and resolve types with."
   (let* ((inside-class
-          (if token-tree (or (phpinspect--find-innermost-incomplete-class 
token-tree)
-                             (phpinspect--find-class-token token-tree))))
-         (inside-class-name (if inside-class 
(phpinspect--get-class-name-from-token
-                                              inside-class))))
+          (and token-tree (or (phpinspect--find-innermost-incomplete-class 
token-tree)
+                              (phpinspect--find-class-token token-tree))))
+         (inside-class-name
+          (and inside-class (phpinspect--get-class-name-from-token 
inside-class))))
     (lambda (type)
       (phpinspect--type-resolve
        types
diff --git a/phpinspect-util.el b/phpinspect-util.el
index 76a484026a..190bfec77f 100644
--- a/phpinspect-util.el
+++ b/phpinspect-util.el
@@ -85,22 +85,19 @@ level of START-FILE in stead of `default-directory`."
 
 (phpinspect--declare-log-group 'bam)
 
-(define-inline phpinspect--log (&rest args)
+(defmacro phpinspect--log (&rest args)
   (let ((log-group (alist-get (or load-file-name buffer-file-name) 
phpinspect-log-groups nil nil #'string=)))
-    (push 'list args)
-    (inline-quote
-     (when (and phpinspect--debug
+    `(when (and phpinspect--debug
                 (or (not phpinspect-enabled-log-groups)
                     ,(when log-group
-                       (inline-quote
-                        (member (quote ,log-group) 
phpinspect-enabled-log-groups)))))
+                       `(member (quote ,log-group) 
phpinspect-enabled-log-groups))))
        (with-current-buffer (get-buffer-create "**phpinspect-logs**")
          (unless window-point-insertion-type
            (set (make-local-variable 'window-point-insertion-type) t))
          (goto-char (buffer-end 1))
          (insert (concat "[" (format-time-string "%H:%M:%S") "]: "
                          ,(if log-group (concat "(" (symbol-name log-group) ") 
") "")
-                         (apply #'format ,args) "\n")))))))
+                         (format ,@args) "\n"))))))
 
 (defun phpinspect-filter-logs (group-name)
   (interactive (list (completing-read "Log group: "
diff --git a/phpinspect-worker.el b/phpinspect-worker.el
index c9bc372dc8..70ec5c2fbe 100644
--- a/phpinspect-worker.el
+++ b/phpinspect-worker.el
@@ -29,6 +29,7 @@
 (require 'phpinspect-index)
 (require 'phpinspect-class)
 (require 'phpinspect-queue)
+(require 'phpinspect-pipeline)
 
 (defvar phpinspect-worker nil
   "Contains the phpinspect worker that is used by all projects.")
@@ -124,24 +125,26 @@ already present in the queue."
     (while (phpinspect-worker-continue-running worker)
       ;; This error is used to wake up the thread when new tasks are added to 
the
       ;; queue.
-      (ignore-error 'phpinspect-wakeup-thread
-        (let* ((task (phpinspect-queue-dequeue (phpinspect-worker-queue 
worker)))
-               (mx (make-mutex))
-               (continue (make-condition-variable mx)))
-          (if task
-              ;; Execute task if it belongs to a project that has not been
-              ;; purged (meaning that it is still actively used).
-              (unless (phpinspect-project-purged (phpinspect-task-project 
task))
-                (phpinspect-task-execute task worker))
-            ;; else: join with the main thread until wakeup is signaled
-            (thread-join main-thread))
-
-          ;; Pause for a second after indexing something, to allow user input 
to
-          ;; interrupt the thread.
-          (unless (or (not (input-pending-p))
-                      (phpinspect-worker-skip-next-pause worker))
-            (phpinspect-thread-pause 1 mx continue))
-          (setf (phpinspect-worker-skip-next-pause worker) nil))))
+      (condition-case err
+          (ignore-error 'phpinspect-wakeup-thread
+            (let* ((task (phpinspect-queue-dequeue (phpinspect-worker-queue 
worker)))
+                   (mx (make-mutex))
+                   (continue (make-condition-variable mx)))
+              (if task
+                  ;; Execute task if it belongs to a project that has not been
+                  ;; purged (meaning that it is still actively used).
+                  (unless (phpinspect-project-purged (phpinspect-task-project 
task))
+                    (phpinspect-task-execute task worker))
+                ;; else: join with the main thread until wakeup is signaled
+                (thread-join main-thread))
+
+              ;; Pause for a second after indexing something, to allow user 
input to
+              ;; interrupt the thread.
+              (unless (or (not (input-pending-p))
+                          (phpinspect-worker-skip-next-pause worker))
+                (phpinspect-thread-pause 1 mx continue))
+              (setf (phpinspect-worker-skip-next-pause worker) nil)))
+        (t (message "Phpinspect worker thread errored :%s" err))))
     (phpinspect--log "Worker thread exiting")
     (message "phpinspect worker thread exited")))
 
@@ -236,6 +239,7 @@ already present in the queue."
 (cl-defmethod phpinspect-task-project ((task phpinspect-index-task))
   (phpinspect-index-task-project task))
 
+
 (cl-defmethod phpinspect-task= ((task1 phpinspect-index-task) (task2 
phpinspect-index-task))
   (and (eq (phpinspect-index-task-project task1)
            (phpinspect-index-task-project task2))
@@ -265,7 +269,33 @@ already present in the queue."
              (when root-index
                (phpinspect-project-add-index project root-index)))))))
 
-;;; PARSE BUFFER TASK
+;;; INDEX FILE TASK
+(cl-defstruct (phpinspect-index-dir-task (:constructor 
phpinspect-make-index-dir-task))
+  "A task for the indexation of files"
+  (project nil
+           :type phpinspect-project)
+  (dir nil
+       :type string))
+
+(cl-defmethod phpinspect-task=
+  ((task1 phpinspect-index-dir-task) (task2 phpinspect-index-dir-task))
+  (and (eq (phpinspect-index-dir-task-project task1)
+           (phpinspect-index-dir-task-project task2))
+       (string= (phpinspect-index-dir-task-dir task1)
+                (phpinspect-index-dir-task-dir task2))))
+
+(cl-defmethod phpinspect-task-project ((task phpinspect-index-dir-task))
+  (phpinspect-index-dir-task-project task))
+
+(cl-defmethod phpinspect-task-execute ((task phpinspect-index-dir-task)
+                                       (_worker phpinspect-worker))
+  (phpinspect--log "Entering..")
+  (let* ((project (phpinspect-index-dir-task-project task))
+         (fs (phpinspect-project-fs project))
+         (dir (phpinspect-index-dir-task-dir task)))
+    (phpinspect--log "Indexing directory %s" dir)
+    (phpinspect-pipeline (phpinspect-fs-directory-files-recursively fs dir 
"\\.php$")
+      :into (phpinspect-project-add-file-index :with-context project))))
 
 (provide 'phpinspect-worker)
 ;;; phpinspect-worker.el ends here
diff --git a/phpinspect.el b/phpinspect.el
index c8b66b7399..bfd7346301 100644
--- a/phpinspect.el
+++ b/phpinspect.el
@@ -85,6 +85,7 @@
 
 (defun phpinspect--init-mode ()
   "Initialize the phpinspect minor mode for the current buffer."
+  (phpinspect-ensure-worker)
   (setq phpinspect-current-buffer
         (phpinspect-make-buffer
          :buffer (current-buffer)
@@ -103,7 +104,6 @@
   (eldoc-add-command 'c-electric-paren)
   (eldoc-add-command 'c-electric-backspace)
 
-  (phpinspect-ensure-worker)
   (phpinspect--after-save-action)
 
   (add-hook 'after-save-hook #'phpinspect--after-save-action nil 'local))
@@ -219,9 +219,12 @@ Example configuration:
           ((looking-back "::[A-Za-z_0-9-]*" nil)
            (let ((match (match-string 0)))
              (substring match 2 (length match))))
-          ((looking-back "\\$[A-Za-z_0-9-]*" nil)
+          ((looking-back "\\$[A-Za-z_0-9-]" nil)
            (let ((match (match-string 0)))
-             (substring match 1 (length match))))))
+             (substring match 1 (length match))))
+          ((looking-back "[A-Za-z_0-9-]+" nil t)
+           (message "Matched string %s" (match-string 0))
+           (match-string 0))))
    ((eq command 'post-completion)
     (when (eq 'function (phpinspect--completion-kind
                          (phpinspect--completion-list-get-metadata
@@ -338,7 +341,8 @@ before the search is executed."
     ;; appear frozen while the thread is executing.
     (redisplay)
 
-    (phpinspect-autoloader-refresh autoloader)))
+    (phpinspect-autoloader-refresh autoloader)
+    (phpinspect-project-enqueue-include-dirs project)))
 
 
 (provide 'phpinspect)
diff --git a/test/test-index.el b/test/test-index.el
index 0c49199f8a..cfd3981870 100644
--- a/test/test-index.el
+++ b/test/test-index.el
@@ -181,3 +181,53 @@ return StaticThing::create(new 
ThingFactory())->makeThing((((new Potato())->anti
 
       (should (alist-get 'location index1-class))
       (should (alist-get 'location index1-class)))))
+
+(ert-deftest phpinspect-index-functions ()
+  (let* ((code "<?php
+use Example\\Thing;
+
+function test_func(): array {}
+
+function example(): Thing {}")
+         (tokens (phpinspect-parse-string code))
+         (index (phpinspect--index-tokens tokens))
+         functions)
+
+    (should (setq functions (alist-get 'functions index)))
+    (should (= 2 (length functions)))
+    (should (string= "test_func" (phpinspect--function-name (cadr functions))))
+    (should (string= "example" (phpinspect--function-name (car functions))))
+
+    (should (phpinspect--type= (phpinspect--make-type :name "\\array")
+                               (phpinspect--function-return-type (cadr 
functions))))
+    (should (phpinspect--type= (phpinspect--make-type :name "\\Example\\Thing")
+                               (phpinspect--function-return-type (car 
functions))))))
+
+(ert-deftest phpinspect-index-functions-in-namespace ()
+  (let* ((code "<?php
+namespace Local;
+
+use Example\\Thing;
+
+function test_func(): array {}
+
+function example(Firewall $wall): Thing {}")
+         (tokens (phpinspect-parse-string code))
+         (index (phpinspect--index-tokens tokens))
+         functions)
+
+    (should (setq functions (alist-get 'functions index)))
+    (should (= 2 (length functions)))
+    (should (string= "Local\\test_func" (phpinspect--function-name (cadr 
functions))))
+    (should (string= "Local\\example" (phpinspect--function-name (car 
functions))))
+
+    (should (phpinspect--type= (phpinspect--make-type :name "\\array")
+                               (phpinspect--function-return-type (cadr 
functions))))
+    (should (phpinspect--type= (phpinspect--make-type :name "\\Example\\Thing")
+                               (phpinspect--function-return-type (car 
functions))))
+    (should (= 3 (length (alist-get 'used-types index))))
+    (should (member "Firewall" (alist-get 'used-types index)))
+    (should (member "array" (alist-get 'used-types index)))
+    (should (member "Thing" (alist-get 'used-types index)))
+
+    (should (alist-get 'used-types index))))

Reply via email to