From 0bc9e795b2d37551268ccdc7ac021dd535bffc89 Mon Sep 17 00:00:00 2001 From: Hugo Thunnissen Date: Sun, 1 May 2022 02:40:51 +0200 Subject: [PATCH] Fix tests and patch bugs that came to light in the process --- phpinspect-class.el | 81 ++++++----- phpinspect-index.el | 2 +- phpinspect-serialize.el | 105 ++++++++++++++ phpinspect-type.el | 7 + phpinspect.el | 64 ++------- test/fixtures/IndexClass1-indexed.eld | 2 +- test/fixtures/IndexClass2-indexed.eld | 2 +- test/phpinspect-test.el | 192 +++++++++++++++----------- test/util/generate-test-data.el | 5 +- 9 files changed, 287 insertions(+), 173 deletions(-) create mode 100644 phpinspect-serialize.el diff --git a/phpinspect-class.el b/phpinspect-class.el index dba4045..c524ad1 100644 --- a/phpinspect-class.el +++ b/phpinspect-class.el @@ -106,28 +106,36 @@ (cl-defmethod phpinspect--class-get-static-method ((class phpinspect--class) method-name) (gethash method-name (phpinspect--class-static-methods class))) -(cl-defmethod phpinspect--class-set-method ((class phpinspect--class) - (method phpinspect--function)) - (phpinspect--log "Adding method by name %s to class" - (phpinspect--function-name method)) +(cl-defmethod phpinspect--add-method-copy-to-map + ((map hash-table) + (class-name phpinspect--type) + (method phpinspect--function)) (setq method (phpinspect--copy-function method)) - (when (phpinspect--type-does-late-static-binding - (phpinspect--function-return-type method)) + (setf (phpinspect--function-return-type method) + (phpinspect--resolve-late-static-binding + (phpinspect--function-return-type method) + class-name)) - (setf (phpinspect--function-return-type method) - (alist-get 'class-name (phpinspect--class-index class)))) + (puthash (phpinspect--function-name-symbol method) + method + map)) - (puthash (phpinspect--function-name-symbol method) - method - (phpinspect--class-methods class))) +(cl-defmethod phpinspect--class-set-method ((class phpinspect--class) + (method phpinspect--function)) + (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) (method phpinspect--function)) - (setq method (phpinspect--copy-function method)) - (puthash (phpinspect--function-name-symbol method) - method - (phpinspect--class-static-methods class))) + (phpinspect--add-method-copy-to-map + (phpinspect--class-static-methods class) + (alist-get 'class-name (phpinspect--class-index class)) + method)) (cl-defmethod phpinspect--class-get-method-return-type ((class phpinspect--class) (method-name symbol)) @@ -155,39 +163,38 @@ (phpinspect--class-static-methods class)) 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) (method phpinspect--function)) (let ((existing (gethash (phpinspect--function-name-symbol method) (phpinspect--class-static-methods class)))) (if existing - (progn - (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--merge-method + (alist-get 'class-name (phpinspect--class-index class)) + existing method) (phpinspect--class-set-static-method class method)))) (cl-defmethod phpinspect--class-update-method ((class phpinspect--class) (method phpinspect--function)) - (let ((existing (gethash (phpinspect--function-name-symbol method) + (let* ((existing (gethash (phpinspect--function-name-symbol method) (phpinspect--class-methods class)))) (if existing - (progn - (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--merge-method + (alist-get 'class-name (phpinspect--class-index class)) + existing method) (phpinspect--class-set-method class method)))) (cl-defmethod phpinspect--class-incorporate ((class phpinspect--class) diff --git a/phpinspect-index.el b/phpinspect-index.el index 4cb4b61..a955eb8 100644 --- a/phpinspect-index.el +++ b/phpinspect-index.el @@ -267,9 +267,9 @@ (let ((class-name (funcall type-resolver (phpinspect--make-type :name class-name)))) `(,class-name . (phpinspect--indexed-class + (class-name . ,class-name) (imports . ,imports) (methods . ,methods) - (class-name . ,class-name) (static-methods . ,static-methods) (static-variables . ,static-variables) (variables . ,variables) diff --git a/phpinspect-serialize.el b/phpinspect-serialize.el new file mode 100644 index 0000000..45d61b8 --- /dev/null +++ b/phpinspect-serialize.el @@ -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 +;; 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 . + +;;; 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 diff --git a/phpinspect-type.el b/phpinspect-type.el index 7f55d42..c197cea 100644 --- a/phpinspect-type.el +++ b/phpinspect-type.el @@ -84,6 +84,13 @@ 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--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) (catch 'found (dolist (native phpinspect-native-types) diff --git a/phpinspect.el b/phpinspect.el index 1a4482e..f1c7b9d 100644 --- a/phpinspect.el +++ b/phpinspect.el @@ -359,7 +359,9 @@ TODO: (phpinspect--resolvecontext-project-root resolvecontext)) type-of-previous-statement)) (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 type of previous statement: %s" type-of-previous-statement) @@ -418,20 +420,18 @@ TODO: (phpinspect--find-assignments-in-token block-or-list) assignments))))) ;; return - (phpinspect--log "Yayo Returning %s" assignments) - (phpinspect--log "Yayo had statements %s" statements) + (phpinspect--log "Found assignments in token: %s" assignments) + (phpinspect--log "Found statements in token: %s" statements) assignments)) (cl-defmethod phpinspect--find-assignments-in-token ((token (head :list))) "Find assignments that are in a list token." (phpinspect--log "looking for assignments in list %s" token) - (let ((ajaja (seq-filter - (lambda (statement) - (phpinspect--log "checking statement %s" statement) - (seq-find #'phpinspect-maybe-assignment-p statement)) - (phpinspect--split-list #'phpinspect-end-of-statement-p (cdr token))))) - (phpinspect--log "Found ajaja %s" ajaja) - ajaja)) + (seq-filter + (lambda (statement) + (phpinspect--log "checking statement %s" statement) + (seq-find #'phpinspect-maybe-assignment-p statement)) + (phpinspect--split-list #'phpinspect-end-of-statement-p (cdr token)))) (defsubst phpinspect-not-assignment-p (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))))) (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 ;; (:variable "variable") (:terminator ";") or (:string "string") (:terminator ";") ;; 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)) (string= (cadar last-assignment-value) "new")) (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)) (phpinspect--log "Variable was assigned with a derived statement") (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 ;; function argument and otherwise recurse to find the type of that variable. ((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 (phpinspect-get-variable-type-in-function-arg-list (cadar last-assignment-value) type-resolver @@ -852,44 +854,6 @@ level of a token. Nested variables are ignored." (defun phpinspect--buffer-index (buffer) (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) (not (phpinspect-variable-p token))) diff --git a/test/fixtures/IndexClass1-indexed.eld b/test/fixtures/IndexClass1-indexed.eld index 9e0aea2..53bcf3d 100644 --- a/test/fixtures/IndexClass1-indexed.eld +++ b/test/fixtures/IndexClass1-indexed.eld @@ -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)) \ No newline at end of file +`(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))) \ No newline at end of file diff --git a/test/fixtures/IndexClass2-indexed.eld b/test/fixtures/IndexClass2-indexed.eld index 18459ec..c6c276f 100644 --- a/test/fixtures/IndexClass2-indexed.eld +++ b/test/fixtures/IndexClass2-indexed.eld @@ -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)) \ No newline at end of file +`(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))) \ No newline at end of file diff --git a/test/phpinspect-test.el b/test/phpinspect-test.el index 3ae2e8c..ff76475 100644 --- a/test/phpinspect-test.el +++ b/test/phpinspect-test.el @@ -39,6 +39,11 @@ (insert-file-contents-literally (concat phpinspect-test-php-file-directory "/" name ".eld")) (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) (phpinspect-parse-file (concat phpinspect-test-php-file-directory "/" name ".php"))) @@ -113,21 +118,19 @@ (phpinspect-test-read-fixture-data "IndexClass1")))) (should (equal index expected-result)))) -(ert-deftest phpinspect-index-tokens () - (should (equal - (phpinspect--index-tokens - (phpinspect-test-read-fixture-data "IndexClass1")) - (phpinspect-test-read-fixture-data "IndexClass1-indexed")))) - -(ert-deftest phpinspect-merge-class-indexes () - (should (equal - (phpinspect--merge-indexes - (phpinspect-test-read-fixture-data "IndexClass1-indexed") - (phpinspect-test-read-fixture-data "IndexClass2-indexed")) - (phpinspect-test-read-fixture-data - "class-index-1-2-undestructive-merge")))) - -(ert-deftest phpinspect--get-resolvecontext () +(ert-deftest phpinspect-index-tokens-class () + (let* ((index1 + (phpinspect--index-tokens + (phpinspect-test-read-fixture-data "IndexClass1"))) + (index2 + (phpinspect-test-read-fixture-serialization "IndexClass1-indexed")) + (index1-class (cdr (alist-get 'classes index1))) + (index2-class (cdr (alist-get 'classes index2)))) + (dolist (key '(class-name imports methods static-methods static-variables variables constants extends implements)) + (should (equal (alist-get key index1-class) + (alist-get key index2-class)))))) + +(ert-deftest phpinspect-get-resolvecontext () (let ((resolvecontext (phpinspect--get-resolvecontext (phpinspect-test-read-fixture-data "IncompleteClass")))) @@ -158,15 +161,25 @@ (type-resolver (phpinspect--make-type-resolver-for-resolvecontext resolvecontext))) - (should (string= "\\array" (funcall type-resolver "array"))) - (should (string= "\\array" (funcall type-resolver "\\array"))) - (should (string= "\\Symfony\\Component\\HttpFoundation\\Response" - (funcall type-resolver "Response"))) - (should (string= "\\Response" (funcall type-resolver "\\Response"))) - (should (string= "\\App\\Controller\\GastonLagaffe" - (funcall type-resolver "GastonLagaffe"))) - (should (string= "\\App\\Controller\\Dupuis\\GastonLagaffe" - (funcall type-resolver "Dupuis\\GastonLagaffe"))))) + (should (phpinspect--type= (phpinspect--make-type :name "\\array") + (funcall type-resolver + (phpinspect--make-type :name "array")))) + (should (phpinspect--type= (phpinspect--make-type :name "\\array") + (funcall type-resolver + (phpinspect--make-type :name "\\array")))) + (should (phpinspect--type= (phpinspect--make-type + :name "\\Symfony\\Component\\HttpFoundation\\Response") + (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 () (let* ((resolvecontext (phpinspect--get-resolvecontext @@ -175,15 +188,21 @@ (type-resolver (phpinspect--make-type-resolver-for-resolvecontext resolvecontext))) - (should (string= "\\array" (funcall type-resolver "array"))) - (should (string= "\\array" (funcall type-resolver "\\array"))) - (should (string= "\\Symfony\\Component\\HttpFoundation\\Response" - (funcall type-resolver "Response"))) - (should (string= "\\Response" (funcall type-resolver "\\Response"))) - (should (string= "\\App\\Controller\\GastonLagaffe" - (funcall type-resolver "GastonLagaffe"))) - (should (string= "\\App\\Controller\\Dupuis\\GastonLagaffe" - (funcall type-resolver "Dupuis\\GastonLagaffe"))))) + (should (phpinspect--type= (phpinspect--make-type :name "\\array") + (funcall type-resolver (phpinspect--make-type :name "array")))) + (should (phpinspect--type= (phpinspect--make-type :name "\\array") + (funcall type-resolver (phpinspect--make-type :name "\\array")))) + (should (phpinspect--type= (phpinspect--make-type + :name "\\Symfony\\Component\\HttpFoundation\\Response") + (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-multiple-namespace-blocks () (let* ((resolvecontext (phpinspect--get-resolvecontext @@ -192,15 +211,24 @@ (type-resolver (phpinspect--make-type-resolver-for-resolvecontext resolvecontext))) - (should (string= "\\array" (funcall type-resolver "array"))) - (should (string= "\\array" (funcall type-resolver "\\array"))) - (should (string= "\\Symfony\\Component\\HttpFoundation\\Response" - (funcall type-resolver "Response"))) - (should (string= "\\Response" (funcall type-resolver "\\Response"))) - (should (string= "\\App\\Controller\\GastonLagaffe" - (funcall type-resolver "GastonLagaffe"))) - (should (string= "\\App\\Controller\\Dupuis\\GastonLagaffe" - (funcall type-resolver "Dupuis\\GastonLagaffe"))))) + (should (phpinspect--type= (phpinspect--make-type :name "\\array") + (funcall type-resolver + (phpinspect--make-type :name "array")))) + (should (phpinspect--type= (phpinspect--make-type :name "\\array") + (funcall type-resolver + (phpinspect--make-type :name "\\array")))) + (should (phpinspect--type= (phpinspect--make-type + :name "\\Symfony\\Component\\HttpFoundation\\Response") + (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 () (let* ((class-tokens @@ -219,22 +247,28 @@ (index (phpinspect--index-tokens class-tokens)) (expected-index `(phpinspect--root-index + (imports) (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) - (class-name . "\\Potato") (static-methods . (,(phpinspect--make-function :name "staticMethod" :scope '(:public) - :arguments '(("untyped" nil) - ("things" "\\array")) - :return-type nil))) + :arguments `(("untyped" nil) + ("things" ,(phpinspect--make-type :name "\\array" + :fully-qualified t))) + :return-type phpinspect--null-type))) (static-variables) (variables) (constants) (extends) (implements))) (functions)))) + ;; (pp expected-index) + ;; (pp index)) (should (equal expected-index index)))) (ert-deftest phpinspect-resolve-type-from-context () @@ -256,7 +290,7 @@ class FluffBall if ($ball) { if(isset($ball->fluff()->poof->upFluff->")) - (fluffer " + (fluffer (phpinspect-parse-string " namespace Amazing; use Vendor\\FluffLib\\Fluff; @@ -266,8 +300,8 @@ class Fluffer public function fluff(): Fluff { } -}") - (vendor-fluff " +}")) + (vendor-fluff (phpinspect-parse-string " namespace Vendor\\FluffLib; class Fluff { @@ -275,8 +309,8 @@ class Fluff * @var FlufferUpper */ public $poof; -}") - (vendor-fluffer-upper " +}")) + (vendor-fluffer-upper (phpinspect-parse-string " namespace Vendor\\FluffLib; class FlufferUpper { @@ -285,33 +319,25 @@ class FlufferUpper { $this->upFluff = $upFluff; } -}") +}")) (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))) - (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" - (phpinspect-resolve-type-from-context - context - (phpinspect--make-type-resolver-for-resolvecontext - context)))))) + (setf (phpinspect--resolvecontext-project-root context) + "phpinspect-test") + + (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)))))) + + (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 () (let* ((php-code " @@ -330,6 +356,7 @@ class Thing (phpinspect-project-root-function (lambda () "phpinspect-test")) (phpinspect-eldoc-word-width 100)) (phpinspect-purge-cache) + (phpinspect--ensure-index-thread) (phpinspect-cache-project-class (phpinspect-project-root) (cdar (alist-get 'classes (cdr index)))) @@ -356,6 +383,7 @@ class Thing (phpinspect-project-root-function (lambda () "phpinspect-test")) (phpinspect-eldoc-word-width 100)) (phpinspect-purge-cache) + (phpinspect--ensure-index-thread) (phpinspect-cache-project-class (phpinspect-project-root) (cdar (alist-get 'classes (cdr index)))) @@ -388,11 +416,11 @@ class Thing (phpinspect-project-root) (cdar (alist-get 'classes (cdr index)))) - (should (string= "\\Thing" - (phpinspect-resolve-type-from-context - context - (phpinspect--make-type-resolver-for-resolvecontext - context)))))) + (should (phpinspect--type= (phpinspect--make-type :name "\\Thing") + (phpinspect-resolve-type-from-context + context + (phpinspect--make-type-resolver-for-resolvecontext + context)))))) (ert-deftest phpinspect-resolve-type-from-context-static-method-with-preceding-words () (let* ((php-code " @@ -417,7 +445,7 @@ class Thing (phpinspect-project-root) (cdar (alist-get 'classes (cdr index)))) - (should (string= "\\Thing" + (should (phpinspect--type= (phpinspect--make-type :name "\\Thing") (phpinspect-resolve-type-from-context context (phpinspect--make-type-resolver-for-resolvecontext diff --git a/test/util/generate-test-data.el b/test/util/generate-test-data.el index 4da4404..26d3593 100644 --- a/test/util/generate-test-data.el +++ b/test/util/generate-test-data.el @@ -1,5 +1,7 @@ (require 'phpinspect) +(require 'phpinspect-index) +(require 'phpinspect-serialize) (let ((here (file-name-directory (or load-file-name @@ -20,5 +22,6 @@ (insert-file-contents-literally (concat here "/../fixtures/" class ".eld")) (read (current-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"))))))