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

    Replace phpinspect--class with new phpinspect-typedef structure
    
    Typedef is more flexible and allows for more finegrained management of 
methods
    and their origins.
---
 phpinspect-buffer.el                  |  38 ++--
 phpinspect-cache.el                   |   4 +-
 phpinspect-class-struct.el            |  78 --------
 phpinspect-class.el                   | 291 ----------------------------
 phpinspect-completion.el              |  26 ++-
 phpinspect-eldoc.el                   |  25 +--
 phpinspect-imports.el                 |   5 -
 phpinspect-index.el                   |  27 +--
 phpinspect-method-cell.el             | 158 ++++++++++++++-
 phpinspect-project-struct.el          |  14 +-
 phpinspect-project.el                 | 171 ++++++++--------
 phpinspect-resolve.el                 |  63 +++---
 phpinspect-resolvecontext.el          |   4 +-
 phpinspect-serialize.el               |   4 +-
 phpinspect-suggest.el                 |  21 +-
 phpinspect-type.el                    |  24 ++-
 phpinspect-typedef.el                 | 355 ++++++++++++++++++++++++++++++++++
 phpinspect-worker.el                  |   2 +-
 phpinspect.el                         |   2 +-
 test/fixtures/IndexClass1-indexed.eld |   2 +-
 test/fixtures/IndexClass2-indexed.eld |   2 +-
 test/phpinspect-test.el               |   2 +-
 test/test-autoload.el                 |   2 +-
 test/test-buffer.el                   |  62 +++---
 test/test-class.el                    | 176 ++++++++---------
 test/test-eldoc.el                    |   2 +-
 test/test-index.el                    |  88 +++++----
 test/test-typedef.el                  |  75 +++++++
 28 files changed, 976 insertions(+), 747 deletions(-)

diff --git a/phpinspect-buffer.el b/phpinspect-buffer.el
index a056807776..2dafc97e59 100644
--- a/phpinspect-buffer.el
+++ b/phpinspect-buffer.el
@@ -23,7 +23,6 @@
 
 ;;; Code:
 
-(require 'phpinspect-class)
 (require 'phpinspect-parser)
 (require 'phpinspect-bmap)
 (require 'phpinspect-edtrack)
@@ -32,6 +31,7 @@
 (require 'phpinspect-resolvecontext)
 (require 'phpinspect-resolve)
 (require 'phpinspect-util)
+(require 'phpinspect-typedef)
 
 (phpinspect--declare-log-group 'buffer)
 
@@ -158,24 +158,24 @@ linked with."
   (cond ((phpinspect-class-p token)
          (when-let ((class (gethash token (phpinspect-buffer-token-index 
buffer))))
            (remhash token (phpinspect-buffer-token-index buffer))
-           (phpinspect-project-delete-class (phpinspect-buffer-project buffer) 
class)))
+           (phpinspect-project-delete-typedef (phpinspect-buffer-project 
buffer) class)))
         ((or (phpinspect-const-p token) (phpinspect-variable-p token))
          (when-let ((var (gethash token (phpinspect-buffer-token-index 
buffer))))
            (remhash token (phpinspect-buffer-token-index buffer))
-           (when-let ((class (phpinspect-project-get-class
+           (when-let ((class (phpinspect-project-get-typedef
                               (phpinspect-buffer-project buffer)
                               (car var))))
-             (phpinspect--class-delete-variable class (cdr var)))))
+             (phpi-typedef-delete-variable class (cdr var)))))
         ((phpinspect-function-p token)
          (when-let ((func (gethash token (phpinspect-buffer-token-index 
buffer))))
            (remhash token (phpinspect-buffer-token-index buffer))
            (cond ((phpinspect-project-p (car func))
                   (phpinspect-project-delete-function 
(phpinspect-buffer-project buffer) (phpinspect--function-name-symbol (cdr 
func))))
                  ((phpinspect--type-p (car func))
-                  (when-let ((class (phpinspect-project-get-class
+                  (when-let ((class (phpinspect-project-get-typedef
                                      (phpinspect-buffer-project buffer)
                                      (car func))))
-                    (phpinspect--class-delete-method class (cdr func))))
+                    (phpi-typedef-delete-method class (cdr func))))
                  (t (error "Invalid index location")))))
         (t (error "Cannot delete index for token %s" token))))
 
@@ -241,11 +241,11 @@ linked with."
           (dolist (deleted deleted-classes)
             (if (and (setq class (phpinspect-buffer-get-index-for-token
                                   buffer (phpinspect-meta-token deleted)))
-                     (setq replaced (assoc (phpinspect--class-declaration 
class) new-declarations #'equal)))
+                     (setq replaced (assoc (phpi-typedef-declaration class) 
new-declarations #'equal)))
                 (pcase-let ((`(,imports ,namespace-name) 
(phpinspect-get-token-index-context namespaces buffer-imports (cdr replaced))))
                   (phpinspect-buffer-update-index-reference-for-token
                    buffer (phpinspect-meta-token deleted) 
(phpinspect-meta-token (cdr replaced)))
-                  (phpinspect--class-update-declaration class (car replaced) 
imports namespace-name)
+                  (phpi-typedef-update-declaration class (car replaced) 
imports namespace-name nil)
                   (push (cdr replaced) indexed))
               (phpinspect-buffer-delete-index-for-token buffer 
(phpinspect-meta-token deleted))))
 
@@ -260,9 +260,9 @@ linked with."
                                              (phpinspect-class-block 
(phpinspect-meta-token (cdr class)))
                                              namespace-name)))
                 (when class-name
-                  (setq  class-obj (phpinspect-project-get-class-create 
project class-name 'no-enqueue))
+                  (setq  class-obj (phpinspect-project-get-typedef-create 
project class-name 'no-enqueue))
                   (phpinspect-buffer-set-index-reference-for-token buffer 
(phpinspect-meta-token (cdr class)) class-obj)
-                  (phpinspect--class-update-declaration class-obj (car class) 
imports namespace-name))))))
+                  (phpi-typedef-update-declaration class-obj (car class) 
imports namespace-name nil))))))
       ;; Else: Index all classes
       (setf (phpinspect-buffer-classes buffer) (phpinspect-make-toc classes))
       (phpinspect-splayt-traverse (class classes)
@@ -276,9 +276,9 @@ linked with."
                                        namespace-name)))
                      (class-obj))
           (when class-name
-            (setq class-obj (phpinspect-project-get-class-create project 
class-name 'no-enqueue))
+            (setq class-obj (phpinspect-project-get-typedef-create project 
class-name 'no-enqueue))
             (phpinspect-buffer-set-index-reference-for-token buffer 
(phpinspect-meta-token class) class-obj)
-            (phpinspect--class-update-declaration class-obj 
(phpinspect-meta-token declaration) imports namespace-name)))))))
+            (phpi-typedef-update-declaration class-obj (phpinspect-meta-token 
declaration) imports namespace-name nil)))))))
 
 (cl-defmethod phpinspect-buffer-index-functions ((buffer phpinspect-buffer) 
(functions (head phpinspect-splayt)))
   (let ((classes (phpinspect-buffer-classes buffer))
@@ -331,14 +331,14 @@ linked with."
                              type-resolver
                              scope
                              (and (phpinspect-comment-p comment-before) 
comment-before)))
-              (unless (phpinspect--function-anonyous-p indexed)
+              (unless (phpinspect--function-anonymous-p indexed)
                 (if static
-                    (phpinspect--class-set-static-method class-obj indexed)
-                  (phpinspect--class-set-method class-obj indexed)))
+                    (phpi-typedef-set-static-method class-obj indexed)
+                  (phpi-typedef-set-method class-obj indexed)))
 
               (phpinspect-buffer-set-index-reference-for-token
                buffer (phpinspect-meta-token func)
-               (cons (phpinspect--class-name class-obj) indexed))))
+               (cons (phpi-typedef-name class-obj) indexed))))
         ;; Else: index function
         (pcase-let ((`(,imports ,namespace-name) 
(phpinspect-get-token-index-context namespaces imports func))
                     (comment-before (phpinspect-meta-find-left-sibling func)))
@@ -432,15 +432,15 @@ linked with."
 
           (when (and (phpinspect-variable-p (phpinspect-meta-token var)) (not 
(phpinspect--variable-type indexed)))
             (setf (phpinspect--variable-type indexed)
-                  (phpinspect--class-resolve-property-type
+                  (phpi-typedef-resolve-property-type
                    class-obj (phpinspect-buffer-project buffer)
                    (cadr (phpinspect-meta-token var)) type-resolver class)))
 
-          (phpinspect--class-set-variable class-obj indexed)
+          (phpi-typedef-set-variable class-obj indexed)
 
           (phpinspect-buffer-set-index-reference-for-token
            buffer (phpinspect-meta-token var)
-           (cons (phpinspect--class-name class-obj) indexed)))))))
+           (cons (phpi-typedef-name class-obj) indexed)))))))
 
 (cl-defmethod phpinspect-buffer-reset ((buffer phpinspect-buffer))
   (setf (phpinspect-buffer-tree buffer) nil)
diff --git a/phpinspect-cache.el b/phpinspect-cache.el
index d8f2d1265f..643872300e 100644
--- a/phpinspect-cache.el
+++ b/phpinspect-cache.el
@@ -102,7 +102,7 @@ as keys and project caches as values."))
     (phpinspect--log "Getting stub class for %s" fqn)
     (catch 'return
       (maphash (lambda (_name project)
-                 (when-let ((class (phpinspect-project-get-class project fqn)))
+                 (when-let ((class (phpinspect-project-get-typedef project 
fqn)))
                    (throw 'return class)))
                (phpinspect--cache-projects stub-cache)))))
 
@@ -176,7 +176,7 @@ then returned."
                        (phpinspect--make-project
                         :fs (phpinspect-make-fs)
                         :root project-root
-                        :extra-class-retriever 
(phpinspect--cache-extra-class-retriever cache)
+                        :extra-typedef-retriever 
(phpinspect--cache-extra-class-retriever cache)
                         :extra-function-retriever 
(phpinspect--cache-extra-function-retriever cache)
                         :worker (phpinspect-make-dynamic-worker))
                        (phpinspect--cache-projects cache)))
diff --git a/phpinspect-class-struct.el b/phpinspect-class-struct.el
deleted file mode 100644
index 9b7131c1ad..0000000000
--- a/phpinspect-class-struct.el
+++ /dev/null
@@ -1,78 +0,0 @@
-;;; phpinspect-class-struct.el --- PHP parsing and completion package  -*- 
lexical-binding: t; -*-
-
-;; Copyright (C) 2021-2023  Free Software Foundation, Inc
-
-;; Author: Hugo Thunnissen <de...@hugot.nl>
-;; Keywords: php, languages, tools, convenience
-;; Version: 1.2.1
-
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;;; Code:
-
-
-(cl-defstruct (phpinspect--class (:constructor 
phpinspect--make-class-generated))
-  (class-retriever nil
-                   :type lambda
-                   :documentaton
-                   "A function that returns classes for types
-(should accept `phpinspect--type' as argument)")
-
-  (read-only-p nil
-               :type boolean
-               :documentation
-               "Whether this class instance is read-only, meaning that its data
-should never be changed. Methods and functions that are meant to
-manipulate class data should become no-ops when this slot has a
-non-nil value.")
-  (index nil
-         :type phpinspect--indexed-class
-         :documentation
-         "The index that this class is derived from")
-  (methods (make-hash-table :test 'eq :size 20 :rehash-size 20)
-           :type hash-table
-           :documentation
-           "All methods, including those from extended classes.")
-  (static-methods (make-hash-table :test 'eq :size 20 :rehash-size 20)
-                  :type hash-table
-                  :documentation
-                  "All static methods this class provides,
-                  including those from extended classes.")
-  (name nil
-        :type phpinspect--type)
-  (variables nil
-             :type list
-             :documentation
-             "Variables that belong to this class.")
-  (extended-classes nil
-                    :type list
-                    :documentation
-                    "All extended/implemented classes.")
-  (subscriptions (make-hash-table :test #'eq :size 10 :rehash-size 1.5)
-                 :type hash-table
-                 :documentation
-                 "A list of subscription functions that should be
-                 called whenever anything about this class is
-                 updated")
-  (declaration nil)
-  (initial-index nil
-                 :type bool
-                 :documentation
-                 "A boolean indicating whether or not this class
-                 has been indexed yet."))
-
-
-(provide 'phpinspect-class-struct)
diff --git a/phpinspect-class.el b/phpinspect-class.el
deleted file mode 100644
index 012dc7cbbf..0000000000
--- a/phpinspect-class.el
+++ /dev/null
@@ -1,291 +0,0 @@
-;;; phpinspect-class.el --- A model for php type definitions  -*- 
lexical-binding: t; -*-
-
-;; Copyright (C) 2021-2023  Free Software Foundation, Inc
-
-;; Author: Hugo Thunnissen <de...@hugot.nl>
-;; Keywords: php, languages, tools, convenience
-;; Version: 1.2.1
-
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'phpinspect-type)
-(require 'phpinspect-class-struct)
-
-(defmacro phpinspect--class-edit (class &rest body)
-  "Declare intent to edit CLASS in BODY.
-
-Conditionally executes BODY depending on
-`phpinspect--class-read-only-p' value."
-  (declare (indent 1))
-  `(unless (phpinspect--class-read-only-p ,class)
-     ,@body))
-
-(cl-defmethod phpinspect--class-trigger-update ((class phpinspect--class))
-  (dolist (sub (hash-table-values (phpinspect--class-subscriptions class)))
-    (funcall sub class)))
-
-(cl-defmethod phpinspect--class-update-extensions ((class phpinspect--class) 
extensions)
-  (phpinspect--class-edit class
-    (setf (phpinspect--class-extended-classes class)
-          (seq-filter
-           #'phpinspect--class-p
-           (mapcar
-            (lambda (class-name)
-              (funcall (phpinspect--class-class-retriever class) class-name))
-            extensions)))
-
-    (dolist (extended (phpinspect--class-extended-classes class))
-      (phpinspect--class-incorporate class extended))))
-
-
-(cl-defmethod phpinspect--class-set-index ((class phpinspect--class)
-                                           (index (head 
phpinspect--indexed-class)))
-  (phpinspect--class-edit class
-    (setf (phpinspect--class-declaration class) (alist-get 'declaration index))
-    (setf (phpinspect--class-name class) (alist-get 'class-name index))
-
-    ;; Override methods when class seems syntactically correct (has balanced 
braces)
-    (when (alist-get 'complete index)
-      (let ((methods (phpinspect--class-methods class))
-            (static-methods (phpinspect--class-static-methods class)))
-
-        (dolist (method (hash-table-values methods))
-          (unless (phpinspect--function--inherited method)
-            (remhash (phpinspect--function-name-symbol method) methods)))
-        (dolist (method (hash-table-values static-methods))
-          (unless (phpinspect--function--inherited method)
-            (remhash (phpinspect--function-name-symbol method) 
static-methods)))))
-
-    (setf (phpinspect--class-initial-index class) t)
-    (setf (phpinspect--class-index class) index)
-
-  (dolist (method (alist-get 'methods index))
-    (phpinspect--class-update-method class method))
-
-  (dolist (method (alist-get 'static-methods index))
-    (phpinspect--class-update-static-method class method))
-
-  (setf (phpinspect--class-variables class)
-        (append (alist-get 'variables index)
-                (alist-get 'constants index)
-                (alist-get 'static-variables index)))
-
-  (phpinspect--class-update-extensions
-   class `(,@(alist-get 'implements index) ,@(alist-get 'extends index)))
-
-  (phpinspect--class-trigger-update class)))
-
-(cl-defmethod phpinspect--class-update-declaration
-  ((class phpinspect--class) declaration imports namespace-name)
-  (phpinspect--class-edit class
-    (pcase-let ((`(,class-name ,extends ,implements ,_used-types)
-                 (phpinspect--index-class-declaration
-                  declaration (phpinspect--make-type-resolver
-                               (phpinspect--uses-to-types imports) nil 
namespace-name))))
-      (setf (phpinspect--class-name class) class-name)
-      (setf (phpinspect--class-declaration class) declaration)
-      (phpinspect--class-update-extensions class `(,@extends ,@implements)))))
-
-(cl-defmethod phpinspect--class-get-method ((class phpinspect--class) 
(method-name (head phpinspect-name)))
-  (gethash method-name (phpinspect--class-methods class)))
-
-(cl-defmethod phpinspect--class-get-method ((class phpinspect--class) 
(method-name string))
-  (phpinspect--class-get-method class (phpinspect-intern-name method-name)))
-
-(cl-defmethod phpinspect--class-get-static-method ((class phpinspect--class) 
(method-name (head phpinspect-name)))
-  (gethash method-name (phpinspect--class-static-methods class)))
-
-(cl-defmethod phpinspect--class-get-static-method ((class phpinspect--class) 
(method-name string))
-  (phpinspect--class-get-static-method class (phpinspect-intern-name 
method-name)))
-
-
-(cl-defmethod phpinspect--class-get-variable
-  ((class phpinspect--class) (variable-name string))
-  (catch 'found
-    (dolist (variable (phpinspect--class-variables class))
-      (when (string= variable-name (phpinspect--variable-name variable))
-        (throw 'found variable)))))
-
-(cl-defmethod phpinspect--class-set-variable ((class phpinspect--class)
-                                              (var phpinspect--variable))
-  (phpinspect--class-edit class
-    (push var (phpinspect--class-variables class))))
-
-(cl-defmethod phpinspect--class-delete-variable ((class phpinspect--class)
-                                                 (var phpinspect--variable))
-  (phpinspect--class-edit class
-    (setf (phpinspect--class-variables class)
-          (seq-filter (lambda (clvar) (not (eq var clvar)))
-                      (phpinspect--class-variables class)))))
-
-(cl-defmethod phpinspect--class-get-variables ((class phpinspect--class))
-  (seq-filter #'phpinspect--variable-vanilla-p (phpinspect--class-variables 
class)))
-
-(cl-defmethod phpinspect--class-get-static-variables ((class 
phpinspect--class))
-  (seq-filter #'phpinspect--variable-static-p (phpinspect--class-variables 
class)))
-
-(cl-defmethod phpinspect--class-get-constants ((class phpinspect--class))
-  (seq-filter #'phpinspect--variable-const-p (phpinspect--class-variables 
class)))
-
-(cl-defmethod phpinspect--add-method-copy-to-map
-  ((map hash-table)
-   (class-name phpinspect--type)
-   (method phpinspect--function))
-  (setq method (phpinspect--copy-function method))
-
-  (setf (phpinspect--function-return-type method)
-        (phpinspect--resolve-late-static-binding
-         (phpinspect--function-return-type method)
-         class-name))
-
-  (puthash (phpinspect--function-name-symbol method)
-           method
-           map)
-  method)
-
-(cl-defmethod phpinspect--class-set-method ((class phpinspect--class)
-                                            (method phpinspect--function)
-                                            &optional extended)
-  (phpinspect--class-edit class
-    (phpinspect--log "Adding method by name %s to class"
-                     (phpinspect--function-name method))
-    (setq method (phpinspect--add-method-copy-to-map
-                  (phpinspect--class-methods class)
-                  (phpinspect--class-name class)
-                  method))
-    (when extended
-      (setf (phpinspect--function--inherited method) extended))))
-
-(cl-defmethod phpinspect--class-set-static-method ((class phpinspect--class)
-                                                   (method 
phpinspect--function)
-                                                   &optional extended)
-  (phpinspect--class-edit class
-    (setq method (phpinspect--add-method-copy-to-map
-                  (phpinspect--class-static-methods class)
-                  (phpinspect--class-name class)
-                  method))
-
-    (when extended
-      (setf (phpinspect--function--inherited method) extended))))
-
-
-
-(cl-defmethod phpinspect--class-delete-method ((class phpinspect--class) 
(method phpinspect--function))
-  (phpinspect--class-edit class
-    (remhash (phpinspect--function-name-symbol method) 
(phpinspect--class-static-methods class))
-    (remhash (phpinspect--function-name-symbol method) 
(phpinspect--class-methods class))))
-
-(cl-defmethod phpinspect--class-get-method-return-type
-  ((class phpinspect--class) (method-name (head phpinspect-name)))
-  (let ((method (phpinspect--class-get-method class method-name)))
-    (when method
-      (phpinspect--function-return-type method))))
-
-(cl-defmethod phpinspect--class-get-static-method-return-type
-  ((class phpinspect--class) (method-name (head phpinspect-name)))
-  (let ((method (phpinspect--class-get-static-method class method-name)))
-    (when method
-      (phpinspect--function-return-type method))))
-
-(cl-defmethod phpinspect--class-get-method-list ((class phpinspect--class))
-  (hash-table-values (phpinspect--class-methods class)))
-
-(cl-defmethod phpinspect--class-get-static-method-list ((class 
phpinspect--class))
-  (hash-table-values (phpinspect--class-static-methods class)))
-
-
-(cl-defmethod phpinspect--merge-method ((class-name phpinspect--type)
-                                        (existing phpinspect--function)
-                                        (method phpinspect--function)
-                                        &optional extended)
-  (let ((new-return-type (phpinspect--resolve-late-static-binding
-                          (phpinspect--function-return-type method)
-                          class-name)))
-    (unless (phpinspect--type= new-return-type phpinspect--null-type)
-      (phpinspect--log "method return type %s" 
(phpinspect--function-return-type method))
-      (setf (phpinspect--function-return-type existing)
-            new-return-type))
-
-    (setf (phpinspect--function--inherited existing)
-          extended)
-
-    (setf (phpinspect--function-arguments existing)
-          (phpinspect--function-arguments method)))
-  existing)
-
-(cl-defmethod phpinspect--class-update-static-method ((class phpinspect--class)
-                                                      (method 
phpinspect--function)
-                                                      &optional extended)
-  (phpinspect--class-edit class
-    (let ((existing (gethash (phpinspect--function-name-symbol method)
-                             (phpinspect--class-static-methods class))))
-      (if existing
-          (phpinspect--merge-method (phpinspect--class-name class) existing 
method extended)
-        (phpinspect--class-set-static-method class method extended)))))
-
-(cl-defmethod phpinspect--class-update-method ((class phpinspect--class)
-                                               (method phpinspect--function)
-                                               &optional extended)
-  (phpinspect--class-edit class
-    (let* ((existing (gethash (phpinspect--function-name-symbol method)
-                              (phpinspect--class-methods class))))
-
-      (if existing
-          (phpinspect--merge-method (phpinspect--class-name class) existing 
method extended)
-        (phpinspect--class-set-method class method extended)))))
-
-(define-inline phpinspect--scope-inherits-p (scope)
-  "Returns non-nil when FN has a public or protected scope."
-  (inline-letevals (scope)
-    (inline-quote (or (phpinspect-public-p ,scope)
-                      (phpinspect-protected-p ,scope)))))
-
-(define-inline phpinspect--function-inherits-p (fn)
-  (inline-quote (phpinspect--scope-inherits-p (phpinspect--function-scope 
,fn))))
-
-;; FIXME: Remove inherited methods when they no longer exist in parent classes
-;; (and/or the current class in the case of abstract methods).
-;; TODO: Check if above comment is still accurate ^^
-(cl-defmethod phpinspect--class-incorporate ((class phpinspect--class)
-                                             (other-class phpinspect--class))
-  (phpinspect--class-edit class
-    (dolist (method (phpinspect--class-get-method-list other-class))
-      (when (phpinspect--function-inherits-p method)
-        (phpinspect--class-update-method class method 'extended)))
-
-    (dolist (method (phpinspect--class-get-static-method-list other-class))
-      (when (phpinspect--function-inherits-p method)
-        (phpinspect--class-update-static-method class method 'extended)))
-
-    (phpinspect--class-subscribe class other-class)))
-
-(cl-defmethod phpinspect--class-subscribe ((class phpinspect--class)
-                                           (subscription-class 
phpinspect--class))
-  (phpinspect--class-edit class
-    (unless (gethash subscription-class (phpinspect--class-subscriptions 
class))
-      (let ((update-function
-             (lambda (new-class)
-               (phpinspect--class-edit class
-                 (phpinspect--class-incorporate class new-class)
-                 (phpinspect--class-trigger-update class)))))
-        (puthash subscription-class update-function
-                 (phpinspect--class-subscriptions subscription-class))))))
-
-
-(provide 'phpinspect-class)
-;;; phpinspect-class.el ends here
diff --git a/phpinspect-completion.el b/phpinspect-completion.el
index d0c4675888..15a585ec64 100644
--- a/phpinspect-completion.el
+++ b/phpinspect-completion.el
@@ -244,25 +244,35 @@ Returns list of `phpinspect--completion'."
     (phpinspect--log "Returning completion list %s" completion-list)
     (setq phpinspect--last-completion-list completion-list)))
 
-(cl-defmethod phpinspect--make-completion
-  ((completion-candidate phpinspect--function))
-  "Create a `phpinspect--completion` for COMPLETION-CANDIDATE."
+
+(defun phpinspect-make-fn-completion (completion-candidate)
   (phpinspect--construct-completion
-   :value (phpinspect--function-name completion-candidate)
+   :value (phpi-fn-name completion-candidate)
    :meta (concat "(" (mapconcat (lambda (arg)
                                   (concat "$" (if (> (length (car arg)) 8)
                                                   (truncate-string-to-width 
(car arg) 8 nil)
                                                 (car arg))))
-                                (phpinspect--function-arguments 
completion-candidate)
+                                (phpi-fn-arguments completion-candidate)
                                 ", ")
                  ") "
-                 (phpinspect--display-format-type-name 
(phpinspect--function-return-type completion-candidate)))
+                 (phpinspect--display-format-type-name (phpi-fn-return-type 
completion-candidate)))
    :annotation (concat " "
                        (phpinspect--type-bare-name
-                        (phpinspect--function-return-type 
completion-candidate)))
+                        (phpi-fn-return-type completion-candidate)))
    :target completion-candidate
    :kind 'function))
 
+
+(cl-defmethod phpinspect--make-completion
+  ((completion-candidate phpinspect--function))
+  "Create a `phpinspect--completion` for COMPLETION-CANDIDATE."
+  (phpinspect-make-fn-completion completion-candidate))
+
+(cl-defmethod phpinspect--make-completion
+  ((completion-candidate phpinspect-method))
+  "Create a `phpinspect--completion` for COMPLETION-CANDIDATE."
+  (phpinspect-make-fn-completion completion-candidate))
+
 (cl-defmethod phpinspect--make-completion
   ((completion-candidate phpinspect--variable))
   (phpinspect--construct-completion
@@ -312,7 +322,7 @@ Returns list of `phpinspect--completion'."
                      (when (and (eq 'finished state)
                                 (eq 'function (phpinspect--completion-kind 
comp)))
                        (insert "(")
-                       (when (= 0 (length (phpinspect--function-arguments
+                       (when (= 0 (length (phpi-fn-arguments
                                            (phpinspect--completion-target 
comp))))
                          (insert ")")))))
                  :company-kind (lambda (comp-name)
diff --git a/phpinspect-eldoc.el b/phpinspect-eldoc.el
index 538a9d2732..7974f3496d 100644
--- a/phpinspect-eldoc.el
+++ b/phpinspect-eldoc.el
@@ -84,30 +84,30 @@ be implemented for return values of 
`phpinspect-eld-strategy-execute'")
     (setq type-before (phpinspect-resolve-type-from-context rctx nil t))
 
     (when type-before
-      (let ((class (phpinspect-project-get-class-extra-or-create
+      (let ((class (phpinspect-project-get-typedef-extra-or-create
                     (phpinspect--resolvecontext-project rctx)
                     type-before 'no-enqueue))
             (attribute-name (cadadr attrib))
             variable method result)
         (when attribute-name
           (cond ((phpinspect-static-attrib-p attrib)
-                 (setq variable (phpinspect--class-get-variable class 
attribute-name))
+                 (setq variable (phpi-typedef-get-variable class 
attribute-name))
 
                  (if (and variable
                           (or (phpinspect--variable-static-p variable)
                               (phpinspect--variable-const-p variable)))
                      (setq result variable)
-                   (setq method (phpinspect--class-get-static-method
+                   (setq method (phpi-typedef-get-static-method
                                  class (phpinspect-intern-name 
attribute-name)))
                    (when method
                      (setq result (phpinspect-make-function-doc :fn method)))))
                 ((phpinspect-object-attrib-p attrib)
-                 (setq variable (phpinspect--class-get-variable class 
attribute-name))
+                 (setq variable (phpi-typedef-get-variable class 
attribute-name))
 
                  (if (and variable
                           (phpinspect--variable-vanilla-p variable))
                      (setq result variable)
-                   (setq method (phpinspect--class-get-method
+                   (setq method (phpi-typedef-get-method
                                  class (phpinspect-intern-name 
attribute-name)))
                    (when method
                      (setq result (phpinspect-make-function-doc :fn 
method))))))
@@ -170,6 +170,7 @@ be implemented for return values of 
`phpinspect-eld-strategy-execute'")
        ((setq match-result (phpinspect--match-sequence (last statement 2)
                              :f (phpinspect-meta-wrap-token-pred 
#'phpinspect-attrib-p)
                              :f (phpinspect-meta-wrap-token-pred 
#'phpinspect-list-p)))
+        (phpinspect--log "Eldoc context is a method call")
 
         (setq arg-list (car (last match-result))
               static (phpinspect-static-attrib-p (phpinspect-meta-token (car 
match-result)))
@@ -189,11 +190,12 @@ be implemented for return values of 
`phpinspect-eld-strategy-execute'")
         (when-let* ((type-of-previous-statement
                      (phpinspect-resolve-type-from-context rctx nil t))
                     (method-name (cadadr (phpinspect-meta-token (car 
match-result))))
-                    (class (phpinspect-rctx-get-or-create-cached-project-class
+
+                    (class (phpinspect-rctx-get-typedef
                             rctx type-of-previous-statement 'no-enqueue))
                     (method (if static
-                                (phpinspect--class-get-static-method class 
method-name)
-                              (phpinspect--class-get-method class 
method-name))))
+                                (phpi-typedef-get-static-method class 
method-name)
+                              (phpi-typedef-get-method class method-name))))
 
           (when method
             (phpinspect-make-function-doc :fn method :arg-pos arg-pos))))
@@ -231,12 +233,13 @@ be implemented for return values of 
`phpinspect-eld-strategy-execute'")
       :type phpinspect--function)
   (arg-pos nil))
 
+
 (cl-defmethod phpinspect-eldoc-string ((doc phpinspect-function-doc))
   (let ((fn (phpinspect-function-doc-fn doc))
         (arg-pos (phpinspect-function-doc-arg-pos doc))
         (arg-count 0))
     (concat (truncate-string-to-width
-             (phpinspect--function-name fn) phpinspect-eldoc-word-width) ": ("
+             (phpi-fn-name fn) phpinspect-eldoc-word-width) ": ("
              (mapconcat
               (lambda (arg)
                 (let ((doc-string
@@ -250,10 +253,10 @@ be implemented for return values of 
`phpinspect-eld-strategy-execute'")
                            doc-string 'face 
'eldoc-highlight-function-argument)))
                   (setq arg-count (+ arg-count 1))
                   doc-string))
-              (phpinspect--function-arguments fn)
+              (phpi-fn-arguments fn)
               ", ")
              "): "
-              (phpinspect--display-format-type-name 
(phpinspect--function-return-type fn)))))
+              (phpinspect--display-format-type-name (phpi-fn-return-type 
fn)))))
 
 (defvar phpinspect-eldoc-strategies (list (phpinspect-make-eld-attribute)
                                           (phpinspect-make-eld-function-args)
diff --git a/phpinspect-imports.el b/phpinspect-imports.el
index 41743f15b6..f481c8ca00 100644
--- a/phpinspect-imports.el
+++ b/phpinspect-imports.el
@@ -378,11 +378,6 @@ that there are import (\"use\") statements for them."
             (phpinspect-add-use-statements-for-missing-types
              used-types buffer (append imports namespace-imports) project 
token-meta)
 
-            (with-current-buffer (get-buffer-create 
"attempt-before-namespace-removal-code")
-              (erase-buffer)
-              (insert (with-current-buffer (phpinspect-buffer-buffer buffer) 
(buffer-string))))
-
-
             (phpinspect-remove-unneeded-use-statements
              used-types buffer (append imports namespace-imports) token-meta)
 
diff --git a/phpinspect-index.el b/phpinspect-index.el
index 12b226241b..59f55aa374 100644
--- a/phpinspect-index.el
+++ b/phpinspect-index.el
@@ -181,7 +181,7 @@ function (think \"new\" statements, return types etc.)."
      :token php-func
      :name (concat (if namespace (concat namespace "\\") "") name)
      :throws throws
-     :return-type (or type phpinspect--null-type)
+     :return-type type
      :arguments arguments)))
 
 (define-inline phpinspect--safe-cadr (list)
@@ -329,6 +329,7 @@ SCOPE should be a scope token (`phpinspect-scope-p')."
   "Create an alist with relevant attributes of a parsed class."
   (phpinspect--log "INDEXING CLASS")
   (let ((methods)
+        (trait-config)
         (static-methods)
         (static-variables)
         (variables)
@@ -414,9 +415,10 @@ SCOPE should be a scope token (`phpinspect-scope-p')."
 
             ;; Prevent comments from sticking around too long
             ((and (phpinspect-use-p token) (phpinspect-word-p (cadr token)))
-             ;; FIXME: Actually implement indexation of trait usage. This just
-             ;; marks the type as used for now.
-             (push (cadadr token) used-types))
+             ;; Trait use statement
+             (setq trait-config
+                   (nconc trait-config
+                          (phpinspect--index-trait-use token type-resolver 
add-used-types))))
             (t
              (phpinspect--log "Unsetting comment-before")
              (setq comment-before nil))))
@@ -458,6 +460,7 @@ SCOPE should be a scope token (`phpinspect-scope-p')."
     `(,class-name .
                   (phpinspect--indexed-class
                    (complete . ,(not (phpinspect-incomplete-class-p class)))
+                   (trait-confg . ,trait-config)
                    (class-name . ,class-name)
                    (declaration . ,(seq-find #'phpinspect-declaration-p class))
                    (location . ,(funcall location-resolver class))
@@ -560,13 +563,13 @@ NAMESPACE will be assumed the root namespace if not 
provided"
              (setq function (phpinspect--index-function-from-scope
                              type-resolver `(:public ,token) comment-before 
add-used-types
                              namespace))
-             (unless (phpinspect--function-anonyous-p function)
+             (unless (phpinspect--function-anonymous-p function)
              (push function functions)))
             ((phpinspect-block-or-list-p token)
              (dolist (fn (phpinspect--index-functions-in-tokens
                           (cdr token) type-resolver-factory imports namespace
                           add-used-types type-resolver))
-               (unless (phpinspect--function-anonyous-p fn)
+               (unless (phpinspect--function-anonymous-p fn)
                  (push fn functions))))))
 
     functions))
@@ -710,10 +713,10 @@ Returns a list of type name strings."
 
 (defun phpinspect--index-trait-use (token type-resolver add-used-types)
   (cl-assert (phpinspect-use-p token))
-  (setq token (cddr (seq-filter #'phpinspect-not-comment-p token)))
+  (setq token (cdr (seq-filter #'phpinspect-not-comment-p token)))
 
   (let ((block? (car (last token)))
-        used-types config match)
+        used-types config)
     (when (phpinspect-end-of-statement-p block?)
       (setq token (butlast token)))
 
@@ -721,7 +724,7 @@ Returns a list of type name strings."
 
     (dolist (word token)
       (when (phpinspect-word-p word)
-        (push (cadr token) used-types)
+        (push (cadr word) used-types)
         (push `(,(funcall type-resolver (phpinspect--make-type :name (cadr 
word))))
               config)))
 
@@ -762,9 +765,11 @@ Returns a list of type name strings."
                    (push `(alias ,(cadadr (cadr block?)) ,(cadr (nth 3 
block?)))
                          (cdr t-config))))
 
-               (setq block? (nthcdr 4 block?)))))
+               (setq block? (nthcdr 4 block?))))))
 
-      config)))
+    (when add-used-types
+      (funcall add-used-types used-types))
+    config))
 
 (provide 'phpinspect-index)
 ;;; phpinspect-index.el ends here
diff --git a/phpinspect-method-cell.el b/phpinspect-method-cell.el
index 1b7b81823f..0fe412fe24 100644
--- a/phpinspect-method-cell.el
+++ b/phpinspect-method-cell.el
@@ -24,17 +24,35 @@
 ;;; Code:
 
 (require 'cl-macs)
+(require 'phpinspect-util)
+(require 'phpinspect-type)
 
 (cl-defstruct (phpinspect-method
-               (:constructor phpinspect-make-method)
-               (:conc-name phpi-method-))
+               (:constructor phpinspect-make-method-generated)
+               (:conc-name phpi-method-)
+               (:copier phpi-copy-method))
   (name nil
         :type phpinspect-name)
+  (aliased-from nil
+                :type phpinspect-name)
   (origin-type nil
                :type phpinspect--type)
   (definition  nil
                :type phpinspect--function))
 
+(defun phpinspect-make-method (origin-type definition)
+  "Create a method for ORIGIN-TYPE, defined in DEFINITION.
+
+ORIGIN-TYPE must be a structure of type `phpinspect--type'.
+DEFINITION must be a structure of type `phpinspect--function'."
+  (phpinspect-make-method-generated
+   :name (phpinspect--function-name-symbol definition)
+   :origin-type origin-type
+   :definition definition))
+
+(defun phpi-method-name-string (method)
+  (phpinspect-name-string (phpi-method-name method)))
+
 (cl-defstruct (phpinspect-method-cell
                (:constructor phpinspect-make-method-cell)
                (:conc-name phpi-mc-))
@@ -58,6 +76,14 @@
          :type alist
          :documentation "<phpinspect-name, phpinspect-method-cell>"))
 
+(defun phpi-mcol-set-home-type (mcol type)
+  "Set home type of MCOL to TYPE.
+
+Also updates all members of MCOL with the same origin-type."
+  (setf (phpi-mcol-home-type mcol) type)
+  (dolist (method (phpi-mcol-list-own mcol))
+    (setf (phpi-method-origin-type method) type)))
+
 (defun phpi-mcol-find-cell (mcol method-name &optional remove)
   (cl-assert (phpinspect-name-p method-name))
 
@@ -72,24 +98,61 @@
 
     cell))
 
-(defun phpi-mcol-add (mcol method)
+(defun phpi-mcol-add (mcol method &optional overwrite)
   (let ((cell (phpi-mcol-find-cell-create mcol (phpi-method-name method))))
-    (phpi-mc-set cell (phpi-mcol-home-type mcol) (phpi-method-origin-type 
method) method)
-    cell))
+    ;; insert when not present or overwriting
+    (when (or (not (phpi-mc-get-for-type-category
+                    cell (phpi-mcol-home-type mcol) (phpi-method-origin-type 
method))))
+              overwrite)
+      (phpi-mc-set cell (phpi-mcol-home-type mcol) (phpi-method-origin-type 
method) method)
+      cell))
+
+(defun phpi-mcol-list-own (mcol)
+  (let (list)
+    (dolist (cons (phpi-mcol-cells mcol))
+      (when-let ((method (phpi-mc-own (cdr cons))))
+        (push method list)))
+    list))
+
+(defun phpi-mcol-list-active (mcol)
+  "List all active methods in MCOL."
+  (let (list)
+    (dolist (cons (phpi-mcol-cells mcol))
+      (when-let ((method (phpi-mc-get-active (cdr cons))))
+        (push method list)))
+    list))
 
+(defun phpi-method-set-return-type (method type)
+  (setf (phpinspect--function-return-type (phpi-method-definition method))
+        type))
 
 (defun phpi-mc-set (cell home-type origin-type method)
-  (if (phpinspect--type= home-type
-                         origin-type)
+  (if (phpinspect--type= home-type origin-type)
       ;; Method belongs to home type
-      (setf (phpi-mc-own cell) method)
+      (progn
+        (when (and method
+                   (phpi-method-return-type method)
+                   (phpinspect--type-does-late-static-binding 
(phpi-method-return-type method)))
+          (phpi-method-set-return-type
+           method (phpinspect--resolve-late-static-binding
+                   (phpi-method-return-type method) home-type)))
+
+        (setf (phpi-mc-own cell) method))
     ;; Method is from a trait, interface or inherited
-    (pcase (phpinspect--type-category (phpi-method-origin-type method))
+    (pcase (phpinspect--type-category origin-type)
       ('trait (setf (phpi-mc-trait cell) method))
       ('interface (setf (phpi-mc-interface cell) method))
       ;; class or abstract class
       (_ (setf (phpi-mc-inherited cell) method)))))
 
+(defun phpi-mc-get-for-type-category (cell home-type type)
+  (if (phpinspect--type= home-type type)
+      (phpi-mc-own cell)
+    (pcase (phpinspect--type-category type)
+      ('trait (phpi-mc-trait cell))
+      ('interface (phpi-mc-interface cell))
+      (_ (phpi-mc-inherited cell)))))
+
 (defun phpi-method-origin-type= (method type)
   (phpinspect--type= (phpi-method-origin-type method) type))
 
@@ -119,13 +182,31 @@ https://www.php.net/manual/en/language.oop5.traits.php";
       (phpi-mc-inherited cell)
       (phpi-mc-interface cell)))
 
+(defun phpi-mc-get-return-type (cell)
+  (when-let ((method (phpi-mc-get-active cell)))
+    (phpi-method-return-type method)))
+
+(define-inline phpi-try-method-return-type (method?)
+  (inline-letevals (method?)
+    (inline-quote
+     (and ,method? (phpi-method-return-type ,method?)))))
+
+(defun phpi-mc-get-return-type-tryhard (cell)
+  (or (phpi-try-method-return-type (phpi-mc-own cell))
+      (phpi-try-method-return-type (phpi-mc-trait cell))
+      (phpi-try-method-return-type (phpi-mc-inherited cell))
+      (phpi-try-method-return-type (phpi-mc-interface cell))))
+
+(defun phpi-method-return-type (method)
+  (phpinspect--function-return-type (phpi-method-definition method)))
+
 (defun phpi-mcol-delete-for-type (mcol type &optional name)
   "Delete from MCOL all methods that originate from TYPE.
 
 When NAME is provided, only method with NAME is deleted."
   (if name
       ;; Name is provided, only delete method with NAME.
-      (let ((cell (phpi-mcol-find-cell mcol name)))
+      (when-let ((cell (phpi-mcol-find-cell mcol name)))
         (when (phpi-mc-get-for-type cell type)
           (phpi-mc-set cell (phpi-mcol-home-type mcol) type nil))
 
@@ -146,5 +227,62 @@ When NAME is provided, only method with NAME is deleted."
       ;; Delete all empty cells
       (setf (phpi-mcol-cells mcol) (delete (cons nil nil) cells)))))
 
+(defun phpi-mcol-get-active-method (mcol name)
+  (when-let ((cell (phpi-mcol-find-cell mcol name)))
+    (phpi-mc-get-active cell)))
+
+(defun phpi-mcol-get-return-type (mcol name &optional tryhard)
+  "Get the returntype of method with NAME from MCOL.
+
+If TRYHARD is provided and non-nil, also check for possible
+return types in extended classes, traits and interfaces."
+  (when-let ((cell (phpi-mcol-find-cell mcol name)))
+    (if tryhard
+        (phpi-mc-get-return-type-tryhard cell)
+      (phpi-mc-get-return-type cell))))
+
+;; Helpers for generic property access
+(cl-defmethod phpi-fn-name ((fn phpinspect--function))
+  (phpinspect--function-name fn))
+
+(cl-defmethod phpi-fn-name ((method phpinspect-method))
+  (phpi-method-name-string method))
+
+(cl-defmethod phpi-fn-name-symbol ((fn phpinspect--function))
+  (phpinspect--function-name-symbol fn))
+
+(cl-defmethod phpi-fn-name-symbol ((fn phpinspect-method))
+  (phpi-method-name-string fn))
+
+(cl-defmethod phpi-fn-arguments ((method phpinspect-method))
+  (phpi-fn-arguments (phpi-method-definition method)))
+
+(cl-defmethod phpi-fn-arguments ((fn phpinspect--function))
+  (phpinspect--function-arguments fn))
+
+(cl-defmethod phpi-fn-return-type ((fn phpinspect--function))
+  (phpinspect--function-return-type fn))
+
+(cl-defmethod phpi-fn-return-type ((method phpinspect-method))
+  (phpi-method-return-type method))
+
+(cl-defmethod phpi-fn-argument-type ((fn phpinspect--function) argument-name)
+  (phpinspect--function-argument-type fn argument-name))
+
+(cl-defmethod phpi-fn-argument-type ((method phpinspect-method) argument-name)
+  (phpi-fn-argument-type (phpi-method-definition method) argument-name))
+
+(cl-defmethod phpi-fn-anonymous-p ((fn phpinspect--function))
+  (phpinspect--function-anonymous-p fn))
+
+(cl-defmethod phpi-fn-anonymous-p ((_method phpinspect-method))
+  nil)
+
+(cl-defmethod phpi-fn-token ((fn phpinspect--function))
+  (phpinspect--function-token fn))
+
+(cl-defmethod phpi-fn-token ((method phpinspect-method))
+  (phpi-fn-token (phpi-method-definition method)))
+
 (provide 'phpinspect-method-cell)
 ;;; phpinspect-method-cell.el ends here
diff --git a/phpinspect-project-struct.el b/phpinspect-project-struct.el
index 2720f00dce..07f4d269b5 100644
--- a/phpinspect-project-struct.el
+++ b/phpinspect-project-struct.el
@@ -35,15 +35,15 @@ should never be changed.
 
 When this slot has a non-nil value:
 
-- Methods and functions that are meant to manipulate class data
+- Methods and functions that are meant to manipulate typedef data
 should become no-ops.
-- All classes retrieved from it should be marked as read-only as well.")
-  (extra-class-retriever nil
+- All typedefes retrieved from it should be marked as read-only as well.")
+  (extra-typedef-retriever nil
                          :type lambda
                          :documentation
                          "A function that should accept a `phpinspect--type' 
and return
-matching `phpinspect--class' instances or nil. Used to discover
-classes that are defined outside of project code.")
+matching `phpinspect--typedef' instances or nil. Used to discover
+typedefes that are defined outside of project code.")
   (extra-function-retriever nil
                             :type lambda
                             :documentation
@@ -51,11 +51,11 @@ classes that are defined outside of project code.")
 `phpinspect-intern-name') and return matching `phpinspect--function'
 instances or nil. Used to discover functions that are defined
 outside of project code.")
-  (class-index (make-hash-table :test 'eq :size 100 :rehash-size 1.5)
+  (typedef-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")
+indexed typedefs in the project")
   (function-index (make-hash-table :test 'eq :size 100 :rehash-size 2.0)
                   :type hash-table
                   :documentation
diff --git a/phpinspect-project.el b/phpinspect-project.el
index 3f46942f5e..ef38af5245 100644
--- a/phpinspect-project.el
+++ b/phpinspect-project.el
@@ -27,9 +27,11 @@
 (require 'phpinspect-autoload)
 (require 'phpinspect-worker)
 (require 'phpinspect-index)
-(require 'phpinspect-class)
+(require 'phpinspect-typedef)
 (require 'phpinspect-type)
 (require 'phpinspect-fs)
+(require 'phpinspect-typedef)
+(require 'phpinspect-method-cell)
 (require 'filenotify)
 
 (defvar phpinspect-auto-reindex nil
@@ -74,10 +76,10 @@ serious performance hits. Enable at your own risk (:")
   ((project phpinspect-project) methods)
   (phpinspect-project-edit project
     (dolist (method methods)
-      (when (phpinspect--function-return-type method)
+      (when (phpi-method-return-type method)
         (phpinspect-project-enqueue-if-not-present
          project
-         (phpinspect--function-return-type method))))))
+         (phpi-method-return-type method))))))
 
 (cl-defmethod phpinspect-project-add-variable-types-to-index-queue
   ((project phpinspect-project) variables)
@@ -90,27 +92,27 @@ serious performance hits. Enable at your own risk (:")
   ((project phpinspect-project) (type phpinspect--type))
   (phpinspect-project-edit project
     (unless (phpinspect--type-is-native type)
-      (let ((class (phpinspect-project-get-class project type)))
-        (when (or (not class)
-                  (not (or (phpinspect--class-initial-index class))))
+      (let ((typedef (phpinspect-project-get-typedef project type)))
+        (when (or (not typedef)
+                  (not (or (phpi-typedef-initial-index typedef))))
           (unless (or (phpinspect--type= phpinspect--null-type type)
                       (phpinspect--type-is-native type))
-            (phpinspect--log "Adding unpresent class %s to index queue" type)
+            (phpinspect--log "Adding unpresent typedef %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))
+(cl-defmethod phpinspect-project-add-typedef-attribute-types-to-index-queue
+  ((project phpinspect-project) (typedef phpinspect-typedef))
   (phpinspect-project-edit project
     (phpinspect-project-add-return-types-to-index-queueue
      project
-     (phpinspect--class-get-method-list class))
+     (phpi-typedef-get-methods typedef))
     (phpinspect-project-add-return-types-to-index-queueue
      project
-     (phpinspect--class-get-static-method-list class))
+     (phpi-typedef-get-static-methods typedef))
     (phpinspect-project-add-variable-types-to-index-queue
      project
-     (phpinspect--class-variables class))))
+     (phpi-typedef-variables typedef))))
 
 (cl-defmethod phpinspect-project-add-index
   ((project phpinspect-project) (index (head phpinspect--root-index)) 
&optional index-imports)
@@ -118,8 +120,8 @@ serious performance hits. Enable at your own risk (:")
     (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))
+    (dolist (indexed-typedef (alist-get 'classes (cdr index)))
+      (phpinspect-project-add-typedef project (cdr indexed-typedef) 
index-imports))
 
     (dolist (func (alist-get 'functions (cdr index)))
       (phpinspect-project-set-function project func))))
@@ -183,107 +185,106 @@ serious performance hits. Enable at your own risk (:")
         (phpinspect--log "Adding import to index queue: %s" import)
         (phpinspect-project-enqueue-if-not-present project (cdr import))))))
 
-(cl-defmethod phpinspect-project-delete-class ((project phpinspect-project) 
(class phpinspect--class))
-  (phpinspect-project-delete-class project (phpinspect--class-name class)))
+(cl-defmethod phpinspect-project-delete-typedef ((project phpinspect-project) 
(typedef phpinspect-typedef))
+  (phpinspect-project-delete-typedef project (phpi-typedef-name typedef)))
 
-(cl-defmethod phpinspect-project-delete-class ((project phpinspect-project) 
(class-name phpinspect--type))
+(cl-defmethod phpinspect-project-delete-typedef ((project phpinspect-project) 
(typedef-name phpinspect--type))
   (phpinspect-project-edit project
-    (remhash (phpinspect--type-name-symbol class-name) 
(phpinspect-project-class-index project))))
+    (remhash (phpinspect--type-name-symbol typedef-name) 
(phpinspect-project-typedef-index project))))
 
-(cl-defmethod phpinspect-project-add-class
-  ((project phpinspect-project) (indexed-class (head 
phpinspect--indexed-class)) &optional index-imports)
+(cl-defmethod phpinspect-project-add-typedef
+  ((project phpinspect-project) (indexed-typedef (head 
phpinspect--indexed-class)) &optional index-imports)
   (phpinspect-project-edit project
-    (if (not (alist-get 'class-name (cdr indexed-class)))
-        (phpinspect--log "Error: Class with declaration %s does not have a 
name" (alist-get 'declaration indexed-class))
+    (if (not (alist-get 'class-name (cdr indexed-typedef)))
+        (phpinspect--log "Error: Typedef with declaration %s does not have a 
name" (alist-get 'declaration indexed-typedef))
       ;; Else
-      (let* ((class-name (phpinspect--type-name-symbol
-                          (alist-get 'class-name (cdr indexed-class))))
-             (class (gethash class-name
-                             (phpinspect-project-class-index project))))
-        (unless class
-          (setq class (phpinspect--make-class-generated
-                       :class-retriever 
(phpinspect-project-make-class-retriever project))))
+      (let* ((typedef-type-name (alist-get 'class-name (cdr indexed-typedef)))
+             (typedef-name (phpinspect--type-name-symbol typedef-type-name))
+             (typedef (gethash typedef-name
+                               (phpinspect-project-typedef-index project))))
+        (unless typedef
+          (setq typedef (phpinspect-make-typedef typedef-type-name 
(phpinspect-project-make-typedef-retriever project))))
+        ;; :typedef-retriever (phpinspect-project-make-typedef-retriever 
project))))
 
         (when index-imports
           (phpinspect-project-enqueue-imports
-           project (alist-get 'imports (cdr indexed-class))))
+           project (alist-get 'imports (cdr indexed-typedef))))
 
-        (phpinspect--class-set-index class indexed-class)
-        (puthash class-name class (phpinspect-project-class-index project))
-        (phpinspect-project-add-class-attribute-types-to-index-queue project 
class)))))
+        (phpi-typedef-set-index typedef indexed-typedef)
+        (puthash typedef-name typedef (phpinspect-project-typedef-index 
project))
+        (phpinspect-project-add-typedef-attribute-types-to-index-queue project 
typedef)))))
 
-(cl-defmethod phpinspect-project-set-class
-  ((project phpinspect-project) (class-fqn phpinspect--type) (class 
phpinspect--class))
+(cl-defmethod phpinspect-project-set-typedef
+  ((project phpinspect-project) (typedef-fqn phpinspect--type) (typedef 
phpinspect-typedef))
   (phpinspect-project-edit project
-    (puthash (phpinspect--type-name-symbol class-fqn)
-             class
-             (phpinspect-project-class-index project))))
+    (puthash (phpinspect--type-name-symbol typedef-fqn)
+             typedef
+             (phpinspect-project-typedef-index project))))
 
-(cl-defmethod phpinspect-project-create-class
-  ((project phpinspect-project) (class-fqn phpinspect--type))
+(cl-defmethod phpinspect-project-create-typedef
+  ((project phpinspect-project) (typedef-fqn phpinspect--type))
   (phpinspect-project-edit project
-    (let ((class (phpinspect--make-class-generated
-                  :class-retriever (phpinspect-project-make-class-retriever 
project))))
-      (phpinspect-project-set-class project class-fqn class)
-      class)))
+    (let ((typedef (phpinspect-make-typedef typedef-fqn 
(phpinspect-project-make-typedef-retriever project))))
+      (phpinspect-project-set-typedef project typedef-fqn typedef)
+      typedef)))
 
-(cl-defmethod phpinspect-project-get-class-create
-  ((project phpinspect-project) (class-fqn phpinspect--type) &optional 
no-enqueue)
-  "Get class object belonging to CLASS-FQN from PROJECT.
+(cl-defmethod phpinspect-project-get-typedef-create
+  ((project phpinspect-project) (typedef-fqn phpinspect--type) &optional 
no-enqueue)
+  "Get typedef object belonging to TYPEDEF-FQN from PROJECT.
 
-If the class does exist on the filesystem but has not yet been
-indexed, it will be queued for indexation and an empty class
+If the typedef does exist on the filesystem but has not yet been
+indexed, it will be queued for indexation and an empty typedef
 object (awaiting indedaxation) is returned.
 
-If NO-ENQUEUE is non-nil, the class will not be queued for
+If NO-ENQUEUE is non-nil, the typedef will not be queued for
 indexation, but indexed synchronously before returning."
-  (let ((class (phpinspect-project-get-class project class-fqn)))
-    (unless class
+  (let ((typedef (phpinspect-project-get-typedef project typedef-fqn)))
+    (unless typedef
       (phpinspect-project-edit project
-        (setq class (phpinspect-project-create-class project class-fqn))
+        (setq typedef (phpinspect-project-create-typedef project typedef-fqn))
         (unless no-enqueue
-          (phpinspect-project-enqueue-if-not-present project class-fqn))))
+          (phpinspect-project-enqueue-if-not-present project typedef-fqn))))
 
-    (phpinspect--log "Got project class, no-enqueue is set to: %s, 
initial-index is: %s"
-                     no-enqueue (phpinspect--class-initial-index class))
+    (phpinspect--log "Got project typedef, no-enqueue is set to: %s, 
initial-index is: %s"
+                     no-enqueue (phpi-typedef-initial-index typedef))
 
     (phpinspect-project-edit project
-      (when  (and no-enqueue (phpinspect--class-initial-index class))
-        (phpinspect--log "Indexing type file for %s" class-fqn)
+      (when  (and no-enqueue (phpi-typedef-initial-index typedef))
+        (phpinspect--log "Indexing type file for %s" typedef-fqn)
         (phpinspect-project-add-index
          project
-         (phpinspect-project-index-type-file project class-fqn))))
-    class))
+         (phpinspect-project-index-type-file project typedef-fqn))))
+    typedef))
 
-(cl-defmethod phpinspect-project-get-class-extra-or-create
-  ((project phpinspect-project) (class-fqn phpinspect--type) &optional 
no-enqueue)
-  (or (phpinspect-project-get-class-or-extra project class-fqn no-enqueue)
-      (phpinspect-project-get-class-create project class-fqn no-enqueue)))
+(cl-defmethod phpinspect-project-get-typedef-extra-or-create
+  ((project phpinspect-project) (typedef-fqn phpinspect--type) &optional 
no-enqueue)
+  (or (phpinspect-project-get-typedef-or-extra project typedef-fqn no-enqueue)
+      (phpinspect-project-get-typedef-create project typedef-fqn no-enqueue)))
 
 
-(cl-defmethod phpinspect-project-get-class
-  ((project phpinspect-project) (class-fqn phpinspect--type) &optional index)
-  "Get indexed class by name of CLASS-FQN stored in PROJECT."
-  (let ((class (gethash (phpinspect--type-name-symbol class-fqn)
-                        (phpinspect-project-class-index project))))
-    (when class
+(cl-defmethod phpinspect-project-get-typedef
+  ((project phpinspect-project) (typedef-fqn phpinspect--type) &optional index)
+  "Get indexed typedef by name of TYPEDEF-FQN stored in PROJECT."
+  (let ((typedef (gethash (phpinspect--type-name-symbol typedef-fqn)
+                          (phpinspect-project-typedef-index project))))
+    (when typedef
       (when (and (phpinspect-project-read-only-p project)
-                 (not (phpinspect--class-read-only-p class)))
-        (setf (phpinspect--class-read-only-p class) t))
+                 (not (phpi-typedef-read-only-p typedef)))
+        (setf (phpi-typedef-read-only-p typedef) t))
 
-      (when (and index (not (phpinspect--class-initial-index class)))
+      (when (and index (not (phpi-typedef-initial-index typedef)))
         (phpinspect-project-add-index
          project
-         (phpinspect-project-index-type-file project class-fqn))))
+         (phpinspect-project-index-type-file project typedef-fqn))))
 
-    class))
+    typedef))
 
-(cl-defmethod phpinspect-project-get-class-or-extra
-  ((project phpinspect-project) (class-fqn phpinspect--type) &optional index)
-  (or (phpinspect-project-get-class project class-fqn index)
-      (and (phpinspect-project-extra-class-retriever project)
-           (funcall (phpinspect-project-extra-class-retriever project)
-                    class-fqn))))
+(cl-defmethod phpinspect-project-get-typedef-or-extra
+  ((project phpinspect-project) (typedef-fqn phpinspect--type) &optional index)
+  (or (phpinspect-project-get-typedef project typedef-fqn index)
+      (and (phpinspect-project-extra-typedef-retriever project)
+           (funcall (phpinspect-project-extra-typedef-retriever project)
+                    typedef-fqn))))
 
 (cl-defmethod phpinspect-project-get-type-filepath
   ((project phpinspect-project) (type phpinspect--type) &optional index-new)
@@ -348,10 +349,10 @@ before the search is executed."
 (defun phpinspect-project-make-root-resolver (project)
   (lambda () (phpinspect-project-root project)))
 
-(defun phpinspect-project-make-class-retriever (project)
+(defun phpinspect-project-make-typedef-retriever (project)
   (lambda (type)
-    (or (phpinspect-project-get-class-or-extra project type)
-        (phpinspect-project-get-class-create project type))))
+    (or (phpinspect-project-get-typedef-or-extra project type)
+        (phpinspect-project-get-typedef-create project type))))
 
 ;;; INDEX TASK
 (cl-defstruct (phpinspect-index-task
@@ -387,7 +388,7 @@ before the search is executed."
   (let ((project (phpinspect-index-task-project task))
         (is-native-type (phpinspect--type-is-native
                          (phpinspect-index-task-type task))))
-    (phpinspect--log "Indexing class %s for project in %s as task."
+    (phpinspect--log "Indexing typedef %s for project in %s as task."
                      (phpinspect-index-task-type task)
                      (phpinspect-project-root project))
 
diff --git a/phpinspect-resolve.el b/phpinspect-resolve.el
index e66217f83d..01c05ea26d 100644
--- a/phpinspect-resolve.el
+++ b/phpinspect-resolve.el
@@ -25,7 +25,7 @@
 
 (require 'phpinspect-resolvecontext)
 (require 'phpinspect-cache)
-(require 'phpinspect-class)
+(require 'phpinspect-typedef)
 (require 'phpinspect-type)
 (require 'phpinspect-token-predicates)
 
@@ -151,50 +151,50 @@ Destructively removes tokens from the end of 
ASSIGNMENT-TOKENS."
   statement)
 
 (defsubst phpinspect-get-cached-project-class (rctx class-fqn)
-  (phpinspect-project-get-class-or-extra (phpinspect--resolvecontext-project 
rctx) class-fqn))
+  (phpinspect-project-get-typedef-or-extra (phpinspect--resolvecontext-project 
rctx) class-fqn))
 
-(defun phpinspect-get-cached-project-class-methods (rctx class-fqn &optional 
static)
+(defun phpinspect-get-cached-project-typedef-methods (rctx class-fqn &optional 
static)
     (phpinspect--log "Getting cached project class methods for %s"
                      class-fqn)
-    (let ((class (phpinspect-rctx-get-or-create-cached-project-class rctx 
class-fqn)))
+    (let ((class (phpinspect-rctx-get-typedef rctx class-fqn)))
       (when class
         (phpinspect--log "Retrieved class index, starting method collection 
for %s"
                          class-fqn)
         (if static
-            (phpinspect--class-get-static-method-list class)
-          (phpinspect--class-get-method-list class)))))
+            (phpi-typedef-get-static-methods class)
+          (phpi-typedef-get-methods class)))))
 
-(defsubst phpinspect-get-cached-project-class-method-type (rctx class-fqn 
method-name)
-  (let* ((class (phpinspect-rctx-get-or-create-cached-project-class rctx 
class-fqn))
+(defsubst phpinspect-get-cached-project-typedef-method-type (rctx class-fqn 
method-name)
+  (let* ((class (phpinspect-rctx-get-typedef rctx class-fqn))
          (method))
     (when class
       (setq method
-            (phpinspect--class-get-method class (phpinspect-intern-name 
method-name)))
+            (phpi-typedef-get-method class (phpinspect-intern-name 
method-name)))
       (when method
-        (phpinspect--function-return-type method)))))
+        (phpi-fn-return-type method)))))
 
-(defsubst phpinspect-get-cached-project-class-variable-type
+(defsubst phpinspect-get-cached-project-typedef-variable-type
   (rctx class-fqn variable-name)
   (phpinspect--log "Getting cached project class variable type %s::%s"
                    class-fqn variable-name)
   (let ((found-variable
-         (phpinspect--class-get-variable
-          (phpinspect-rctx-get-or-create-cached-project-class rctx class-fqn)
+         (phpi-typedef-get-variable
+          (phpinspect-rctx-get-typedef rctx class-fqn)
           variable-name)))
     (when found-variable
       (phpinspect--variable-type found-variable))))
 
-(defsubst phpinspect-get-cached-project-class-static-method-type
+(defsubst phpinspect-get-cached-project-typedef-static-method-type
   (rctx class-fqn method-name)
-  (let* ((class (phpinspect-rctx-get-or-create-cached-project-class rctx 
class-fqn))
+  (let* ((class (phpinspect-rctx-get-typedef rctx class-fqn))
          (method))
     (when class
       (setq method
-            (phpinspect--class-get-static-method
+            (phpi-typedef-get-static-method
              class
              (phpinspect-intern-name method-name)))
       (when method
-        (phpinspect--function-return-type method)))))
+        (phpi-fn-return-type method)))))
 
 (defun phpinspect-get-derived-statement-type-in-block
     (resolvecontext statement php-block type-resolver &optional 
function-arg-list assignments)
@@ -258,14 +258,14 @@ value/type of ->bar must be derived from the type of 
$foo. So
                        (pop statement)
                        (setq type-before
                              (or
-                              (phpinspect-get-cached-project-class-method-type
+                              
(phpinspect-get-cached-project-typedef-method-type
                                resolvecontext
                                (funcall type-resolver type-before)
                                (cadr attribute-word))
                               type-before)))
                    (setq type-before
                          (or
-                          (phpinspect-get-cached-project-class-variable-type
+                          (phpinspect-get-cached-project-typedef-variable-type
                            resolvecontext
                            (funcall type-resolver type-before)
                            (cadr attribute-word))
@@ -281,7 +281,7 @@ value/type of ->bar must be derived from the type of $foo. 
So
                        (pop statement)
                        (setq type-before
                              (or
-                              
(phpinspect-get-cached-project-class-static-method-type
+                              
(phpinspect-get-cached-project-typedef-static-method-type
                                resolvecontext
                                (funcall type-resolver type-before)
                                (cadr attribute-word))
@@ -603,13 +603,13 @@ type. (`phpinspect--type-p')"
 (defun phpinspect--function-get-pattern-type (fn rctx pattern type-resolver)
   (phpinspect-get-pattern-type-in-block
    rctx pattern
-   (phpinspect-function-block (phpinspect--function-token fn))
+   (phpinspect-function-block (phpi-fn-token fn))
    type-resolver
-   (phpinspect-function-argument-list (phpinspect--function-token fn))))
+   (phpinspect-function-argument-list (phpi-fn-token fn))))
 
 
-(cl-defmethod phpinspect--class-resolve-property-type
-  ((class phpinspect--class) (project phpinspect-project) (property-name 
string) type-resolver class-token-meta)
+(cl-defmethod phpi-typedef-resolve-property-type
+  ((typedef phpinspect-typedef) (project phpinspect-project) (property-name 
string) type-resolver class-token-meta)
   "Resolve type of POPERTY-NAME in the context of CLASS using
 CLASS-TOKEN-META as parse result."
   (let ((pattern (phpinspect--make-pattern
@@ -621,17 +621,18 @@ CLASS-TOKEN-META as parse result."
         (constructor-name (phpinspect-intern-name "__construct")))
 
     (or
-     (when-let ((constructor (phpinspect--class-get-method class 
constructor-name)))
-       (phpinspect--function-get-pattern-type constructor rctx pattern 
type-resolver))
+     (when-let ((constructor (phpi-typedef-get-method typedef 
constructor-name)))
+       (phpinspect--function-get-pattern-type (phpi-method-definition 
constructor) rctx pattern type-resolver))
      (catch 'found
-       (dolist (method (phpinspect--class-get-method-list class))
-         (unless (eq constructor-name (phpinspect--function-name-symbol 
method))
-           (when-let ((result (phpinspect--function-get-pattern-type method 
rctx pattern type-resolver)))
+       (dolist (method (phpi-typedef-get-methods typedef))
+         (unless (eq constructor-name (phpi-method-name method))
+           (when-let ((result (phpinspect--function-get-pattern-type
+                               (phpi-method-definition method) rctx pattern 
type-resolver)))
              (throw 'found result))))
        nil))))
 
-(cl-defmethod phpinspect--class-resolve-property-type
-  ((_class phpinspect--class) (_project phpinspect-project) property-name 
&rest _ignored)
+(cl-defmethod phpi-typedef-resolve-property-type
+  ((_typedef phpinspect-typedef) (_project phpinspect-project) property-name 
&rest _ignored)
   ;; Catch-all for cases where one attempts to resolve a nil property
   ;; name. Saves an if-statement for the caller.
   ;; Can't resolve property type when property name is nil, so we do nothing.
diff --git a/phpinspect-resolvecontext.el b/phpinspect-resolvecontext.el
index a36e8b31f4..e5d1fa1b1f 100644
--- a/phpinspect-resolvecontext.el
+++ b/phpinspect-resolvecontext.el
@@ -217,10 +217,10 @@ accompanied by all of its enclosing tokens."
 
     resolvecontext)))
 
-(defun phpinspect-rctx-get-or-create-cached-project-class (rctx class-fqn 
&optional no-enqueue)
+(defun phpinspect-rctx-get-typedef (rctx class-fqn &optional no-enqueue)
   (cl-assert (phpinspect--resolvecontext-p rctx))
   (let ((project (phpinspect--resolvecontext-project rctx)))
-    (phpinspect-project-get-class-extra-or-create project class-fqn 
no-enqueue)))
+    (phpinspect-project-get-typedef-extra-or-create project class-fqn 
no-enqueue)))
 
 (defun phpinspect-rctx-get-function-return-type (rctx function-name)
   (cl-assert (phpinspect--resolvecontext-p rctx))
diff --git a/phpinspect-serialize.el b/phpinspect-serialize.el
index ca46d703fb..d40ecafd74 100644
--- a/phpinspect-serialize.el
+++ b/phpinspect-serialize.el
@@ -24,7 +24,7 @@
 ;;; Code:
 
 (require 'phpinspect-type)
-(require 'phpinspect-class)
+(require 'phpinspect-typedef)
 
 (cl-defgeneric phpinspect--serialize-type (_type)
   nil)
@@ -63,6 +63,8 @@
 (cl-defmethod phpinspect--serialize-indexed-class ((class (head 
phpinspect--indexed-class)))
   ``(phpinspect--indexed-class
      (complete . ,,(alist-get 'complete class))
+     (trait-config . ,,(mapcar (lambda (conf) (list 
(phpinspect--serialize-type (car conf)) (cdr conf)))
+                               (alist-get 'trait-config class)))
      (class-name . ,,(phpinspect--serialize-type (alist-get 'class-name 
class)))
      (declaration . ,(quote ,(alist-get 'declaration class)))
      (location . ,(quote ,(alist-get 'location class)))
diff --git a/phpinspect-suggest.el b/phpinspect-suggest.el
index 2a492998cb..1e2d93202e 100644
--- a/phpinspect-suggest.el
+++ b/phpinspect-suggest.el
@@ -28,7 +28,7 @@
 (require 'phpinspect-token-predicates)
 (require 'phpinspect-type)
 (require 'phpinspect-project)
-(require 'phpinspect-class)
+(require 'phpinspect-typedef)
 
 (phpinspect--declare-log-group 'suggest)
 
@@ -75,31 +75,31 @@
 
       variable-list)))
 
-(defun phpinspect-get-cached-project-class-methods (rctx class-fqn &optional 
static)
+(defun phpinspect-get-cached-project-typedef-methods (rctx class-fqn &optional 
static)
   (phpinspect--log "Getting cached project class methods for %s" class-fqn)
-  (let ((class (phpinspect-rctx-get-or-create-cached-project-class rctx 
class-fqn 'no-enqueue)))
+  (let ((class (phpinspect-rctx-get-typedef rctx class-fqn 'no-enqueue)))
     (phpinspect--log (if class
                          "Retrieved class index, starting method collection %s"
                        "No class index found for %s")
                      class-fqn)
     (when class
       (if static
-          (phpinspect--class-get-static-method-list class)
-        (phpinspect--class-get-method-list class)))))
+          (phpi-typedef-get-static-methods class)
+        (phpi-typedef-get-methods class)))))
 
 (defun phpinspect--get-methods-for-class
     (resolvecontext class &optional static)
   "Find all known cached methods for CLASS."
-  (or (phpinspect-get-cached-project-class-methods resolvecontext class static)
+  (or (phpinspect-get-cached-project-typedef-methods resolvecontext class 
static)
       (progn (phpinspect--log "Failed to find methods for class %s :(" class) 
nil)))
 
 (defun phpinspect--get-variables-for-class (rctx class-name &optional static)
-  (let ((class (phpinspect-rctx-get-or-create-cached-project-class
+  (let ((class (phpinspect-rctx-get-typedef
                 rctx class-name 'no-enqueue)))
     (when class
       (if static
-          (append (phpinspect--class-get-static-variables class) 
(phpinspect--class-get-constants class))
-        (phpinspect--class-get-variables class)))))
+          (append (phpi-typedef-get-static-variables class) 
(phpi-typedef-get-constants class))
+        (phpi-typedef-get-variables class)))))
 
 (defun phpinspect--make-method-lister (resolvecontext &optional static)
   (lambda (fqn)
@@ -108,6 +108,9 @@
 (cl-defmethod phpinspect--candidate-scope ((candidate phpinspect--function))
   (phpinspect--function-scope candidate))
 
+(cl-defmethod phpinspect--candidate-scope ((candidate phpinspect-method))
+  (phpinspect--function-scope (phpi-method-definition candidate)))
+
 (cl-defmethod phpinspect--candidate-scope ((candidate phpinspect--variable))
   (phpinspect--variable-scope candidate))
 
diff --git a/phpinspect-type.el b/phpinspect-type.el
index e4dea22951..e3cb085004 100644
--- a/phpinspect-type.el
+++ b/phpinspect-type.el
@@ -107,11 +107,10 @@ See https://wiki.php.net/rfc/static_return_type ."
   (or (phpinspect--type= type phpinspect--static-type)
       (phpinspect--type= type phpinspect--this-type)))
 
-(cl-defmethod phpinspect--resolve-late-static-binding
-  ((type phpinspect--type)
-   (class-type phpinspect--type))
+(defun phpinspect--resolve-late-static-binding (type origin-type)
+  "Resolve TYPE late static binding using ORIGIN-TYPE."
   (if (phpinspect--type-does-late-static-binding type)
-      class-type
+      origin-type
     type))
 
 (defsubst phpinspect--type-is-native (type)
@@ -284,7 +283,7 @@ return type of the function."))
 (defun phpinspect--function-argument-type (fn argument-name)
   (alist-get argument-name (phpinspect--function-arguments fn) nil nil 
#'string=))
 
-(defun phpinspect--function-anonyous-p (fn)
+(defun phpinspect--function-anonymous-p (fn)
   (eq (phpinspect-intern-name "anonymous") (phpinspect--function-name-symbol 
fn)))
 
 (defmacro phpinspect--make-function (&rest property-list)
@@ -368,7 +367,7 @@ mutability of the variable")
 
 (defun phpinspect--index-class-declaration (decl type-resolver)
   ;; Find out what the class extends or implements
-  (let (encountered-extends encountered-implements encountered-class
+  (let (keyword encountered-extends encountered-implements encountered-class
         class-name extends implements used-types)
     (dolist (word decl)
       (if (phpinspect-word-p word)
@@ -383,7 +382,8 @@ mutability of the variable")
                   (eval-when-compile
                     (concat "^" (phpinspect--class-keyword-handler-regexp) 
"?$"))
                   (cadr word))
-                 (setq encountered-class t))
+                 (setq keyword word
+                       encountered-class t))
                 (t
                  (phpinspect--log "Calling Resolver from index-class on %s" 
(cadr word))
                  (cond (encountered-extends
@@ -397,7 +397,15 @@ mutability of the variable")
                               implements)
                         (push (cadr word) used-types))
                        (encountered-class
-                        (setq class-name (funcall type-resolver 
(phpinspect--make-type :name (cadr word)))
+                        (setq class-name
+                              (funcall type-resolver (phpinspect--make-type
+                                                      :category (pcase (cadr 
keyword)
+                                                                  ("class" 
'class)
+                                                                  ("trait" 
'trait)
+                                                                  ("interface" 
'interface)
+                                                                  ("enum" 
'enum)
+                                                                  (_ 'class))
+                                                      :name (cadr word)))
                               encountered-class nil)))))))
 
     (list class-name extends implements used-types)))
diff --git a/phpinspect-typedef.el b/phpinspect-typedef.el
new file mode 100644
index 0000000000..1015159841
--- /dev/null
+++ b/phpinspect-typedef.el
@@ -0,0 +1,355 @@
+
+
+(require 'phpinspect-method-cell)
+
+(cl-defstruct (phpinspect-typedef
+               (:constructor phpinspect-make-typedef-generated)
+               (:conc-name phpi-typedef-))
+  (read-only-p nil
+               :type boolean
+               :documentation
+               "Whether this typedef is read-only, meaning that its data
+should never be changed. Methods and functions that are meant to
+manipulate typedef data should become no-ops when this slot has a
+non-nil value.")
+  (retriever nil
+                   :type lambda
+                   :documentaton
+                   "A function that returns typedefs for types
+(should accept object of type `phpinspect--type' as argument)")
+  (methods nil
+           :type phpinspect-method-collection)
+  (static-methods nil
+                  :type phpinspect-method-collection)
+  (variables nil
+             :type list)
+  (initial-index nil
+                 :type bool)
+  (trait-config nil
+                :documentation
+                "The configuration of traits that are used in this type")
+  (method-adder nil
+                :type phpinspect-method-adder)
+  (subscribed-types nil
+                    :type list
+                    :documentation "list of phpinspect--type structures.")
+  (subscribed-to-types nil
+                       :type list
+                       :documentation "list of phpinspect--type structures")
+  (name nil
+        :type phpinspect--type)
+  (declaration nil
+               :type phpinspect-declaration-p))
+
+(defun phpinspect-make-typedef (type &optional retriever)
+  (cl-assert (phpinspect--type-p type))
+
+  (let ((def (phpinspect-make-typedef-generated
+              :name type
+              :retriever retriever
+              :methods (phpinspect-make-method-collection :home-type type)
+              :static-methods (phpinspect-make-method-collection :home-type 
type)
+              :method-adder (phpinspect-make-method-adder))))
+    def))
+
+(define-inline phpi--typedef-get-foreign-type (def type)
+  (inline-letevals (def type)
+    (inline-quote
+     (when-let ((retriever (phpi-typedef-retriever ,def)))
+       (funcall retriever ,type)))))
+
+(defmacro phpi--typedef-edit (typedef &rest body)
+  "Declare intent to edit TYPEDEF in BODY.
+
+Conditionally executes BODY depending on
+`phpi-typedef-read-only-p' value."
+  (declare (indent 1))
+  `(unless (phpi-typedef-read-only-p ,typedef)
+     ,@body))
+
+(cl-defstruct (phpinspect-method-adder
+               (:constructor phpinspect-make-method-adder)
+               (:conc-name phpi-ma-))
+  (aliases nil
+           :type alist)
+  (overrides nil
+             :type alist))
+
+(defun phpi-ma-get-overrides (ma type)
+  (alist-get type (phpi-ma-overrides ma) nil nil #'phpinspect--type=))
+
+(defun phpi-ma-get-aliases (ma type)
+  (alist-get type (phpi-ma-aliases ma) nil nil #'phpinspect--type=))
+
+(defun phpi-ma-set-config (ma config)
+  "Set type method import config for MA to CONFIG.
+
+This function reconfigures MA to add methods according to the
+rules specified in CONFIG. CONFIG is expected to be a list of the
+structure returned by `phpinspect--index-trait-use'."
+  (setf (phpi-ma-aliases ma) nil)
+  (setf (phpi-ma-overrides ma) nil)
+
+  (dolist (typeconf config)
+    (let ((type (car typeconf))
+          overrides aliases)
+      (dolist (setting (cdr typeconf))
+        (pcase (car setting)
+          ('alias (push (cons (phpinspect-intern-name (cadr setting))
+                              (phpinspect-intern-name (caddr setting)))
+                        aliases))
+          ('override (push (cons (phpinspect-intern-name (cadr setting))
+                                 (caddr setting))
+                           overrides))
+          (_ (error (format "Invalid type configuration instruction %s" (car 
setting))))))
+
+      (push (cons type aliases) (phpi-ma-aliases ma))
+      (push (cons type overrides) (phpi-ma-overrides ma)))))
+
+(defun phpi-ma-add (ma mcol method &optional overwrite)
+  (if-let ((overrides (phpi-ma-get-overrides ma (phpi-method-origin-type 
method)))
+           (aliases (phpi-ma-get-aliases ma (phpi-method-origin-type method))))
+      (progn
+        (if-let ((override (alist-get (phpi-method-name method) overrides)))
+            ;; Override basically just means insert and overwrite without 
checking
+            (phpi-mcol-add mcol method 'overwrite)
+          ;; Can't alias if overriding, can't override if aliasing
+          (when-let ((alias (alist-get (phpi-method-name method) aliases))
+                     (copy (phpi-copy-method method)))
+            ;; Rename method to alias, record original name in aliased-from 
slot
+            (setf (phpi-method-aliased-from method) (phpi-method-name method)
+                  (phpi-method-name method) alias))))
+
+    ;; Not dealing with aliases or overrides, just add the methods (unless they
+    ;; already exist)
+    (phpi-mcol-add mcol method overwrite)))
+
+(defun phpi-typedef-get-methods (def)
+  (phpi-mcol-list-active (phpi-typedef-methods def)))
+
+(defun phpi-typedef-get-static-methods (def)
+  (phpi-mcol-list-active (phpi-typedef-static-methods def)))
+
+(cl-defmethod phpi-typedef-get-method ((def phpinspect-typedef) (method-name 
(head phpinspect-name)))
+  (phpi-mcol-get-active-method (phpi-typedef-methods def) method-name))
+
+(cl-defmethod phpi-typedef-get-method ((def phpinspect-typedef) (method-name 
string))
+  (phpi-typedef-get-method def (phpinspect-intern-name method-name)))
+
+(cl-defmethod phpi-typedef-get-static-method ((def phpinspect-typedef) 
(method-name (head phpinspect-name)))
+  (phpi-mcol-get-active-method (phpi-typedef-static-methods def) method-name))
+
+(cl-defmethod phpi-typedef-get-static-method ((def phpinspect-typedef) 
(method-name string))
+  (phpi-typedef-get-static-method def (phpinspect-intern-name method-name)))
+
+(cl-defmethod phpi-typedef-set-method ((def phpinspect-typedef) (fn 
phpinspect--function))
+  (let ((method (phpinspect-make-method (phpi-typedef-name def) fn)))
+    (phpi-ma-add (phpi-typedef-method-adder def)
+                 (phpi-typedef-methods def)
+                 method 'overwrite)))
+
+(cl-defmethod phpi-typedef-set-static-method ((def phpinspect-typedef) (fn 
phpinspect--function))
+  (let ((method (phpinspect-make-method (phpi-typedef-name def) fn)))
+    (phpi-ma-add (phpi-typedef-method-adder def)
+                 (phpi-typedef-static-methods def)
+                 method 'overwrite)))
+
+
+(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-mcol-delete-for-type
+   (phpi-typedef-static-methods def) (phpi-typedef-name def) name))
+
+(cl-defmethod phpi-typedef-delete-method ((def phpinspect-typedef) (fn 
phpinspect--function))
+  (phpi-typedef-delete-method def (phpinspect--function-name-symbol fn)))
+
+(defun phpi-typedef-set-trait-config (def config)
+  (phpi--typedef-edit def
+    (let ((existing-config (phpi-typedef-trait-config def))
+          types)
+      (if existing-config
+          ;; This can probably be made more sophisticated by only applying the
+          ;; difference, but just deleting all incorporated methods will do for
+          ;; an initial implementation.
+          (dolist (use existing-config)
+            (phpi-mcol-delete-for-type (phpi-typedef-methods def) (car use)))
+        ;; Apply new config
+        (progn
+          (phpi-ma-set-config (phpi-typedef-method-adder def) config)
+          (dolist (cons config)
+            (push (car config) types))))
+      ;; return all types that were in config
+      types)))
+
+(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))
+
+    (dolist (method (phpi-typedef-get-static-methods foreign-def))
+      (phpi-ma-add (phpi-typedef-method-adder def) (phpi-typedef-methods def) 
method))
+
+    (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)))
+
+(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."
+  (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=))
+
+  ;; 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."
+  (dolist (type (phpi-typedef-subscribed-types def))
+    (when-let ((foreign-def (phpi--typedef-get-foreign-type def type)))
+      (phpi-typedef-add-foreign-members foreign-def def))))
+
+(defun phpi-typedef-set-name (def type)
+  "Set the TYPE name of DEF.
+
+TYPE must be a structure of type `phpinspect--type'."
+  (phpi--typedef-edit def
+    (cl-assert (phpinspect--type-p type))
+
+    (let ((existing (phpi-typedef-name def)))
+      ;; Only update if type name is actually different
+      (unless (phpinspect--type= existing type)
+        (setf (phpi-typedef-name def) type)
+        (phpi-mcol-set-home-type (phpi-typedef-methods def) type)))))
+
+(defun phpi-typedef-update-declaration (def declaration imports namespace-name 
trait-config)
+  (phpi--typedef-edit def
+    (pcase-let ((`(,type ,extends ,implements ,_used-types)
+                 (phpinspect--index-class-declaration
+                  declaration (phpinspect--make-type-resolver
+                               (phpinspect--uses-to-types imports) nil 
namespace-name))))
+      (phpi-typedef-set-name def type)
+      (setf (phpi-typedef-declaration def) declaration)
+      (phpi-typedef-update-extensions
+       def `(,@extends ,@implements ,@(phpi-typedef-set-trait-config def 
trait-config))))))
+
+(defun phpi-typedef-update-extensions (def extensions)
+  (phpi--typedef-edit def
+    (when-let ((subscriptions (phpi-typedef-subscribed-to-types def)))
+      (dolist (sub subscriptions)
+        (unless (cl-member sub extensions :test #'phpinspect--type=)
+          ;; No longer an extended type, unsubscribe
+          (when-let ((fd (phpi--typedef-get-foreign-type def sub)))
+            (phpi-typedef-unsubscribe-from-foreign-typedef def fd))))
+
+      (dolist (ext extensions)
+        (when (cl-member ext subscriptions :test #'phpinspect--type=)
+            ;; Already subscribed, no refresh needed
+          (delq ext extensions))))
+
+    (when-let ((foreign-defs
+                (seq-filter
+                 #'phpinspect-typedef-p
+                 (mapcar
+                  (lambda (class-name)
+                    (funcall (phpi-typedef-retriever def) class-name))
+                  extensions))))
+
+      (dolist (fd foreign-defs)
+        (phpi-typedef-add-foreign-members def fd)
+        (phpi-typedef-subscribe-to-foreign-typedef def fd)))))
+
+(cl-defmethod phpi-typedef-set-index ((def phpinspect-typedef)
+                                      (index (head phpinspect--indexed-class)))
+  (phpi--typedef-edit def
+    (setf (phpi-typedef-declaration def) (alist-get 'declaration index))
+
+
+
+    (let ((ma (phpi-typedef-method-adder def))
+          (mcol (phpi-typedef-methods def))
+          (stmcol (phpi-typedef-static-methods def))
+          (home-type (phpi-typedef-name def)))
+
+    ;; Override methods when class seems syntactically correct (has balanced 
braces)
+      (when (alist-get 'complete index)
+        ;; Delete all known own methods
+        (phpi-mcol-delete-for-type mcol home-type))
+
+      (dolist (method (alist-get 'methods index))
+        (phpi-ma-add ma mcol (phpinspect-make-method home-type method) 
'overwrite))
+
+      (dolist (method (alist-get 'static-methods index))
+        (phpi-ma-add ma stmcol (phpinspect-make-method home-type method) 
'overwrite))
+
+      (setf (phpi-typedef-initial-index def) t)
+
+      (setf (phpi-typedef-variables def)
+            (append (alist-get 'variables index)
+                    (alist-get 'constants index)
+                    (alist-get 'static-variables index)))
+
+      (phpi-typedef-update-extensions
+       def `(,@(alist-get 'implements index)
+             ,@(alist-get 'extends index)
+             ,@(phpi-typedef-set-trait-config def (alist-get 'trait-usage 
index))))
+
+      (phpi-typedef-trigger-subscriber-update def))))
+
+(cl-defmethod phpi-typedef-get-method-return-type
+  ((def phpinspect-typedef) (method-name (head phpinspect-name)) &optional 
tryhard)
+  (phpi-mcol-get-return-type (phpi-typedef-methods def) method-name tryhard))
+
+(cl-defmethod phpi-typedef-get-static-method-return-type
+  ((def phpinspect-typedef) (method-name (head phpinspect-name)) &optional 
tryhard)
+  (phpi-mcol-get-return-type (phpi-typedef-static-methods def) method-name 
tryhard))
+
+(cl-defmethod phpi-typedef-set-variable ((def phpinspect-typedef)
+                                         (var phpinspect--variable))
+  (phpi--typedef-edit def
+    (push var (phpi-typedef-variables def))))
+
+(cl-defmethod phpi-typedef-delete-variable ((def phpinspect-typedef)
+                                            (var phpinspect--variable))
+  (phpi--typedef-edit def
+    (let ((first-half (seq-take-while (lambda (clvar) (not (eq var clvar)))
+                                      (phpi-typedef-variables def))))
+      ;; Only remove the first occurrence. If a parent class or a trait has the
+      ;; same variable, it will stick around.
+      (setf (phpi-typedef-variables def)
+            (append first-half (nthcdr (+ 1 (length first-half))
+                                       (phpi-typedef-variables def)))))))
+
+(cl-defmethod phpi-typedef-get-variables ((class phpinspect-typedef))
+  (seq-filter #'phpinspect--variable-vanilla-p (phpi-typedef-variables class)))
+
+(cl-defmethod phpi-typedef-get-static-variables ((class phpinspect-typedef))
+  (seq-filter #'phpinspect--variable-static-p (phpi-typedef-variables class)))
+
+(cl-defmethod phpi-typedef-get-constants ((class phpinspect-typedef))
+  (seq-filter #'phpinspect--variable-const-p (phpi-typedef-variables class)))
+
+(cl-defmethod phpi-typedef-get-variable
+  ((def phpinspect-typedef) (variable-name string))
+  (catch 'found
+    (dolist (variable (phpi-typedef-variables def))
+      (when (string= variable-name (phpinspect--variable-name variable))
+        (throw 'found variable)))))
+
+(provide 'phpinspect-typedef)
+;;; phpinspect-typedef.el ends here
diff --git a/phpinspect-worker.el b/phpinspect-worker.el
index b7fde19fef..b2566ad250 100644
--- a/phpinspect-worker.el
+++ b/phpinspect-worker.el
@@ -27,7 +27,7 @@
 (require 'phpinspect-util)
 (require 'phpinspect-project-struct)
 (require 'phpinspect-index)
-(require 'phpinspect-class)
+(require 'phpinspect-typedef)
 (require 'phpinspect-queue)
 (require 'phpinspect-pipeline)
 
diff --git a/phpinspect.el b/phpinspect.el
index e38cedc517..5721588792 100644
--- a/phpinspect.el
+++ b/phpinspect.el
@@ -54,7 +54,7 @@
 (require 'phpinspect-util)
 (require 'phpinspect-type)
 (require 'phpinspect-index)
-(require 'phpinspect-class)
+(require 'phpinspect-typedef)
 (require 'phpinspect-worker)
 (require 'phpinspect-autoload)
 (require 'phpinspect-imports)
diff --git a/test/fixtures/IndexClass1-indexed.eld 
b/test/fixtures/IndexClass1-indexed.eld
index 848dcca241..6a9c0d6de8 100644
--- a/test/fixtures/IndexClass1-indexed.eld
+++ b/test/fixtures/IndexClass1-indexed.eld
@@ -1 +1 @@
-`(phpinspect--root-index (imports \, (list)) (classes \, (list (cons 
(phpinspect--make-type :name "\\App\\Entity\\AuthToken" :collection nil 
:contains nil :fully-qualified t) `(phpinspect--indexed-class (complete \, t) 
(class-name \, (phpinspect--make-type :name "\\App\\Entity\\AuthToken" 
:collection nil :contains nil :fully-qualified t)) (declaration \, 
'(:declaration (:word "class") (:word "AuthToken"))) (location \, '(0 0)) 
(imports \, (list (cons (phpinspect-intern-name "ORM") (phpin [...]
+`(phpinspect--root-index (imports \, (list)) (classes \, (list (cons 
(phpinspect--make-type :name "\\App\\Entity\\AuthToken" :collection nil 
:contains nil :fully-qualified t) `(phpinspect--indexed-class (complete \, t) 
(trait-config \, nil) (class-name \, (phpinspect--make-type :name 
"\\App\\Entity\\AuthToken" :collection nil :contains nil :fully-qualified t)) 
(declaration \, '(:declaration (:word "class") (:word "AuthToken"))) (location 
\, '(0 0)) (imports \, (list (cons (phpinspect-int [...]
diff --git a/test/fixtures/IndexClass2-indexed.eld 
b/test/fixtures/IndexClass2-indexed.eld
index a34d222ff0..ba8abb27af 100644
--- a/test/fixtures/IndexClass2-indexed.eld
+++ b/test/fixtures/IndexClass2-indexed.eld
@@ -1 +1 @@
-`(phpinspect--root-index (imports \, (list)) (classes \, (list (cons 
(phpinspect--make-type :name "\\App\\Entity\\AuthToken" :collection nil 
:contains nil :fully-qualified t) `(phpinspect--indexed-class (complete \, t) 
(class-name \, (phpinspect--make-type :name "\\App\\Entity\\AuthToken" 
:collection nil :contains nil :fully-qualified t)) (declaration \, 
'(:declaration (:word "class") (:word "AuthToken"))) (location \, '(0 0)) 
(imports \, (list (cons (phpinspect-intern-name "ORM") (phpin [...]
+`(phpinspect--root-index (imports \, (list)) (classes \, (list (cons 
(phpinspect--make-type :name "\\App\\Entity\\AuthToken" :collection nil 
:contains nil :fully-qualified t) `(phpinspect--indexed-class (complete \, t) 
(trait-config \, nil) (class-name \, (phpinspect--make-type :name 
"\\App\\Entity\\AuthToken" :collection nil :contains nil :fully-qualified t)) 
(declaration \, '(:declaration (:word "class") (:word "AuthToken"))) (location 
\, '(0 0)) (imports \, (list (cons (phpinspect-int [...]
diff --git a/test/phpinspect-test.el b/test/phpinspect-test.el
index 51e0a7173e..7ea20a616c 100644
--- a/test/phpinspect-test.el
+++ b/test/phpinspect-test.el
@@ -323,7 +323,7 @@ class FlufferUpper
 (load-file (concat phpinspect-test-directory "/test-project.el"))
 (load-file (concat phpinspect-test-directory "/test-buffer.el"))
 (load-file (concat phpinspect-test-directory "/test-index.el"))
-(load-file (concat phpinspect-test-directory "/test-class.el"))
+(load-file (concat phpinspect-test-directory "/test-typedef.el"))
 (load-file (concat phpinspect-test-directory "/test-type.el"))
 (load-file (concat phpinspect-test-directory "/test-util.el"))
 (load-file (concat phpinspect-test-directory "/test-bmap.el"))
diff --git a/test/test-autoload.el b/test/test-autoload.el
index 89b7442ff7..216e70b34f 100644
--- a/test/test-autoload.el
+++ b/test/test-autoload.el
@@ -175,7 +175,7 @@
     (should-not (hash-table-empty-p (phpinspect-autoloader-own-types 
autoloader)))
     (should-not (hash-table-empty-p (phpinspect-autoloader-types autoloader)))
 
-    (should (phpinspect-project-get-class project (phpinspect--make-type :name 
"\\FilesList")))
+    (should (phpinspect-project-get-typedef project (phpinspect--make-type 
:name "\\FilesList")))
 
     (should (string= 
"/project/root/vendor/runescape/client/src/Runescape/Banana/App.php"
                      (phpinspect-autoloader-resolve
diff --git a/test/test-buffer.el b/test/test-buffer.el
index 3a06e06cc5..329703c58e 100644
--- a/test/test-buffer.el
+++ b/test/test-buffer.el
@@ -424,11 +424,11 @@ use CCC;
     (phpinspect-buffer-index-namespaces buffer namespaces)
     (phpinspect-buffer-index-classes buffer classes)
 
-    (should (phpinspect-project-get-class (phpinspect-buffer-project buffer) 
(phpinspect--make-type :name "\\TestNamespace\\TestClass")))
+    (should (phpinspect-project-get-typedef (phpinspect-buffer-project buffer) 
(phpinspect--make-type :name "\\TestNamespace\\TestClass")))
 
-    (should (= 2 (hash-table-count (phpinspect-project-class-index 
(phpinspect-buffer-project buffer)))))
-    (should (= 1 (length (phpinspect--class-extended-classes
-                          (phpinspect-project-get-class
+    (should (= 2 (hash-table-count (phpinspect-project-typedef-index 
(phpinspect-buffer-project buffer)))))
+    (should (= 1 (length (phpi-typedef-subscribed-to-types
+                          (phpinspect-project-get-typedef
                            (phpinspect-buffer-project buffer)
                            (phpinspect--make-type :name 
"\\TestNamespace\\TestClass"))))))
 
@@ -451,12 +451,12 @@ use CCC;
 
       (phpinspect-buffer-index-declarations buffer new-declarations)
       (phpinspect-buffer-index-classes buffer new-classes)
-      (should (phpinspect-project-get-class
+      (should (phpinspect-project-get-typedef
                (phpinspect-buffer-project buffer)
                (phpinspect--make-type :name "\\TestNamespace\\TestClass")))
 
-      (should (= 0 (length (phpinspect--class-extended-classes
-                          (phpinspect-project-get-class
+      (should (= 0 (length (phpi-typedef-subscribed-to-types
+                          (phpinspect-project-get-typedef
                            (phpinspect-buffer-project buffer)
                            (phpinspect--make-type :name 
"\\TestNamespace\\TestClass")))))))
 
@@ -465,11 +465,11 @@ use CCC;
       (setf (phpinspect-bmap--root-meta (phpinspect-buffer-map buffer)) 
new-root)
       (phpinspect-buffer-index-classes buffer new-classes)
 
-      (should-not (phpinspect-project-get-class
+      (should-not (phpinspect-project-get-typedef
                    (phpinspect-buffer-project buffer)
                    (phpinspect--make-type :name "\\TestNamespace\\TestClass")))
 
-      (should (= 1 (hash-table-count (phpinspect-project-class-index 
(phpinspect-buffer-project buffer))))))))
+      (should (= 1 (hash-table-count (phpinspect-project-typedef-index 
(phpinspect-buffer-project buffer))))))))
 
 (ert-deftest phpinspect-buffer-index-functions ()
   (with-temp-buffer
@@ -486,23 +486,23 @@ class TestClass
       (phpinspect-buffer-update-project-index buffer)
 
 
-      (should (phpinspect-project-get-class
+      (should (phpinspect-project-get-typedef
                (phpinspect-buffer-project buffer)
                (phpinspect--make-type :name "\\NS\\TestClass")))
 
-      (should (= 1 (hash-table-count (phpinspect--class-methods
-                                      (phpinspect-project-get-class
-                                       (phpinspect-buffer-project buffer)
-                                       (phpinspect--make-type :name 
"\\NS\\TestClass"))))))
+      (should (= 1 (length (phpi-typedef-get-methods
+                            (phpinspect-project-get-typedef
+                             (phpinspect-buffer-project buffer)
+                             (phpinspect--make-type :name 
"\\NS\\TestClass"))))))
 
       (setf (phpinspect-buffer-map buffer) (phpinspect-make-bmap :-root-meta 
(phpinspect-make-meta nil 1 400 "" 'root)))
 
       (phpinspect-buffer-index-functions buffer (phpinspect-make-splayt))
 
-      (should (= 0 (hash-table-count (phpinspect--class-methods
-                                      (phpinspect-project-get-class
-                                       (phpinspect-buffer-project buffer)
-                                       (phpinspect--make-type :name 
"\\NS\\TestClass")))))))))
+      (should (= 0 (length (phpi-typedef-get-methods
+                            (phpinspect-project-get-typedef
+                             (phpinspect-buffer-project buffer)
+                             (phpinspect--make-type :name 
"\\NS\\TestClass")))))))))
 
 (ert-deftest phpinspect-buffer-index-class-variables ()
   (let ((buffer (phpinspect-make-buffer :-project (phpinspect--make-project 
:autoload (phpinspect-make-autoloader))))
@@ -542,25 +542,25 @@ class TestClass
 
     (phpinspect-buffer-index-class-variables buffer variables)
 
-    (should (phpinspect-project-get-class
+    (should (phpinspect-project-get-typedef
              (phpinspect-buffer-project buffer)
              (phpinspect--make-type :name "\\TestClass")))
 
-    (should (= 2 (length (phpinspect--class-variables
-                          (phpinspect-project-get-class
+    (should (= 2 (length (phpi-typedef-variables
+                          (phpinspect-project-get-typedef
                            (phpinspect-buffer-project buffer)
                            (phpinspect--make-type :name "\\TestClass"))))))
 
 
-    (should (= 1 (length (phpinspect--class-get-constants
-                          (phpinspect-project-get-class
+    (should (= 1 (length (phpi-typedef-get-constants
+                          (phpinspect-project-get-typedef
                            (phpinspect-buffer-project buffer)
                            (phpinspect--make-type :name "\\TestClass"))))))
 
     (should (phpinspect--type= (phpinspect--make-type :name "\\array")
                               (phpinspect--variable-type
-                               (phpinspect--class-get-variable
-                                (phpinspect-project-get-class
+                               (phpi-typedef-get-variable
+                                (phpinspect-project-get-typedef
                                  (phpinspect-buffer-project buffer)
                                  (phpinspect--make-type :name "\\TestClass"))
                                 "banana"))))))
@@ -616,19 +616,19 @@ class AccountStatisticsController {
 
       (phpinspect-buffer-update-project-index buffer)
 
-      (let ((class (phpinspect-project-get-class
+      (let ((class (phpinspect-project-get-typedef
                     (phpinspect-buffer-project buffer)
                     (phpinspect--make-type
                      :name 
"\\App\\Controller\\Api\\V1\\AccountStatisticsController"
                      :fully-qualified t))))
         (should class)
 
-        (let ((model (phpinspect--class-get-variable class "model"))
-              (priv-model (phpinspect--class-get-variable class "privModel"))
+        (let ((model (phpi-typedef-get-variable class "model"))
+              (priv-model (phpi-typedef-get-variable class "privModel"))
               ;; Static variables are stored with "$" prefix
-              (relation (phpinspect--class-get-variable class "$relation"))
-              (static-relation (phpinspect--class-get-variable class 
"$staticRelation"))
-              (relations (phpinspect--class-get-variable class "relations")))
+              (relation (phpi-typedef-get-variable class "$relation"))
+              (static-relation (phpi-typedef-get-variable class 
"$staticRelation"))
+              (relations (phpi-typedef-get-variable class "relations")))
           (should model)
           (should priv-model)
           (should relation)
diff --git a/test/test-class.el b/test/test-class.el
index 154336c302..dbf03762dd 100644
--- a/test/test-class.el
+++ b/test/test-class.el
@@ -23,91 +23,91 @@
 
 ;;; Code:
 
-(require 'ert)
-(require 'phpinspect-class)
-(require 'phpinspect-project)
-(require 'subr-x)
-(require 'phpinspect-worker)
-
-(phpinspect-ensure-worker)
-
-(ert-deftest phpinspect--merge-method-return-type ()
-  (let* ((class-name (phpinspect--make-type :name "\\Something"))
-         (method1 (phpinspect--make-function
-                  :name "fun"
-                  :return-type (phpinspect--make-type :name "\\array")))
-         (method2 (phpinspect--make-function
-                   :name "fun"
-                   :return-type (phpinspect--make-type :name "\\bool")))
-         (result (phpinspect--merge-method class-name method1 method2)))
-
-    (should (phpinspect--type= (phpinspect--make-type :name "\\bool")
-                               (phpinspect--function-return-type result)))
-    (should (phpinspect--type= (phpinspect--make-type :name "\\bool")
-                               (phpinspect--function-return-type method1)))))
-
-(ert-deftest phpinspect-class-incorporate ()
-  (let ((class (phpinspect--make-class-generated))
-        (other-class (phpinspect--make-class-generated)))
-    (phpinspect--class-set-index class `(phpinspect--indexed-class (class-name 
. ,(phpinspect--make-type :name "Class"))))
-    (phpinspect--class-set-index other-class `(phpinspect--indexed-class 
(class-name . ,(phpinspect--make-type :name "OtherClass"))))
-    (phpinspect--class-update-method
-     class (phpinspect--make-function :scope '(:private) :name "test" 
:return-type phpinspect--null-type))
-
-    (phpinspect--class-update-method
-     other-class (phpinspect--make-function :scope '(:protected) :name 
"other-test" :return-type phpinspect--null-type))
-
-    (phpinspect--class-incorporate class other-class)
-
-    (should (= 2 (length (hash-table-values (phpinspect--class-methods 
class)))))
-    (should (= 1 (length (hash-table-values (phpinspect--class-subscriptions 
other-class)))))
-
-    (phpinspect--class-set-index
-     class
-     `(phpinspect--indexed-class
-       (complete . t)
-       (class-name . ,(phpinspect--make-type :name "Class"))
-       (methods . ,(list (phpinspect--make-function :name "test" :return-type 
phpinspect--null-type)
-                         (phpinspect--make-function :name "foobar" 
:return-type phpinspect--null-type)))))
-
-    (should (= 3 (length (hash-table-values (phpinspect--class-methods 
class)))))
-
-    (phpinspect--class-incorporate class other-class)
-    (should (= 3 (length (hash-table-values (phpinspect--class-methods 
class)))))
-
-    (phpinspect--class-set-index
-     class
-     `(phpinspect--indexed-class
-       (complete . t)
-       (class-name . ,(phpinspect--make-type :name "Class"))
-       (methods . ,(list (phpinspect--make-function :name "foobar" 
:return-type phpinspect--null-type)))))
-
-    (should (= 2 (length (hash-table-values (phpinspect--class-methods 
class)))))
-    (should (phpinspect--class-get-method class (phpinspect-intern-name 
"other-test")))
-    (should (phpinspect--class-get-method class (phpinspect-intern-name 
"foobar")))
-
-    (phpinspect--class-set-index
-     class
-     `(phpinspect--indexed-class
-       (complete . t)
-       (class-name . ,(phpinspect--make-type :name "Class"))
-       (methods)))
-
-    (should (= 1 (length (hash-table-values (phpinspect--class-methods 
class)))))
-    (should (phpinspect--class-get-method class (phpinspect-intern-name 
"other-test")))
-
-    (phpinspect--class-incorporate class other-class)
-    (should (= 1 (length (hash-table-values (phpinspect--class-methods 
class)))))
-    (should (= 1 (length (hash-table-values (phpinspect--class-subscriptions 
other-class)))))))
-
-(ert-deftest phpinspect--class-update-declaration ()
-  (let ((class (phpinspect--make-class-generated
-                :class-retriever (phpinspect-project-make-class-retriever
-                                  (phpinspect--make-project)))))
-    (phpinspect--class-update-declaration class '(:declaration (:word "class") 
(:word "TestClass")
-                                                               (:word 
"extends") (:word "OtherClass")
-                                                               (:word 
"implements") (:word "ImplClass"))
-                                          nil "NS")
-    (should (= 2 (length (phpinspect--class-extended-classes class))))
-    (should (phpinspect--type= (phpinspect--make-type :name "\\NS\\TestClass" 
:fully-qualified t)
-                               (phpinspect--class-name class)))))
+;; (require 'ert)
+;; (require 'phpinspect-typedef)
+;; (require 'phpinspect-project)
+;; (require 'subr-x)
+;; (require 'phpinspect-worker)
+
+;; (phpinspect-ensure-worker)
+
+;; (ert-deftest phpinspect--merge-method-return-type ()
+;;   (let* ((class-name (phpinspect--make-type :name "\\Something"))
+;;          (method1 (phpinspect--make-function
+;;                   :name "fun"
+;;                   :return-type (phpinspect--make-type :name "\\array")))
+;;          (method2 (phpinspect--make-function
+;;                    :name "fun"
+;;                    :return-type (phpinspect--make-type :name "\\bool")))
+;;          (result (phpinspect--merge-method class-name method1 method2)))
+
+;;     (should (phpinspect--type= (phpinspect--make-type :name "\\bool")
+;;                                (phpinspect--function-return-type result)))
+;;     (should (phpinspect--type= (phpinspect--make-type :name "\\bool")
+;;                                (phpinspect--function-return-type 
method1)))))
+
+;; (ert-deftest phpinspect-class-incorporate ()
+;;   (let ((class (phpinspect--make-class-generated))
+;;         (other-class (phpinspect--make-class-generated)))
+;;     (phpinspect--class-set-index class `(phpinspect--indexed-class 
(class-name . ,(phpinspect--make-type :name "Class"))))
+;;     (phpinspect--class-set-index other-class `(phpinspect--indexed-class 
(class-name . ,(phpinspect--make-type :name "OtherClass"))))
+;;     (phpinspect--class-update-method
+;;      class (phpinspect--make-function :scope '(:private) :name "test" 
:return-type phpinspect--null-type))
+
+;;     (phpinspect--class-update-method
+;;      other-class (phpinspect--make-function :scope '(:protected) :name 
"other-test" :return-type phpinspect--null-type))
+
+;;     (phpinspect--class-incorporate class other-class)
+
+;;     (should (= 2 (length (hash-table-values (phpinspect--class-methods 
class)))))
+;;     (should (= 1 (length (hash-table-values 
(phpinspect--class-subscriptions other-class)))))
+
+;;     (phpinspect--class-set-index
+;;      class
+;;      `(phpinspect--indexed-class
+;;        (complete . t)
+;;        (class-name . ,(phpinspect--make-type :name "Class"))
+;;        (methods . ,(list (phpinspect--make-function :name "test" 
:return-type phpinspect--null-type)
+;;                          (phpinspect--make-function :name "foobar" 
:return-type phpinspect--null-type)))))
+
+;;     (should (= 3 (length (hash-table-values (phpinspect--class-methods 
class)))))
+
+;;     (phpinspect--class-incorporate class other-class)
+;;     (should (= 3 (length (hash-table-values (phpinspect--class-methods 
class)))))
+
+;;     (phpinspect--class-set-index
+;;      class
+;;      `(phpinspect--indexed-class
+;;        (complete . t)
+;;        (class-name . ,(phpinspect--make-type :name "Class"))
+;;        (methods . ,(list (phpinspect--make-function :name "foobar" 
:return-type phpinspect--null-type)))))
+
+;;     (should (= 2 (length (hash-table-values (phpinspect--class-methods 
class)))))
+;;     (should (phpinspect--class-get-method class (phpinspect-intern-name 
"other-test")))
+;;     (should (phpinspect--class-get-method class (phpinspect-intern-name 
"foobar")))
+
+;;     (phpinspect--class-set-index
+;;      class
+;;      `(phpinspect--indexed-class
+;;        (complete . t)
+;;        (class-name . ,(phpinspect--make-type :name "Class"))
+;;        (methods)))
+
+;;     (should (= 1 (length (hash-table-values (phpinspect--class-methods 
class)))))
+;;     (should (phpinspect--class-get-method class (phpinspect-intern-name 
"other-test")))
+
+;;     (phpinspect--class-incorporate class other-class)
+;;     (should (= 1 (length (hash-table-values (phpinspect--class-methods 
class)))))
+;;     (should (= 1 (length (hash-table-values 
(phpinspect--class-subscriptions other-class)))))))
+
+;; (ert-deftest phpinspect--class-update-declaration ()
+;;   (let ((class (phpinspect--make-class-generated
+;;                 :class-retriever (phpinspect-project-make-class-retriever
+;;                                   (phpinspect--make-project)))))
+;;     (phpinspect--class-update-declaration class '(:declaration (:word 
"class") (:word "TestClass")
+;;                                                                (:word 
"extends") (:word "OtherClass")
+;;                                                                (:word 
"implements") (:word "ImplClass"))
+;;                                           nil "NS")
+;;     (should (= 2 (length (phpinspect--class-extended-classes class))))
+;;     (should (phpinspect--type= (phpinspect--make-type :name 
"\\NS\\TestClass" :fully-qualified t)
+;;                                (phpinspect--class-name class)))))
diff --git a/test/test-eldoc.el b/test/test-eldoc.el
index a697aa1047..ad1b03cd9e 100644
--- a/test/test-eldoc.el
+++ b/test/test-eldoc.el
@@ -77,7 +77,7 @@ class Thing
 
           (should (phpinspect-function-doc-p result))
           (should (= (cdr expected) (phpinspect-function-doc-arg-pos result)))
-          (should (string= "getThis" (phpinspect--function-name 
(phpinspect-function-doc-fn result)))))))))
+          (should (string= "getThis" (phpi-fn-name (phpinspect-function-doc-fn 
result)))))))))
 
 
 (ert-deftest phpinspect-eldoc-function-for-object-method ()
diff --git a/test/test-index.el b/test/test-index.el
index 9244fef669..9e511ccc7a 100644
--- a/test/test-index.el
+++ b/test/test-index.el
@@ -55,6 +55,7 @@
              (,(phpinspect--make-type :name "\\Potato" :fully-qualified t)
               phpinspect--indexed-class
               (complete . t)
+              (trait-config)
               (class-name . ,(phpinspect--make-type :name "\\Potato" 
:fully-qualified t))
               (declaration . (:declaration (:word "class") (:word "Potato")))
               (location . (0 0))
@@ -74,7 +75,7 @@
                                                 ("things" . 
,(phpinspect--make-type :name "\\array"
                                                                                
   :collection t
                                                                                
   :fully-qualified t)))
-                                   :return-type phpinspect--null-type)))
+                                   :return-type nil)))
               (static-variables)
               (variables)
               (constants)
@@ -116,6 +117,7 @@ try {
 })))));
 }")))
          (used-types (alist-get 'used-types (car (alist-get 'classes 
result)))))
+
     (should (equal
              (mapcar #'phpinspect-intern-name
                      (sort
@@ -159,33 +161,33 @@ try {
          (methods (alist-get 'methods class)))
     (should (= 3 (length methods)))
     (dolist (method methods)
-      (should (member (phpinspect--function-name method)
+      (should (member (phpi-fn-name method)
                       '("duplicate" "hold" "peel")))
 
-      (cond ((string= (phpinspect--function-name method)
+      (cond ((string= (phpi-fn-name method)
                       "duplicate")
              (should (phpinspect--type=
                       (phpinspect--make-type :name "\\Banana" :fully-qualified 
t)
-                      (phpinspect--function-return-type method))))
-            ((string= (phpinspect--function-name method)
+                      (phpi-fn-return-type method))))
+            ((string= (phpi-fn-name method)
                       "peel")
              (should (phpinspect--type=
                       (phpinspect--make-type :name "\\int" :fully-qualified t)
-                      (phpinspect--function-return-type method)))
+                      (phpi-fn-return-type method)))
 
-             (should (= 2 (length (phpinspect--function-arguments method))))
+             (should (= 2 (length (phpi-fn-arguments method))))
              (should (phpinspect--type=
                       (phpinspect--make-type :name "\\array" :fully-qualified 
t)
-                      (phpinspect--function-argument-type method "loose")))
+                      (phpi-fn-argument-type method "loose")))
 
              (should (phpinspect--type=
                       (phpinspect--make-type :name "\\bool" :fully-qualified t)
-                      (phpinspect--function-argument-type method "fast"))))
-            ((string= (phpinspect--function-name method)
+                      (phpi-fn-argument-type method "fast"))))
+            ((string= (phpi-fn-name method)
                       "hold")
              (should (phpinspect--type=
                       (phpinspect--make-type :name "\\void" :fully-qualified t)
-                      (phpinspect--function-return-type method))))))))
+                      (phpi-fn-return-type method))))))))
 
 (ert-deftest phpinspect-index-static-method-annotations ()
   (let* ((result (phpinspect--index-tokens
@@ -200,32 +202,32 @@ try {
          (methods (alist-get 'static-methods class)))
     (should (= 3 (length methods)))
     (dolist (method methods)
-      (should (member (phpinspect--function-name method)
+      (should (member (phpi-fn-name method)
                       '("create" "hold" "peel")))
 
-      (cond ((string= (phpinspect--function-name method)
+      (cond ((string= (phpi-fn-name method)
                       "duplicate")
              (should (phpinspect--type=
                       (phpinspect--make-type :name "\\Banana" :fully-qualified 
t)
-                      (phpinspect--function-return-type method))))
-            ((string= (phpinspect--function-name method)
+                      (phpi-fn-return-type method))))
+            ((string= (phpi-fn-name method)
                       "peel")
              (should (phpinspect--type=
                       (phpinspect--make-type :name "\\int" :fully-qualified t)
-                      (phpinspect--function-return-type method)))
+                      (phpi-fn-return-type method)))
 
-             (should (= 2 (length (phpinspect--function-arguments method))))
+             (should (= 2 (length (phpi-fn-arguments method))))
              (should (phpinspect--type=
                       (phpinspect--make-type :name "\\array" :fully-qualified 
t)
-                      (phpinspect--function-argument-type method "loose")))
+                      (phpi-fn-argument-type method "loose")))
              (should (phpinspect--type=
                       (phpinspect--make-type :name "\\bool" :fully-qualified t)
-                      (phpinspect--function-argument-type method "fast"))))
-            ((string= (phpinspect--function-name method)
+                      (phpi-fn-argument-type method "fast"))))
+            ((string= (phpi-fn-name method)
                       "hold")
              (should (phpinspect--type=
                       (phpinspect--make-type :name "\\void" :fully-qualified t)
-                      (phpinspect--function-return-type method))))))))
+                      (phpi-fn-return-type method))))))))
 
 (require 'phpinspect-serialize)
 
@@ -284,19 +286,19 @@ function example($bing): Thing {}")
 
     (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 (string= "test_func" (phpi-fn-name (cadr functions))))
+    (should (string= "example" (phpi-fn-name (car functions))))
 
     (let ((example (car functions)))
-      (should (= 1 (length (phpinspect--function-arguments example))))
+      (should (= 1 (length (phpi-fn-arguments example))))
       (should (phpinspect--type=
                (phpinspect--make-type :name "\\array")
-               (phpinspect--function-argument-type example "bing"))))
+               (phpi-fn-argument-type example "bing"))))
 
     (should (phpinspect--type= (phpinspect--make-type :name "\\array")
-                               (phpinspect--function-return-type (cadr 
functions))))
+                               (phpi-fn-return-type (cadr functions))))
     (should (phpinspect--type= (phpinspect--make-type :name "\\Example\\Thing")
-                               (phpinspect--function-return-type (car 
functions))))))
+                               (phpi-fn-return-type (car functions))))))
 
 (ert-deftest phpinspect-index-functions-in-namespace ()
   (let* ((code "<?php
@@ -316,13 +318,13 @@ function example(Firewall $wall): Thing {}")
 
     (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 (string= "Local\\test_func" (phpi-fn-name (cadr functions))))
+    (should (string= "Local\\example" (phpi-fn-name (car functions))))
 
     (should (phpinspect--type= (phpinspect--make-type :name "\\array")
-                               (phpinspect--function-return-type (cadr 
functions))))
+                               (phpi-fn-return-type (cadr functions))))
     (should (phpinspect--type= (phpinspect--make-type :name "\\Example\\Thing")
-                               (phpinspect--function-return-type (car 
functions))))
+                               (phpi-fn-return-type (car functions))))
     (should (alist-get 'used-types namespace))
     (should (= 3 (length (alist-get 'used-types namespace))))
     (should (member (phpinspect-intern-name "Firewall") (alist-get 'used-types 
namespace)))
@@ -350,18 +352,18 @@ class AccountStatisticsController {
 }")
       (phpinspect-project-add-index project (phpinspect-index-current-buffer))
 
-      (let ((class (phpinspect-project-get-class
+      (let ((class (phpinspect-project-get-typedef
                    project
                     (phpinspect--make-type
                      :name 
"\\App\\Controller\\Api\\V1\\AccountStatisticsController"
                      :fully-qualified t))))
         (should class)
 
-        (let ((model (phpinspect--class-get-variable class "model"))
-              (priv-model (phpinspect--class-get-variable class "privModel"))
+        (let ((model (phpi-typedef-get-variable class "model"))
+              (priv-model (phpi-typedef-get-variable class "privModel"))
               ;; Static variables are stored with "$" prefix
-              (relation (phpinspect--class-get-variable class "$relation"))
-              (static-relation (phpinspect--class-get-variable class 
"$staticRelation")))
+              (relation (phpi-typedef-get-variable class "$relation"))
+              (static-relation (phpi-typedef-get-variable class 
"$staticRelation")))
           (should model)
           (should priv-model)
           (should relation)
@@ -405,14 +407,14 @@ public function doStuff()
       (let* ((type (phpinspect--make-type
                      :name 
"\\App\\Controller\\Api\\V1\\AccountStatisticsController"
                      :fully-qualified t))
-             (class (phpinspect-project-get-class project type)))
+             (class (phpinspect-project-get-typedef project type)))
 
         (should class)
 
-        (let ((method (phpinspect--class-get-method class "doStuff")))
+        (let ((method (phpi-typedef-get-method class "doStuff")))
           (should method)
-          (should (phpinspect--function-return-type method))
-          (should (phpinspect--type= type (phpinspect--function-return-type 
method))))))))
+          (should (phpi-method-return-type method))
+          (should (phpinspect--type= type (phpi-method-return-type 
method))))))))
 
 (ert-deftest phpinspect-index-nested-functions ()
   (with-temp-buffer
@@ -437,12 +439,12 @@ if (something()) {
 
       (let ((nestedConditional (car functions))
             (conditional (cadr functions)))
-        (should (string= "conditional" (phpinspect--function-name 
conditional)))
-        (should (string= "nestedConditional" (phpinspect--function-name 
nestedConditional)))))))
+        (should (string= "conditional" (phpi-fn-name conditional)))
+        (should (string= "nestedConditional" (phpi-fn-name 
nestedConditional)))))))
 
 (ert-deftest phpinspect-index-trait-use ()
   (let* ((tree (with-temp-buffer
-                 (insert "use B, C { C::foo insteadof B, B::bar as banana }")
+                 (insert "B, C { C::foo insteadof B, B::bar as banana }")
                  (goto-char (point-min))
                  (phpinspect--parse-use (current-buffer) (point-max))))
          (expected `((,(phpinspect--make-type :name "\\C" :fully-qualified t))
diff --git a/test/test-typedef.el b/test/test-typedef.el
new file mode 100644
index 0000000000..76adbd33db
--- /dev/null
+++ b/test/test-typedef.el
@@ -0,0 +1,75 @@
+
+
+(require 'ert)
+(require 'phpinspect-typedef)
+(require 'phpinspect-index)
+(require 'phpinspect-parser)
+(require 'phpinspect-test-env
+         (expand-file-name "phpinspect-test-env.el"
+                           (file-name-directory (macroexp-file-name))))
+
+(ert-deftest phpinspect-typedef-set-index-simple ()
+  (let* ((code "class A { function B(): C {} }")
+         (index (phpinspect--index-tokens (phpinspect-parse-string code)))
+         (class (cdar (alist-get 'classes index)))
+         (typedef (phpinspect-make-typedef (alist-get 'class-name class))))
+    (phpi-typedef-set-index typedef class)
+
+    (should (phpi-typedef-get-methods typedef))
+    (should (= 1 (length (phpi-typedef-get-methods typedef))))
+
+    (should (eq (phpinspect-intern-name "B")
+                (phpi-method-name (car (phpi-typedef-get-methods typedef)))))))
+
+(ert-deftest phpinspect-typedef-subscribe ()
+  (let* ((def1 (phpinspect-make-typedef (phpinspect--make-type :name "\\A")))
+         (def2 (phpinspect-make-typedef (phpinspect--make-type :name "\\B")))
+         (retriever (lambda (type)
+                      (cond ((phpinspect--type= type (phpinspect--make-type 
:name "\\A"))
+                             def1)
+                            ((phpinspect--type= type (phpinspect--make-type 
:name "\\B"))
+                             def2)))))
+
+    (setf (phpi-typedef-retriever def1) retriever
+          (phpi-typedef-retriever def2) retriever)
+    (phpi-typedef-set-method def2 (phpinspect--make-function :name "test"))
+
+    (phpi-typedef-update-extensions def1 (list (phpi-typedef-name def2)))
+
+    (let ((method (phpi-typedef-get-method def1 (phpinspect-intern-name 
"test"))))
+      (should method)
+      (should-not (phpi-method-return-type method))
+
+      (phpi-typedef-set-method def1 (phpinspect--make-function
+                                     :name "test"
+                                     :return-type (phpinspect--make-type :name 
"\\aaa")))
+
+      (setq method (phpi-typedef-get-method def1 (phpinspect-intern-name 
"test")))
+      (should method)
+      (should (phpi-method-return-type method))
+
+      (phpi-typedef-delete-method def1 (phpinspect-intern-name "test"))
+
+      (setq method (phpi-typedef-get-method def1 (phpinspect-intern-name 
"test")))
+      (should method)
+      (should-not (phpi-method-return-type method))
+
+      (phpi-typedef-update-extensions def1 nil)
+
+      (setq method (phpi-typedef-get-method def1 (phpinspect-intern-name 
"test")))
+      (should-not method))))
+
+(ert-deftest phpinspect-typedef-variables ()
+  (let ((def (phpinspect-make-typedef (phpinspect--make-type :name "\\test"))))
+
+    (phpi-typedef-set-variable def (phpinspect--make-variable :name "test"))
+    (phpi-typedef-set-variable def (phpinspect--make-variable :name "test2"))
+
+    (let ((test1 (phpi-typedef-get-variable def "test"))
+          (test2 (phpi-typedef-get-variable def "test2")))
+
+      (should test1)
+      (should (string= "test" (phpinspect--variable-name test1)))
+
+      (should (phpi-typedef-get-variable def "test2"))
+      (should (string= "test2" (phpinspect--variable-name test2))))))

Reply via email to