(require 'ert) (require 'phpinspect-resolve) (require 'phpinspect) (require 'phpinspect-test-env (expand-file-name "phpinspect-test-env.el" (file-name-directory (macroexp-file-name)))) (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)) (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]; }}") (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 context "bar" (phpinspect-function-block function-token) (phpinspect--make-type-resolver-for-resolvecontext context) (phpinspect-function-argument-list function-token))) (result2 (phpinspect-get-variable-type-in-block context "bark" (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") result1)) (should (phpinspect--type= (phpinspect--make-type :name "\\Thing") result2))))) (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)) (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-wrapped-in-list () (let* ((code "function () { $bar = (new Foo())->bar") (bmap (phpinspect-parse-string-to-bmap code)) (project (phpinspect--make-dummy-project)) (context (phpinspect-get-resolvecontext project bmap (length code))) (result (phpinspect-resolve-type-from-context context))) (phpinspect-project-add-index project (phpinspect--index-tokens (phpinspect-parse-string "class Foo { public string $bar; }"))) (should (phpinspect--type= (phpinspect--make-type :name "\\string") (phpinspect-resolve-type-from-context context))))) (ert-deftest phpinspect-get-variable-type-in-block-assignment-wrapped-in-list () (let ((base-code "function () { $bar = ($banana = new Foo())") (paths (list "->bar" "; $banana->bar" "; $bar->bar")) (project (phpinspect--make-dummy-project))) (phpinspect-project-add-index project (phpinspect--index-tokens (phpinspect-parse-string "class Foo { public string $bar; }"))) (dolist (path paths) (let* ((code (concat base-code path)) (bmap (phpinspect-parse-string-to-bmap code)) (context (phpinspect-get-resolvecontext project bmap (length code))) (result (phpinspect-resolve-type-from-context context))) (should (phpinspect--type= (phpinspect--make-type :name "\\string") (phpinspect-resolve-type-from-context context))))))) (ert-deftest phpinspect-get-variable-type-in-block-assignment-wrapped-in-if-condition () (let ((base-code "function () { if ($bar = ($banana = new Foo())) {") (paths (list "$banana->bar" "$bar->bar" "$baz = new \\DateTime();} $banana->bar" "if ($baz = $bar->bar) { $baz")) (project (phpinspect--make-dummy-project))) (phpinspect-project-add-index project (phpinspect--index-tokens (phpinspect-parse-string "class Foo { public string $bar; }"))) (dolist (path paths) (let* ((code (concat base-code path)) (bmap (phpinspect-parse-string-to-bmap code)) (context (phpinspect-get-resolvecontext project bmap (length code))) (result (phpinspect-resolve-type-from-context context))) (should (phpinspect--type= (phpinspect--make-type :name "\\string") (phpinspect-resolve-type-from-context context))))))) (ert-deftest phpinspect-get-variable-type-in-block-var-annotation () (let ((base-code "/* @var \\Foo $banana */ $banana = $undefined;") (paths (list "$banana->bar" "if ($baz = $banana) { $bar = $banana; } $bar->bar" "$baz = new \\DateTime(); /** @var \\DateTime $pear */} $banana->bar" "if ($baz = $banana->bar) { $baz")) (project (phpinspect--make-dummy-project))) (phpinspect-project-add-index project (phpinspect--index-tokens (phpinspect-parse-string "class Foo { public string $bar; }"))) (dolist (path paths) (let* ((code (concat base-code path)) (bmap (phpinspect-parse-string-to-bmap code)) (context (phpinspect-get-resolvecontext project bmap (length code))) (result (phpinspect-resolve-type-from-context context))) (should result) (should (phpinspect--type= (phpinspect--make-type :name "\\string") result)))))) (ert-deftest phpinspect-get-variable-type-in-block-typecast () (let ((base-code "$foo = new \\DateTime();") (paths (list "$foo = (string) $foo; $foo" "((Foo) $foo)->bar" "$baz = (string) $foo; $baz" "if ($baz = (string) $banana->bar) { $baz")) (project (phpinspect--make-dummy-project))) (phpinspect-project-add-index project (phpinspect--index-tokens (phpinspect-parse-string "class Foo { public string $bar; }"))) (dolist (path paths) (let* ((code (concat base-code path)) (bmap (phpinspect-parse-string-to-bmap code)) (context (phpinspect-get-resolvecontext project bmap (length code))) (result (phpinspect-resolve-type-from-context context))) (should result) (should (phpinspect--type= (phpinspect--make-type :name "\\string") result)))))) (ert-deftest phpinspect-get-variable-type-in-block-function-return () (let ((base-code "$bar = foo();") (paths (list (cons "$bar" "Foo") (cons "$bar->baz" "string"))) (project (phpinspect--make-dummy-project))) (phpinspect-project-add-index project (phpinspect--index-tokens (phpinspect-parse-string "class Foo { public string $baz; } function foo(): Foo { return 'bla'; }"))) (dolist (path paths) (let* ((code (concat base-code (car path))) (bmap (phpinspect-parse-string-to-bmap code)) (context (phpinspect-get-resolvecontext project bmap (length code))) (result (phpinspect-resolve-type-from-context context))) (should result) (should (phpinspect--type= (phpinspect--make-type :name (concat "\\" (cdr path))) result))))))