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

Reply via email to