[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/phpinspect f013b3c709 036/126: WIP: Support ambiguous t
From: |
ELPA Syncer |
Subject: |
[elpa] externals/phpinspect f013b3c709 036/126: WIP: Support ambiguous typehints |
Date: |
Sat, 12 Aug 2023 00:58:38 -0400 (EDT) |
branch: externals/phpinspect
commit f013b3c709746a0f8e49fa9447153ac743e63a2b
Author: Hugo Thunnissen <devel@hugot.nl>
Commit: Hugo Thunnissen <devel@hugot.nl>
WIP: Support ambiguous typehints
- Try to infer type of "object" typehint by using the return annotation
- Support late static binding with "static" and "this" return type
---
phpinspect-class.el | 53 +++++++++++++++++++++++++++++++++++++----------------
phpinspect-index.el | 22 +++++++++++++++-------
phpinspect-type.el | 38 +++++++++++++++++++++++++++++++-------
phpinspect.el | 12 ++----------
4 files changed, 85 insertions(+), 40 deletions(-)
diff --git a/phpinspect-class.el b/phpinspect-class.el
index c2918f6ca2..7b6e12be0c 100644
--- a/phpinspect-class.el
+++ b/phpinspect-class.el
@@ -99,12 +99,21 @@
(method phpinspect--function))
(phpinspect--log "Adding method by name %s to class"
(phpinspect--function-name method))
- (puthash (phpinspect--function-name-symbol method)
- method
- (phpinspect--class-methods class)))
+ (setq method (phpinspect--copy-function method))
+
+ (when (phpinspect--type-does-late-static-binding
+ (phpinspect--function-return-type method))
+
+ (setf (phpinspect--function-return-type method)
+ (alist-get 'class-name (phpinspect--class-index class))))
+
+ (puthash (phpinspect--function-name-symbol method)
+ method
+ (phpinspect--class-methods class)))
(cl-defmethod phpinspect--class-set-static-method ((class phpinspect--class)
(method
phpinspect--function))
+ (setq method (phpinspect--copy-function method))
(puthash (phpinspect--function-name-symbol method)
method
(phpinspect--class-static-methods class)))
@@ -135,12 +144,12 @@
(phpinspect--class-static-methods class))))
(if existing
(progn
- (unless (eq (phpinspect--function-return-type method)
- phpinspect--null-type)
- (setf (phpinspect--function-return-type existing)
- (phpinspect--function-return-type method))
+ (unless (phpinspect--type= (phpinspect--function-return-type method)
+ phpinspect--null-type)
+ (setf (phpinspect--function-return-type existing)
+ (phpinspect--function-return-type method)))
(setf (phpinspect--function-arguments existing)
- (phpinspect--function-arguments method))))
+ (phpinspect--function-arguments method)))
(phpinspect--class-set-static-method class method))))
(cl-defmethod phpinspect--class-update-method ((class phpinspect--class)
@@ -149,19 +158,31 @@
(phpinspect--class-methods class))))
(if existing
(progn
- (unless (eq (phpinspect--function-return-type method)
- phpinspect--null-type)
- (setf (phpinspect--function-return-type existing)
- (phpinspect--function-return-type method))
+ (unless (phpinspect--type= (phpinspect--function-return-type method)
+ phpinspect--null-type)
+ (phpinspect--log "method return type %s"
(phpinspect--function-return-type method))
+ (setf (phpinspect--function-return-type existing)
+ ;; The "static" return type returns the class that the method
+ ;; is called on
+ (if (phpinspect--type-does-late-static-binding
+ (phpinspect--function-return-type method))
+ (alist-get 'class-name (phpinspect--class-index class))
+ (phpinspect--function-return-type method))))
+
(setf (phpinspect--function-arguments existing)
- (phpinspect--function-arguments method))))
+ (phpinspect--function-arguments method)))
(phpinspect--class-set-method class method))))
(cl-defmethod phpinspect--class-incorporate ((class phpinspect--class)
(other-class phpinspect--class))
- (maphash (lambda (k method)
- (phpinspect--class-update-method class method))
- (phpinspect--class-methods other-class)))
+ (let ((class-index (phpinspect--class-index other-class)))
+ (dolist (method (alist-get 'methods class-index))
+ (phpinspect--class-update-method class method))
+
+ (dolist (method (alist-get 'static-methods class-index))
+ (phpinspect--class-update-static-method class method))))
+
+
(cl-defmethod phpinspect--class-subscribe ((class phpinspect--class)
(subscription-class
phpinspect--class))
diff --git a/phpinspect-index.el b/phpinspect-index.el
index 9211ed9f47..c1fd2c9350 100644
--- a/phpinspect-index.el
+++ b/phpinspect-index.el
@@ -56,26 +56,34 @@
arg-index))))
(nreverse arg-index)))
+(defsubst phpinspect--should-prefer-return-annotation (type)
+ "When the return annotation should be preferred over typehint of TYPE, if
available."
+ (or (not type)
+ (phpinspect--type= type phpinspect--object-type)))
+
(defun phpinspect--index-function-from-scope (type-resolver scope
comment-before)
(let* ((php-func (cadr scope))
(declaration (cadr php-func))
(type (if (phpinspect-word-p (car (last declaration)))
- (phpinspect--make-type :name (cadar (last declaration))))))
+ (funcall type-resolver
+ (phpinspect--make-type :name (cadar (last
declaration)))))))
- ;; @return annotation. Has precedence over typehint when dealing with a
collection.
+ ;; @return annotation. When dealing with a collection, we want to store the
+ ;; type of its members.
(let* ((is-collection
(when type
- (member (phpinspect--type-name
- (funcall type-resolver type))
phpinspect-collection-types)))
+ (member (phpinspect--type-name type)
phpinspect-collection-types)))
(return-annotation-type
- (when (or (not type) is-collection)
+ (when (or (phpinspect--should-prefer-return-annotation type)
is-collection)
(cadadr
(seq-find #'phpinspect-return-annotation-p
comment-before)))))
- (phpinspect--log "found return annotation %s" return-annotation-type)
+ (phpinspect--log "found return annotation %s when type is %s"
+ return-annotation-type
+ type)
(when return-annotation-type
- (cond ((not type)
+ (cond ((phpinspect--should-prefer-return-annotation type)
(setq type (funcall type-resolver
(phpinspect--make-type :name
return-annotation-type))))
(is-collection
diff --git a/phpinspect-type.el b/phpinspect-type.el
index 0816fa04a0..e9f628652c 100644
--- a/phpinspect-type.el
+++ b/phpinspect-type.el
@@ -49,11 +49,37 @@
`(phpinspect--make-type-generated
,@(phpinspect--wrap-plist-name-in-symbol property-list)))
-(defconst phpinspect--null-type (phpinspect--make-type :name "\\null"))
+(defun phpinspect--make-types (&rest type-names)
+ (mapcar (lambda (name) (phpinspect--make-type :name name))
+ type-names))
+
+(defconst phpinspect-native-types
+ ;; self, parent and resource are not valid type name.
+ ;; see https://www.php.net/manual/ja/language.types.declarations.php
+ ;;;
+ ;; However, this list does not need to be valid, it just needs to contain the
+ ;; list of type names that we should not attempt to resolve relatively.
+ '("array" "bool" "callable" "float" "int" "iterable" "mixed" "object"
"string" "void" "self" "static" "this"))
+
+(defvar phpinspect-collection-types
+ (phpinspect--make-types '("\\array" "\\iterable" "\\SplObjectCollection"
"\\mixed"))
+ "FQNs of types that should be treated as collecitons when inferring types.")
+
+(defconst phpinspect--object-type (phpinspect--make-type :name "\\object"
:fully-qualified t))
+(defconst phpinspect--static-type (phpinspect--make-type :name "\\static"
:fully-qualified t))
+(defconst phpinspect--self-type (phpinspect--make-type :name "\\self"
:fully-qualified t))
+(defconst phpinspect--this-type (phpinspect--make-type :name "\\this"
:fully-qualified t))
+(defconst phpinspect--null-type (phpinspect--make-type :name "\\null"
:fully-qualified t))
(cl-defmethod phpinspect--type-set-name ((type phpinspect--type) (name string))
(setf (phpinspect--type-name-symbol type) (phpinspect-intern-name name)))
+(cl-defmethod phpinspect--type-does-late-static-binding ((type
phpinspect--type))
+ "Whether or not TYPE is used for late static binding.
+See https://wiki.php.net/rfc/static_return_type ."
+ (or (phpinspect--type= type phpinspect--static-type)
+ (phpinspect--type= type phpinspect--this-type)))
+
(cl-defmethod phpinspect--type-name ((type phpinspect--type))
(symbol-name (phpinspect--type-name-symbol type)))
@@ -107,15 +133,12 @@ NAMESPACE may be nil, or a string with a namespace FQN."
(if token-tree (or (phpinspect--find-innermost-incomplete-class
token-tree)
(phpinspect--find-class-token token-tree))))
(inside-class-name (if inside-class
(phpinspect--get-class-name-from-token
- inside-class)))
- (self-type (phpinspect--make-type :name "self"))
- (static-type (phpinspect--make-type :name "static")))
+ inside-class))))
(lambda (type)
(phpinspect--type-resolve
types
namespace
- (if (and inside-class-name (or (phpinspect--type= type self-type)
- (phpinspect--type= type static-type)))
+ (if (and inside-class-name (phpinspect--type= type
phpinspect--self-type))
(progn
(phpinspect--log "Returning inside class name for %s : %s"
type inside-class-name)
@@ -129,7 +152,8 @@ NAMESPACE may be nil, or a string with a namespace FQN."
(cl-defmethod phpinspect--format-type-name ((type phpinspect--type))
(phpinspect--format-type-name (phpinspect--type-name type)))
-(cl-defstruct (phpinspect--function (:constructor
phpinspect--make-function-generated))
+(cl-defstruct (phpinspect--function (:constructor
phpinspect--make-function-generated)
+ (:copier phpinspect--copy-function))
"A PHP function."
(name-symbol nil
:type symbol
diff --git a/phpinspect.el b/phpinspect.el
index e0eec178b1..20dc8a84f7 100644
--- a/phpinspect.el
+++ b/phpinspect.el
@@ -74,14 +74,6 @@ phpinspect")
Should normally be set to \"phpinspect-index.bash\" in the source
file directory.")
-(defconst phpinspect-native-types
- ;; self, parent and resource are not valid type name.
- ;; see https://www.php.net/manual/ja/language.types.declarations.php
- '("array" "bool" "callable" "float" "int" "iterable" "mixed" "object"
"string" "void"))
-
-(defvar phpinspect-collection-types
- '("\\array" "\\iterable" "\\SplObjectCollection" "\\mixed")
- "FQNs of types that should be treated as collecitons when inferring types.")
(cl-defstruct (phpinspect--completion
(:constructor phpinspect--construct-completion))
@@ -229,7 +221,7 @@ accompanied by all of its enclosing tokens."
(defsubst phpinspect-get-cached-project-class-method-type
(project-root class-fqn method-name)
(when project-root
- (let* ((class (phpinspect-get-cached-project-class project-root class-fqn))
+ (let* ((class (phpinspect-get-or-create-cached-project-class project-root
class-fqn))
(method))
(when class
(setq method
@@ -266,7 +258,7 @@ accompanied by all of its enclosing tokens."
(defsubst phpinspect-get-cached-project-class-static-method-type
(project-root class-fqn method-name)
(when project-root
- (let* ((class (phpinspect-get-cached-project-class project-root class-fqn))
+ (let* ((class (phpinspect-get-or-create-cached-project-class project-root
class-fqn))
(method))
(when class
(setq method
- [elpa] externals/phpinspect ca8d0972ff 050/126: Implement psr-0 and psr-4 autoloaders, (continued)
- [elpa] externals/phpinspect ca8d0972ff 050/126: Implement psr-0 and psr-4 autoloaders, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 1f145665ef 083/126: Exclude "return" from resolvecontext subject + count comma at point for eldoc arg number, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 0ca527dbbd 070/126: Adapt `phpinspect-purge-parser-cache' to new parser caching approach, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 6627f6f76f 073/126: Remove commented parser code, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect e270729e14 088/126: Implement splay tree for overlay storage/lookup, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 94d5b75455 107/126: Add `phpinspect-pipeline-pause-time', ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect e8f486f095 013/126: Improve codestyle and documentation + add tests for indexation, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect c0786db131 040/126: WIP: Index every possibly required type ahead of time., ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 2e487e7810 039/126: Fix resolving of function argument types, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 2fd575dbf5 044/126: Add drone.yml, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect f013b3c709 036/126: WIP: Support ambiguous typehints,
ELPA Syncer <=
- [elpa] externals/phpinspect ef9a7336cf 049/126: Replace virtual-directory with more general virtual-fs implementation, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect dbf0ec0390 051/126: Transition from index script to autoloader, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 97377c2922 055/126: Fix bugs in phpinspect-fix-imports, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 281c5e4ae6 077/126: Remove some overly verbose logging, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 0596bc52bf 091/126: Optimize splay tree and use it to store token's children, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect ab6954faf5 090/126: Retrieve and wrap metadata using the correct overlay for region, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 389e77eb8b 092/126: Expand existing overlay when possible, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 23245d0158 098/126: Fix some compilation warnings, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect db370623da 108/126: Implement "files" autoload strategy, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 6678ba20c6 103/126: Implement async processing pipeline, ELPA Syncer, 2023/08/12