emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/phpinspect f013b3c709 036/126: WIP: Support ambiguous t


From: ELPA Syncer
Subject: [elpa] externals/phpinspect f013b3c709 036/126: WIP: Support ambiguous typehints
Date: Sat, 12 Aug 2023 00:58:38 -0400 (EDT)

branch: externals/phpinspect
commit f013b3c709746a0f8e49fa9447153ac743e63a2b
Author: Hugo Thunnissen <devel@hugot.nl>
Commit: Hugo Thunnissen <devel@hugot.nl>

    WIP: Support ambiguous typehints
    
    - Try to infer type of "object" typehint by using the return annotation
    - Support late static binding with "static" and "this" return type
---
 phpinspect-class.el | 53 +++++++++++++++++++++++++++++++++++++----------------
 phpinspect-index.el | 22 +++++++++++++++-------
 phpinspect-type.el  | 38 +++++++++++++++++++++++++++++++-------
 phpinspect.el       | 12 ++----------
 4 files changed, 85 insertions(+), 40 deletions(-)

diff --git a/phpinspect-class.el b/phpinspect-class.el
index c2918f6ca2..7b6e12be0c 100644
--- a/phpinspect-class.el
+++ b/phpinspect-class.el
@@ -99,12 +99,21 @@
                                             (method phpinspect--function))
   (phpinspect--log "Adding method by name %s to class"
                    (phpinspect--function-name method))
-  (puthash (phpinspect--function-name-symbol method)
-           method
-           (phpinspect--class-methods class)))
+  (setq method (phpinspect--copy-function method))
+
+  (when (phpinspect--type-does-late-static-binding
+         (phpinspect--function-return-type method))
+
+    (setf (phpinspect--function-return-type method)
+          (alist-get 'class-name (phpinspect--class-index class))))
+
+    (puthash (phpinspect--function-name-symbol method)
+             method
+             (phpinspect--class-methods class)))
 
 (cl-defmethod phpinspect--class-set-static-method ((class phpinspect--class)
                                                    (method 
phpinspect--function))
+  (setq method (phpinspect--copy-function method))
   (puthash (phpinspect--function-name-symbol method)
            method
            (phpinspect--class-static-methods class)))
@@ -135,12 +144,12 @@
                            (phpinspect--class-static-methods class))))
     (if existing
         (progn
-          (unless (eq (phpinspect--function-return-type method)
-                    phpinspect--null-type)
-          (setf (phpinspect--function-return-type existing)
-                (phpinspect--function-return-type method))
+          (unless (phpinspect--type= (phpinspect--function-return-type method)
+                      phpinspect--null-type)
+            (setf (phpinspect--function-return-type existing)
+                  (phpinspect--function-return-type method)))
           (setf (phpinspect--function-arguments existing)
-                (phpinspect--function-arguments method))))
+                (phpinspect--function-arguments method)))
       (phpinspect--class-set-static-method class method))))
 
 (cl-defmethod phpinspect--class-update-method ((class phpinspect--class)
@@ -149,19 +158,31 @@
                            (phpinspect--class-methods class))))
     (if existing
         (progn
-          (unless (eq (phpinspect--function-return-type method)
-                    phpinspect--null-type)
-          (setf (phpinspect--function-return-type existing)
-                (phpinspect--function-return-type method))
+          (unless (phpinspect--type= (phpinspect--function-return-type method)
+                                     phpinspect--null-type)
+            (phpinspect--log "method return type %s" 
(phpinspect--function-return-type method))
+            (setf (phpinspect--function-return-type existing)
+                  ;; The "static" return type returns the class that the method
+                  ;; is called on
+                  (if (phpinspect--type-does-late-static-binding
+                       (phpinspect--function-return-type method))
+                      (alist-get 'class-name (phpinspect--class-index class))
+                    (phpinspect--function-return-type method))))
+
           (setf (phpinspect--function-arguments existing)
-                (phpinspect--function-arguments method))))
+                (phpinspect--function-arguments method)))
       (phpinspect--class-set-method class method))))
 
 (cl-defmethod phpinspect--class-incorporate ((class phpinspect--class)
                                              (other-class phpinspect--class))
-  (maphash (lambda (k method)
-             (phpinspect--class-update-method class method))
-           (phpinspect--class-methods other-class)))
+  (let ((class-index (phpinspect--class-index other-class)))
+    (dolist (method (alist-get 'methods class-index))
+      (phpinspect--class-update-method class method))
+
+    (dolist (method (alist-get 'static-methods class-index))
+      (phpinspect--class-update-static-method class method))))
+
+
 
 (cl-defmethod phpinspect--class-subscribe ((class phpinspect--class)
                                            (subscription-class 
phpinspect--class))
diff --git a/phpinspect-index.el b/phpinspect-index.el
index 9211ed9f47..c1fd2c9350 100644
--- a/phpinspect-index.el
+++ b/phpinspect-index.el
@@ -56,26 +56,34 @@
                    arg-index))))
     (nreverse arg-index)))
 
+(defsubst phpinspect--should-prefer-return-annotation (type)
+  "When the return annotation should be preferred over typehint of TYPE, if 
available."
+  (or (not type)
+      (phpinspect--type= type phpinspect--object-type)))
+
 (defun phpinspect--index-function-from-scope (type-resolver scope 
comment-before)
   (let* ((php-func (cadr scope))
          (declaration (cadr php-func))
          (type (if (phpinspect-word-p (car (last declaration)))
-                   (phpinspect--make-type :name (cadar (last declaration))))))
+                   (funcall type-resolver
+                            (phpinspect--make-type :name (cadar (last 
declaration)))))))
 
-    ;; @return annotation. Has precedence over typehint when dealing with a 
collection.
+    ;; @return annotation. When dealing with a collection, we want to store the
+    ;; type of its members.
     (let* ((is-collection
            (when type
-             (member (phpinspect--type-name
-                      (funcall type-resolver type)) 
phpinspect-collection-types)))
+             (member (phpinspect--type-name type) 
phpinspect-collection-types)))
            (return-annotation-type
-            (when (or (not type) is-collection)
+            (when (or (phpinspect--should-prefer-return-annotation type) 
is-collection)
               (cadadr
                (seq-find #'phpinspect-return-annotation-p
                          comment-before)))))
-      (phpinspect--log "found return annotation %s" return-annotation-type)
+      (phpinspect--log "found return annotation %s when type is %s"
+                       return-annotation-type
+                       type)
 
       (when return-annotation-type
-        (cond ((not type)
+        (cond ((phpinspect--should-prefer-return-annotation type)
                (setq type (funcall type-resolver
                                    (phpinspect--make-type :name 
return-annotation-type))))
               (is-collection
diff --git a/phpinspect-type.el b/phpinspect-type.el
index 0816fa04a0..e9f628652c 100644
--- a/phpinspect-type.el
+++ b/phpinspect-type.el
@@ -49,11 +49,37 @@
   `(phpinspect--make-type-generated
     ,@(phpinspect--wrap-plist-name-in-symbol property-list)))
 
-(defconst phpinspect--null-type (phpinspect--make-type :name "\\null"))
+(defun phpinspect--make-types (&rest type-names)
+  (mapcar (lambda (name) (phpinspect--make-type :name name))
+          type-names))
+
+(defconst phpinspect-native-types
+  ;; self, parent and resource are not valid type name.
+  ;; see https://www.php.net/manual/ja/language.types.declarations.php
+  ;;;
+  ;; However, this list does not need to be valid, it just needs to contain the
+  ;; list of type names that we should not attempt to resolve relatively.
+  '("array" "bool" "callable" "float" "int" "iterable" "mixed" "object" 
"string" "void" "self" "static" "this"))
+
+(defvar phpinspect-collection-types
+  (phpinspect--make-types '("\\array" "\\iterable" "\\SplObjectCollection" 
"\\mixed"))
+  "FQNs of types that should be treated as collecitons when inferring types.")
+
+(defconst phpinspect--object-type (phpinspect--make-type :name "\\object" 
:fully-qualified t))
+(defconst phpinspect--static-type (phpinspect--make-type :name "\\static" 
:fully-qualified t))
+(defconst phpinspect--self-type (phpinspect--make-type :name "\\self" 
:fully-qualified t))
+(defconst phpinspect--this-type (phpinspect--make-type :name "\\this" 
:fully-qualified t))
+(defconst phpinspect--null-type (phpinspect--make-type :name "\\null" 
:fully-qualified t))
 
 (cl-defmethod phpinspect--type-set-name ((type phpinspect--type) (name string))
   (setf (phpinspect--type-name-symbol type) (phpinspect-intern-name name)))
 
+(cl-defmethod phpinspect--type-does-late-static-binding ((type 
phpinspect--type))
+  "Whether or not TYPE is used for late static binding.
+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--type-name ((type phpinspect--type))
   (symbol-name (phpinspect--type-name-symbol type)))
 
@@ -107,15 +133,12 @@ NAMESPACE may be nil, or a string with a namespace FQN."
           (if token-tree (or (phpinspect--find-innermost-incomplete-class 
token-tree)
                              (phpinspect--find-class-token token-tree))))
          (inside-class-name (if inside-class 
(phpinspect--get-class-name-from-token
-                                              inside-class)))
-         (self-type (phpinspect--make-type :name "self"))
-         (static-type (phpinspect--make-type :name "static")))
+                                              inside-class))))
     (lambda (type)
       (phpinspect--type-resolve
        types
        namespace
-       (if (and inside-class-name (or (phpinspect--type= type self-type)
-                                      (phpinspect--type= type static-type)))
+       (if (and inside-class-name (phpinspect--type= type 
phpinspect--self-type))
            (progn
              (phpinspect--log "Returning inside class name for %s : %s"
                               type inside-class-name)
@@ -129,7 +152,8 @@ NAMESPACE may be nil, or a string with a namespace FQN."
 (cl-defmethod phpinspect--format-type-name ((type phpinspect--type))
   (phpinspect--format-type-name (phpinspect--type-name type)))
 
-(cl-defstruct (phpinspect--function (:constructor 
phpinspect--make-function-generated))
+(cl-defstruct (phpinspect--function (:constructor 
phpinspect--make-function-generated)
+                                    (:copier phpinspect--copy-function))
   "A PHP function."
   (name-symbol nil
                :type symbol
diff --git a/phpinspect.el b/phpinspect.el
index e0eec178b1..20dc8a84f7 100644
--- a/phpinspect.el
+++ b/phpinspect.el
@@ -74,14 +74,6 @@ phpinspect")
 Should normally be set to \"phpinspect-index.bash\" in the source
   file directory.")
 
-(defconst phpinspect-native-types
-  ;; self, parent and resource are not valid type name.
-  ;; see https://www.php.net/manual/ja/language.types.declarations.php
-  '("array" "bool" "callable" "float" "int" "iterable" "mixed" "object" 
"string" "void"))
-
-(defvar phpinspect-collection-types
-  '("\\array" "\\iterable" "\\SplObjectCollection" "\\mixed")
-  "FQNs of types that should be treated as collecitons when inferring types.")
 
 (cl-defstruct (phpinspect--completion
                (:constructor phpinspect--construct-completion))
@@ -229,7 +221,7 @@ accompanied by all of its enclosing tokens."
 (defsubst phpinspect-get-cached-project-class-method-type
   (project-root class-fqn method-name)
     (when project-root
-    (let* ((class (phpinspect-get-cached-project-class project-root class-fqn))
+    (let* ((class (phpinspect-get-or-create-cached-project-class project-root 
class-fqn))
            (method))
       (when class
         (setq method
@@ -266,7 +258,7 @@ accompanied by all of its enclosing tokens."
 (defsubst phpinspect-get-cached-project-class-static-method-type
   (project-root class-fqn method-name)
   (when project-root
-    (let* ((class (phpinspect-get-cached-project-class project-root class-fqn))
+    (let* ((class (phpinspect-get-or-create-cached-project-class project-root 
class-fqn))
            (method))
       (when class
         (setq method



reply via email to

[Prev in Thread] Current Thread [Next in Thread]