From 58ef5e359976ad60c9bb45c9f686aaa724e64abb Mon Sep 17 00:00:00 2001 From: Hugo Thunnissen Date: Fri, 16 Aug 2024 18:21:04 +0200 Subject: [PATCH] Refactor use of project root to project obj injection + test and fix some bugs - Test/Fix indexation of method return types - Get rid of some technical debt (use of project-root and global variables) - Cleanup/refactor tests --- phpinspect-cache.el | 11 ++-- phpinspect-class.el | 7 +++ phpinspect-completion.el | 3 +- phpinspect-eldoc.el | 45 +++++++-------- phpinspect-index.el | 9 +-- phpinspect-resolve.el | 107 +++++++++++++++-------------------- phpinspect-resolvecontext.el | 28 ++++----- phpinspect-suggest.el | 40 ++++++------- phpinspect.el | 7 --- test/phpinspect-test-env.el | 6 ++ test/phpinspect-test.el | 68 ++++++---------------- test/test-autoload.el | 4 ++ test/test-eldoc.el | 85 +++++++++++++++++----------- test/test-index.el | 28 +++++++++ test/test-resolve.el | 42 +++++++------- test/test-resolvecontext.el | 7 ++- 16 files changed, 248 insertions(+), 249 deletions(-) diff --git a/phpinspect-cache.el b/phpinspect-cache.el index 25dec47..14bfe62 100644 --- a/phpinspect-cache.el +++ b/phpinspect-cache.el @@ -163,13 +163,6 @@ currently opened projects." project)) -(defun phpinspect-get-or-create-cached-project-class (project-root class-fqn &optional no-enqueue) - (when project-root - (let ((project (phpinspect--cache-get-project-create - (phpinspect--get-or-create-global-cache) - project-root))) - (phpinspect-project-get-class-extra-or-create project class-fqn no-enqueue)))) - (cl-defmethod phpinspect--cache-get-project-create ((cache phpinspect--cache) (project-root string)) "Get a project that is located in PROJECT-ROOT from CACHE. @@ -196,6 +189,10 @@ then returned." (phpinspect-project-enqueue-include-dirs project)))) project)) +(defun phpinspect-current-project () + (phpinspect--cache-get-project-create (phpinspect--get-or-create-global-cache) + (phpinspect-current-project-root))) + (defun phpinspect-project-enqueue-include-dirs (project) (interactive (list (phpinspect--cache-get-project-create (phpinspect--get-or-create-global-cache) diff --git a/phpinspect-class.el b/phpinspect-class.el index 2a71acc..478f175 100644 --- a/phpinspect-class.el +++ b/phpinspect-class.el @@ -104,9 +104,16 @@ Conditionally executes BODY depending on (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 diff --git a/phpinspect-completion.el b/phpinspect-completion.el index 69d1c23..0e15a9b 100644 --- a/phpinspect-completion.el +++ b/phpinspect-completion.el @@ -224,7 +224,8 @@ Returns list of `phpinspect--completion'." (let* ((buffer (phpinspect-completion-query-buffer query)) (point (phpinspect-completion-query-point query)) (buffer-map (phpinspect-buffer-parse-map buffer)) - (rctx (phpinspect-get-resolvecontext buffer-map point)) + (rctx (phpinspect-get-resolvecontext + (phpinspect-buffer-project buffer) buffer-map point)) (completion-list (phpinspect--make-completion-list))) (phpinspect-buffer-update-project-index buffer) diff --git a/phpinspect-eldoc.el b/phpinspect-eldoc.el index 8208114..166acb3 100644 --- a/phpinspect-eldoc.el +++ b/phpinspect-eldoc.el @@ -128,21 +128,15 @@ be implemented for return values of `phpinspect-eld-strategy-execute'") (phpinspect-list-p (car (last (phpinspect--resolvecontext-subject rctx))))))) -(cl-defmethod phpinspect-eld-strategy-execute - ((_strat phpinspect-eld-function-args) (q phpinspect-eldoc-query) (rctx phpinspect--resolvecontext)) - (phpinspect--log "Executing `phpinspect-eld-function-args' strategy") - (let* ((enclosing-token (car (phpinspect--resolvecontext-enclosing-metadata - rctx))) - (left-sibling ) - (statement ) - match-result static arg-list arg-pos) +(defun phpinspect--determine-function-call-statement (rctx eld-query enclosing-token) + (let (statement left-sibling) (cond ;; Subject is a statement ((and (phpinspect-list-p (car (last (phpinspect--resolvecontext-subject rctx)))) enclosing-token) (setq left-sibling (phpinspect-meta-find-child-before-recursively - enclosing-token (phpinspect-eldoc-query-point q)))) - ;; Subject is inside an argument list + enclosing-token (phpinspect-eldoc-query-point eld-query)))) + ;; Subject is inside an argument list ((and enclosing-token (phpinspect-list-p (phpinspect-meta-token enclosing-token))) (setq left-sibling (phpinspect-meta-find-left-sibling enclosing-token) @@ -160,6 +154,15 @@ be implemented for return values of `phpinspect-eld-strategy-execute'") (phpinspect--log "Eldoc statement is: %s" (mapcar #'phpinspect-meta-token statement)) (phpinspect--log "Enclosing token was: %s" (phpinspect-meta-token enclosing-token)) + statement)) + +(cl-defmethod phpinspect-eld-strategy-execute + ((_strat phpinspect-eld-function-args) (q phpinspect-eldoc-query) (rctx phpinspect--resolvecontext)) + (phpinspect--log "Executing `phpinspect-eld-function-args' strategy") + (let* ((enclosing-token (car (phpinspect--resolvecontext-enclosing-metadata + rctx))) + (statement (phpinspect--determine-function-call-statement rctx q enclosing-token)) + match-result static arg-list arg-pos) (when enclosing-token (cond @@ -167,7 +170,6 @@ 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))) @@ -184,18 +186,14 @@ be implemented for return values of `phpinspect-eld-strategy-execute'") (setf (phpinspect--resolvecontext-subject rctx) (mapcar #'phpinspect-meta-token (butlast statement 2))) - - - (when-let* ((type-of-previous-statement + (let* ((type-of-previous-statement (phpinspect-resolve-type-from-context rctx)) - (method-name-sym (phpinspect-intern-name (cadadr (phpinspect-meta-token (car match-result))))) - (class (phpinspect-project-get-class-extra-or-create - (phpinspect--resolvecontext-project rctx) - type-of-previous-statement - 'no-enqueue)) - (method (if static - (phpinspect--class-get-static-method class method-name-sym) - (phpinspect--class-get-method class method-name-sym)))) + (method-name (cadadr (phpinspect-meta-token (car match-result)))) + (class (phpinspect-rctx-get-or-create-cached-project-class + 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)))) (when method (phpinspect-make-function-doc :fn method :arg-pos arg-pos)))) @@ -268,7 +266,7 @@ also `phpinspect-eldoc-query-execute'.") (let* ((buffer (phpinspect-eldoc-query-buffer query)) (point (phpinspect-eldoc-query-point query)) (buffer-map (phpinspect-buffer-parse-map buffer)) - (rctx (phpinspect-get-resolvecontext buffer-map point)) + (rctx (phpinspect-get-resolvecontext (phpinspect-buffer-project buffer) buffer-map point)) responses) (phpinspect-buffer-update-project-index buffer) (dolist (strategy phpinspect-eldoc-strategies) @@ -276,6 +274,7 @@ also `phpinspect-eldoc-query-execute'.") (when (phpinspect-eld-strategy-supports strategy query rctx) (phpinspect--log "Found matching eldoc strategy. Executing...") (push (phpinspect-eld-strategy-execute strategy query rctx) responses)))) + (remove nil responses))) (defun phpinspect-eldoc-function () diff --git a/phpinspect-index.el b/phpinspect-index.el index 93507e4..9e4eddc 100644 --- a/phpinspect-index.el +++ b/phpinspect-index.el @@ -138,10 +138,11 @@ function (think \"new\" statements, return types etc.)." ;; @return annotation. When dealing with a collection, we want to store the ;; type of its members. - (when type - (let* ((return-annotation-type - (cadadr (seq-find #'phpinspect-return-annotation-p comment-before)))) - (phpinspect--apply-annotation-type return-annotation-type type type-resolver))) + (when-let* ((return-annotation-type + (cadadr (seq-find #'phpinspect-return-annotation-p comment-before)))) + (if type + (phpinspect--apply-annotation-type return-annotation-type type type-resolver) + (setq type (funcall type-resolver (phpinspect--make-type :name return-annotation-type))))) (when add-used-types (let ((used-types (phpinspect--find-used-types-in-tokens diff --git a/phpinspect-resolve.el b/phpinspect-resolve.el index f50f208..8ce6263 100644 --- a/phpinspect-resolve.el +++ b/phpinspect-resolve.el @@ -141,65 +141,51 @@ Destructively removes tokens from the end of ASSIGNMENT-TOKENS." (pop statement)) statement) -;; FIXME: the use of this function and similar ones should be replaced with code -;; that uses locally injected project objects in stead of retrieving the project -;; object through global variables. -(defsubst phpinspect-get-cached-project-class (project-root class-fqn) - (when project-root - (phpinspect-project-get-class-or-extra - (phpinspect--cache-get-project-create (phpinspect--get-or-create-global-cache) - project-root) - class-fqn))) - -(defun phpinspect-get-cached-project-class-methods (project-root class-fqn &optional static) - (phpinspect--log "Getting cached project class methods for %s (%s)" - project-root class-fqn) - (when project-root - (let ((class (phpinspect-get-or-create-cached-project-class - project-root - class-fqn))) - (when class - (phpinspect--log "Retrieved class index, starting method collection %s (%s)" - project-root class-fqn) - (if static - (phpinspect--class-get-static-method-list class) - (phpinspect--class-get-method-list class)))))) - -(defsubst phpinspect-get-cached-project-class-method-type - (project-root class-fqn method-name) - (when project-root - (let* ((class (phpinspect-get-or-create-cached-project-class project-root class-fqn)) - (method)) +(defsubst phpinspect-get-cached-project-class (rctx class-fqn) + (phpinspect-project-get-class-or-extra (phpinspect--resolvecontext-project rctx) class-fqn)) + +(defun phpinspect-get-cached-project-class-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))) (when class - (setq method - (phpinspect--class-get-method class (phpinspect-intern-name method-name))) - (when method - (phpinspect--function-return-type method)))))) + (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))))) + +(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)) + (method)) + (when class + (setq method + (phpinspect--class-get-method class (phpinspect-intern-name method-name))) + (when method + (phpinspect--function-return-type method))))) (defsubst phpinspect-get-cached-project-class-variable-type - (project-root class-fqn variable-name) - (phpinspect--log "Getting cached project class variable type for %s (%s::%s)" - project-root class-fqn variable-name) - (when project-root - (let ((found-variable - (phpinspect--class-get-variable - (phpinspect-get-or-create-cached-project-class project-root class-fqn) - variable-name))) - (when found-variable - (phpinspect--variable-type found-variable))))) + (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) + variable-name))) + (when found-variable + (phpinspect--variable-type found-variable)))) (defsubst phpinspect-get-cached-project-class-static-method-type - (project-root class-fqn method-name) - (when project-root - (let* ((class (phpinspect-get-or-create-cached-project-class project-root class-fqn)) - (method)) - (when class - (setq method - (phpinspect--class-get-static-method - class - (phpinspect-intern-name method-name))) - (when method - (phpinspect--function-return-type method)))))) + (rctx class-fqn method-name) + (let* ((class (phpinspect-rctx-get-or-create-cached-project-class rctx class-fqn)) + (method)) + (when class + (setq method + (phpinspect--class-get-static-method + class + (phpinspect-intern-name method-name))) + (when method + (phpinspect--function-return-type method))))) (defun phpinspect-get-derived-statement-type-in-block (resolvecontext statement php-block type-resolver &optional function-arg-list assignments) @@ -265,16 +251,14 @@ $variable = $variable->method();" (setq previous-attribute-type (or (phpinspect-get-cached-project-class-method-type - (phpinspect--resolvecontext-project-root - resolvecontext) - (funcall type-resolver previous-attribute-type) - (cadr attribute-word)) + resolvecontext + (funcall type-resolver previous-attribute-type) + (cadr attribute-word)) previous-attribute-type))) (setq previous-attribute-type (or (phpinspect-get-cached-project-class-variable-type - (phpinspect--resolvecontext-project-root - resolvecontext) + resolvecontext (funcall type-resolver previous-attribute-type) (cadr attribute-word)) previous-attribute-type)))))) @@ -290,8 +274,7 @@ $variable = $variable->method();" (setq previous-attribute-type (or (phpinspect-get-cached-project-class-static-method-type - (phpinspect--resolvecontext-project-root - resolvecontext) + resolvecontext (funcall type-resolver previous-attribute-type) (cadr attribute-word)) previous-attribute-type))))))) diff --git a/phpinspect-resolvecontext.el b/phpinspect-resolvecontext.el index 0d7b48b..5c0cee8 100644 --- a/phpinspect-resolvecontext.el +++ b/phpinspect-resolvecontext.el @@ -55,10 +55,10 @@ :type phpinspect--token :documentation "The statement we're trying to resolve the type of.") - (project-root nil - :type string - :documentation - "The root directory of the project we're resolving types for.") + (project nil + :type phpinspect-project + :documentation + "The project we're resolving types for.") (enclosing-metadata nil :type list :documentation @@ -127,7 +127,7 @@ it would no longer be valid for the new enclosing tokens." (reverse token)))) (cl-defmethod phpinspect-get-resolvecontext - ((bmap phpinspect-bmap) (point integer)) + ((project phpinspect-project) (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 @@ -184,14 +184,9 @@ it would no longer be valid for the new enclosing tokens." :subject (phpinspect--get-last-statement-in-token subject-token) :enclosing-tokens (nreverse (mapcar #'phpinspect-meta-token enclosing-tokens)) :enclosing-metadata (nreverse enclosing-tokens) - :project-root (phpinspect-current-project-root)))) - -(defun phpinspect--resolvecontext-project (rctx) - (phpinspect--cache-get-project-create - (phpinspect--get-or-create-global-cache) - (phpinspect--resolvecontext-project-root rctx))) + :project project))) -(defun phpinspect--get-resolvecontext (token &optional resolvecontext) +(defun phpinspect--get-resolvecontext (project token &optional resolvecontext) "Find the deepest nested incomplete token in TOKEN. If RESOLVECONTEXT is nil, it is created. Returns RESOLVECONTEXT of type `phpinspect--resolvecontext' containing the last @@ -199,7 +194,7 @@ statement of the innermost incomplete token as subject accompanied by all of its enclosing tokens." (unless resolvecontext (setq resolvecontext (phpinspect--make-resolvecontext - :project-root (phpinspect-current-project-root)))) + :project project))) (let ((last-token (car (last token))) (last-encountered-token (car @@ -213,13 +208,18 @@ accompanied by all of its enclosing tokens." (phpinspect--resolvecontext-push-enclosing-token resolvecontext token)) (if (phpinspect-incomplete-token-p last-token) - (phpinspect--get-resolvecontext last-token resolvecontext) + (phpinspect--get-resolvecontext project last-token resolvecontext) ;; else (setf (phpinspect--resolvecontext-subject resolvecontext) (phpinspect--get-last-statement-in-token token)) resolvecontext))) +(defun phpinspect-rctx-get-or-create-cached-project-class (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))) + (defun phpinspect--make-type-resolver-for-resolvecontext (resolvecontext) (let ((namespace-or-root diff --git a/phpinspect-suggest.el b/phpinspect-suggest.el index d7be82c..5748d5c 100644 --- a/phpinspect-suggest.el +++ b/phpinspect-suggest.el @@ -75,34 +75,27 @@ 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)" - project-root class-fqn) - (when project-root - (let ((class (phpinspect-get-or-create-cached-project-class - project-root - class-fqn 'no-enqueue))) - (phpinspect--log (if class - "Retrieved class index, starting method collection %s (%s)" - "No class index found in %s for %s") - project-root class-fqn) - (when class - (if static - (phpinspect--class-get-static-method-list class) - (phpinspect--class-get-method-list class)))))) +(defun phpinspect-get-cached-project-class-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))) + (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))))) (defun phpinspect--get-methods-for-class (resolvecontext class &optional static) "Find all known cached methods for CLASS." - (or (phpinspect-get-cached-project-class-methods - (phpinspect--resolvecontext-project-root resolvecontext) - class static) + (or (phpinspect-get-cached-project-class-methods resolvecontext class static) (progn (phpinspect--log "Failed to find methods for class %s :(" class) nil))) -(defun phpinspect--get-variables-for-class (class-name &optional static) - (let ((class (phpinspect-get-or-create-cached-project-class - (phpinspect-current-project-root) - class-name 'no-enqueue))) +(defun phpinspect--get-variables-for-class (rctx class-name &optional static) + (let ((class (phpinspect-rctx-get-or-create-cached-project-class + rctx class-name 'no-enqueue))) (when class (if static (append (phpinspect--class-get-static-variables class) (phpinspect--class-get-constants class)) @@ -149,8 +142,7 @@ static variables and static methods." (let ((type (funcall type-resolver statement-type))) (when-let ((result (append (phpinspect--get-variables-for-class - type - static) + resolvecontext type static) (funcall method-lister type)))) (phpinspect--log "Returning attributes %s" result) result)))))) diff --git a/phpinspect.el b/phpinspect.el index bf8d413..1a43af5 100644 --- a/phpinspect.el +++ b/phpinspect.el @@ -57,13 +57,6 @@ (inline-quote (funcall phpinspect-type-filepath-function ,fqn))) -(defsubst phpinspect-cache-project-class (project-root indexed-class) - (when project-root - (phpinspect-project-add-class - (phpinspect--cache-get-project-create (phpinspect--get-or-create-global-cache) - project-root) - indexed-class))) - (defun phpinspect-parse-string-to-bmap (string) (with-temp-buffer (insert string) diff --git a/test/phpinspect-test-env.el b/test/phpinspect-test-env.el index 8325721..becfc1d 100644 --- a/test/phpinspect-test-env.el +++ b/test/phpinspect-test-env.el @@ -10,6 +10,12 @@ (phpinspect-ensure-worker) (phpinspect-purge-cache) +(defun phpinspect--make-dummy-project () + (phpinspect--make-project + :fs (phpinspect-make-virtual-fs) + :autoload (phpinspect-make-autoloader) + :worker 'nil-worker)) + (defvar phpinspect-test-directory (file-name-directory (macroexp-file-name)) "Directory that phpinspect tests reside in.") diff --git a/test/phpinspect-test.el b/test/phpinspect-test.el index 8690fb6..3a6c275 100644 --- a/test/phpinspect-test.el +++ b/test/phpinspect-test.el @@ -34,8 +34,8 @@ (let* ((code "class Foo { function a(\\Thing $baz) { $foo = new \\DateTime(); $bar = $foo; Whatever comes after don't matter.") (bmap (phpinspect-parse-string-to-bmap code)) (tokens (phpinspect-parse-string "class Foo { function a(\\Thing $baz) { $foo = new \\DateTime(); $bar = $foo;")) - (context (phpinspect--get-resolvecontext tokens)) - (bmap-context (phpinspect-get-resolvecontext bmap (- (length code) 36))) + (context (phpinspect--get-resolvecontext (phpinspect-current-project) tokens)) + (bmap-context (phpinspect-get-resolvecontext (phpinspect--make-dummy-project) bmap (- (length code) 36))) (project-root "could never be a real project root") (phpinspect-project-root-function (lambda (&rest _ignored) project-root)) @@ -65,7 +65,7 @@ (ert-deftest phpinspect-get-pattern-type-in-block () (let* ((code "class Foo { function a(\\Thing $baz) { $foo = new \\DateTime(); $this->potato = $foo;") (bmap (phpinspect-parse-string-to-bmap "class Foo { function a(\\Thing $baz) { $foo = new \\DateTime(); $this->potato = $foo;")) - (context (phpinspect-get-resolvecontext bmap (length code))) + (context (phpinspect-get-resolvecontext (phpinspect--make-dummy-project) bmap (length code))) (project-root "could never be a real project root") (phpinspect-project-root-function (lambda (&rest _ignored) project-root)) @@ -90,8 +90,8 @@ (code2 "class Foo { function a(\\Thing $baz) { $foo = []; $foo[] = $baz; $bar = $foo[0]; $bork = [$foo[0]]; $bark = $bork[0]; $borknest = [$bork]; $barknest = $borknest[0][0]") (bmap (phpinspect-parse-string-to-bmap code1)) (tokens (phpinspect-parse-string code2)) - (context1 (phpinspect-get-resolvecontext bmap (- (length code1) 4))) - (context2 (phpinspect--get-resolvecontext tokens))) + (context1 (phpinspect-get-resolvecontext (phpinspect--make-dummy-project) bmap (- (length code1) 4))) + (context2 (phpinspect--get-resolvecontext (phpinspect-current-project) tokens))) (should (equal (phpinspect--resolvecontext-subject context1) (phpinspect--resolvecontext-subject context2))) @@ -101,7 +101,7 @@ (ert-deftest phpinspect-get-variable-type-in-block-array-foreach () (let* ((code "class Foo { function a(\\Thing $baz) { $foo = []; $foo[] = $baz; foreach ($foo as $bar) {$bar->") (bmap (phpinspect-parse-string-to-bmap code)) - (context (phpinspect-get-resolvecontext bmap (length code))) + (context (phpinspect-get-resolvecontext (phpinspect--make-dummy-project) bmap (length code))) (project-root "could never be a real project root") (phpinspect-project-root-function (lambda (&rest _ignored) project-root)) @@ -123,32 +123,6 @@ (should (phpinspect--type= (phpinspect--make-type :name "\\Thing") result))))) -(ert-deftest phpinspect-get-variable-type-in-block-nested-array () - (let* ((code "class Foo { function a(\\Thing $baz) { $foo = [[$baz]]; foreach ($foo[0] as $bar) {$bar->") - (bmap (phpinspect-parse-string-to-bmap code)) - (context (phpinspect-get-resolvecontext bmap (length code))) - (project-root "could never be a real project root") - (phpinspect-project-root-function - (lambda (&rest _ignored) project-root)) - (project (phpinspect--make-project - :fs (phpinspect-make-virtual-fs) - :root project-root - :worker (phpinspect-make-worker)))) - - (puthash project-root project (phpinspect--cache-projects phpinspect-cache)) - - (let* ((function-token (seq-find #'phpinspect-function-p - (phpinspect--resolvecontext-enclosing-tokens context))) - (result (phpinspect-get-variable-type-in-block - context "bar" - (phpinspect-function-block function-token) - (phpinspect--make-type-resolver-for-resolvecontext context) - (phpinspect-function-argument-list function-token)))) - - (should (phpinspect--type= (phpinspect--make-type :name "\\Thing") - result))))) - - (ert-deftest phpinspect--find-assignment-ctxs-in-token () (let* ((tokens (cadr (phpinspect-parse-string "{ $foo = ['nr 1']; $bar = $nr2; if (true === ($foo = $nr3)) { $foo = $nr4; $notfoo = $nr5; if ([] === ($foo = [ $nr6 ])){ $foo = [ $nr7 ];}}}"))) @@ -241,17 +215,12 @@ class FlufferUpper $this->upFluff = $upFluff; } }")) - (phpinspect-project-root-function (lambda () "phpinspect-test")) - (context (phpinspect-get-resolvecontext bmap 310))) - - (setf (phpinspect--resolvecontext-project-root context) - "phpinspect-test") + (project (phpinspect--make-dummy-project)) + (context (phpinspect-get-resolvecontext project bmap 310))) (phpinspect-purge-cache) (dolist (tree (list token-tree fluffer vendor-fluff vendor-fluffer-upper)) - (phpinspect-cache-project-class - "phpinspect-test" - (cdar (alist-get 'classes (cdr (phpinspect--index-tokens tree)))))) + (phpinspect-project-add-index project (phpinspect--index-tokens tree))) (should (phpinspect--type= (phpinspect--make-type :name "\\Vendor\\FluffLib\\DoubleFluffer") @@ -260,7 +229,7 @@ class FlufferUpper (phpinspect--make-type-resolver-for-resolvecontext context)))) - (setq context (phpinspect-get-resolvecontext bmap 405)) + (setq context (phpinspect-get-resolvecontext project bmap 405)) (should (phpinspect--type= (phpinspect--make-type :name "\\Vendor\\FluffLib\\FlufferUpper") (phpinspect-resolve-type-from-context @@ -268,7 +237,6 @@ class FlufferUpper (phpinspect--make-type-resolver-for-resolvecontext context)))))) - (ert-deftest phpinspect-resolve-type-from-context-static-method () (with-temp-buffer (insert " @@ -289,11 +257,11 @@ class Thing (index (phpinspect--index-tokens tokens)) (phpinspect-project-root-function (lambda () "phpinspect-test")) (phpinspect-eldoc-word-width 100) - (context (phpinspect-get-resolvecontext bmap (point)))) + (project (phpinspect--make-dummy-project)) + (context (phpinspect-get-resolvecontext project bmap (point)))) + (phpinspect-purge-cache) - (phpinspect-cache-project-class - (phpinspect-current-project-root) - (cdar (alist-get 'classes (cdr index)))) + (phpinspect-project-add-index project index) (should (phpinspect--type= (phpinspect--make-type :name "\\Thing") (phpinspect-resolve-type-from-context @@ -320,13 +288,11 @@ class Thing :bmap bmap) (phpinspect-parse-current-buffer))) (index (phpinspect--index-tokens tokens)) - (phpinspect-project-root-function (lambda () "phpinspect-test")) (phpinspect-eldoc-word-width 100) - (context (phpinspect-get-resolvecontext bmap (point)))) + (project (phpinspect--make-dummy-project)) + (context (phpinspect-get-resolvecontext project bmap (point)))) (phpinspect-purge-cache) - (phpinspect-cache-project-class - (phpinspect-current-project-root) - (cdar (alist-get 'classes (cdr index)))) + (phpinspect-project-add-index project index) (should (phpinspect--type= (phpinspect--make-type :name "\\Thing") (phpinspect-resolve-type-from-context diff --git a/test/test-autoload.el b/test/test-autoload.el index e7f8663..89b7442 100644 --- a/test/test-autoload.el +++ b/test/test-autoload.el @@ -28,6 +28,10 @@ (require 'phpinspect-fs) (require 'phpinspect-autoload) (require 'phpinspect-resolvecontext) +(require 'phpinspect-test-env + (expand-file-name "phpinspect-test-env.el" + (file-name-directory (macroexp-file-name)))) + (ert-deftest phpinspect-filename-to-typename () (should (eq (phpinspect-intern-name "\\Foo\\Bar") (phpinspect-filename-to-typename "src/" "src/Foo////////Bar.php"))) diff --git a/test/test-eldoc.el b/test/test-eldoc.el index c3bd509..a697aa1 100644 --- a/test/test-eldoc.el +++ b/test/test-eldoc.el @@ -2,13 +2,16 @@ (require 'phpinspect) (require 'phpinspect-eldoc) +(require 'phpinspect-test-env + (expand-file-name "phpinspect-test-env.el" + (file-name-directory (macroexp-file-name)))) (ert-deftest phpinspect-eld-method-call () + (setq phpinspect-load-stubs nil) (with-temp-buffer - (phpinspect-ensure-worker) (phpinspect-purge-cache) - (let* ((php-code " + (let* ((php-code "getThis(new \\DateTime(), bla)") - (tokens (phpinspect-parse-string php-code)) - (index (phpinspect--index-tokens tokens)) (phpinspect-project-root-function (lambda () "phpinspect-test")) (phpinspect-eldoc-word-width 100) - (buffer (phpinspect-make-buffer :buffer (current-buffer))) + (project (phpinspect--make-project :autoload (phpinspect-make-autoloader) :worker 'nil-worker)) + (buffer (phpinspect-make-buffer :buffer (current-buffer) :-project project)) second-arg-pos inside-nested-list-pos first-arg-pos) - (phpinspect-cache-project-class - (phpinspect-current-project-root) - (cdar (alist-get 'classes (cdr index)))) - + (setq-local phpinspect-current-buffer buffer) (insert php-code) + (backward-char) (setq second-arg-pos (point)) (backward-char 6) @@ -38,22 +38,47 @@ class Thing (backward-char 8) (setq first-arg-pos (point)) - (let ((result (seq-find #'phpinspect-function-doc-p - (phpinspect-eldoc-query-execute - (phpinspect-make-eldoc-query :point second-arg-pos :buffer buffer))))) - (should (phpinspect-function-doc-p result)) - (should (= 1 (phpinspect-function-doc-arg-pos result))) - (should (string= "getThis" (phpinspect--function-name (phpinspect-function-doc-fn result)))) + (phpinspect-buffer-reindex buffer) + + ;; Strategy should not trigger inside constructor/function arguments + (let ((query (phpinspect-make-eldoc-query :point inside-nested-list-pos :buffer buffer)) + (strat (phpinspect-make-eld-function-args)) + (rctx (phpinspect-get-resolvecontext project (phpinspect-buffer-parse-map buffer) inside-nested-list-pos))) + (should-not (phpinspect-eld-strategy-execute strat query rctx))) + + (dolist (expected (list (cons second-arg-pos 1) (cons first-arg-pos 0))) + ;; Test strat separately to ensure it is not erroneous + (let ((query (phpinspect-make-eldoc-query :point (car expected) :buffer buffer)) + (strat (phpinspect-make-eld-function-args)) + (rctx (phpinspect-get-resolvecontext project (phpinspect-buffer-parse-map buffer) (car expected)))) + + ;; Subject is correct + (should (phpinspect-word-p (car (phpinspect--resolvecontext-subject rctx)))) - (setq result (phpinspect-eldoc-query-execute - (phpinspect-make-eldoc-query :point inside-nested-list-pos :buffer buffer))) - (should-not result) + ;; Enclosing token is correct + (should (phpinspect-list-p (car (phpinspect--resolvecontext-enclosing-tokens rctx)))) + + ;; Statement is correctly determined + (should (equal (cdr (phpinspect-parse-string "$this->getThis(new \\DateTime(), bla)")) + (mapcar #'phpinspect-meta-token + (phpinspect--determine-function-call-statement + rctx query (car (phpinspect--resolvecontext-enclosing-metadata + rctx)))))) + ;; Strategy correctly signals support + (should (phpinspect-eld-strategy-supports strat query rctx)) + + ;; Strategy correctly returns result + (should (phpinspect-eld-strategy-execute strat query rctx))) + + ;; Test query execution + (let ((result (seq-find #'phpinspect-function-doc-p + (phpinspect-eldoc-query-execute + (phpinspect-make-eldoc-query :point (car expected) :buffer buffer))))) + + (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))))))))) - (setq result (car (phpinspect-eldoc-query-execute - (phpinspect-make-eldoc-query :point first-arg-pos :buffer buffer)))) - (should (phpinspect-function-doc-p result)) - (should (= 0 (phpinspect-function-doc-arg-pos result))) - (should (string= "getThis" (phpinspect--function-name (phpinspect-function-doc-fn result)))))))) (ert-deftest phpinspect-eldoc-function-for-object-method () (phpinspect-purge-cache) @@ -70,18 +95,16 @@ class Thing $this->getThis(new \\DateTime(), bla)") (tokens (phpinspect-parse-string php-code)) (index (phpinspect--index-tokens tokens)) - (phpinspect-project-root-function (lambda () "phpinspect-test")) + (project (phpinspect--make-dummy-project)) (phpinspect-eldoc-word-width 100)) - (phpinspect-cache-project-class - (phpinspect-current-project-root) - (cdar (alist-get 'classes (cdr index)))) + (phpinspect-project-add-index project index) (should (string= "getThis: ($moment DateTime, $thing Thing, $other): Thing" (with-temp-buffer (insert php-code) (backward-char) (setq-local phpinspect-current-buffer - (phpinspect-make-buffer :buffer (current-buffer))) + (phpinspect-make-buffer :buffer (current-buffer) :-project project)) (phpinspect-buffer-parse phpinspect-current-buffer) (phpinspect-eldoc-function)))))) @@ -100,11 +123,9 @@ class Thing self::doThing(") (tokens (phpinspect-parse-string php-code)) (index (phpinspect--index-tokens tokens)) - (phpinspect-project-root-function (lambda () "phpinspect-test")) + (project (phpinspect--make-dummy-project)) (phpinspect-eldoc-word-width 100)) - (phpinspect-cache-project-class - (phpinspect-current-project-root) - (cdar (alist-get 'classes (cdr index)))) + (phpinspect-project-add-index project index) (should (string= "doThing: ($moment DateTime, $thing Thing, $other): Thing" (with-temp-buffer diff --git a/test/test-index.el b/test/test-index.el index 4e9c0b5..4e9b23d 100644 --- a/test/test-index.el +++ b/test/test-index.el @@ -356,3 +356,31 @@ class AccountStatisticsController { (should (phpinspect--type= relation-type (phpinspect--variable-type relation))) (should (phpinspect--variable-type static-relation)) (should (phpinspect--type= relation-type (phpinspect--variable-type static-relation))))))))) + + +(ert-deftest phpinspect-index-return-type-annotation-for-method () + (with-temp-buffer + (let ((project (phpinspect--make-project :autoload (phpinspect-make-autoloader)))) + (insert "") + (bmap (phpinspect-parse-string-to-bmap code)) + (project (phpinspect--make-dummy-project)) + (context (phpinspect-get-resolvecontext project bmap (length code)))) + + (let* ((function-token (seq-find #'phpinspect-function-p + (phpinspect--resolvecontext-enclosing-tokens context))) + (result (phpinspect-get-variable-type-in-block + context "bar" + (phpinspect-function-block function-token) + (phpinspect--make-type-resolver-for-resolvecontext context) + (phpinspect-function-argument-list function-token)))) + + (should (phpinspect--type= (phpinspect--make-type :name "\\Thing") + result))))) (ert-deftest phpinspect-get-variable-type-in-block-array-access () (let* ((code "class Foo { function a(\\Thing $baz) { $foo = []; $foo[] = $baz; $bar = $foo[0]; $bork = [$foo[0]]; $bark = $bork[0]; $borknest = [$bork]; $barknest = $borknest[0][0]; }}") - (tokens (phpinspect-parse-string-to-bmap code)) - (context (phpinspect-get-resolvecontext tokens (- (length code) 4))) - (project-root "could never be a real project root") - (phpinspect-project-root-function - (lambda (&rest _ignored) project-root)) - (project (phpinspect--make-project - :fs (phpinspect-make-virtual-fs) - :root project-root - :worker (phpinspect-make-worker)))) - - (puthash project-root project (phpinspect--cache-projects phpinspect-cache)) + (bmap (phpinspect-parse-string-to-bmap code)) + (project (phpinspect--make-dummy-project)) + (context (phpinspect-get-resolvecontext project bmap (length code)))) (let* ((function-token (car (phpinspect--resolvecontext-enclosing-tokens context))) (result1 (phpinspect-get-variable-type-in-block @@ -41,16 +49,8 @@ (ert-deftest phpinspect-get-variable-type-in-block-array-foreach-self-referential () (let* ((code "class Foo { function a(\\Thing $baz) { $foo = []; $foo[] = $baz; foreach ($foo as $bar) {$bar = $bar; $bar->") (bmap (phpinspect-parse-string-to-bmap code)) - (context (phpinspect-get-resolvecontext bmap (length code))) - (project-root "could never be a real project root") - (phpinspect-project-root-function - (lambda (&rest _ignored) project-root)) - (project (phpinspect--make-project - :fs (phpinspect-make-virtual-fs) - :root project-root - :worker (phpinspect-make-worker)))) - - (puthash project-root project (phpinspect--cache-projects phpinspect-cache)) + (project (phpinspect--make-dummy-project)) + (context (phpinspect-get-resolvecontext project bmap (length code)))) (let* ((function-token (seq-find #'phpinspect-function-p (phpinspect--resolvecontext-enclosing-tokens context))) diff --git a/test/test-resolvecontext.el b/test/test-resolvecontext.el index 06a27ef..ff7fbca 100644 --- a/test/test-resolvecontext.el +++ b/test/test-resolvecontext.el @@ -28,7 +28,7 @@ class TestClass { (phpinspect-parse-string code)) (setq bmap (phpinspect-pctx-bmap ctx)) - (let ((rctx (phpinspect-get-resolvecontext bmap 317))) + (let ((rctx (phpinspect-get-resolvecontext (phpinspect--make-dummy-project) bmap 317))) (should (phpinspect--resolvecontext-subject rctx)) (should (phpinspect--resolvecontext-enclosing-tokens rctx))))) @@ -37,7 +37,7 @@ class TestClass { (with-temp-buffer (insert-file-contents (expand-file-name "IncompleteClass.php" phpinspect-test-php-file-directory)) (let* ((bmap (phpinspect-parse-string-to-bmap (buffer-string))) - (resolvecontext (phpinspect-get-resolvecontext bmap (point-max))) + (resolvecontext (phpinspect-get-resolvecontext (phpinspect--make-dummy-project) bmap (point-max))) (type-resolver (phpinspect--make-type-resolver-for-resolvecontext resolvecontext))) @@ -65,7 +65,7 @@ class TestClass { (with-temp-buffer (insert-file-contents (concat phpinspect-test-php-file-directory "/IncompleteClassBlockedNamespace.php")) (let* ((bmap (phpinspect-parse-string-to-bmap (buffer-string))) - (resolvecontext (phpinspect-get-resolvecontext bmap (point-max))) + (resolvecontext (phpinspect-get-resolvecontext (phpinspect--make-dummy-project) bmap (point-max))) (type-resolver (phpinspect--make-type-resolver-for-resolvecontext resolvecontext))) @@ -87,6 +87,7 @@ class TestClass { (ert-deftest phpinspect-type-resolver-for-resolvecontext-multiple-namespace-blocks () (let* ((resolvecontext (phpinspect--get-resolvecontext + (phpinspect-current-project) (phpinspect-test-read-fixture-data "IncompleteClassMultipleNamespaces"))) (type-resolver (phpinspect--make-type-resolver-for-resolvecontext