From d3f100388eeefde2f218faa6f5056fe59352889c Mon Sep 17 00:00:00 2001 From: Hugo Thunnissen Date: Mon, 12 Aug 2024 22:47:19 +0200 Subject: [PATCH] Resolve property types using other methods when resolving from constructor fails Property types of classes in live buffers are now resolved from assignments in other methods when resolving from the __construct method fails. --- phpinspect-buffer.el | 14 +++---------- phpinspect-class.el | 1 + phpinspect-resolve.el | 38 ++++++++++++++++++++++++++++++++++++ phpinspect-resolvecontext.el | 3 ++- 4 files changed, 44 insertions(+), 12 deletions(-) diff --git a/phpinspect-buffer.el b/phpinspect-buffer.el index 4872aed..bfd603c 100644 --- a/phpinspect-buffer.el +++ b/phpinspect-buffer.el @@ -404,17 +404,9 @@ linked with." static))) (when (and (phpinspect-variable-p (phpinspect-meta-token var)) (not (phpinspect--variable-type indexed))) - (when-let* ((constructor (phpinspect--class-get-method class-obj (phpinspect-intern-name "__construct"))) - (rctx (phpinspect--make-resolvecontext :enclosing-tokens (list (phpinspect-meta-token class)) - :enclosing-metadata (list class)))) - (setf (phpinspect--variable-type indexed) - (phpinspect-get-pattern-type-in-block - rctx (phpinspect--make-pattern :m `(:variable "this") - :m `(:object-attrib (:word ,(cadr (phpinspect-meta-token var))))) - (phpinspect-function-block (phpinspect--function-token constructor)) - type-resolver - (phpinspect-function-argument-list (phpinspect--function-token constructor)))))) - + (setf (phpinspect--variable-type indexed) + (phpinspect--class-resolve-property-type + class-obj (cadr (phpinspect-meta-token var)) type-resolver class))) (phpinspect--class-set-variable class-obj indexed) diff --git a/phpinspect-class.el b/phpinspect-class.el index 2ee761e..2a71acc 100644 --- a/phpinspect-class.el +++ b/phpinspect-class.el @@ -259,5 +259,6 @@ Conditionally executes BODY depending on (puthash subscription-class update-function (phpinspect--class-subscriptions subscription-class)))))) + (provide 'phpinspect-class) ;;; phpinspect-class.el ends here diff --git a/phpinspect-resolve.el b/phpinspect-resolve.el index bf473c4..2dfc2b5 100644 --- a/phpinspect-resolve.el +++ b/phpinspect-resolve.el @@ -25,6 +25,7 @@ (require 'phpinspect-resolvecontext) (require 'phpinspect-cache) +(require 'phpinspect-class) (require 'phpinspect-type) (require 'phpinspect-token-predicates) @@ -497,4 +498,41 @@ EXPRESSION." (phpinspect-function-argument-list enclosing-token)))))) type)) +(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)) + type-resolver + (phpinspect-function-argument-list (phpinspect--function-token fn)))) + + +(cl-defmethod phpinspect--class-resolve-property-type + ((class phpinspect--class) (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 + :m `(:variable "this") + :m `(:object-attrib (:word ,property-name)))) + (rctx (phpinspect--make-resolvecontext :enclosing-tokens (list (phpinspect-meta-token class-token-meta)) + :enclosing-metadata (list class-token-meta))) + (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)) + (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))) + (throw 'found result)))) + nil)))) + +(cl-defmethod phpinspect--class-resolve-property-type + ((_class phpinspect--class) 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. + (cl-assert (not property-name)) + nil) + (provide 'phpinspect-resolve) diff --git a/phpinspect-resolvecontext.el b/phpinspect-resolvecontext.el index 4290aba..42d087f 100644 --- a/phpinspect-resolvecontext.el +++ b/phpinspect-resolvecontext.el @@ -31,7 +31,6 @@ (require 'phpinspect-meta) (require 'phpinspect-util) - (defsubst phpinspect-blocklike-p (token) (or (phpinspect-block-p token) (phpinspect-function-p token) @@ -111,6 +110,7 @@ (cl-defmethod phpinspect-get-resolvecontext ((bmap phpinspect-bmap) (point integer)) + "Construct resolvecontext for BMAP, orienting around POINT." (let* ((enclosing-tokens) ;; When there are no enclosing tokens, point is probably at the absolute ;; end of the buffer, so we find the last child before point. @@ -227,5 +227,6 @@ return it. Pops enclosing tokens to keep both in sync." (pop (phpinspect--resolvecontext-enclosing-tokens rctx)) (pop (phpinspect--resolvecontext-enclosing-metadata rctx))) + (provide 'phpinspect-resolvecontext) ;;; phpinspect-resolvecontext.el ends here