Make project indexation asynchronous using `phpinspect-pipeline'
ci/woodpecker/push/woodpecker Pipeline failed Details

WIP-cache
Hugo Thunnissen 10 months ago
parent 2fd91898a3
commit f003b6a279

@ -27,12 +27,19 @@
(require 'phpinspect-project) (require 'phpinspect-project)
(require 'phpinspect-fs) (require 'phpinspect-fs)
(require 'phpinspect-util) (require 'phpinspect-util)
(require 'phpinspect-pipeline)
(cl-defstruct (phpinspect-psr0 (cl-defstruct (phpinspect-psr0
(:constructor phpinspect-make-psr0-generated)) (:constructor phpinspect-make-psr0-generated))
(prefix nil (prefix nil
:type string :type string
:documentation "The namespace prefix for which the directories contain code.") :documentation "The namespace prefix for which the directories contain code.")
(autoloader nil
:type phpinspect-autoloader)
(own nil
:type boolean)
(fs nil
:type phpinspect-fs)
(directories nil (directories nil
:type list :type list
:documentation :documentation
@ -43,17 +50,17 @@
(prefix nil (prefix nil
:type string :type string
:documentation "The namespace prefix for which the directories contain code.") :documentation "The namespace prefix for which the directories contain code.")
(autoloader nil
:type phpinspect-autoloader)
(own nil
:type boolean)
(fs nil
:type phpinspect-fs)
(directories nil (directories nil
:type list :type list
:documentation :documentation
"The directories that this autoloader finds code in.")) "The directories that this autoloader finds code in."))
(cl-defstruct (phpinspect-classmap
(:constructor phpinspect-make-classmap-generated))
(directories nil
:type list
:documentation
"The directories that this autoloader finds code in."))
(cl-defstruct (phpinspect-autoloader (cl-defstruct (phpinspect-autoloader
(:constructor phpinspect-make-autoloader)) (:constructor phpinspect-make-autoloader))
@ -75,34 +82,29 @@
qualified names congruent with a bareword type name. Keyed by qualified names congruent with a bareword type name. Keyed by
bareword typenames.")) bareword typenames."))
(defun phpinspect-make-autoload-definition-closure (project-root fs typehash) ;; (define-inline phpinspect-directory-lister (dirs &optional fs)
"Create a closure that can be used to `maphash' the autoload ;; (inline-letevals (dirs fs)
section of a composer-json." ;; (inline-quote
(lambda (type prefixes) ;; (let* ((directory (pop ,dirs))
(let ((strategy)) ;; (files
(cond ;; (phpinspect-fs-directory-files ,fs directory))
((string= "psr-0" type) ;; listing)
(maphash ;; (dolist (file files)
(lambda (prefix directory-paths) ;; (if (phpinspect-fs-file-directory-p ,fs file)
(when (stringp directory-paths) (setq directory-paths (list directory-paths))) ;; (push file ,dirs)
(setq strategy (phpinspect-make-psr0-generated :prefix prefix)) ;; (push file listing)))
(dolist (path directory-paths)
(push (concat project-root "/" path) ;; listing))))
(phpinspect-psr0-directories strategy))))
prefixes)) ;; (phpinspect-define-pipeline-step phpinspect-directory-lister phpinspect-directory-lister)
((string= "psr-4" type)
(maphash (cl-defstruct (phpinspect-cj-iter-ctx (:constructor phpinspect-make-cj-iter-ctx))
(lambda (prefix directory-paths) (autoloader nil
(when (stringp directory-paths) (setq directory-paths (list directory-paths))) :type phpinspect-autoloader)
(setq strategy (phpinspect-make-psr4-generated :prefix prefix)) (compiled-dirs nil
(dolist (path directory-paths) :type boolean)
(push (concat project-root "/" path) (dirs nil
(phpinspect-psr4-directories strategy)))) :type list))
prefixes))
(t (phpinspect--log "Unsupported autoload strategy \"%s\" encountered" type)))
(when strategy
(phpinspect-al-strategy-fill-typehash strategy fs typehash)))))
(cl-defmethod phpinspect--read-json-file (fs file) (cl-defmethod phpinspect--read-json-file (fs file)
(with-temp-buffer (with-temp-buffer
@ -110,100 +112,161 @@ section of a composer-json."
(goto-char 0) (goto-char 0)
(phpinspect-json-preset (json-read)))) (phpinspect-json-preset (json-read))))
(cl-defmethod phpinspect-autoloader-refresh ((autoloader phpinspect-autoloader)) (define-inline phpinspect-filename-to-typename (dir filename &optional prefix)
"Refresh autoload definitions by reading composer.json files (inline-quote
from the project and vendor folders." (phpinspect-intern-name
(let* ((project-root (phpinspect-project-root (phpinspect-autoloader-project autoloader))) (replace-regexp-in-string
(fs (phpinspect-project-fs (phpinspect-autoloader-project autoloader))) "[\\\\]+"
(vendor-dir (concat project-root "/vendor")) "\\\\"
(composer-json-path (concat project-root "/composer.json")) (concat "\\"
(composer-json) (or ,prefix "")
(project-autoload ) (replace-regexp-in-string
(type-name-fqn-bags (make-hash-table :test 'eq :size 3000 :rehash-size 3000)) "/" "\\\\"
(own-types (make-hash-table :test 'eq :size 10000 :rehash-size 10000)) (string-remove-suffix
(types (make-hash-table :test 'eq :size 10000 :rehash-size 10000))) ".php"
(string-remove-prefix ,dir ,filename))))))))
(when (phpinspect-fs-file-exists-p fs composer-json-path)
(setq composer-json (phpinspect--read-json-file fs composer-json-path))
(if (hash-table-p composer-json)
(setq project-autoload (gethash "autoload" composer-json))
(phpinspect--log "Error: Parsing %s did not return a hashmap."
composer-json-path)))
(defun phpinspect-find-composer-json-files (fs project-root)
(when project-autoload (let ((cj-path (concat project-root "/composer.json"))
(maphash (phpinspect-make-autoload-definition-closure project-root fs own-types) (vendor-dir (concat project-root "/vendor"))
project-autoload) files)
(when (phpinspect-fs-file-exists-p fs cj-path)
(maphash (phpinspect-make-autoload-definition-closure project-root fs types) (push `(local . ,cj-path) files))
project-autoload))
(when (phpinspect-fs-file-directory-p fs vendor-dir) (when (phpinspect-fs-file-directory-p fs vendor-dir)
(dolist (author-dir (phpinspect-fs-directory-files fs vendor-dir)) (dolist (author-dir (phpinspect-fs-directory-files fs vendor-dir))
(when (phpinspect-fs-file-directory-p fs author-dir) (when (phpinspect-fs-file-directory-p fs author-dir)
(dolist (dependency-dir (phpinspect-fs-directory-files fs author-dir)) (dolist (dependency-dir (phpinspect-fs-directory-files fs author-dir))
(setq cj-path (concat dependency-dir "/composer.json"))
(when (and (phpinspect-fs-file-directory-p fs dependency-dir) (when (and (phpinspect-fs-file-directory-p fs dependency-dir)
(phpinspect-fs-file-exists-p fs (concat dependency-dir "/composer.json"))) (phpinspect-fs-file-exists-p fs cj-path))
(let* ((dependency-json (phpinspect--read-json-file (push `(vendor . ,cj-path) files))))))
fs files))
(concat dependency-dir "/composer.json")))
(dependency-autoload (gethash "autoload" dependency-json))) (cl-defmethod phpinspect-al-strategy-execute ((strat phpinspect-psr4))
(when dependency-autoload (let* ((fs (phpinspect-psr4-fs strat))
(maphash (phpinspect-make-autoload-definition-closure (al (phpinspect-psr4-autoloader strat))
dependency-dir fs types) (own (phpinspect-psr4-own strat))
dependency-autoload)))))))) (own-typehash (phpinspect-autoloader-own-types al))
(typehash (phpinspect-autoloader-types al))
(maphash (lambda (type-fqn _) (prefix (phpinspect-psr4-prefix strat))
(let* ((type-name (phpinspect-intern-name type-fqn)
(car (last (split-string (symbol-name type-fqn) "\\\\"))))) (dolist (dir (phpinspect-psr4-directories strat))
(bag (gethash type-name type-name-fqn-bags))) (dolist (file (phpinspect-fs-directory-files-recursively fs dir "\\.php$"))
(push type-fqn bag) (setq type-fqn (phpinspect-filename-to-typename dir file prefix))
(puthash type-name bag type-name-fqn-bags))) (phpinspect-autoloader-put-type-bag al type-fqn)
types) (puthash type-fqn file typehash)
(when own
(setf (phpinspect-autoloader-own-types autoloader) own-types) (puthash type-fqn file own-typehash))))))
(setf (phpinspect-autoloader-types autoloader) types)
(setf (phpinspect-autoloader-type-name-fqn-bags autoloader) (cl-defmethod phpinspect-al-strategy-execute ((strat phpinspect-psr0))
type-name-fqn-bags))) (let* ((fs (phpinspect-psr0-fs strat))
(al (phpinspect-psr0-autoloader strat))
(own (phpinspect-psr0-own strat))
(own-typehash (phpinspect-autoloader-own-types al))
(typehash (phpinspect-autoloader-types al))
type-fqn)
(dolist (dir (phpinspect-psr0-directories strat))
(dolist (file (phpinspect-fs-directory-files-recursively fs dir "\\.php$"))
(setq type-fqn (phpinspect-filename-to-typename dir file))
(phpinspect-autoloader-put-type-bag al type-fqn)
(puthash type-fqn file typehash)
(when own
(puthash type-fqn file own-typehash))))))
(cl-defmethod phpinspect-autoloader-put-type-bag ((al phpinspect-autoloader) (type-fqn symbol))
(let* ((type-name (phpinspect-intern-name
(car (last (split-string (symbol-name type-fqn) "\\\\")))))
(bag (gethash type-name (phpinspect-autoloader-type-name-fqn-bags al))))
(if bag
(push type-fqn bag)
(push type-fqn bag)
(puthash type-name bag (phpinspect-autoloader-type-name-fqn-bags al)))))
(phpinspect-define-pipeline-step phpinspect-al-strategy-execute phpinspect-al-strategy-execute)
(cl-defmethod phpinspect-iterate-composer-jsons
((al phpinspect-autoloader) file)
(let* ((fs (phpinspect-project-fs (phpinspect-autoloader-project al)))
(project-root (file-name-directory (cdr file)))
(json (phpinspect--read-json-file fs (cdr file)))
(autoload (gethash "autoload" json))
batch)
(when (hash-table-p autoload)
(maphash
(lambda (type prefixes)
(let ((strategy))
(pcase type
("psr-0"
(maphash
(lambda (prefix directory-paths)
(when (stringp directory-paths)
(setq directory-paths (list directory-paths)))
(setq strategy (phpinspect-make-psr0-generated
:autoloader al
:fs fs
:prefix prefix
:own (eq 'local (car file))))
(dolist (path directory-paths)
(push (file-name-concat project-root path)
(phpinspect-psr0-directories strategy))))
prefixes))
("psr-4"
(maphash
(lambda (prefix directory-paths)
(when (stringp directory-paths)
(setq directory-paths (list directory-paths)))
(setq strategy (phpinspect-make-psr4-generated
:fs fs
:autoloader al
:prefix prefix
:own (eq 'local (car file))))
(dolist (path directory-paths)
(push (file-name-concat project-root path)
(phpinspect-psr4-directories strategy))))
prefixes))
(_ (phpinspect--log "Unsupported autoload strategy \"%s\" encountered" type)))
(push strategy batch)))
autoload)
(phpinspect-pipeline-emit-all batch))))
(phpinspect-define-pipeline-step phpinspect-iterate-composer-jsons
phpinspect-iterate-composer-jsons)
(cl-defmethod phpinspect-autoloader-resolve ((autoloader phpinspect-autoloader) (cl-defmethod phpinspect-autoloader-resolve ((autoloader phpinspect-autoloader)
typename-symbol) typename-symbol)
(or (gethash typename-symbol (phpinspect-autoloader-own-types autoloader)) (or (gethash typename-symbol (phpinspect-autoloader-own-types autoloader))
(gethash typename-symbol (phpinspect-autoloader-types autoloader)))) (gethash typename-symbol (phpinspect-autoloader-types autoloader))))
(cl-defmethod phpinspect-autoloader-refresh ((autoloader phpinspect-autoloader) &optional async-callback)
"Refresh autoload definitions by reading composer.json files
from the project and vendor folders."
(let* ((project-root (phpinspect-project-root (phpinspect-autoloader-project autoloader)))
(fs (phpinspect-project-fs (phpinspect-autoloader-project autoloader)))
result error)
(setf (phpinspect-autoloader-type-name-fqn-bags autoloader)
(make-hash-table :test 'eq :size 3000 :rehash-size 3000))
(setf (phpinspect-autoloader-own-types autoloader)
(make-hash-table :test 'eq :size 10000 :rehash-size 10000))
(setf (phpinspect-autoloader-types autoloader)
(make-hash-table :test 'eq :size 10000 :rehash-size 10000))
(phpinspect-pipeline (phpinspect-find-composer-json-files fs project-root)
:async (or async-callback
(lambda (_result error)
(if error
(message "Error during autoloader refresh: %s" error)
(message (concat "Refreshed project autoloader. Found %d types within project,"
" %d types total.")
(hash-table-count (phpinspect-autoloader-own-types autoloader))
(hash-table-count (phpinspect-autoloader-types autoloader))))))
:into (phpinspect-iterate-composer-jsons :with-context autoloader)
:into phpinspect-al-strategy-execute)))
(cl-defmethod phpinspect-autoloader-refresh
(cl-defgeneric phpinspect-al-strategy-fill-typehash (strategy fs typehash)
"Make STRATEGY return a map with type names as keys and the
paths to the files they are defined in as values.")
(defsubst phpinspect-filename-to-typename (dir filename &optional prefix)
(phpinspect-intern-name
(replace-regexp-in-string
"[\\\\]+"
"\\\\"
(concat "\\"
(or prefix "")
(replace-regexp-in-string
"/" "\\\\"
(string-remove-suffix
".php"
(string-remove-prefix dir filename)))))))
(cl-defmethod phpinspect-al-strategy-fill-typehash ((strategy phpinspect-psr0)
fs
typehash)
(dolist (dir (phpinspect-psr0-directories strategy))
(dolist (file (phpinspect-fs-directory-files-recursively fs dir "\\.php$"))
(puthash (phpinspect-filename-to-typename dir file) file typehash))))
(cl-defmethod phpinspect-al-strategy-fill-typehash ((strategy phpinspect-psr4)
fs
typehash)
(let ((prefix (phpinspect-psr4-prefix strategy)))
(dolist (dir (phpinspect-psr4-directories strategy))
(dolist (file (phpinspect-fs-directory-files-recursively fs dir "\\.php$"))
(puthash (phpinspect-filename-to-typename dir file prefix) file typehash)))))
(provide 'phpinspect-autoload) (provide 'phpinspect-autoload)
;;; phpinspect-autoload.el ends here ;;; phpinspect-autoload.el ends here

@ -55,9 +55,9 @@ then returned."
:root project-root :root project-root
:worker (phpinspect-make-dynamic-worker)) :worker (phpinspect-make-dynamic-worker))
(phpinspect--cache-projects cache))) (phpinspect--cache-projects cache)))
(let ((autoload (phpinspect-make-autoloader :project project))) (let ((autoloader (phpinspect-make-autoloader :project project)))
(setf (phpinspect-project-autoload project) autoload) (setf (phpinspect-project-autoload project) autoloader)
(phpinspect-autoloader-refresh autoload))) (phpinspect-autoloader-refresh autoloader)))
project)) project))
(provide 'phpinspect-cache) (provide 'phpinspect-cache)

@ -41,9 +41,8 @@
(defalias 'phpinspect-virtual-file-modification-time #'cadr) (defalias 'phpinspect-virtual-file-modification-time #'cadr)
(defalias 'phpinspect-virtual-file-contents #'car) (defalias 'phpinspect-virtual-file-contents #'car)
(cl-defmethod phpinspect-virtual-fs-set-file ((fs phpinspect-virtual-fs) (defun phpinspect-virtual-fs-set-file (fs path contents)
path (declare (indent defun))
contents)
(puthash path (phpinspect-make-virtual-file contents) (puthash path (phpinspect-make-virtual-file contents)
(phpinspect-virtual-fs-files fs))) (phpinspect-virtual-fs-files fs)))

@ -70,7 +70,7 @@
thread-live (thread-live-p (car thread))) thread-live (thread-live-p (car thread)))
(when thread-live (when thread-live
(if ended (if end
(setq errors (nconc errors (list (format "Thread %s ended pipeline, but is still running" (setq errors (nconc errors (list (format "Thread %s ended pipeline, but is still running"
(thread-name (car thread)))))) (thread-name (car thread))))))
(setq errors (nconc errors (list (format "Thread %s is still running when pipeline is closing" (setq errors (nconc errors (list (format "Thread %s is still running when pipeline is closing"
@ -91,13 +91,19 @@
(signal 'phpinspect-pipeline-error errors)))) (signal 'phpinspect-pipeline-error errors))))
(defmacro phpinspect-pipeline-emit (data) (define-inline phpinspect-pipeline-emit (data)
`(throw 'phpinspect-pipeline-emit ,data)) (inline-letevals (data)
(inline-quote
(throw 'phpinspect-pipeline-emit ,data))))
(defmacro phpinspect-pipeline-emit-all (collection) (define-inline phpinspect-pipeline-emit-all (collection)
`(throw 'phpinspect-pipeline-emit (inline-letevals (collection)
(phpinspect-make-pipeline-emission (inline-quote
:collection ,collection))) (throw 'phpinspect-pipeline-emit
(if ,collection
(phpinspect-make-pipeline-emission
:collection ,collection)
,collection)))))
(defmacro phpinspect-pipeline-end (&optional value) (defmacro phpinspect-pipeline-end (&optional value)
(if value (if value
@ -197,8 +203,8 @@
(end-queue-sym (gensym "end-queue")) (end-queue-sym (gensym "end-queue"))
(ctx-sym (gensym "ctx")) (ctx-sym (gensym "ctx"))
(recv-sym (gensym)) (recv-sym (gensym))
(errors (gensym))
(result-sym (gensym)) (result-sym (gensym))
(seed-sym (gensym))
(collecting-sym (gensym))) (collecting-sym (gensym)))
`(progn `(progn
(when (eq main-thread (current-thread)) (when (eq main-thread (current-thread))
@ -209,13 +215,15 @@
(,queue-sym (phpinspect-make-queue)) (,queue-sym (phpinspect-make-queue))
(,end-queue-sym (phpinspect-make-queue)) (,end-queue-sym (phpinspect-make-queue))
(,collecting-sym t) (,collecting-sym t)
,recv-sym ,result-sym) ,recv-sym ,result-sym ,seed-sym)
,(phpinspect--chain-pipeline-steps steps queue-sym end-queue-sym ctx-sym) ,(phpinspect--chain-pipeline-steps steps queue-sym end-queue-sym ctx-sym)
(phpinspect-pipeline--enqueue (setq ,seed-sym ,seed-form)
,queue-sym (when ,seed-sym
(phpinspect-make-pipeline-emission :collection ,seed-form) 'no-notify) (phpinspect-pipeline--enqueue
,queue-sym
(phpinspect-make-pipeline-emission :collection ,seed-form) 'no-notify))
(phpinspect-pipeline--enqueue (phpinspect-pipeline--enqueue
,queue-sym (phpinspect-make-pipeline-end :thread (current-thread))) ,queue-sym (phpinspect-make-pipeline-end :thread (current-thread)))
@ -249,7 +257,7 @@
(lambda () (lambda ()
(condition-case err (condition-case err
(let ((,result ,(append '(phpinspect--pipeline) (list seed-form) macro-params))) (let ((,result ,(append '(phpinspect--pipeline) (list seed-form) macro-params)))
(funcall ,async ,result nil)) (funcall ,async (or ,result 'phpinspect-pipeline-nil-result) nil))
(t (funcall ,async nil err)))) (t (funcall ,async nil err))))
"phpinspect-pipeline-async") "phpinspect-pipeline-async")
,(append '(phpinspect--pipeline) (list seed-form) macro-params))))) ,(append '(phpinspect--pipeline) (list seed-form) macro-params)))))
@ -257,11 +265,11 @@
(define-inline phpinspect-pipeline-receive (queue) (define-inline phpinspect-pipeline-receive (queue)
(inline-letevals (queue) (inline-letevals (queue)
`(or (phpinspect-queue-dequeue ,queue) (inline-quote
(let ((mx (make-mutex))) (let ((val))
(with-mutex mx (while (not (setq val (phpinspect-queue-dequeue ,queue)))
(condition-wait (make-condition-variable mx "phpinspect-pipeline-receive"))) (thread-yield))
(phpinspect-queue-dequeue ,queue))))) val))))
(defun phpinspect-pipeline-step-name (name &optional suffix) (defun phpinspect-pipeline-step-name (name &optional suffix)
(intern (concat (symbol-name name) (if suffix (concat "-" suffix) "")))) (intern (concat (symbol-name name) (if suffix (concat "-" suffix) ""))))
@ -275,17 +283,16 @@
(define-inline phpinspect-pipeline--enqueue (queue emission &optional no-notify) (define-inline phpinspect-pipeline--enqueue (queue emission &optional no-notify)
(inline-letevals (queue emission no-notify) (inline-letevals (queue emission no-notify)
(inline-quote (inline-quote
(if (and (phpinspect-pipeline-emission-p ,emission) (when ,emission
(phpinspect-pipeline-emission-collection ,emission)) (if (phpinspect-pipeline-emission-p ,emission)
(progn (when (phpinspect-pipeline-emission-collection ,emission)
(while (cdr (phpinspect-pipeline-emission-collection ,emission)) (while (cdr (phpinspect-pipeline-emission-collection ,emission))
(phpinspect-queue-enqueue
,queue (pop (phpinspect-pipeline-emission-collection ,emission))
,no-notify))
(phpinspect-queue-enqueue (phpinspect-queue-enqueue
,queue (pop (phpinspect-pipeline-emission-collection ,emission)) ,queue (pop (phpinspect-pipeline-emission-collection ,emission)) ,no-notify))
,no-notify)) (phpinspect-queue-enqueue ,queue ,emission ,no-notify))))))
(phpinspect-queue-enqueue
,queue (pop (phpinspect-pipeline-emission-collection ,emission)) ,no-notify))
(phpinspect-queue-enqueue ,queue ,emission ,no-notify)))))
(defmacro phpinspect-define-pipeline-step (name function-name) (defmacro phpinspect-define-pipeline-step (name function-name)
(unless (symbolp name) (unless (symbolp name)
@ -320,7 +327,6 @@
(out-queue (gensym "queue")) (out-queue (gensym "queue"))
(context-sym (gensym "context")) (context-sym (gensym "context"))
(continue-running (gensym "continue-running")) (continue-running (gensym "continue-running"))
(original-thread (gensym "original-thread"))
(pctx-sym (gensym "pipeline-ctx")) (pctx-sym (gensym "pipeline-ctx"))
(incoming-end (gensym "incoming-end")) (incoming-end (gensym "incoming-end"))
(end (gensym "end"))) (end (gensym "end")))
@ -330,8 +336,7 @@
(setq statement (nconc statement (list context-sym)))) (setq statement (nconc statement (list context-sym))))
(inline-quote (inline-quote
(let ((,original-thread (current-thread)) (let ((,inc-queue ,queue)
(,inc-queue ,queue)
(,out-queue ,consumer-queue) (,out-queue ,consumer-queue)
(,context-sym ,context) (,context-sym ,context)
(,pctx-sym ,pipeline-ctx)) (,pctx-sym ,pipeline-ctx))
@ -345,33 +350,29 @@
(condition-case err (condition-case err
(progn (progn
(phpinspect-pipeline-pause) (phpinspect-pipeline-pause)
(catch 'phpinspect-pipeline-break (setq ,incoming (phpinspect-pipeline-receive ,inc-queue))
(while ,continue-running
(setq ,incoming (phpinspect-pipeline-receive ,inc-queue)) (if (phpinspect-pipeline-end-p ,incoming)
(if (phpinspect-pipeline-end-p ,incoming) (progn
(setq ,incoming-end ,incoming)
(when (phpinspect-pipeline-end-value ,incoming)
(progn (progn
(setq ,incoming-end ,incoming) (setq ,incoming (phpinspect-pipeline-end-value ,incoming)
(when (phpinspect-pipeline-end-value ,incoming) ,outgoing ,statement)
(progn (phpinspect-pipeline--enqueue ,out-queue ,outgoing 'no-notify)))
(setq ,incoming (phpinspect-pipeline-end-value ,incoming)
,outgoing ,statement) (setq ,end (phpinspect-make-pipeline-end :thread (current-thread)))
(phpinspect-pipeline--enqueue ,out-queue ,outgoing 'no-notify))) (phpinspect-pipeline-ctx-register-end ,pctx-sym ,end)
(setq ,continue-running nil)
(setq ,end (phpinspect-make-pipeline-end :thread (current-thread))) (phpinspect-pipeline--enqueue ,out-queue ,end))
(phpinspect-pipeline-ctx-register-end ,pctx-sym ,end)
(setq ,continue-running nil) ;; Else
(phpinspect-pipeline--enqueue ,out-queue ,end)) (setq ,outgoing ,statement)
(when (phpinspect-pipeline-end-p ,outgoing)
;; Else (setq ,end (phpinspect-make-pipeline-end :thread (current-thread)))
(setq ,outgoing ,statement) (phpinspect-pipeline-ctx-register-end ,pctx-sym ,end)
(when (phpinspect-pipeline-end-p ,outgoing) (setq ,continue-running nil))
(setq ,end (phpinspect-make-pipeline-end :thread (current-thread))) (phpinspect-pipeline--enqueue ,out-queue ,outgoing)))
(phpinspect-pipeline-ctx-register-end ,pctx-sym ,end)
(setq ,continue-running nil))
(phpinspect-pipeline--enqueue ,out-queue ,outgoing))
(when ,end
(throw 'phpinspect-pipeline-break nil)))))
(phpinspect-pipeline-incoming) (phpinspect-pipeline-incoming)
(t (phpinspect--log "Pipeline thread errored: %s" err) (t (phpinspect--log "Pipeline thread errored: %s" err)
(setq ,end (phpinspect-make-pipeline-end :thread (current-thread) :error err)) (setq ,end (phpinspect-make-pipeline-end :thread (current-thread) :error err))

@ -352,11 +352,15 @@ before the search is executed."
(phpinspect--get-or-create-global-cache) (phpinspect--get-or-create-global-cache)
(phpinspect-current-project-root))) (phpinspect-current-project-root)))
(autoloader (phpinspect-project-autoload project))) (autoloader (phpinspect-project-autoload project)))
(phpinspect-autoloader-refresh autoloader) ;; Update display so that it is clear to the user that emacs is
(message (concat "Refreshed project autoloader. Found %d types within project," ;; responsive. Otherwise the autoloader refresh thread hogging the cpu will
" %d types total.") ;; make it look like emacs is not responsive, especially when M-x uses some
(hash-table-count (phpinspect-autoloader-own-types autoloader)) ;; kind of completion framework, in which case the completion popup will
(hash-table-count (phpinspect-autoloader-types autoloader))))) ;; appear frozen while the thread is executing.
(redisplay)
(phpinspect-autoloader-refresh autoloader)))
(provide 'phpinspect) (provide 'phpinspect)
;;; phpinspect.el ends here ;;; phpinspect.el ends here

@ -28,91 +28,73 @@
(require 'phpinspect-fs) (require 'phpinspect-fs)
(require 'phpinspect-autoload) (require 'phpinspect-autoload)
(ert-deftest phpinspect-psr0-fill-typehash () (ert-deftest phpinspect-find-composer-json-files ()
(let* ((fs (phpinspect-make-virtual-fs)) (let* ((fs (phpinspect-make-virtual-fs))
(typehash (make-hash-table :size 10 :test 'eq)) (autoloader (phpinspect-make-autoloader
(autoload :project (phpinspect--make-project :root "/root" :fs fs))))
(phpinspect-make-psr0-generated :prefix "App\\"))) (phpinspect-virtual-fs-set-file fs
"/root/composer.json"
(phpinspect-virtual-fs-set-file "{ \"autoload\": { \"psr-4\": {\"WoW\\\\Dwarves\\\\\": \"src/\"}}}")
fs "/home/user/projects/app/src/App/Services/SuperService.php" "")
(phpinspect-virtual-fs-set-file
fs "/home/user/projects/app/src/Kernel.php" "")
(phpinspect-virtual-fs-set-file
fs "/home/user/projects/app/src/App/Controller/Banana.php" "")
(phpinspect-virtual-fs-set-file
fs "/home/user/projects/app/lib/Mailer_Lib.php" "")
(setf (phpinspect-psr0-directories autoload) (list "/home/user/projects/app/src/" (phpinspect-virtual-fs-set-file fs
"/home/user/projects/app/lib/")) "/root/vendor/runescape/client/composer.json"
"{\"autoload\": { \"psr-0\": {\"Runescape\\\\Banana\\\\\": [\"src/\", \"lib\"]}}}")
(phpinspect-al-strategy-fill-typehash autoload fs typehash)
(should-not (hash-table-empty-p typehash)) (phpinspect-virtual-fs-set-file fs
"/root/vendor/apples/pears/composer.json"
"{\"autoload\": { \"psr-0\": {\"Runescape\\\\Banana\\\\\": [\"src/\", \"lib\"]}}}")
(should (string= "/home/user/projects/app/src/App/Services/SuperService.php" (let ((sorter (lambda (file1 file2) (string-lessp (cdr file1) (cdr file2)))))
(gethash (phpinspect-intern-name "\\App\\Services\\SuperService")
typehash)))
(should (string= "/home/user/projects/app/src/Kernel.php"
(gethash (phpinspect-intern-name "\\Kernel")
typehash)))
(should (string= "/home/user/projects/app/src/App/Controller/Banana.php"
(gethash (phpinspect-intern-name "\\App\\Controller\\Banana")
typehash)))
(should (string= "/home/user/projects/app/lib/Mailer_Lib.php" (should (equal (sort '((vendor . "/root/vendor/apples/pears/composer.json")
(gethash (phpinspect-intern-name "\\Mailer_Lib") (vendor . "/root/vendor/runescape/client/composer.json")
typehash))))) (local . "/root/composer.json"))
sorter)
(sort (phpinspect-find-composer-json-files fs "/root")
sorter))))))
(ert-deftest phpinspect-psr4-fill-typehash () (ert-deftest phpinspect-autoload-composer-json-iterator ()
(let* ((fs (phpinspect-make-virtual-fs)) (let* ((fs (phpinspect-make-virtual-fs))
(typehash (make-hash-table :size 10 :test 'eq)) (autoloader (phpinspect-make-autoloader
(autoload :project (phpinspect--make-project :root "/root" :fs fs)))
(phpinspect-make-psr4-generated :prefix "App\\"))) result error)
(phpinspect-virtual-fs-set-file
fs "/home/user/projects/app/src/Services/SuperService.php" "")
(phpinspect-virtual-fs-set-file (phpinspect-virtual-fs-set-file fs
fs "/home/user/projects/app/src/Kernel.php" "") "/root/composer.json"
"{ \"autoload\": { \"psr-4\": {\"WoW\\\\Dwarves\\\\\": \"src/\"}}}")
(phpinspect-virtual-fs-set-file (phpinspect-virtual-fs-set-file fs
fs "/home/user/projects/app/src/Controller/Banana.php" "") "/root/vendor/runescape/client/composer.json"
"{\"autoload\": { \"psr-0\": {\"Runescape\\\\Banana\\\\\": [\"src/\", \"lib\"]}}}")
(phpinspect-virtual-fs-set-file
fs "/home/user/projects/app/lib/Mailer_Lib.php" "")
(setf (phpinspect-psr4-directories autoload) (list "/home/user/projects/app/src/" (phpinspect-virtual-fs-set-file fs
"/home/user/projects/app/lib/")) "/root/vendor/apples/pears/composer.json"
"{\"autoload\": { \"psr-0\": {\"Runescape\\\\Banana\\\\\": [\"src/\", \"lib\"]},
\"psr-4\": {\"Another\\\\Namespace\\\\\": [\"separate/\"]}}}")
(phpinspect-al-strategy-fill-typehash autoload fs typehash) (phpinspect-pipeline (phpinspect-find-composer-json-files fs "/root")
:async (lambda (res err)
(setq result res
error err))
:into (phpinspect-iterate-composer-jsons :with-context autoloader))
(should-not (hash-table-empty-p typehash)) (while (not (or result error))
(thread-yield))
(should (string= "/home/user/projects/app/src/Services/SuperService.php" (should-not error)
(gethash (phpinspect-intern-name "\\App\\Services\\SuperService")
typehash)))
(should (string= "/home/user/projects/app/src/Kernel.php"
(gethash (phpinspect-intern-name "\\App\\Kernel")
typehash)))
(should (string= "/home/user/projects/app/src/Controller/Banana.php"
(gethash (phpinspect-intern-name "\\App\\Controller\\Banana")
typehash)))
(should (string= "/home/user/projects/app/lib/Mailer_Lib.php" (should (= 4 (length result)))
(gethash (phpinspect-intern-name "\\App\\Mailer_Lib") (should (= 2 (length (seq-filter #'phpinspect-psr0-p result))))
typehash))))) (should (= 2 (length (seq-filter #'phpinspect-psr4-p result))))))
(ert-deftest phpinspect-autoloader-refresh () (ert-deftest phpinspect-al-strategy-execute ()
(let* ((fs (phpinspect-make-virtual-fs)) (let* ((fs (phpinspect-make-virtual-fs))
(project (phpinspect--make-project
:fs fs
:root "/project/root"))
(autoloader (phpinspect-make-autoloader (autoloader (phpinspect-make-autoloader
:project project))) :project (phpinspect--make-project :root "/project/root" :fs fs)))
result error)
(phpinspect-virtual-fs-set-file (phpinspect-virtual-fs-set-file
fs fs
"/project/root/composer.json" "/project/root/composer.json"
@ -144,7 +126,17 @@
(phpinspect-virtual-fs-set-file (phpinspect-virtual-fs-set-file
fs "/project/root/vendor/not-runescape/wow/src/TestClass.php" "") fs "/project/root/vendor/not-runescape/wow/src/TestClass.php" "")
(phpinspect-autoloader-refresh autoloader) (phpinspect-pipeline (phpinspect-find-composer-json-files fs "/project/root")
:async (lambda (res err)
(setq result res
error err))
:into (phpinspect-iterate-composer-jsons :with-context autoloader)
:into phpinspect-al-strategy-execute)
(while (not (or result error))
(thread-yield))
(should-not error)
(should-not (hash-table-empty-p (phpinspect-autoloader-own-types autoloader))) (should-not (hash-table-empty-p (phpinspect-autoloader-own-types autoloader)))
(should-not (hash-table-empty-p (phpinspect-autoloader-types autoloader))) (should-not (hash-table-empty-p (phpinspect-autoloader-types autoloader)))
@ -152,4 +144,8 @@
(should (string= "/project/root/vendor/runescape/client/src/Runescape/Banana/App.php" (should (string= "/project/root/vendor/runescape/client/src/Runescape/Banana/App.php"
(phpinspect-autoloader-resolve (phpinspect-autoloader-resolve
autoloader autoloader
(phpinspect-intern-name "\\Runescape\\Banana\\App")))))) (phpinspect-intern-name "\\Runescape\\Banana\\App"))))
(should (string= "/project/root/vendor/not-runescape/wow/src/TestClass.php"
(phpinspect-autoloader-resolve
autoloader
(phpinspect-intern-name "\\WoW\\Dwarves\\TestClass"))))))

Loading…
Cancel
Save