Fix tests and patch bugs that came to light in the process

WIP-incremental-parsing
Hugo Thunnissen 2 years ago
parent 3a3e2cd362
commit 0bc9e795b2

@ -106,28 +106,36 @@
(cl-defmethod phpinspect--class-get-static-method ((class phpinspect--class) method-name) (cl-defmethod phpinspect--class-get-static-method ((class phpinspect--class) method-name)
(gethash method-name (phpinspect--class-static-methods class))) (gethash method-name (phpinspect--class-static-methods class)))
(cl-defmethod phpinspect--class-set-method ((class phpinspect--class) (cl-defmethod phpinspect--add-method-copy-to-map
(method phpinspect--function)) ((map hash-table)
(phpinspect--log "Adding method by name %s to class" (class-name phpinspect--type)
(phpinspect--function-name method)) (method phpinspect--function))
(setq method (phpinspect--copy-function method)) (setq method (phpinspect--copy-function method))
(when (phpinspect--type-does-late-static-binding (setf (phpinspect--function-return-type method)
(phpinspect--function-return-type method)) (phpinspect--resolve-late-static-binding
(phpinspect--function-return-type method)
class-name))
(setf (phpinspect--function-return-type method) (puthash (phpinspect--function-name-symbol method)
(alist-get 'class-name (phpinspect--class-index class)))) method
map))
(puthash (phpinspect--function-name-symbol method) (cl-defmethod phpinspect--class-set-method ((class phpinspect--class)
method (method phpinspect--function))
(phpinspect--class-methods class))) (phpinspect--log "Adding method by name %s to class"
(phpinspect--function-name method))
(phpinspect--add-method-copy-to-map
(phpinspect--class-methods class)
(alist-get 'class-name (phpinspect--class-index class))
method))
(cl-defmethod phpinspect--class-set-static-method ((class phpinspect--class) (cl-defmethod phpinspect--class-set-static-method ((class phpinspect--class)
(method phpinspect--function)) (method phpinspect--function))
(setq method (phpinspect--copy-function method)) (phpinspect--add-method-copy-to-map
(puthash (phpinspect--function-name-symbol method) (phpinspect--class-static-methods class)
method (alist-get 'class-name (phpinspect--class-index class))
(phpinspect--class-static-methods class))) method))
(cl-defmethod phpinspect--class-get-method-return-type (cl-defmethod phpinspect--class-get-method-return-type
((class phpinspect--class) (method-name symbol)) ((class phpinspect--class) (method-name symbol))
@ -155,39 +163,38 @@
(phpinspect--class-static-methods class)) (phpinspect--class-static-methods class))
methods)) methods))
(cl-defmethod phpinspect--merge-method ((class-name phpinspect--type)
(existing phpinspect--function)
(method phpinspect--function))
(let ((new-return-type (phpinspect--resolve-late-static-binding
class-name
(phpinspect--function-return-type method))))
(unless (phpinspect--type= new-return-type phpinspect--null-type)
(phpinspect--log "method return type %s" (phpinspect--function-return-type method))
(setf (phpinspect--function-return-type existing)
new-return-type))
(setf (phpinspect--function-arguments existing)
(phpinspect--function-arguments method))))
(cl-defmethod phpinspect--class-update-static-method ((class phpinspect--class) (cl-defmethod phpinspect--class-update-static-method ((class phpinspect--class)
(method phpinspect--function)) (method phpinspect--function))
(let ((existing (gethash (phpinspect--function-name-symbol method) (let ((existing (gethash (phpinspect--function-name-symbol method)
(phpinspect--class-static-methods class)))) (phpinspect--class-static-methods class))))
(if existing (if existing
(progn (phpinspect--merge-method
(unless (phpinspect--type= (phpinspect--function-return-type method) (alist-get 'class-name (phpinspect--class-index class))
phpinspect--null-type) existing method)
(setf (phpinspect--function-return-type existing)
(phpinspect--function-return-type method)))
(setf (phpinspect--function-arguments existing)
(phpinspect--function-arguments method)))
(phpinspect--class-set-static-method class method)))) (phpinspect--class-set-static-method class method))))
(cl-defmethod phpinspect--class-update-method ((class phpinspect--class) (cl-defmethod phpinspect--class-update-method ((class phpinspect--class)
(method phpinspect--function)) (method phpinspect--function))
(let ((existing (gethash (phpinspect--function-name-symbol method) (let* ((existing (gethash (phpinspect--function-name-symbol method)
(phpinspect--class-methods class)))) (phpinspect--class-methods class))))
(if existing (if existing
(progn (phpinspect--merge-method
(unless (phpinspect--type= (phpinspect--function-return-type method) (alist-get 'class-name (phpinspect--class-index class))
phpinspect--null-type) existing method)
(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--class-set-method class method)))) (phpinspect--class-set-method class method))))
(cl-defmethod phpinspect--class-incorporate ((class phpinspect--class) (cl-defmethod phpinspect--class-incorporate ((class phpinspect--class)

@ -267,9 +267,9 @@
(let ((class-name (funcall type-resolver (phpinspect--make-type :name class-name)))) (let ((class-name (funcall type-resolver (phpinspect--make-type :name class-name))))
`(,class-name . `(,class-name .
(phpinspect--indexed-class (phpinspect--indexed-class
(class-name . ,class-name)
(imports . ,imports) (imports . ,imports)
(methods . ,methods) (methods . ,methods)
(class-name . ,class-name)
(static-methods . ,static-methods) (static-methods . ,static-methods)
(static-variables . ,static-variables) (static-variables . ,static-variables)
(variables . ,variables) (variables . ,variables)

@ -0,0 +1,105 @@
;;; phpinspect-index.el --- PHP parsing and completion package -*- lexical-binding: t; -*-
;; Copyright (C) 2021 Free Software Foundation, Inc
;; Author: Hugo Thunnissen <devel@hugot.nl>
;; Keywords: php, languages, tools, convenience
;; Version: 0
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
(require 'phpinspect-type)
(require 'phpinspect-class)
(cl-defmethod phpinspect--serialize-type ((type phpinspect--type))
`(phpinspect--make-type
:name ,(phpinspect--type-name type)
:collection ,(phpinspect--type-collection type)
:contains ,(when (phpinspect--type-contains type)
(phpinspect--serialize-type (phpinspect--type-contains type)))
:fully-qualified ,(phpinspect--type-fully-qualified type)))
(cl-defmethod phpinspect--serialize-function ((func phpinspect--function))
`(phpinspect--make-function
:name ,(phpinspect--function-name func)
:scope (quote ,(phpinspect--function-scope func))
:arguments ,(append '(list)
(mapcar (lambda (arg)
`(list ,(car arg) ,(phpinspect--serialize-type (cadr arg))))
(phpinspect--function-arguments func)))
:return-type ,(when (phpinspect--function-return-type func)
(phpinspect--serialize-type
(phpinspect--function-return-type func)))))
(cl-defmethod phpinspect--serialize-variable ((var phpinspect--variable))
`(phpinspect--make-variable :name ,(phpinspect--variable-name var)
:type ,(when (phpinspect--variable-type var)
(phpinspect--serialize-type
(phpinspect--variable-type var)))
:scope (quote ,(phpinspect--variable-scope var))))
(cl-defmethod phpinspect--serialize-indexed-class ((class (head phpinspect--indexed-class)))
``(phpinspect--indexed-class
(class-name . ,,(phpinspect--serialize-type (alist-get 'class-name class)))
(imports . ,,(append '(list)
(mapcar #'phpinspect--serialize-import
(alist-get 'imports class))))
(methods . ,,(append '(list)
(mapcar #'phpinspect--serialize-function
(alist-get 'methods class))))
(static-methods . ,,(append '(list)
(mapcar #'phpinspect--serialize-function
(alist-get 'static-methods class))))
(static-variables . ,,(append '(list)
(mapcar #'phpinspect--serialize-variable
(alist-get 'static-variables class))))
(variables . ,,(append '(list)
(mapcar #'phpinspect--serialize-variable
(alist-get 'variables class))))
(constants . ,,(append '(list)
(mapcar #'phpinspect--serialize-variable
(alist-get 'constants class))))
(extends . ,,(append '(list)
(mapcar #'phpinspect--serialize-type
(alist-get 'extends class))))
(implements . ,,(append '(list)
(mapcar #'phpinspect--serialize-type
(alist-get 'implements class))))))
(cl-defmethod phpinspect--serialize-root-index ((index (head phpinspect--root-index)))
``(phpinspect--root-index
(imports . ,,(append '(list)
(mapcar #'phpinspect--serialize-import
(alist-get 'imports index))))
(classes ,,@(mapcar (lambda (cons-class)
`(list ,(phpinspect--serialize-type (car cons-class))
,(phpinspect--serialize-indexed-class (cdr cons-class))))
(alist-get 'classes index)))
(functions . ,,(append '(list)
(mapcar #'phpinspect--serialize-function
(alist-get 'functions index))))))
(defun phpinspect--serialize-import (import)
`(cons
(phpinspect-intern-name ,(symbol-name (car import)))
,(phpinspect--serialize-type (cdr import))))
(provide 'phpinspect-serialize)
;;; phpinspect-serialize.el ends here

@ -84,6 +84,13 @@ See https://wiki.php.net/rfc/static_return_type ."
(or (phpinspect--type= type phpinspect--static-type) (or (phpinspect--type= type phpinspect--static-type)
(phpinspect--type= type phpinspect--this-type))) (phpinspect--type= type phpinspect--this-type)))
(cl-defmethod phpinspect--resolve-late-static-binding
((type phpinspect--type)
(class-type phpinspect--type))
(if (phpinspect--type-does-late-static-binding type)
class-type
type))
(defsubst phpinspect--type-is-native (type) (defsubst phpinspect--type-is-native (type)
(catch 'found (catch 'found
(dolist (native phpinspect-native-types) (dolist (native phpinspect-native-types)

@ -359,7 +359,9 @@ TODO:
(phpinspect--resolvecontext-project-root resolvecontext)) (phpinspect--resolvecontext-project-root resolvecontext))
type-of-previous-statement)) type-of-previous-statement))
(method (when class (method (when class
(phpinspect--class-get-method class method-name-sym)))) (if static
(phpinspect--class-get-static-method class method-name-sym)
(phpinspect--class-get-method class method-name-sym)))))
(phpinspect--log "Eldoc method name: %s" method-name-sym) (phpinspect--log "Eldoc method name: %s" method-name-sym)
(phpinspect--log "Eldoc type of previous statement: %s" (phpinspect--log "Eldoc type of previous statement: %s"
type-of-previous-statement) type-of-previous-statement)
@ -418,20 +420,18 @@ TODO:
(phpinspect--find-assignments-in-token block-or-list) (phpinspect--find-assignments-in-token block-or-list)
assignments))))) assignments)))))
;; return ;; return
(phpinspect--log "Yayo Returning %s" assignments) (phpinspect--log "Found assignments in token: %s" assignments)
(phpinspect--log "Yayo had statements %s" statements) (phpinspect--log "Found statements in token: %s" statements)
assignments)) assignments))
(cl-defmethod phpinspect--find-assignments-in-token ((token (head :list))) (cl-defmethod phpinspect--find-assignments-in-token ((token (head :list)))
"Find assignments that are in a list token." "Find assignments that are in a list token."
(phpinspect--log "looking for assignments in list %s" token) (phpinspect--log "looking for assignments in list %s" token)
(let ((ajaja (seq-filter (seq-filter
(lambda (statement) (lambda (statement)
(phpinspect--log "checking statement %s" statement) (phpinspect--log "checking statement %s" statement)
(seq-find #'phpinspect-maybe-assignment-p statement)) (seq-find #'phpinspect-maybe-assignment-p statement))
(phpinspect--split-list #'phpinspect-end-of-statement-p (cdr token))))) (phpinspect--split-list #'phpinspect-end-of-statement-p (cdr token))))
(phpinspect--log "Found ajaja %s" ajaja)
ajaja))
(defsubst phpinspect-not-assignment-p (token) (defsubst phpinspect-not-assignment-p (token)
"Inverse of applying `phpinspect-assignment-p to TOKEN." "Inverse of applying `phpinspect-assignment-p to TOKEN."
@ -595,6 +595,7 @@ resolve types of function argument variables."
(last-assignment-value (when assignments (car (last assignments))))) (last-assignment-value (when assignments (car (last assignments)))))
(phpinspect--log "Last assignment: %s" last-assignment-value) (phpinspect--log "Last assignment: %s" last-assignment-value)
(phpinspect--log "Current block: %s" php-block)
;; When the right of an assignment is more than $variable; or "string";(so ;; When the right of an assignment is more than $variable; or "string";(so
;; (:variable "variable") (:terminator ";") or (:string "string") (:terminator ";") ;; (:variable "variable") (:terminator ";") or (:string "string") (:terminator ";")
;; in tokens), we're likely working with a derived assignment like $object->method() ;; in tokens), we're likely working with a derived assignment like $object->method()
@ -602,7 +603,7 @@ resolve types of function argument variables."
(cond ((and (phpinspect-word-p (car last-assignment-value)) (cond ((and (phpinspect-word-p (car last-assignment-value))
(string= (cadar last-assignment-value) "new")) (string= (cadar last-assignment-value) "new"))
(funcall type-resolver (phpinspect--make-type :name (cadadr last-assignment-value)))) (funcall type-resolver (phpinspect--make-type :name (cadadr last-assignment-value))))
((and (> (length last-assignment-value) 2) ((and (> (length last-assignment-value) 1)
(seq-find #'phpinspect-attrib-p last-assignment-value)) (seq-find #'phpinspect-attrib-p last-assignment-value))
(phpinspect--log "Variable was assigned with a derived statement") (phpinspect--log "Variable was assigned with a derived statement")
(phpinspect-get-derived-statement-type-in-block resolvecontext (phpinspect-get-derived-statement-type-in-block resolvecontext
@ -613,7 +614,8 @@ resolve types of function argument variables."
;; If the right of an assignment is just $variable;, we can check if it is a ;; If the right of an assignment is just $variable;, we can check if it is a
;; function argument and otherwise recurse to find the type of that variable. ;; function argument and otherwise recurse to find the type of that variable.
((phpinspect-variable-p (car last-assignment-value)) ((phpinspect-variable-p (car last-assignment-value))
(phpinspect--log "Variable was assigned with the value of another variable") (phpinspect--log "Variable was assigned with the value of another variable: %s"
last-assignment-value)
(or (when function-arg-list (or (when function-arg-list
(phpinspect-get-variable-type-in-function-arg-list (cadar last-assignment-value) (phpinspect-get-variable-type-in-function-arg-list (cadar last-assignment-value)
type-resolver type-resolver
@ -852,44 +854,6 @@ level of a token. Nested variables are ignored."
(defun phpinspect--buffer-index (buffer) (defun phpinspect--buffer-index (buffer)
(with-current-buffer buffer phpinspect--buffer-index)) (with-current-buffer buffer phpinspect--buffer-index))
(cl-defgeneric phpinspect--merge-indexes (index1 index2)
"Merge two phpinspect index types into one and return it")
(cl-defmethod phpinspect--merge-indexes
((class1 (head phpinspect--indexed-class))
(class2 (head phpinspect--indexed-class)))
"Merge two indexed classes."
(let* ((class1-methods (alist-get 'methods (cdr class1)))
(class1-variables (alist-get 'variables (cdr class1))))
(dolist (method (alist-get 'methods (cdr class2)))
(cl-pushnew method class1-methods :test #'equal))
(setf (alist-get 'methods (cdr class1)) class1-methods)
(dolist (variable (alist-get 'variables (cdr class2)))
(cl-pushnew variable class1-variables :test #'equal))
(setf (alist-get 'variables (cdr class1)) class1-variables))
class1)
(cl-defmethod phpinspect--merge-indexes
((index1 (head phpinspect--root-index))
(index2 (head phpinspect--root-index)))
(let ((index1-classes (alist-get 'classes (cdr index1)))
(index2-classes (alist-get 'classes (cdr index2))))
(dolist (class index2-classes)
(when class
(let* ((class-name (alist-get 'class-name (cdr class)))
(existing-class (alist-get class-name index1-classes nil nil 'phpinspect--type=)))
(if existing-class
(progn
(phpinspect--log "Found existing class in root index: %s" class-name)
(setcdr (assoc class-name index1-classes)
(phpinspect--merge-indexes existing-class (cdr class))))
;; else
(phpinspect--log "Didn't find existing class in root index: %s" class-name)
(push class index1-classes)))))
(setf (alist-get 'classes index1) index1-classes)
index1))
(defsubst phpinspect-not-variable-p (token) (defsubst phpinspect-not-variable-p (token)
(not (phpinspect-variable-p token))) (not (phpinspect-variable-p token)))

@ -1 +1 @@
(phpinspect--root-index (classes ("\\App\\Entity\\AuthToken" phpinspect--class (methods #s(phpinspect--function "getCreationTime" (:public) nil "\\DateTime") #s(phpinspect--function "isValid" (:public) nil "\\bool") #s(phpinspect--function "hasStudentRole" (:public) nil "\\bool") #s(phpinspect--function "getUser" (:public) nil "\\App\\Entity\\User") #s(phpinspect--function "getToken" (:public) nil "\\string") #s(phpinspect--function "__construct" (:public) (("token" "\\string") ("user" "\\App\\Entity\\User") ("valid" "\\bool") ("creation_time" "\\DateTime")) nil)) (class-name . "\\App\\Entity\\AuthToken") (static-methods) (static-variables) (variables #s(phpinspect--variable "creation_time" (:private) "\\DateTime") #s(phpinspect--variable "valid" (:private) "\\bool") #s(phpinspect--variable "user" (:private) "\\App\\Entity\\App\\\\Entity\\\\User") #s(phpinspect--variable "token" (:private) "\\string")) (constants) (extends) (implements))) (functions)) `(phpinspect--root-index (imports \, (list)) (classes ,(list (phpinspect--make-type :name "\\App\\Entity\\AuthToken" :collection nil :contains nil :fully-qualified t) `(phpinspect--indexed-class (class-name \, (phpinspect--make-type :name "\\App\\Entity\\AuthToken" :collection nil :contains nil :fully-qualified t)) (imports \, (list (cons (phpinspect-intern-name "ORM") (phpinspect--make-type :name "\\Doctrine\\ORM\\Mapping" :collection nil :contains nil :fully-qualified t)))) (methods \, (list (phpinspect--make-function :name "getCreationTime" :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\DateTime" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "isValid" :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "hasStudentRole" :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "getUser" :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\App\\Entity\\User" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "getToken" :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\string" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "__construct" :scope '(:public) :arguments (list (list "token" (phpinspect--make-type :name "\\string" :collection nil :contains nil :fully-qualified t)) (list "user" (phpinspect--make-type :name "\\App\\Entity\\User" :collection nil :contains nil :fully-qualified t)) (list "valid" (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t)) (list "creation_time" (phpinspect--make-type :name "\\DateTime" :collection nil :contains nil :fully-qualified t))) :return-type (phpinspect--make-type :name "\\null" :collection nil :contains nil :fully-qualified t)))) (static-methods \, (list)) (static-variables \, (list)) (variables \, (list (phpinspect--make-variable :name "creation_time" :type (phpinspect--make-type :name "\\DateTime" :collection nil :contains nil :fully-qualified t) :scope '(:private)) (phpinspect--make-variable :name "valid" :type (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t) :scope '(:private)) (phpinspect--make-variable :name "user" :type (phpinspect--make-type :name "\\App\\Entity\\App\\\\Entity\\\\User" :collection nil :contains nil :fully-qualified t) :scope '(:private)) (phpinspect--make-variable :name "token" :type (phpinspect--make-type :name "\\string" :collection nil :contains nil :fully-qualified t) :scope '(:private)))) (constants \, (list)) (extends \, (list)) (implements \, (list))))) (functions \, (list)))

@ -1 +1 @@
(phpinspect--root-index (classes ("\\App\\Entity\\AuthToken" phpinspect--class (methods #s(phpinspect--function "getCreationTime" (:public) nil "\\DateTime") #s(phpinspect--function "anAddedFunction" (:public) nil nil) #s(phpinspect--function "isValid" (:public) nil "\\bool") #s(phpinspect--function "hasStudentRole" (:public) nil "\\bool") #s(phpinspect--function "getUser" (:public) nil "\\App\\Entity\\User") #s(phpinspect--function "getToken" (:public) nil "\\bool") #s(phpinspect--function "__construct" (:public) (("token" "\\string") ("user" "\\App\\Entity\\User") ("valid" "\\bool") ("creation_time" "\\DateTime")) nil)) (class-name . "\\App\\Entity\\AuthToken") (static-methods) (static-variables) (variables #s(phpinspect--variable "creation_time" (:private) "\\DateTime") #s(phpinspect--variable "valid" (:private) "\\bool") #s(phpinspect--variable "user" (:private) "\\App\\Entity\\App\\\\Entity\\\\User") #s(phpinspect--variable "extra" (:private) nil) #s(phpinspect--variable "token" (:private) "\\string")) (constants) (extends) (implements))) (functions)) `(phpinspect--root-index (imports \, (list)) (classes ,(list (phpinspect--make-type :name "\\App\\Entity\\AuthToken" :collection nil :contains nil :fully-qualified t) `(phpinspect--indexed-class (class-name \, (phpinspect--make-type :name "\\App\\Entity\\AuthToken" :collection nil :contains nil :fully-qualified t)) (imports \, (list (cons (phpinspect-intern-name "ORM") (phpinspect--make-type :name "\\Doctrine\\ORM\\Mapping" :collection nil :contains nil :fully-qualified t)))) (methods \, (list (phpinspect--make-function :name "getCreationTime" :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\DateTime" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "anAddedFunction" :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\null" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "isValid" :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "hasStudentRole" :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "getUser" :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\App\\Entity\\User" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "getToken" :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "__construct" :scope '(:public) :arguments (list (list "token" (phpinspect--make-type :name "\\string" :collection nil :contains nil :fully-qualified t)) (list "user" (phpinspect--make-type :name "\\App\\Entity\\User" :collection nil :contains nil :fully-qualified t)) (list "valid" (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t)) (list "creation_time" (phpinspect--make-type :name "\\DateTime" :collection nil :contains nil :fully-qualified t))) :return-type (phpinspect--make-type :name "\\null" :collection nil :contains nil :fully-qualified t)))) (static-methods \, (list)) (static-variables \, (list)) (variables \, (list (phpinspect--make-variable :name "creation_time" :type (phpinspect--make-type :name "\\DateTime" :collection nil :contains nil :fully-qualified t) :scope '(:private)) (phpinspect--make-variable :name "valid" :type (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t) :scope '(:private)) (phpinspect--make-variable :name "user" :type (phpinspect--make-type :name "\\App\\Entity\\App\\\\Entity\\\\User" :collection nil :contains nil :fully-qualified t) :scope '(:private)) (phpinspect--make-variable :name "extra" :type nil :scope '(:private)) (phpinspect--make-variable :name "token" :type (phpinspect--make-type :name "\\string" :collection nil :contains nil :fully-qualified t) :scope '(:private)))) (constants \, (list)) (extends \, (list)) (implements \, (list))))) (functions \, (list)))

@ -39,6 +39,11 @@
(insert-file-contents-literally (concat phpinspect-test-php-file-directory "/" name ".eld")) (insert-file-contents-literally (concat phpinspect-test-php-file-directory "/" name ".eld"))
(read (current-buffer)))) (read (current-buffer))))
(defun phpinspect-test-read-fixture-serialization (name)
(with-temp-buffer
(insert-file-contents-literally (concat phpinspect-test-php-file-directory "/" name ".eld"))
(eval (read (current-buffer)))))
(defun phpinspect-test-parse-fixture-code (name) (defun phpinspect-test-parse-fixture-code (name)
(phpinspect-parse-file (phpinspect-parse-file
(concat phpinspect-test-php-file-directory "/" name ".php"))) (concat phpinspect-test-php-file-directory "/" name ".php")))
@ -113,21 +118,19 @@
(phpinspect-test-read-fixture-data "IndexClass1")))) (phpinspect-test-read-fixture-data "IndexClass1"))))
(should (equal index expected-result)))) (should (equal index expected-result))))
(ert-deftest phpinspect-index-tokens () (ert-deftest phpinspect-index-tokens-class ()
(should (equal (let* ((index1
(phpinspect--index-tokens (phpinspect--index-tokens
(phpinspect-test-read-fixture-data "IndexClass1")) (phpinspect-test-read-fixture-data "IndexClass1")))
(phpinspect-test-read-fixture-data "IndexClass1-indexed")))) (index2
(phpinspect-test-read-fixture-serialization "IndexClass1-indexed"))
(ert-deftest phpinspect-merge-class-indexes () (index1-class (cdr (alist-get 'classes index1)))
(should (equal (index2-class (cdr (alist-get 'classes index2))))
(phpinspect--merge-indexes (dolist (key '(class-name imports methods static-methods static-variables variables constants extends implements))
(phpinspect-test-read-fixture-data "IndexClass1-indexed") (should (equal (alist-get key index1-class)
(phpinspect-test-read-fixture-data "IndexClass2-indexed")) (alist-get key index2-class))))))
(phpinspect-test-read-fixture-data
"class-index-1-2-undestructive-merge")))) (ert-deftest phpinspect-get-resolvecontext ()
(ert-deftest phpinspect--get-resolvecontext ()
(let ((resolvecontext (phpinspect--get-resolvecontext (let ((resolvecontext (phpinspect--get-resolvecontext
(phpinspect-test-read-fixture-data "IncompleteClass")))) (phpinspect-test-read-fixture-data "IncompleteClass"))))
@ -158,15 +161,25 @@
(type-resolver (phpinspect--make-type-resolver-for-resolvecontext (type-resolver (phpinspect--make-type-resolver-for-resolvecontext
resolvecontext))) resolvecontext)))
(should (string= "\\array" (funcall type-resolver "array"))) (should (phpinspect--type= (phpinspect--make-type :name "\\array")
(should (string= "\\array" (funcall type-resolver "\\array"))) (funcall type-resolver
(should (string= "\\Symfony\\Component\\HttpFoundation\\Response" (phpinspect--make-type :name "array"))))
(funcall type-resolver "Response"))) (should (phpinspect--type= (phpinspect--make-type :name "\\array")
(should (string= "\\Response" (funcall type-resolver "\\Response"))) (funcall type-resolver
(should (string= "\\App\\Controller\\GastonLagaffe" (phpinspect--make-type :name "\\array"))))
(funcall type-resolver "GastonLagaffe"))) (should (phpinspect--type= (phpinspect--make-type
(should (string= "\\App\\Controller\\Dupuis\\GastonLagaffe" :name "\\Symfony\\Component\\HttpFoundation\\Response")
(funcall type-resolver "Dupuis\\GastonLagaffe"))))) (funcall type-resolver (phpinspect--make-type :name "Response"))))
(should (phpinspect--type= (phpinspect--make-type :name "\\Response")
(funcall type-resolver
(phpinspect--make-type :name "\\Response"))))
(should (phpinspect--type= (phpinspect--make-type :name "\\App\\Controller\\GastonLagaffe")
(funcall type-resolver
(phpinspect--make-type :name "GastonLagaffe"))))
(should (phpinspect--type=
(phpinspect--make-type :name "\\App\\Controller\\Dupuis\\GastonLagaffe")
(funcall type-resolver
(phpinspect--make-type :name "Dupuis\\GastonLagaffe"))))))
(ert-deftest phpinspect-type-resolver-for-resolvecontext-namespace-block () (ert-deftest phpinspect-type-resolver-for-resolvecontext-namespace-block ()
(let* ((resolvecontext (phpinspect--get-resolvecontext (let* ((resolvecontext (phpinspect--get-resolvecontext
@ -175,15 +188,21 @@
(type-resolver (phpinspect--make-type-resolver-for-resolvecontext (type-resolver (phpinspect--make-type-resolver-for-resolvecontext
resolvecontext))) resolvecontext)))
(should (string= "\\array" (funcall type-resolver "array"))) (should (phpinspect--type= (phpinspect--make-type :name "\\array")
(should (string= "\\array" (funcall type-resolver "\\array"))) (funcall type-resolver (phpinspect--make-type :name "array"))))
(should (string= "\\Symfony\\Component\\HttpFoundation\\Response" (should (phpinspect--type= (phpinspect--make-type :name "\\array")
(funcall type-resolver "Response"))) (funcall type-resolver (phpinspect--make-type :name "\\array"))))
(should (string= "\\Response" (funcall type-resolver "\\Response"))) (should (phpinspect--type= (phpinspect--make-type
(should (string= "\\App\\Controller\\GastonLagaffe" :name "\\Symfony\\Component\\HttpFoundation\\Response")
(funcall type-resolver "GastonLagaffe"))) (funcall type-resolver (phpinspect--make-type :name "Response"))))
(should (string= "\\App\\Controller\\Dupuis\\GastonLagaffe" (should (phpinspect--type= (phpinspect--make-type :name "\\Response")
(funcall type-resolver "Dupuis\\GastonLagaffe"))))) (funcall type-resolver (phpinspect--make-type :name "\\Response"))))
(should (phpinspect--type= (phpinspect--make-type :name "\\App\\Controller\\GastonLagaffe")
(funcall type-resolver (phpinspect--make-type
:name "GastonLagaffe"))))
(should (phpinspect--type= (phpinspect--make-type
:name "\\App\\Controller\\Dupuis\\GastonLagaffe")
(funcall type-resolver (phpinspect--make-type :name "Dupuis\\GastonLagaffe"))))))
(ert-deftest phpinspect-type-resolver-for-resolvecontext-multiple-namespace-blocks () (ert-deftest phpinspect-type-resolver-for-resolvecontext-multiple-namespace-blocks ()
(let* ((resolvecontext (phpinspect--get-resolvecontext (let* ((resolvecontext (phpinspect--get-resolvecontext
@ -192,15 +211,24 @@
(type-resolver (phpinspect--make-type-resolver-for-resolvecontext (type-resolver (phpinspect--make-type-resolver-for-resolvecontext
resolvecontext))) resolvecontext)))
(should (string= "\\array" (funcall type-resolver "array"))) (should (phpinspect--type= (phpinspect--make-type :name "\\array")
(should (string= "\\array" (funcall type-resolver "\\array"))) (funcall type-resolver
(should (string= "\\Symfony\\Component\\HttpFoundation\\Response" (phpinspect--make-type :name "array"))))
(funcall type-resolver "Response"))) (should (phpinspect--type= (phpinspect--make-type :name "\\array")
(should (string= "\\Response" (funcall type-resolver "\\Response"))) (funcall type-resolver
(should (string= "\\App\\Controller\\GastonLagaffe" (phpinspect--make-type :name "\\array"))))
(funcall type-resolver "GastonLagaffe"))) (should (phpinspect--type= (phpinspect--make-type
(should (string= "\\App\\Controller\\Dupuis\\GastonLagaffe" :name "\\Symfony\\Component\\HttpFoundation\\Response")
(funcall type-resolver "Dupuis\\GastonLagaffe"))))) (funcall type-resolver (phpinspect--make-type :name "Response"))))
(should (phpinspect--type= (phpinspect--make-type :name "\\Response")
(funcall type-resolver
(phpinspect--make-type :name "\\Response"))))
(should (phpinspect--type= (phpinspect--make-type :name "\\App\\Controller\\GastonLagaffe")
(funcall type-resolver (phpinspect--make-type :name "GastonLagaffe"))))
(should (phpinspect--type= (phpinspect--make-type
:name "\\App\\Controller\\Dupuis\\GastonLagaffe")
(funcall type-resolver (phpinspect--make-type
:name "Dupuis\\GastonLagaffe"))))))
(ert-deftest phpinspect-index-static-methods () (ert-deftest phpinspect-index-static-methods ()
(let* ((class-tokens (let* ((class-tokens
@ -219,22 +247,28 @@
(index (phpinspect--index-tokens class-tokens)) (index (phpinspect--index-tokens class-tokens))
(expected-index (expected-index
`(phpinspect--root-index `(phpinspect--root-index
(imports)
(classes (classes
("\\Potato" phpinspect--class (,(phpinspect--make-type :name"\\Potato" :fully-qualified t)
phpinspect--indexed-class
(class-name . ,(phpinspect--make-type :name "\\Potato" :fully-qualified t))
(imports)
(methods) (methods)
(class-name . "\\Potato")
(static-methods . (,(phpinspect--make-function (static-methods . (,(phpinspect--make-function
:name "staticMethod" :name "staticMethod"
:scope '(:public) :scope '(:public)
:arguments '(("untyped" nil) :arguments `(("untyped" nil)
("things" "\\array")) ("things" ,(phpinspect--make-type :name "\\array"
:return-type nil))) :fully-qualified t)))
:return-type phpinspect--null-type)))
(static-variables) (static-variables)
(variables) (variables)
(constants) (constants)
(extends) (extends)
(implements))) (implements)))
(functions)))) (functions))))
;; (pp expected-index)
;; (pp index))
(should (equal expected-index index)))) (should (equal expected-index index))))
(ert-deftest phpinspect-resolve-type-from-context () (ert-deftest phpinspect-resolve-type-from-context ()
@ -256,7 +290,7 @@ class FluffBall
if ($ball) { if ($ball) {
if(isset($ball->fluff()->poof->upFluff->")) if(isset($ball->fluff()->poof->upFluff->"))
(fluffer " (fluffer (phpinspect-parse-string "
namespace Amazing; namespace Amazing;
use Vendor\\FluffLib\\Fluff; use Vendor\\FluffLib\\Fluff;
@ -266,8 +300,8 @@ class Fluffer
public function fluff(): Fluff public function fluff(): Fluff
{ {
} }
}") }"))
(vendor-fluff " (vendor-fluff (phpinspect-parse-string "
namespace Vendor\\FluffLib; namespace Vendor\\FluffLib;
class Fluff class Fluff
{ {
@ -275,8 +309,8 @@ class Fluff
* @var FlufferUpper * @var FlufferUpper
*/ */
public $poof; public $poof;
}") }"))
(vendor-fluffer-upper " (vendor-fluffer-upper (phpinspect-parse-string "
namespace Vendor\\FluffLib; namespace Vendor\\FluffLib;
class FlufferUpper class FlufferUpper
{ {
@ -285,33 +319,25 @@ class FlufferUpper
{ {
$this->upFluff = $upFluff; $this->upFluff = $upFluff;
} }
}") }"))
(phpinspect-project-root-function (lambda () "phpinspect-test")) (phpinspect-project-root-function (lambda () "phpinspect-test"))
(phpinspect-class-filepath-function
(lambda (fqn)
(pcase fqn
("\\Amazing\\Fluffer" "fluffer")
("\\Vendor\\FluffLib\\Fluff" "vendor-fluff")
("\\Vendor\\FluffLib\\FlufferUpper" "vendor-fluffer-upper")
(_ (ert-fail (format "Unexpected class FQN filepath was requested: %s" fqn))))))
(phpinspect-insert-file-contents-function
(lambda (filepath)
(pcase filepath
("fluffer" (insert fluffer))
("vendor-fluff" (insert vendor-fluff))
("vendor-fluffer-upper" (insert vendor-fluffer-upper))
(_ (ert-fail (format "Unexpected filepath was requested: %s" filepath))))))
(context (phpinspect--get-resolvecontext token-tree))) (context (phpinspect--get-resolvecontext token-tree)))
(phpinspect-purge-cache)
(phpinspect-cache-project-class
(phpinspect-project-root)
(cdar (alist-get 'classes (cdr (phpinspect--index-tokens token-tree)))))
(should (equal "\\Vendor\\FluffLib\\DoubleFluffer" (setf (phpinspect--resolvecontext-project-root context)
(phpinspect-resolve-type-from-context "phpinspect-test")
context
(phpinspect--make-type-resolver-for-resolvecontext (phpinspect-purge-cache)
context)))))) (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))))))
(should (phpinspect--type=
(phpinspect--make-type :name "\\Vendor\\FluffLib\\DoubleFluffer")
(phpinspect-resolve-type-from-context
context
(phpinspect--make-type-resolver-for-resolvecontext
context))))))
(ert-deftest phpinspect-eldoc-function-for-object-method () (ert-deftest phpinspect-eldoc-function-for-object-method ()
(let* ((php-code " (let* ((php-code "
@ -330,6 +356,7 @@ class Thing
(phpinspect-project-root-function (lambda () "phpinspect-test")) (phpinspect-project-root-function (lambda () "phpinspect-test"))
(phpinspect-eldoc-word-width 100)) (phpinspect-eldoc-word-width 100))
(phpinspect-purge-cache) (phpinspect-purge-cache)
(phpinspect--ensure-index-thread)
(phpinspect-cache-project-class (phpinspect-cache-project-class
(phpinspect-project-root) (phpinspect-project-root)
(cdar (alist-get 'classes (cdr index)))) (cdar (alist-get 'classes (cdr index))))
@ -356,6 +383,7 @@ class Thing
(phpinspect-project-root-function (lambda () "phpinspect-test")) (phpinspect-project-root-function (lambda () "phpinspect-test"))
(phpinspect-eldoc-word-width 100)) (phpinspect-eldoc-word-width 100))
(phpinspect-purge-cache) (phpinspect-purge-cache)
(phpinspect--ensure-index-thread)
(phpinspect-cache-project-class (phpinspect-cache-project-class
(phpinspect-project-root) (phpinspect-project-root)
(cdar (alist-get 'classes (cdr index)))) (cdar (alist-get 'classes (cdr index))))
@ -388,11 +416,11 @@ class Thing
(phpinspect-project-root) (phpinspect-project-root)
(cdar (alist-get 'classes (cdr index)))) (cdar (alist-get 'classes (cdr index))))
(should (string= "\\Thing" (should (phpinspect--type= (phpinspect--make-type :name "\\Thing")
(phpinspect-resolve-type-from-context (phpinspect-resolve-type-from-context
context context
(phpinspect--make-type-resolver-for-resolvecontext (phpinspect--make-type-resolver-for-resolvecontext
context)))))) context))))))
(ert-deftest phpinspect-resolve-type-from-context-static-method-with-preceding-words () (ert-deftest phpinspect-resolve-type-from-context-static-method-with-preceding-words ()
(let* ((php-code " (let* ((php-code "
@ -417,7 +445,7 @@ class Thing
(phpinspect-project-root) (phpinspect-project-root)
(cdar (alist-get 'classes (cdr index)))) (cdar (alist-get 'classes (cdr index))))
(should (string= "\\Thing" (should (phpinspect--type= (phpinspect--make-type :name "\\Thing")
(phpinspect-resolve-type-from-context (phpinspect-resolve-type-from-context
context context
(phpinspect--make-type-resolver-for-resolvecontext (phpinspect--make-type-resolver-for-resolvecontext

@ -1,5 +1,7 @@
(require 'phpinspect) (require 'phpinspect)
(require 'phpinspect-index)
(require 'phpinspect-serialize)
(let ((here (file-name-directory (let ((here (file-name-directory
(or load-file-name (or load-file-name
@ -20,5 +22,6 @@
(insert-file-contents-literally (concat here "/../fixtures/" class ".eld")) (insert-file-contents-literally (concat here "/../fixtures/" class ".eld"))
(read (current-buffer))))) (read (current-buffer)))))
(with-temp-buffer (with-temp-buffer
(insert (prin1-to-string (phpinspect--index-tokens index-class))) (insert (prin1-to-string (phpinspect--serialize-root-index
(phpinspect--index-tokens index-class))))
(write-file (concat here "/../fixtures/" class "-indexed.eld")))))) (write-file (concat here "/../fixtures/" class "-indexed.eld"))))))

Loading…
Cancel
Save