Implement indexation and resolving of @param annotation types

master
Hugo Thunnissen 1 month ago
parent 5c61d4b293
commit 6f1e11c32a

@ -242,8 +242,8 @@ be implemented for return values of `phpinspect-eld-strategy-execute'")
(let ((doc-string (let ((doc-string
(concat "$" (truncate-string-to-width (concat "$" (truncate-string-to-width
(car arg) phpinspect-eldoc-word-width) (car arg) phpinspect-eldoc-word-width)
(if (cadr arg) " " "") (if (cdr arg) " " "")
(phpinspect--display-format-type-name (or (cadr arg) ""))))) (phpinspect--display-format-type-name (or (cdr arg) "")))))
(when (and arg-pos (= arg-count arg-pos)) (when (and arg-pos (= arg-count arg-pos))
(setq doc-string (setq doc-string
(propertize (propertize

@ -37,20 +37,35 @@
(cadr scope)) (cadr scope))
(t nil))) (t nil)))
(defun phpinspect--index-function-arg-list (type-resolver arg-list &optional add-used-types) (defun phpinspect--index-function-arg-list (type-resolver arg-list &optional add-used-types comment-before)
(let ((arg-index) (let ((arg-index)
(current-token) (current-token)
param-annotation
(arg-list (cl-copy-list arg-list))) (arg-list (cl-copy-list arg-list)))
(while (setq current-token (pop arg-list)) (while (setq current-token (pop arg-list))
(cond ((and (phpinspect-word-p current-token) (cond ((and (phpinspect-word-p current-token)
(phpinspect-variable-p (car arg-list))) (phpinspect-variable-p (car arg-list)))
(push `(,(cadr (pop arg-list)) (push (cons (cadr (pop arg-list))
,(funcall type-resolver (phpinspect--make-type :name (cadr current-token)))) (funcall type-resolver
(phpinspect--make-type :name (cadr current-token))))
arg-index) arg-index)
(when add-used-types (funcall add-used-types (list (cadr current-token))))) (when add-used-types (funcall add-used-types (list (cadr current-token)))))
((and (phpinspect-variable-p (car arg-list))
comment-before
(setq param-annotation
(phpinspect--find-var-annotation-for-variable
comment-before (cadr (car arg-list)) #'phpinspect-param-annotation-p)))
(push (cons (cadr (car arg-list))
(funcall type-resolver
(phpinspect--make-type
:name (phpinspect-var-annotation-type param-annotation))))
arg-index)
(when add-used-types
(funcall add-used-types
(list (phpinspect-var-annotation-type param-annotation)))))
((phpinspect-variable-p (car arg-list)) ((phpinspect-variable-p (car arg-list))
(push `(,(cadr (pop arg-list)) (push (cons (cadr (pop arg-list)) nil)
nil)
arg-index)))) arg-index))))
(nreverse arg-index))) (nreverse arg-index)))
@ -60,7 +75,7 @@ of TYPE, if available."
(or (not type) (or (not type)
(phpinspect--type= type phpinspect--object-type))) (phpinspect--type= type phpinspect--object-type)))
(defun phpinspect--index-function-declaration (declaration type-resolver add-used-types) (defun phpinspect--index-function-declaration (declaration type-resolver add-used-types &optional comment-before)
(let (current name function-args return-type) (let (current name function-args return-type)
(catch 'break (catch 'break
(while (setq current (pop declaration)) (while (setq current (pop declaration))
@ -71,7 +86,7 @@ of TYPE, if available."
((phpinspect-list-p current) ((phpinspect-list-p current)
(setq function-args (setq function-args
(phpinspect--index-function-arg-list (phpinspect--index-function-arg-list
type-resolver current add-used-types)) type-resolver current add-used-types comment-before))
(when (setq return-type (seq-find #'phpinspect-word-p declaration)) (when (setq return-type (seq-find #'phpinspect-word-p declaration))
(setq return-type (funcall type-resolver (setq return-type (funcall type-resolver
@ -127,7 +142,7 @@ function (think \"new\" statements, return types etc.)."
(pcase-setq `(,name ,arguments ,type) (pcase-setq `(,name ,arguments ,type)
(phpinspect--index-function-declaration (phpinspect--index-function-declaration
declaration type-resolver add-used-types)) declaration type-resolver add-used-types comment-before))
;; FIXME: Anonymous functions should not be indexed! (or if they are, they ;; FIXME: Anonymous functions should not be indexed! (or if they are, they
;; should at least not be visible from various UIs unless assigned to a ;; should at least not be visible from various UIs unless assigned to a
@ -178,10 +193,10 @@ function (think \"new\" statements, return types etc.)."
(define-inline phpinspect-var-annotation-type (annotation) (define-inline phpinspect-var-annotation-type (annotation)
(inline-quote (cadadr ,annotation))) (inline-quote (cadadr ,annotation)))
(defun phpinspect--find-var-annotation-for-variable (annotation-list variable) (defun phpinspect--find-var-annotation-for-variable (annotation-list variable &optional predicate)
(catch 'return (catch 'return
(dolist (annotation annotation-list) (dolist (annotation annotation-list)
(when (and (phpinspect-var-annotation-p annotation) (when (and (or (phpinspect-var-annotation-p annotation) (and predicate (funcall predicate annotation)))
(phpinspect-var-annotation-variable annotation) (phpinspect-var-annotation-variable annotation)
(string= (phpinspect-var-annotation-variable annotation) (string= (phpinspect-var-annotation-variable annotation)
variable)) variable))
@ -408,9 +423,8 @@ SCOPE should be a scope token (`phpinspect-scope-p')."
(phpinspect--log "Looking for variable type in constructor arguments (%s)" (phpinspect--log "Looking for variable type in constructor arguments (%s)"
variable) variable)
(let ((constructor-parameter-type (let ((constructor-parameter-type
(car (alist-get (phpinspect--variable-name variable) (phpinspect--function-argument-type
(phpinspect--function-arguments constructor) constructor (phpinspect--variable-name variable))))
nil nil #'string=))))
(if constructor-parameter-type (if constructor-parameter-type
(setf (phpinspect--variable-type variable) (setf (phpinspect--variable-type variable)
(funcall type-resolver constructor-parameter-type)))))))) (funcall type-resolver constructor-parameter-type))))))))
@ -566,6 +580,13 @@ Returns a list of type name strings."
(let ((type (cadr token))) (let ((type (cadr token)))
(when (not (string-match-p "\\\\" type)) (when (not (string-match-p "\\\\" type))
(setq used-types-rear (setcdr used-types-rear (cons type nil)))))) (setq used-types-rear (setcdr used-types-rear (cons type nil))))))
((phpinspect-comment-p token)
(setq used-types-rear
(nconc used-types-rear (phpinspect--find-used-types-in-tokens (cdr token)))))
((and (or (phpinspect-var-annotation-p token) (phpinspect-param-annotation-p token))
(phpinspect-var-annotation-type token))
(setq used-types-rear
(setcdr used-types-rear (cons (phpinspect-var-annotation-type token) nil))))
((and (phpinspect-static-attrib-p token) ((and (phpinspect-static-attrib-p token)
(phpinspect-word-p previous-token)) (phpinspect-word-p previous-token))
(let ((type (cadr previous-token))) (let ((type (cadr previous-token)))

@ -47,7 +47,7 @@
:scope (quote ,(phpinspect--function-scope func)) :scope (quote ,(phpinspect--function-scope func))
:arguments ,(append '(list) :arguments ,(append '(list)
(mapcar (lambda (arg) (mapcar (lambda (arg)
`(list ,(car arg) ,(phpinspect--serialize-type (cadr arg)))) `(cons ,(car arg) ,(phpinspect--serialize-type (cdr arg))))
(phpinspect--function-arguments func))) (phpinspect--function-arguments func)))
:return-type ,(when (phpinspect--function-return-type func) :return-type ,(when (phpinspect--function-return-type func)
(phpinspect--serialize-type (phpinspect--serialize-type

@ -148,6 +148,9 @@ Type can be any of the token types returned by
(defun phpinspect-var-annotation-p (token) (defun phpinspect-var-annotation-p (token)
(phpinspect-token-type-p token :var-annotation)) (phpinspect-token-type-p token :var-annotation))
(defun phpinspect-param-annotation-p (token)
(phpinspect-token-type-p token :param-annotation))
(defun phpinspect-return-annotation-p (token) (defun phpinspect-return-annotation-p (token)
(phpinspect-token-type-p token :return-annotation)) (phpinspect-token-type-p token :return-annotation))

@ -259,6 +259,9 @@ as first element and the type as second element.")
"A phpinspect--type object representing the the "A phpinspect--type object representing the the
return type of the function.")) return type of the function."))
(defun phpinspect--function-argument-type (fn argument-name)
(alist-get argument-name (phpinspect--function-arguments fn) nil nil #'string=))
(defun phpinspect--function-anonyous-p (fn) (defun phpinspect--function-anonyous-p (fn)
(eq (phpinspect-intern-name "anonymous") (phpinspect--function-name-symbol fn))) (eq (phpinspect-intern-name "anonymous") (phpinspect--function-name-symbol fn)))

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -70,8 +70,8 @@
(:word "array") (:word "array")
(:variable "things"))) (:variable "things")))
(:block)) (:block))
:arguments `(("untyped" nil) :arguments `(("untyped" . nil)
("things" ,(phpinspect--make-type :name "\\array" ("things" . ,(phpinspect--make-type :name "\\array"
:collection t :collection t
:fully-qualified t))) :fully-qualified t)))
:return-type phpinspect--null-type))) :return-type phpinspect--null-type)))
@ -94,13 +94,15 @@ use UsedTrait;
private PropertyType $property; private PropertyType $property;
public function makeThing(): Thing /** @param ParamAnnotation $par */
public function makeThing($par): Thing
{ {
if ((new Monkey())->tree() === true) { if ((new Monkey())->tree() === true) {
return new ExtendedThing(); return new ExtendedThing();
} }
return StaticThing::create(new ThingFactory())->makeThing((((new Potato())->antiPotato(new OtherThing(function (InnerFunctionParam $param) { return StaticThing::create(new ThingFactory())->makeThing((((new Potato())->antiPotato(new OtherThing(function (InnerFunctionParam $param) {
if ($param instanceof InstanceOffed) { if ($param instanceof InstanceOffed) {
/** @var VarAnnotation $bing */
$bing = [ 'bong' => [ 'nested' => NestedArray::call(), ], ]; $bing = [ 'bong' => [ 'nested' => NestedArray::call(), ], ];
// nothing // nothing
} }
@ -113,7 +115,8 @@ if ($param instanceof InstanceOffed) {
(copy-sequence (copy-sequence
'("Cheese" "Bacon" "Ham" "Bagel" "Monkey" "ExtendedThing" '("Cheese" "Bacon" "Ham" "Bagel" "Monkey" "ExtendedThing"
"StaticThing" "Thing" "ThingFactory" "Potato" "OtherThing" "StaticThing" "Thing" "ThingFactory" "Potato" "OtherThing"
"InnerFunctionParam" "PropertyType" "InstanceOffed" "NestedArray" "UsedTrait")) "InnerFunctionParam" "PropertyType" "InstanceOffed"
"NestedArray" "UsedTrait" "VarAnnotation" "ParamAnnotation"))
#'string<)) #'string<))
(sort used-types (lambda (s1 s2) (string< (phpinspect-name-string s1) (phpinspect-name-string s2)))))))) (sort used-types (lambda (s1 s2) (string< (phpinspect-name-string s1) (phpinspect-name-string s2))))))))
@ -163,12 +166,11 @@ if ($param instanceof InstanceOffed) {
(should (= 2 (length (phpinspect--function-arguments method)))) (should (= 2 (length (phpinspect--function-arguments method))))
(should (phpinspect--type= (should (phpinspect--type=
(phpinspect--make-type :name "\\array" :fully-qualified t) (phpinspect--make-type :name "\\array" :fully-qualified t)
(car (alist-get (phpinspect--function-argument-type method "loose")))
"loose" (phpinspect--function-arguments method) nil nil #'string=))))
(should (phpinspect--type= (should (phpinspect--type=
(phpinspect--make-type :name "\\bool" :fully-qualified t) (phpinspect--make-type :name "\\bool" :fully-qualified t)
(car (alist-get (phpinspect--function-argument-type method "fast"))))
"fast" (phpinspect--function-arguments method) nil nil #'string=)))))
((string= (phpinspect--function-name method) ((string= (phpinspect--function-name method)
"hold") "hold")
(should (phpinspect--type= (should (phpinspect--type=
@ -205,12 +207,10 @@ if ($param instanceof InstanceOffed) {
(should (= 2 (length (phpinspect--function-arguments method)))) (should (= 2 (length (phpinspect--function-arguments method))))
(should (phpinspect--type= (should (phpinspect--type=
(phpinspect--make-type :name "\\array" :fully-qualified t) (phpinspect--make-type :name "\\array" :fully-qualified t)
(car (alist-get (phpinspect--function-argument-type method "loose")))
"loose" (phpinspect--function-arguments method) nil nil #'string=))))
(should (phpinspect--type= (should (phpinspect--type=
(phpinspect--make-type :name "\\bool" :fully-qualified t) (phpinspect--make-type :name "\\bool" :fully-qualified t)
(car (alist-get (phpinspect--function-argument-type method "fast"))))
"fast" (phpinspect--function-arguments method) nil nil #'string=)))))
((string= (phpinspect--function-name method) ((string= (phpinspect--function-name method)
"hold") "hold")
(should (phpinspect--type= (should (phpinspect--type=
@ -260,7 +260,8 @@ use Example\\Thing;
function test_func(): array {} function test_func(): array {}
function example(): Thing {}") /** @param \\array $bing */
function example($bing): Thing {}")
(tokens (phpinspect-parse-string code)) (tokens (phpinspect-parse-string code))
(index (phpinspect--index-tokens tokens)) (index (phpinspect--index-tokens tokens))
functions) functions)
@ -270,6 +271,12 @@ function example(): Thing {}")
(should (string= "test_func" (phpinspect--function-name (cadr functions)))) (should (string= "test_func" (phpinspect--function-name (cadr functions))))
(should (string= "example" (phpinspect--function-name (car functions)))) (should (string= "example" (phpinspect--function-name (car functions))))
(let ((example (car functions)))
(should (= 1 (length (phpinspect--function-arguments example))))
(should (phpinspect--type=
(phpinspect--make-type :name "\\array")
(phpinspect--function-argument-type example "bing"))))
(should (phpinspect--type= (phpinspect--make-type :name "\\array") (should (phpinspect--type= (phpinspect--make-type :name "\\array")
(phpinspect--function-return-type (cadr functions)))) (phpinspect--function-return-type (cadr functions))))
(should (phpinspect--type= (phpinspect--make-type :name "\\Example\\Thing") (should (phpinspect--type= (phpinspect--make-type :name "\\Example\\Thing")

Loading…
Cancel
Save