branch: externals/phpinspect commit 870fdb519de9efff9cc54d7f25bc57c68d2c4cd4 Author: Hugo Thunnissen <de...@hugot.nl> Commit: Hugo Thunnissen <de...@hugot.nl>
Optimize process of checking for/loading type dependencies --- phpinspect-project.el | 23 +++++---- phpinspect-type.el | 20 +++++++- phpinspect-typedef.el | 126 ++++++++++++++++++++++++++++++-------------------- 3 files changed, 108 insertions(+), 61 deletions(-) diff --git a/phpinspect-project.el b/phpinspect-project.el index 0aaf24c592..bff03e7b41 100644 --- a/phpinspect-project.el +++ b/phpinspect-project.el @@ -254,16 +254,19 @@ indexation, but indexed synchronously before returning." project (phpinspect-project-index-type-file project (phpi-typedef-name typedef)))) - (dolist (dep (phpi-typedef-get-dependencies typedef)) - (unless (phpi-typedef-initial-index - (phpinspect-project-get-typedef-create project dep)) - (phpinspect-project-add-index - project - (phpinspect-project-index-type-file project dep)))) - - (dolist (extended (phpi-typedef-subscribed-to-types typedef)) - (phpinspect-project-ensure-index-typedef-and-dependencies - project (phpinspect-project-get-typedef-create project extended)))) + (unless (phpi-typedef--dependencies-loaded typedef) + (dolist (dep (phpi-typedef-get-dependencies typedef)) + (unless (phpi-typedef-initial-index + (phpinspect-project-get-typedef-create project dep)) + (phpinspect-project-add-index + project + (phpinspect-project-index-type-file project dep)))) + + (dolist (extended (phpi-typedef-subscribed-to-types typedef)) + (phpinspect-project-ensure-index-typedef-and-dependencies + project (phpinspect-project-get-typedef-create project extended))) + + (setf (phpi-typedef--dependencies-loaded typedef) t))) (cl-defmethod phpinspect-project-get-typedef ((project phpinspect-project) (typedef-fqn phpinspect--type) &optional index) diff --git a/phpinspect-type.el b/phpinspect-type.el index 304b8ee626..7a1610a5dd 100644 --- a/phpinspect-type.el +++ b/phpinspect-type.el @@ -85,7 +85,7 @@ that the collection is expected to contain") (defvar phpinspect--self-type (phpinspect--make-type :name "\\self" :fully-qualified t)) (defvar phpinspect--this-type (phpinspect--make-type :name "\\this" :fully-qualified t)) (defvar phpinspect--null-type (phpinspect--make-type :name "\\null" :fully-qualified t)) -(defvar phpinspect--unknown-type (phpinspect--make-type :name "unknown-type")) +(defvar phpinspect--unknown-type (phpinspect--make-type :name "unknown-type" :fully-qualified t)) (defun phpinspect-define-standard-types () (setq phpinspect-native-types @@ -144,9 +144,25 @@ See https://wiki.php.net/rfc/static_return_type ." (with-memoization (phpinspect--type--bare-name-sym-slot ,type) (phpinspect-intern-name (phpinspect--type-bare-name ,type)))))) -(cl-defmethod phpinspect--type= ((type1 phpinspect--type) (type2 phpinspect--type)) +(defun phpinspect--type= (type1 type2) (eq (phpinspect--type-name-symbol type1) (phpinspect--type-name-symbol type2))) +(defun phpinspect--types-uniq (types) + "Optimized seq-uniq for types." + (let* (table + (filtered (cons nil nil)) + (filtered-rear filtered)) + (dolist (type types) + (let ((name (phpinspect--type-name-symbol type))) + (unless (memq name table) + (setq filtered-rear (setcdr filtered-rear (cons type nil))) + (push name table)))) + + (cdr filtered))) + + + + (defun phpinspect--resolve-type-name (types namespace type) "Get the FQN for TYPE, using TYPES and NAMESPACE as context. diff --git a/phpinspect-typedef.el b/phpinspect-typedef.el index a6f4a659d2..5106b2a0a7 100644 --- a/phpinspect-typedef.el +++ b/phpinspect-typedef.el @@ -52,6 +52,11 @@ non-nil value.") (trait-config nil :documentation "The configuration of traits that are used in this type") + (-dependencies nil + :documentation "cache for dependencies") + (-dependencies-loaded nil + :documentation "Whether dependencies have + been loaded or not. This slot is externally mutated by projects.") (method-adder nil :type phpinspect-method-adder) (subscribed-types nil @@ -88,8 +93,23 @@ non-nil value.") Conditionally executes BODY depending on `phpi-typedef-read-only-p' value." (declare (indent 1)) - `(unless (phpi-typedef-read-only-p ,typedef) - ,@body)) + (let ((typedef-sym (gensym)) + (return-sym (gensym))) + `(let ((,typedef-sym ,typedef) + ,return-sym) + + (cl-assert + (phpinspect-typedef-p ,typedef-sym) t + "First argument of `phpi--typedef-edit' must be of type `phpinspect-typedef'") + + (unless (phpi-typedef-read-only-p ,typedef-sym) + (setq ,return-sym (progn ,@body)) + + ;; Clear cache and unset dependencies loaded. + (setf (phpi-typedef--dependencies ,typedef-sym) nil) + (setf (phpi-typedef--dependencies-loaded ,typedef-sym) nil) + + ,return-sym)))) (cl-defstruct (phpinspect-method-adder (:constructor phpinspect-make-method-adder) @@ -169,29 +189,32 @@ structure returned by `phpinspect--index-trait-use'." (phpi-typedef-get-static-method def (phpinspect-intern-name method-name))) (cl-defmethod phpi-typedef-set-method ((def phpinspect-typedef) (m phpinspect-method) &optional no-propagate) - (phpi-ma-add (phpi-typedef-method-adder def) (phpi-typedef-methods def) m 'overwrite) - (unless no-propagate - (phpi-typedef-trigger-subscriber-method-update def m))) + (phpi--typedef-edit def + (phpi-ma-add (phpi-typedef-method-adder def) (phpi-typedef-methods def) m 'overwrite) + (unless no-propagate + (phpi-typedef-trigger-subscriber-method-update def m)))) (cl-defmethod phpi-typedef-set-method ((def phpinspect-typedef) (fn phpinspect--function) &optional no-propagate) - (phpi-typedef-set-method def (phpinspect-make-method (phpi-typedef-name def) fn) no-propagate)) + (phpi-typedef-set-method def (phpinspect-make-method (phpi-typedef-name def) fn) no-propagate)) (cl-defmethod phpi-typedef-set-static-method ((def phpinspect-typedef) (m phpinspect-method) &optional no-propagate) - (phpi-ma-add (phpi-typedef-method-adder def) (phpi-typedef-static-methods def) m 'overwrite) - (unless no-propagate - (phpi-typedef-trigger-subscriber-method-update def m 'static))) + (phpi--typedef-edit def + (phpi-ma-add (phpi-typedef-method-adder def) (phpi-typedef-static-methods def) m 'overwrite) + (unless no-propagate + (phpi-typedef-trigger-subscriber-method-update def m 'static)))) (cl-defmethod phpi-typedef-set-static-method ((def phpinspect-typedef) (fn phpinspect--function) &optional no-propagate) (phpi-typedef-set-static-method def (phpinspect-make-method (phpi-typedef-name def) fn) no-propagate)) (cl-defmethod phpi-typedef-delete-method ((def phpinspect-typedef) (name (head phpinspect-name))) - (phpi-mcol-delete-for-type - (phpi-typedef-methods def) (phpi-typedef-name def) name) - (phpi-typedef-trigger-subscriber-method-delete def (phpi-typedef-name def) name) + (phpi--typedef-edit def + (phpi-mcol-delete-for-type + (phpi-typedef-methods def) (phpi-typedef-name def) name) + (phpi-typedef-trigger-subscriber-method-delete def (phpi-typedef-name def) name) - (phpi-mcol-delete-for-type - (phpi-typedef-static-methods def) (phpi-typedef-name def) name) - (phpi-typedef-trigger-subscriber-method-delete def (phpi-typedef-name def) name 'static)) + (phpi-mcol-delete-for-type + (phpi-typedef-static-methods def) (phpi-typedef-name def) name) + (phpi-typedef-trigger-subscriber-method-delete def (phpi-typedef-name def) name 'static))) (cl-defmethod phpi-typedef-delete-method ((def phpinspect-typedef) (name string)) (phpi-typedef-delete-method def (phpinspect-intern-name name))) @@ -226,39 +249,42 @@ Note: this function returns all types found in CONFIG." (defun phpi-typedef-add-foreign-members (def foreign-def) "Add methods and properties to DEF from FOREIGN-DEF." - (when foreign-def - (dolist (method (phpi-typedef-get-methods foreign-def)) - (phpi-ma-add (phpi-typedef-method-adder def) (phpi-typedef-methods def) method)) + (phpi--typedef-edit def + (when foreign-def + (dolist (method (phpi-typedef-get-methods foreign-def)) + (phpi-ma-add (phpi-typedef-method-adder def) (phpi-typedef-methods def) method)) - (dolist (method (phpi-typedef-get-static-methods foreign-def)) - (phpi-ma-add (phpi-typedef-method-adder def) (phpi-typedef-static-methods def) method)) + (dolist (method (phpi-typedef-get-static-methods foreign-def)) + (phpi-ma-add (phpi-typedef-method-adder def) (phpi-typedef-static-methods def) method)) - (dolist (var (phpi-typedef-variables foreign-def)) - (phpi-typedef-set-variable def var)))) + (dolist (var (phpi-typedef-variables foreign-def)) + (phpi-typedef-set-variable def var))))) (defun phpi-typedef-subscribe-to-foreign-typedef (def foreign-def) - (push (phpi-typedef-name def) (phpi-typedef-subscribed-types foreign-def)) - (push (phpi-typedef-name foreign-def) (phpi-typedef-subscribed-to-types def))) + (phpi--typedef-edit def + (push (phpi-typedef-name def) (phpi-typedef-subscribed-types foreign-def)) + (push (phpi-typedef-name foreign-def) (phpi-typedef-subscribed-to-types def)))) (defun phpi-typedef-unsubscribe-from-foreign-typedef (def foreign-def) "Unsubscribe DEF from changes in FOREIGN-DEF. This undoes any links and data sharing between this type and any extended classes, used traits or implemented interfaces." + (phpi--typedef-edit def + (setf (phpi-typedef-subscribed-types foreign-def) + (cl-remove (phpi-typedef-name def) (phpi-typedef-subscribed-types foreign-def) + :test #'phpinspect--type=)) - (setf (phpi-typedef-subscribed-types foreign-def) - (cl-remove (phpi-typedef-name def) (phpi-typedef-subscribed-types foreign-def) - :test #'phpinspect--type=)) + (setf (phpi-typedef-subscribed-to-types def) + (cl-remove (phpi-typedef-name foreign-def) (phpi-typedef-subscribed-types def) + :test #'phpinspect--type=)) - (setf (phpi-typedef-subscribed-to-types def) - (cl-remove (phpi-typedef-name foreign-def) (phpi-typedef-subscribed-types def) - :test #'phpinspect--type=)) + ;; Remove all members of foreign typedef + (phpi-mcol-delete-for-type (phpi-typedef-methods def) (phpi-typedef-name foreign-def)) + (phpi-mcol-delete-for-type (phpi-typedef-static-methods def) (phpi-typedef-name foreign-def)) + (dolist (variable (phpi-typedef-variables foreign-def)) + (phpi-typedef-delete-variable def variable)))) - ;; Remove all members of foreign typedef - (phpi-mcol-delete-for-type (phpi-typedef-methods def) (phpi-typedef-name foreign-def)) - (phpi-mcol-delete-for-type (phpi-typedef-static-methods def) (phpi-typedef-name foreign-def)) - (dolist (variable (phpi-typedef-variables foreign-def)) - (phpi-typedef-delete-variable def variable))) (defun phpi-typedef-trigger-subscriber-update (def) "Incorporate DEF into subscribed typedefs." @@ -282,9 +308,10 @@ If STATIC is non-nil, updates static method." "Update subscribers of DEF by deleting METHOD-NAME of origin TYPE." (dolist (subtype (phpi-typedef-subscribed-types def)) (when-let ((foreign-def (phpi--typedef-get-foreign-type def subtype))) - (phpi-mcol-delete-for-type - (if static (phpi-typedef-static-methods foreign-def) (phpi-typedef-methods foreign-def)) - type method-name) + (phpi--typedef-edit foreign-def + (phpi-mcol-delete-for-type + (if static (phpi-typedef-static-methods foreign-def) (phpi-typedef-methods foreign-def)) + type method-name)) (phpi-typedef-trigger-subscriber-method-delete foreign-def type method-name static)))) @@ -443,21 +470,22 @@ them, which are then incorporated into DEF's properties." Return value is a list if structures of the type `phpinspect--type'." - (let ((deps (phpi-typedef-subscribed-to-types def))) - (dolist (method (phpi-typedef-get-methods def)) - (when (phpi-method-return-type method) - (push (phpi-method-return-type method) deps))) + (with-memoization (phpi-typedef--dependencies def) + (let ((deps (phpi-typedef-subscribed-to-types def))) + (dolist (method (phpi-typedef-get-methods def)) + (when (phpi-method-return-type method) + (push (phpi-method-return-type method) deps))) - (dolist (method (phpi-typedef-get-static-methods def)) - (when (phpi-method-return-type method) - (push (phpi-method-return-type method) deps))) + (dolist (method (phpi-typedef-get-static-methods def)) + (when (phpi-method-return-type method) + (push (phpi-method-return-type method) deps))) - (dolist (var (phpi-typedef-variables def)) - (when (phpinspect--variable-type var) - (push (phpinspect--variable-type var) deps))) + (dolist (var (phpi-typedef-variables def)) + (when (phpinspect--variable-type var) + (push (phpinspect--variable-type var) deps))) - (seq-uniq deps #'phpinspect--type=))) + (phpinspect--types-uniq deps)))) (provide 'phpinspect-typedef)