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

    Resolve types of suggested variable completions
---
 phpinspect-resolve.el        |  8 ++++++++
 phpinspect-resolvecontext.el | 17 +++++++++++++++++
 phpinspect-suggest.el        | 34 +++++++++++++++++++++-------------
 3 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/phpinspect-resolve.el b/phpinspect-resolve.el
index 04a9cb558f..f50f208443 100644
--- a/phpinspect-resolve.el
+++ b/phpinspect-resolve.el
@@ -73,6 +73,7 @@
         (blocks-or-lists)
         (statements (phpinspect--split-statements token)))
     (dolist (statement statements)
+      (phpinspect--log "Finding assignment in statement '%s'" statement)
       (when (seq-find #'phpinspect-maybe-assignment-p statement)
         (phpinspect--log "Found assignment statement")
         (push (phpinspect--make-assignment-context
@@ -500,9 +501,16 @@ EXPRESSION."
 
 
 (defun phpinspect-resolve-type-from-context (resolvecontext &optional 
type-resolver)
+  "Resolve the type that RESOLVECONTEXT's subject evaluates to."
+  ;; Subject should be a statement, not a single token.
+  (when (phpinspect-probably-token-p (phpinspect--resolvecontext-subject 
resolvecontext))
+    (setf (phpinspect--resolvecontext-subject resolvecontext)
+          (list (phpinspect--resolvecontext-subject resolvecontext))))
+
   (unless type-resolver
     (setq type-resolver
           (phpinspect--make-type-resolver-for-resolvecontext resolvecontext)))
+
   (phpinspect--log "Looking for type of statement: %s in nested token"
                    (phpinspect--resolvecontext-subject resolvecontext))
   ;; Find all enclosing tokens that aren't classes. Classes do not contain 
variable
diff --git a/phpinspect-resolvecontext.el b/phpinspect-resolvecontext.el
index 8d3b9f580b..0d7b48b75e 100644
--- a/phpinspect-resolvecontext.el
+++ b/phpinspect-resolvecontext.el
@@ -68,6 +68,23 @@
                     :documentation
                     "Tokens that enclose the subject."))
 
+(defun phpinspect--repurpose-resolvecontext (rctx &optional enclosing-tokens 
subject)
+  "Copy RCTX, optionally replacing the enclosing tokens and subject.
+
+Note: if ENCLOSING-TOKENS are provided, the repurposed
+resolvecontext will have it's enclosing token metadata unset as
+it would no longer be valid for the new enclosing tokens."
+  (let ((rctx (phpinspect--copy-resolvecontext rctx)))
+    (when subject
+      (setf (phpinspect--resolvecontext-subject rctx) subject))
+
+    (when enclosing-tokens
+      ;; Unset enclosing-metadata as it is no longer valid.
+      (setf (phpinspect--resolvecontext-enclosing-metadata rctx) nil)
+      (setf (phpinspect--resolvecontext-enclosing-tokens rctx) 
enclosing-tokens))
+
+    rctx))
+
 (cl-defmethod phpinspect--resolvecontext-push-enclosing-token
   ((resolvecontext phpinspect--resolvecontext) enclosing-token)
   "Add ENCLOSING-TOKEN to RESOLVECONTEXTs enclosing token stack."
diff --git a/phpinspect-suggest.el b/phpinspect-suggest.el
index 0a56fd3614..d7be82cd35 100644
--- a/phpinspect-suggest.el
+++ b/phpinspect-suggest.el
@@ -38,7 +38,8 @@
 
 (defun phpinspect-suggest-variables-at-point (resolvecontext)
   (phpinspect--log "Suggesting variables at point")
-  (let ((variables))
+
+  (let ((variables (make-hash-table :test 'equal)))
     (dolist (token (phpinspect--resolvecontext-enclosing-tokens 
resolvecontext))
       (when (phpinspect-not-class-p token)
         (let ((token-list token)
@@ -46,26 +47,33 @@
         (while token-list
           (setq potential-variable (pop token-list))
           (cond ((phpinspect-variable-p potential-variable)
-                 (phpinspect--log "Pushing variable %s" potential-variable)
-                 (push (phpinspect--make-variable
-                        :name (cadr potential-variable)
-                        :type phpinspect--null-type)
-                       variables))
+                 (puthash (cadr potential-variable)
+                          (phpinspect--make-variable :name (cadr 
potential-variable))
+                          variables))
                 ((phpinspect-function-p potential-variable)
                  (push (phpinspect-function-block potential-variable) 
token-list)
                  (dolist (argument (phpinspect-function-argument-list 
potential-variable))
                    (when (phpinspect-variable-p argument)
-                     (push (phpinspect--make-variable
-                            :name (cadr argument)
-                            :type phpinspect--null-type)
-                           variables))))
+                     (puthash (cadr argument)
+                              (phpinspect--make-variable :name (cadr argument))
+                              variables))))
                 ((phpinspect-block-p potential-variable)
                  (dolist (nested-token (cdr potential-variable))
                    (push nested-token token-list))))))))
 
-    ;; Only return variables that have a name. Unnamed variables are just 
dollar
-    ;; signs (:
-    (seq-filter #'phpinspect--variable-name variables)))
+    (let (variable-list)
+      (dolist (var (hash-table-values variables))
+        ;; Only return variables that have a name. Unnamed variables are just 
dollar
+        ;; signs (:
+        (when (phpinspect--variable-name var)
+          (setf (phpinspect--variable-type var)
+                (phpinspect-resolve-type-from-context
+                 (phpinspect--repurpose-resolvecontext
+                  resolvecontext nil `(:variable ,(phpinspect--variable-name 
var)))))
+
+          (push var variable-list)))
+
+      variable-list)))
 
 (defun phpinspect-get-cached-project-class-methods (project-root class-fqn 
&optional static)
     (phpinspect--log "Getting cached project class methods for %s (%s)"

Reply via email to