branch: externals/phpinspect commit fdbaf15279083f67d344d2e008e57013cb263ce9 Author: Hugo Thunnissen <de...@hugot.nl> Commit: Hugo Thunnissen <de...@hugot.nl>
fix: prevent errors caused by (for now unsupported) anonymous classes --- phpinspect-buffer.el | 43 ++++++++++++++++++++---------------------- phpinspect-index.el | 13 +++++++++---- phpinspect-type.el | 10 +++++++++- test/test-buffer-indexation.el | 7 +++++++ test/test-index.el | 6 ++++++ 5 files changed, 51 insertions(+), 28 deletions(-) diff --git a/phpinspect-buffer.el b/phpinspect-buffer.el index c41a2fd11e..c6053686dd 100644 --- a/phpinspect-buffer.el +++ b/phpinspect-buffer.el @@ -429,27 +429,25 @@ DECLARATION must be an object of type `phpinspect-meta'." (unless (phpinspect-comment-p comment-before) (setq comment-before nil)) - (pcase-let* ((`(,imports ,namespace-name) - (phpinspect-buffer-get-index-context-for-token buffer class)) - (type-resolver (phpinspect--make-type-resolver - (phpinspect--uses-to-types imports) - (phpinspect-meta-token class) - namespace-name)) - (typedef (phpinspect-buffer-get-typedef-for-class-token buffer class)) - (indexed (phpinspect--index-function-from-scope - type-resolver scope comment-before))) - - (unless typedef (error "Unable to find typedef for class %s" (phpinspect-meta-string class))) + (when-let ((typedef (phpinspect-buffer-get-typedef-for-class-token buffer class))) + (pcase-let* ((`(,imports ,namespace-name) + (phpinspect-buffer-get-index-context-for-token buffer class)) + (type-resolver (phpinspect--make-type-resolver + (phpinspect--uses-to-types imports) + (phpinspect-meta-token class) + namespace-name)) + (indexed (phpinspect--index-function-from-scope + type-resolver scope comment-before))) - ;; Add function to class - (unless (phpinspect--function-anonymous-p indexed) - (if static - (phpi-typedef-set-static-method typedef indexed) - (phpi-typedef-set-method typedef indexed))) + ;; Add function to class + (unless (phpinspect--function-anonymous-p indexed) + (if static + (phpi-typedef-set-static-method typedef indexed) + (phpi-typedef-set-method typedef indexed))) - (phpinspect-buffer-set-index-reference-for-token - buffer (phpinspect-meta-token func) - (cons (phpi-typedef-name typedef) indexed))))) + (phpinspect-buffer-set-index-reference-for-token + buffer (phpinspect-meta-token func) + (cons (phpi-typedef-name typedef) indexed)))))) (defun phpinspect-buffer--index-function (buffer func) (if-let ((class (phpinspect-buffer-find-token-ancestor-matching buffer func #'phpinspect-class-p))) @@ -562,11 +560,10 @@ DECLARATION must be an object of type `phpinspect-meta'." (phpinspect--make-type-resolver (phpinspect--uses-to-types imports) (phpinspect-meta-token class) - namespace-name)) - (typedef (phpinspect-buffer-get-typedef-for-class-token buffer class))) - + namespace-name))) - (when-let ((indexed + (when-let ((typedef (phpinspect-buffer-get-typedef-for-class-token buffer class)) + (indexed (phpinspect-make-property (phpi-typedef-name typedef) (if (phpinspect-const-p (phpinspect-meta-token var)) diff --git a/phpinspect-index.el b/phpinspect-index.el index ee9f1f27d2..717cc765e5 100644 --- a/phpinspect-index.el +++ b/phpinspect-index.el @@ -327,6 +327,8 @@ SCOPE should be a scope token (`phpinspect-scope-p')." (if static static-methods methods))))) (list static-methods methods))) +(defvar phpinspect--anon-class-counter 0) + (defun phpinspect--index-class (imports type-resolver location-resolver class &optional doc-block) "Create an alist with relevant attributes of a parsed class." (phpinspect--log "INDEXING CLASS") @@ -354,6 +356,8 @@ SCOPE should be a scope token (`phpinspect-scope-p')." (pcase-setq `(,class-name ,extends ,implements ,used-types) (phpinspect--index-class-declaration (cadr class) type-resolver class)) + (unless class-name + (throw 'phpinspect--unnamed-class nil)) (dolist (token (caddr class)) (cond ((phpinspect-scope-p token) @@ -493,10 +497,11 @@ NAMESPACE will be assumed the root namespace if not provided" (cond ((phpinspect-doc-block-p token) (setq comment-before token)) ((phpinspect-class-p token) - (push (phpinspect--index-class - imports (funcall type-resolver-factory imports token namespace) - location-resolver token comment-before) - indexed) + (when-let ((class (catch 'phpinspect--unnamed-class + (phpinspect--index-class + imports (funcall type-resolver-factory imports token namespace) + location-resolver token comment-before)))) + (push class indexed)) (setq comment-before nil)))) indexed)) diff --git a/phpinspect-type.el b/phpinspect-type.el index 91bfa807bb..3a54e23404 100644 --- a/phpinspect-type.el +++ b/phpinspect-type.el @@ -406,7 +406,15 @@ mutability of the variable") (cadr subtoken))) (defun phpinspect--index-class-declaration (decl type-resolver parent) - ;; Find out what the class extends or implements + "Parse DECL into semantically categorized types, resolved using TYPE-RESOLVER. + +PARENT is expected to be the class token that DECL is located in. + +This function returns a list of 4 values which are in this order: +- the class name (as a resolved type) +- a list of types that the class extends (classes or interfaces) +- a list of types that the class implements (interfaces) +- A list of class names as encountered in the declaration token (used types)" (let (encountered-extends encountered-implements class-name extends implements used-types) (dolist (word decl) diff --git a/test/test-buffer-indexation.el b/test/test-buffer-indexation.el index adda846f47..a6140adafa 100644 --- a/test/test-buffer-indexation.el +++ b/test/test-buffer-indexation.el @@ -44,6 +44,13 @@ without errors being thrown." (insert "a") (phpinspect-buffer-update-project-index buffer)))) +(ert-deftest phpinspect-index-anonymous-class-return () + "Confirm that anonymous classes can be parsed/indexed without errors. +Does not test any related functionalities." + (with-temp-buffer + (let ((buffer (phpinspect-claim-buffer (current-buffer) (phpinspect--make-dummy-project)))) + (insert "return new class() { private ?\\DateTime $d; public function __construct() {}") + (phpinspect-buffer-update-project-index buffer)))) (provide 'test-buffer-indexation) ;;; test-buffer-indexation.el ends here diff --git a/test/test-index.el b/test/test-index.el index 2a61580fcd..e884eb2f11 100644 --- a/test/test-index.el +++ b/test/test-index.el @@ -416,6 +416,12 @@ public function doStuff() (should (phpi-method-return-type method)) (should (phpinspect--type= type (phpi-method-return-type method)))))))) +(ert-deftest phpinspect-index-skip-anonymous-class () + (should-not + (seq-filter + #'cdr + (cdr (phpinspect--index-tokens (phpinspect-parse-string "return new class() { public array $foo; };")))))) + (ert-deftest phpinspect-index-nested-functions () (with-temp-buffer (let* ((code "<php