From 68c826243c1c358a24e82df1fef148671b6c40fe Mon Sep 17 00:00:00 2001 From: Hugo Thunnissen Date: Mon, 14 Aug 2023 09:48:16 +0200 Subject: [PATCH] Keep index synchronized with buffer state --- benchmarks/splay-tree.el | 21 +- phpinspect-bmap.el | 54 ++- phpinspect-buffer.el | 355 +++++++++++++++++- phpinspect-cache.el | 28 +- phpinspect-class.el | 130 +++++-- phpinspect-completion.el | 2 + phpinspect-eldoc.el | 4 +- phpinspect-imports.el | 7 +- phpinspect-index.el | 104 ++--- phpinspect-meta.el | 56 ++- phpinspect-parse-context.el | 1 + phpinspect-parser.el | 247 ++---------- phpinspect-project.el | 21 +- phpinspect-serialize.el | 4 +- phpinspect-splayt.el | 120 ++++-- phpinspect-toc.el | 82 ++++ phpinspect-token-predicates.el | 250 ++++++++++++ phpinspect-type.el | 9 + phpinspect-util.el | 11 + phpinspect-worker.el | 2 +- phpinspect.el | 18 - test/fixtures/IncompleteClass.eld | 2 +- .../IncompleteClassBlockedNamespace.eld | 2 +- .../IncompleteClassMultipleNamespaces.eld | 2 +- test/fixtures/IndexClass1-indexed.eld | 2 +- test/fixtures/IndexClass1.eld | 2 +- test/fixtures/IndexClass2-indexed.eld | 2 +- test/fixtures/IndexClass2.eld | 2 +- test/fixtures/NamespacedClass.eld | 2 +- test/phpinspect-test-env.el | 41 ++ test/phpinspect-test.el | 38 +- test/test-buffer.el | 186 ++++++++- test/test-class.el | 69 ++++ test/test-edtrack.el | 2 + test/test-index.el | 9 + test/test-meta.el | 67 ++++ test/test-splayt.el | 9 + test/test-toc.el | 50 +++ 38 files changed, 1548 insertions(+), 465 deletions(-) create mode 100644 phpinspect-toc.el create mode 100644 phpinspect-token-predicates.el create mode 100644 test/phpinspect-test-env.el create mode 100644 test/test-meta.el create mode 100644 test/test-toc.el diff --git a/benchmarks/splay-tree.el b/benchmarks/splay-tree.el index 261ddfe..26ba88b 100644 --- a/benchmarks/splay-tree.el +++ b/benchmarks/splay-tree.el @@ -14,7 +14,19 @@ (garbage-collect) (benchmark 1 '(dotimes (i 10000) - (phpinspect-splayt-find tree i)))) + (phpinspect-splayt-find tree i))) + + (message "Splay tree 10000 items traversal:") + (garbage-collect) + (benchmark + 1 '(phpinspect-splayt-traverse (i tree) + nil)) + + (message "Splay tree 10000 items LR traversal:") + (garbage-collect) + (benchmark + 1 '(phpinspect-splayt-traverse-lr (i tree) + nil))) (let (map) @@ -30,4 +42,9 @@ (garbage-collect) (benchmark 1 '(dotimes (i 10000) - (gethash i map)))) + (gethash i map))) + + (message "Hashtable 10000 iterations:") + (garbage-collect) + (benchmark + 1 '(maphash (lambda (k v) nil) map))) diff --git a/phpinspect-bmap.el b/phpinspect-bmap.el index 0fded42..a2ad9ec 100644 --- a/phpinspect-bmap.el +++ b/phpinspect-bmap.el @@ -28,6 +28,7 @@ (require 'phpinspect-changeset) (require 'phpinspect-util) (require 'compat) +(require 'phpinspect-token-predicates) (eval-when-compile (defvar phpinspect-parse-context nil @@ -39,18 +40,36 @@ (cl-defstruct (phpinspect-bmap (:constructor phpinspect-make-bmap)) (starts (make-hash-table :test #'eql - :size (floor (/ (point-max) 4)) + :size (floor (/ (point-max) 2)) :rehash-size 1.5)) (ends (make-hash-table :test #'eql - :size (floor (/ (point-max) 4)) + :size (floor (/ (point-max) 2)) :rehash-size 1.5)) (meta (make-hash-table :test #'eq - :size (floor (/ (point-max) 4)) + :size (floor (/ (point-max) 2)) :rehash-size 1.5)) (token-stack nil :type list) (overlays (phpinspect-make-splayt) :type phpinspect-splayt) + (declarations (phpinspect-make-splayt) + :type phpinspect-splayt + :documentation "The declaration tokens encountered.") + (imports (phpinspect-make-splayt) + :type phpinspect-splayt + :documentation "The import statements encountered.") + (functions (phpinspect-make-splayt) + :type phpinspect-splayt + :documentation "The function definitions encountered.") + (classes (phpinspect-make-splayt) + :type phpinspect-splayt + :documentation "The classes encountered.") + (class-variables (phpinspect-make-splayt) + :type phpinspect-splayt + :documentation "The class attribute variables encountered") + (namespaces (phpinspect-make-splayt) + :type phpinspect-splayt + :documentation "The namespaces encountered") (-root-meta nil :type phpinspect-meta) (last-token-start nil @@ -158,7 +177,28 @@ (puthash start token-meta starts) - (if existing-end + (cond + ((phpinspect-use-p (phpinspect-meta-token token-meta)) + (phpinspect-splayt-insert + (phpinspect-bmap-imports bmap) (phpinspect-meta-start token-meta) token-meta)) + ((phpinspect-class-p (phpinspect-meta-token token-meta)) + (phpinspect-splayt-insert + (phpinspect-bmap-classes bmap) (phpinspect-meta-start token-meta) token-meta)) + ((phpinspect-declaration-p (phpinspect-meta-token token-meta)) + (phpinspect-splayt-insert + (phpinspect-bmap-declarations bmap) (phpinspect-meta-start token-meta) token-meta)) + ((phpinspect-function-p (phpinspect-meta-token token-meta)) + (phpinspect-splayt-insert + (phpinspect-bmap-functions bmap) (phpinspect-meta-start token-meta) token-meta)) + ((phpinspect-namespace-p (phpinspect-meta-token token-meta)) + (phpinspect-splayt-insert + (phpinspect-bmap-namespaces bmap) (phpinspect-meta-start token-meta) token-meta)) + ((or (phpinspect-const-p (phpinspect-meta-token token-meta)) + (phpinspect-class-variable-p (phpinspect-meta-token token-meta))) + (phpinspect-splayt-insert + (phpinspect-bmap-class-variables bmap) (phpinspect-meta-start token-meta) token-meta))) + + (if existing-end (push token existing-end) (puthash end (list token-meta) ends)) @@ -222,10 +262,6 @@ (cl-defmethod phpinspect-bmap-token-meta ((overlay (head overlay)) token) (phpinspect-bmap-token-meta (phpinspect-overlay-bmap overlay) token)) -(defsubst phpinspect-probably-token-p (token) - (and (listp token) - (keywordp (car token)))) - (cl-defmethod phpinspect-bmap-token-meta ((bmap phpinspect-bmap) token) (unless (phpinspect-probably-token-p token) (error "Unexpected argument, expected `phpinspect-token-p'. Got invalid token %s" token)) @@ -248,7 +284,7 @@ (let* ((overlays (phpinspect-bmap-overlays bmap)) (start (+ (phpinspect-meta-start token-meta) pos-delta)) (end (+ (phpinspect-meta-end token-meta) pos-delta)) - (overlay) + overlay (last-overlay (phpinspect-splayt-node-value (phpinspect-splayt-root-node overlays)))) (phpinspect-meta-with-changeset token-meta diff --git a/phpinspect-buffer.el b/phpinspect-buffer.el index 7a46fd9..905aed2 100644 --- a/phpinspect-buffer.el +++ b/phpinspect-buffer.el @@ -27,6 +27,10 @@ (require 'phpinspect-bmap) (require 'phpinspect-edtrack) (require 'phpinspect-index) +(require 'phpinspect-toc) +(require 'phpinspect-resolvecontext) +(require 'phpinspect-resolve) +(require 'phpinspect-util) (defvar-local phpinspect-current-buffer nil "An instance of `phpinspect-buffer' local to the active @@ -44,12 +48,26 @@ emacs buffer." "Parsed token tree that resulted from last parse") (map nil :type phpinspect-bmap) + (-last-indexed-bmap nil) + (imports nil + :type phpinspect-toc) + (namespaces nil + :type phpinspect-toc) + (classes nil + :type phpinspect-toc) + (class-variables nil + :type phpinspect-toc) + (declarations nil + :type phpinspect-toc) + (functions nil + :type phpinspect-toc) + (token-index (make-hash-table :test 'eq :size 100 :rehash-size 1.5)) (project nil :type phpinspect-project) (edit-tracker (phpinspect-make-edtrack) :type phpinspect-edtrack)) -(cl-defmethod phpinspect-buffer-parse ((buffer phpinspect-buffer) &optional no-interrupt no-index) +(cl-defmethod phpinspect-buffer-parse ((buffer phpinspect-buffer) &optional no-interrupt) "Parse the PHP code in the the emacs buffer that this object is linked with." (let ((tree)) @@ -72,27 +90,331 @@ linked with." (phpinspect-edtrack-clear (phpinspect-buffer-edit-tracker buffer)) ;; set return value - (setq tree parsed) - - (unless (or no-index - (not (phpinspect-buffer-project buffer))) - (phpinspect--log "Adding buffer index to project") - (phpinspect-project-add-index - (phpinspect-buffer-project buffer) - (phpinspect--index-tokens tree nil (phpinspect-buffer-location-resolver buffer)) - 'index-imports)))))) + (setq tree parsed))))) ;; Else: Just return last parse result (setq tree (phpinspect-buffer-tree buffer))) - tree)) + +(cl-defmethod phpinspect-buffer-get-index-for-token ((buffer phpinspect-buffer) token) + (gethash token (phpinspect-buffer-token-index buffer))) + +(cl-defmethod phpinspect-buffer-set-index-reference-for-token ((buffer phpinspect-buffer) token index) + (unless (phpinspect-probably-token-p token) + (error "%s does not seem to be a token" token)) + (puthash token index (phpinspect-buffer-token-index buffer))) + +(cl-defmethod phpinspect-buffer-update-index-reference-for-token ((buffer phpinspect-buffer) old new) + (unless (and (phpinspect-probably-token-p old) (phpinspect-probably-token-p new)) + (when (and old new) + (error "old and new parameters should be tokens"))) + + (when-let ((index (gethash old (phpinspect-buffer-token-index buffer)))) + (remhash old (phpinspect-buffer-token-index buffer)) + (puthash new index (phpinspect-buffer-token-index buffer)))) + +(cl-defmethod phpinspect-buffer-delete-index-for-token ((buffer phpinspect-buffer) token) + (unless (phpinspect-probably-token-p token) + (error "%s does not seem to be a token" token)) + + (cond ((phpinspect-class-p token) + (when-let ((class (gethash token (phpinspect-buffer-token-index buffer)))) + (remhash token (phpinspect-buffer-token-index buffer)) + (phpinspect-project-delete-class (phpinspect-buffer-project buffer) class))) + ((or (phpinspect-const-p token) (phpinspect-variable-p token)) + (when-let ((var (gethash token (phpinspect-buffer-token-index buffer)))) + (remhash token (phpinspect-buffer-token-index buffer)) + (when-let ((class (phpinspect-project-get-class + (phpinspect-buffer-project buffer) + (car var)))) + (phpinspect--class-delete-variable class (cdr var))))) + ((phpinspect-function-p token) + (when-let ((func (gethash token (phpinspect-buffer-token-index buffer)))) + (remhash token (phpinspect-buffer-token-index buffer)) + (cond ((phpinspect-project-p (car func)) + (phpinspect-project-delete-function (phpinspect-buffer-project buffer) (phpinspect--function-name-symbol (cdr func)))) + ((phpinspect--type-p (car func)) + (when-let ((class (phpinspect-project-get-class + (phpinspect-buffer-project buffer) + (car func)))) + (phpinspect--class-delete-method class (cdr func)))) + (t (error "Invalid index location"))))) + (t (error "Cannot delete index for token %s" token)))) + +(cl-defmethod phpinspect-buffer-namespace-at-point ((buffer phpinspect-buffer) (point integer)) + (let ((namespace (phpinspect-splayt-find-largest-before + (phpinspect-toc-tree (phpinspect-buffer-namespaces buffer)) + point))) + (and namespace (phpinspect-meta-overlaps-point namespace point) namespace))) + +(cl-defmethod phpinspect-buffer-index-imports ((buffer phpinspect-buffer) (imports (head phpinspect-splayt))) + (let (to-be-indexed) + (if (phpinspect-buffer-imports buffer) + (pcase-let* ((`(,new) (phpinspect-toc-update + (phpinspect-buffer-imports buffer) imports (phpinspect-buffer-root-meta buffer)))) + (setq to-be-indexed new)) + (setq to-be-indexed (phpinspect-splayt-to-list imports)) + (setf (phpinspect-buffer-imports buffer) (phpinspect-make-toc imports))) + + (phpinspect-project-enqueue-imports + (phpinspect-buffer-project buffer) + (phpinspect--uses-to-types (mapcar #'phpinspect-meta-token to-be-indexed))))) + +(cl-defmethod phpinspect-buffer-index-namespaces ((buffer phpinspect-buffer) (namespaces (head phpinspect-splayt))) + (if (phpinspect-buffer-namespaces buffer) + (phpinspect-toc-update (phpinspect-buffer-namespaces buffer) namespaces (phpinspect-buffer-root-meta buffer)) + (setf (phpinspect-buffer-namespaces buffer) (phpinspect-make-toc namespaces)))) + +(cl-defmethod phpinspect-buffer-index-declarations ((buffer phpinspect-buffer) (declarations (head phpinspect-splayt))) + (if (phpinspect-buffer-declarations buffer) + (phpinspect-toc-update (phpinspect-buffer-declarations buffer) declarations (phpinspect-buffer-root-meta buffer)) + (setf (phpinspect-buffer-declarations buffer) (phpinspect-make-toc declarations)))) + +(defun phpinspect-get-token-index-context (namespaces all-imports meta) + (let ((namespace (phpinspect-toc-token-at-point namespaces (phpinspect-meta-start meta))) + namespace-name imports) + (if namespace + (progn + (setq namespace-name (phpinspect-namespace-name (phpinspect-meta-token namespace)) + imports (mapcar #'phpinspect-meta-token + (phpinspect-toc-tokens-in-region + all-imports (phpinspect-meta-start namespace) (phpinspect-meta-start meta))))) + (setq namespace-name nil + imports (mapcar #'phpinspect-meta-token + (phpinspect-toc-tokens-in-region + all-imports 0 (phpinspect-meta-start meta))))) + + (list imports namespace-name))) + +(cl-defmethod phpinspect-buffer-index-classes ((buffer phpinspect-buffer) (classes (head phpinspect-splayt))) + (let ((declarations (phpinspect-buffer-declarations buffer)) + (namespaces (phpinspect-buffer-namespaces buffer)) + (buffer-imports (phpinspect-buffer-imports buffer)) + (project (phpinspect-buffer-project buffer))) + (if (phpinspect-buffer-classes buffer) + (pcase-let* ((`(,new-classes ,deleted-classes) (phpinspect-toc-update + (phpinspect-buffer-classes buffer) + classes (phpinspect-buffer-root-meta buffer))) + (new-declarations) (declaration) (replaced) (indexed) (class)) + (dolist (class new-classes) + (when (setq declaration (phpinspect-toc-token-at-or-after-point declarations (phpinspect-meta-start class))) + (push (cons (phpinspect-meta-token declaration) class) new-declarations))) + + (dolist (deleted deleted-classes) + (if (and (setq class (phpinspect-buffer-get-index-for-token + buffer (phpinspect-meta-token deleted))) + (setq replaced (assoc (phpinspect--class-declaration class) new-declarations #'equal))) + (pcase-let ((`(,imports ,namespace-name) (phpinspect-get-token-index-context namespaces buffer-imports (cdr replaced)))) + (phpinspect-buffer-update-index-reference-for-token + buffer (phpinspect-meta-token deleted) (phpinspect-meta-token (cdr replaced))) + (phpinspect--class-update-declaration class (car replaced) imports namespace-name) + (push (cdr replaced) indexed)) + (phpinspect-buffer-delete-index-for-token buffer (phpinspect-meta-token deleted)))) + + (dolist (class new-declarations) + (unless (memq (cdr class) indexed) + (pcase-let* ((`(,imports ,namespace-name) (phpinspect-get-token-index-context namespaces buffer-imports (cdr class))) + (`(,class-name) (phpinspect--index-class-declaration + (car class) + (phpinspect--make-type-resolver + (phpinspect--uses-to-types imports) + (phpinspect-class-block (phpinspect-meta-token (cdr class))) + namespace-name))) + (class-obj (phpinspect-project-get-class-create project class-name 'no-enqueue))) + (phpinspect-buffer-set-index-reference-for-token buffer (phpinspect-meta-token (cdr class)) class-obj) + (phpinspect--class-update-declaration class-obj (car class) imports namespace-name))))) + ;; Else: Index all classes + (setf (phpinspect-buffer-classes buffer) (phpinspect-make-toc classes)) + (phpinspect-splayt-traverse (class classes) + (pcase-let* ((declaration (phpinspect-toc-token-at-or-after-point declarations (phpinspect-meta-start class))) + (`(,imports ,namespace-name) (phpinspect-get-token-index-context namespaces buffer-imports class)) + (`(,class-name) (phpinspect--index-class-declaration + (phpinspect-meta-token declaration) + (phpinspect--make-type-resolver + (phpinspect--uses-to-types imports) + (phpinspect-class-block (phpinspect-meta-token class)) + namespace-name))) + (class-obj (phpinspect-project-get-class-create project class-name 'no-enqueue))) + (phpinspect-buffer-set-index-reference-for-token buffer (phpinspect-meta-token class) class-obj) + (phpinspect--class-update-declaration class-obj (phpinspect-meta-token declaration) imports namespace-name)))))) + +(cl-defmethod phpinspect-buffer-index-functions ((buffer phpinspect-buffer) (functions (head phpinspect-splayt))) + (let ((classes (phpinspect-buffer-classes buffer)) + (namespaces (phpinspect-buffer-namespaces buffer)) + (imports (phpinspect-buffer-imports buffer)) + to-be-indexed class-environments class indexed) + (if (phpinspect-buffer-functions buffer) + (pcase-let ((`(,new-funcs ,deleted-funcs) + (phpinspect-toc-update (phpinspect-buffer-functions buffer) functions (phpinspect-buffer-root-meta buffer)))) + (setq to-be-indexed new-funcs) + + (dolist (deleted deleted-funcs) + (phpinspect-buffer-delete-index-for-token buffer (phpinspect-meta-token deleted)))) + (setq to-be-indexed (phpinspect-splayt-to-list functions)) + (setf (phpinspect-buffer-functions buffer) (phpinspect-make-toc functions))) + + (dolist (func to-be-indexed) + (if (setq class (phpinspect-toc-token-at-point classes (phpinspect-meta-start func))) + (let (scope static indexed index-env comment-before) + (if (phpinspect-static-p (phpinspect-meta-token (phpinspect-meta-parent func))) + (progn + (setq static (phpinspect-meta-parent func)) + (when (phpinspect-scope-p (phpinspect-meta-token (phpinspect-meta-parent static))) + (setq scope `(,(car (phpinspect-meta-token (phpinspect-meta-parent static))) + ,(phpinspect-meta-token func)) + comment-before (phpinspect-meta-find-left-sibling (phpinspect-meta-parent static))))) + (when (phpinspect-scope-p (phpinspect-meta-token (phpinspect-meta-parent func))) + (setq scope (phpinspect-meta-token (phpinspect-meta-parent func)) + comment-before (phpinspect-meta-find-left-sibling (phpinspect-meta-parent func))))) + + (unless scope (setq scope `(:public ,(phpinspect-meta-token func)))) + + (unless (setq index-env (alist-get class class-environments nil nil #'eq)) + (setq index-env (phpinspect-get-token-index-context namespaces imports class)) + (setcar index-env (phpinspect--uses-to-types (car index-env))) + (push (phpinspect--make-type-resolver (car index-env) (phpinspect-meta-token class) (cadr index-env)) + index-env) + (push (cons class index-env) class-environments)) + + (unless comment-before + (setq comment-before (phpinspect-meta-find-left-sibling func))) + + (setq comment-before (phpinspect-meta-token comment-before)) + + (pcase-let ((`(,type-resolver) index-env) + (class-obj (phpinspect-buffer-get-index-for-token buffer (phpinspect-meta-token class)))) + (unless class-obj (error "Unable to find class obj for class %s" (phpinspect-meta-token class))) + + (setq indexed (phpinspect--index-function-from-scope + type-resolver + scope + (and (phpinspect-comment-p comment-before) comment-before))) + (if static + (phpinspect--class-set-static-method class-obj indexed) + (phpinspect--class-set-method class-obj indexed)) + + (phpinspect-buffer-set-index-reference-for-token + buffer (phpinspect-meta-token func) + (cons (phpinspect--class-name class-obj) indexed)))) + ;; Else: index function + (pcase-let ((`(,imports ,namespace-name) (phpinspect-get-token-index-context namespaces imports func)) + (comment-before (phpinspect-meta-find-left-sibling func))) + (setq indexed (phpinspect--index-function-from-scope + (phpinspect--make-type-resolver + (phpinspect--uses-to-types imports) nil namespace-name) + `(:public ,(phpinspect-meta-token func)) + (and (phpinspect-comment-p comment-before) comment-before) + nil namespace-name)) + (phpinspect-project-set-function (phpinspect-buffer-project buffer) indexed) + (phpinspect-buffer-set-index-reference-for-token + buffer (phpinspect-meta-token func) + (cons (phpinspect-buffer-project buffer) indexed))))))) + + +(cl-defmethod phpinspect-buffer-index-class-variables ((buffer phpinspect-buffer) (class-variables (head phpinspect-splayt))) + (let ((classes (phpinspect-buffer-classes buffer)) + (namespaces (phpinspect-buffer-namespaces buffer)) + (imports (phpinspect-buffer-imports buffer)) + to-be-indexed class-environments class class-obj) + (if (phpinspect-buffer-class-variables buffer) + (pcase-let ((`(,new-vars ,deleted-vars) + (phpinspect-toc-update + (phpinspect-buffer-class-variables buffer) class-variables (phpinspect-buffer-root-meta buffer)))) + (setq to-be-indexed new-vars) + + (dolist (deleted deleted-vars) + (phpinspect-buffer-delete-index-for-token buffer (phpinspect-meta-token deleted)))) + + (setq to-be-indexed (phpinspect-splayt-to-list class-variables)) + (setf (phpinspect-buffer-class-variables buffer) (phpinspect-make-toc class-variables))) + + (dolist (var to-be-indexed) + (when (and class (> (phpinspect-meta-start var) (phpinspect-meta-end class))) + (setq class nil)) + + (unless class + (setq class (phpinspect-toc-token-at-point classes (phpinspect-meta-start var)))) + + (setq class-obj (phpinspect-buffer-get-index-for-token buffer (phpinspect-meta-token class))) + + (let (scope static indexed index-env comment-before) + (if (phpinspect-static-p (phpinspect-meta-token (phpinspect-meta-parent var))) + (progn + (setq static (phpinspect-meta-parent var)) + (when (phpinspect-scope-p (phpinspect-meta-token (phpinspect-meta-parent static))) + (setq scope `(,(car (phpinspect-meta-token (phpinspect-meta-parent static))) + ,(phpinspect-meta-token var)) + comment-before (phpinspect-meta-find-left-sibling (phpinspect-meta-parent static))))) + (when (phpinspect-scope-p (phpinspect-meta-token (phpinspect-meta-parent var))) + (setq scope (phpinspect-meta-token (phpinspect-meta-parent var)) + comment-before (phpinspect-meta-find-left-sibling (phpinspect-meta-parent var))))) + + (unless scope (setq scope `(:public ,(phpinspect-meta-token var)))) + + (unless (setq index-env (alist-get class class-environments nil nil #'eq)) + (setq index-env (phpinspect-get-token-index-context namespaces imports class)) + (push (cons class index-env) class-environments)) + + (unless comment-before + (setq comment-before (phpinspect-meta-find-left-sibling var))) + + (setq comment-before (phpinspect-meta-token comment-before)) + + (pcase-let* ((`(,imports ,namespace-name) index-env) + (type-resolver + (phpinspect--make-type-resolver + (phpinspect--uses-to-types imports) + (phpinspect-meta-token class) + namespace-name))) + + (setq indexed + (if (phpinspect-const-p (phpinspect-meta-token var)) + (phpinspect--index-const-from-scope scope) + (phpinspect--index-variable-from-scope + type-resolver + scope + (and (phpinspect-comment-p comment-before) comment-before) + static))) + + (when (and (phpinspect-variable-p (phpinspect-meta-token var)) (not (phpinspect--variable-type indexed))) + (when-let* ((constructor (phpinspect--class-get-method class-obj (phpinspect-intern-name "__construct"))) + (rctx (phpinspect--make-resolvecontext :enclosing-tokens (list (phpinspect-meta-token class)) + :enclosing-metadata (list class)))) + (setf (phpinspect--variable-type indexed) + (phpinspect-get-pattern-type-in-block + rctx (phpinspect--make-pattern :m `(:variable "this") :m `(:object-attrib (:word ,(cadr var)))) + (phpinspect-function-block (phpinspect--function-token constructor)) + type-resolver + (phpinspect-function-argument-list (phpinspect--function-token constructor)))))) + + + (phpinspect--class-set-variable class-obj indexed) + + (phpinspect-buffer-set-index-reference-for-token + buffer (phpinspect-meta-token var) + (cons (phpinspect--class-name class-obj) indexed))))))) + (cl-defmethod phpinspect-buffer-reparse ((buffer phpinspect-buffer)) (setf (phpinspect-buffer-tree buffer) nil) (setf (phpinspect-buffer-map buffer) (phpinspect-make-bmap)) + (setf (phpinspect-buffer-declarations buffer) nil) + (setf (phpinspect-buffer-imports buffer) nil) (phpinspect-edtrack-clear (phpinspect-buffer-edit-tracker buffer)) (phpinspect-buffer-parse buffer 'no-interrupt)) +(cl-defmethod phpinspect-buffer-update-project-index ((buffer phpinspect-buffer)) + (when (phpinspect-buffer-project buffer) + (let ((map (phpinspect-buffer-map buffer))) + (unless (eq map (phpinspect-buffer--last-indexed-bmap buffer)) + (phpinspect-buffer-index-imports buffer (phpinspect-bmap-imports map)) + (phpinspect-buffer-index-declarations buffer (phpinspect-bmap-declarations map)) + (phpinspect-buffer-index-namespaces buffer (phpinspect-bmap-namespaces map)) + (phpinspect-buffer-index-classes buffer (phpinspect-bmap-classes map)) + (phpinspect-buffer-index-functions buffer (phpinspect-bmap-functions map)) + (phpinspect-buffer-index-class-variables buffer (phpinspect-bmap-class-variables map)) + (setf (phpinspect-buffer--last-indexed-bmap buffer) map))))) + (defsubst phpinspect-buffer-parse-map (buffer) (phpinspect-buffer-parse buffer) (phpinspect-buffer-map buffer)) @@ -134,14 +456,6 @@ use." (cl-defmethod phpinspect-buffer-root-meta ((buffer phpinspect-buffer)) (phpinspect-bmap-root-meta (phpinspect-buffer-map buffer))) -(defun phpinspect-display-buffer-tree () - (interactive) - (when phpinspect-current-buffer - (let ((buffer phpinspect-current-buffer)) - (pop-to-buffer (generate-new-buffer "phpinspect-buffer-tree")) - (insert (pp-to-string (phpinspect-buffer-parse buffer 'no-interrupt))) - (read-only-mode)))) - (defun phpinspect-display-buffer-index () (interactive) (when phpinspect-current-buffer @@ -150,5 +464,8 @@ use." (insert (pp-to-string (phpinspect--index-tokens (phpinspect-buffer-parse buffer 'no-interrupt)))) (read-only-mode)))) +(defun phpinspect-after-change-function (start end pre-change-length) + (when phpinspect-current-buffer + (phpinspect-buffer-register-edit phpinspect-current-buffer start end pre-change-length))) (provide 'phpinspect-buffer) diff --git a/phpinspect-cache.el b/phpinspect-cache.el index cdf89ee..1b94774 100644 --- a/phpinspect-cache.el +++ b/phpinspect-cache.el @@ -30,14 +30,6 @@ (defvar phpinspect-cache nil "An object used to store and access metadata of PHP projects.") -(defun phpinspect--get-or-create-global-cache () - "Get `phpinspect-cache'. -If its value is nil, it is created and then returned." - (or phpinspect-cache - (setq phpinspect-cache (phpinspect--make-cache)))) - - - (cl-defstruct (phpinspect--cache (:constructor phpinspect--make-cache)) (projects (make-hash-table :test 'equal :size 10) :type hash-table @@ -45,6 +37,26 @@ If its value is nil, it is created and then returned." "A `hash-table` with the root directories of projects as keys and project caches as values.")) +(defun phpinspect--get-or-create-global-cache () + "Get `phpinspect-cache'. +If its value is nil, it is created and then returned." + (or phpinspect-cache + (setq phpinspect-cache (phpinspect--make-cache)))) + +(defun phpinspect-purge-cache () + "Assign a fresh, empty cache object to `phpinspect-cache'. +This effectively purges any cached code information from all +currently opened projects." + (interactive) + (when phpinspect-cache + ;; Allow currently known cached projects to cleanup after themselves + (maphash (lambda (_ project) + (phpinspect-project-purge project)) + (phpinspect--cache-projects phpinspect-cache))) + + ;; Assign a fresh cache object + (setq phpinspect-cache (phpinspect--make-cache))) + (cl-defgeneric phpinspect--cache-getproject ((cache phpinspect--cache) (project-name string)) "Get project by PROJECT-NAME that is located in CACHE.") diff --git a/phpinspect-class.el b/phpinspect-class.el index 923e5df..d5e7221 100644 --- a/phpinspect-class.el +++ b/phpinspect-class.el @@ -43,20 +43,23 @@ :documentation "All static methods this class provides, including those from extended classes.") + (name nil + :type phpinspect--type) (variables nil :type list :documentation "Variables that belong to this class.") - (extended-classes (make-hash-table :test 'eq) - :type hash-table + (extended-classes nil + :type list :documentation "All extended/implemented classes.") - (subscriptions nil - :type list + (subscriptions (make-hash-table :test #'eq :size 10 :rehash-size 1.5) + :type hash-table :documentation "A list of subscription functions that should be called whenever anything about this class is updated") + (declaration nil) (initial-index nil :type bool :documentation @@ -64,13 +67,43 @@ has been indexed yet.")) (cl-defmethod phpinspect--class-trigger-update ((class phpinspect--class)) - (dolist (sub (phpinspect--class-subscriptions class)) + (dolist (sub (hash-table-values (phpinspect--class-subscriptions class))) (funcall sub class))) +(cl-defmethod phpinspect--class-update-extensions ((class phpinspect--class) extensions) + (setf (phpinspect--class-extended-classes class) + (seq-filter + #'phpinspect--class-p + (mapcar + (lambda (class-name) + (phpinspect-project-get-class-create (phpinspect--class-project class) + class-name)) + extensions))) + + (dolist (extended (phpinspect--class-extended-classes class)) + (phpinspect--class-incorporate class extended))) + + (cl-defmethod phpinspect--class-set-index ((class phpinspect--class) (index (head phpinspect--indexed-class))) + (setf (phpinspect--class-declaration class) (alist-get 'declaration index)) + (setf (phpinspect--class-name class) (alist-get 'class-name index)) + + ;; Override methods when class seems syntactically correct (has balanced braces) + (when (alist-get 'complete index) + (let ((methods (phpinspect--class-methods class)) + (static-methods (phpinspect--class-static-methods class))) + + (dolist (method (hash-table-values methods)) + (unless (phpinspect--function--inherited method) + (remhash (phpinspect--function-name-symbol method) methods))) + (dolist (method (hash-table-values static-methods)) + (unless (phpinspect--function--inherited method) + (remhash (phpinspect--function-name-symbol method) static-methods))))) + (setf (phpinspect--class-initial-index class) t) (setf (phpinspect--class-index class) index) + (dolist (method (alist-get 'methods index)) (phpinspect--class-update-method class method)) @@ -82,21 +115,21 @@ (alist-get 'constants index) (alist-get 'static-variables index))) - (setf (phpinspect--class-extended-classes class) - (seq-filter - #'phpinspect--class-p - (mapcar - (lambda (class-name) - (phpinspect-project-get-class-create (phpinspect--class-project class) - class-name)) - `(,@(alist-get 'implements index) ,@(alist-get 'extends index))))) - - (dolist (extended (phpinspect--class-extended-classes class)) - (phpinspect--class-incorporate class extended) - (phpinspect--class-subscribe class extended)) + (phpinspect--class-update-extensions + class `(,@(alist-get 'implements index) ,@(alist-get 'extends index))) (phpinspect--class-trigger-update class)) +(cl-defmethod phpinspect--class-update-declaration + ((class phpinspect--class) declaration imports namespace-name) + (pcase-let ((`(,class-name ,extends ,implements ,_used-types) + (phpinspect--index-class-declaration + declaration (phpinspect--make-type-resolver + (phpinspect--uses-to-types imports) nil namespace-name)))) + (setf (phpinspect--class-name class) class-name) + (setf (phpinspect--class-declaration class) declaration) + (phpinspect--class-update-extensions class `(,@extends ,@implements)))) + (cl-defmethod phpinspect--class-get-method ((class phpinspect--class) (method-name symbol)) (gethash method-name (phpinspect--class-methods class))) @@ -110,6 +143,16 @@ (when (string= variable-name (phpinspect--variable-name variable)) (throw 'found variable))))) +(cl-defmethod phpinspect--class-set-variable ((class phpinspect--class) + (var phpinspect--variable)) + (push var (phpinspect--class-variables class))) + +(cl-defmethod phpinspect--class-delete-variable ((class phpinspect--class) + (var phpinspect--variable)) + (setf (phpinspect--class-variables class) + (seq-filter (lambda (clvar) (not (eq var clvar))) + (phpinspect--class-variables class)))) + (cl-defmethod phpinspect--class-get-variables ((class phpinspect--class)) (seq-filter #'phpinspect--variable-vanilla-p (phpinspect--class-variables class))) @@ -140,16 +183,22 @@ (phpinspect--function-name method)) (phpinspect--add-method-copy-to-map (phpinspect--class-methods class) - (alist-get 'class-name (phpinspect--class-index class)) + (phpinspect--class-name class) method)) + (cl-defmethod phpinspect--class-set-static-method ((class phpinspect--class) (method phpinspect--function)) - (phpinspect--add-method-copy-to-map + (phpinspect--add-method-copy-to-map (phpinspect--class-static-methods class) - (alist-get 'class-name (phpinspect--class-index class)) + (phpinspect--class-name class) method)) + +(cl-defmethod phpinspect--class-delete-method ((class phpinspect--class) (method phpinspect--function)) + (remhash (phpinspect--function-name-symbol method) (phpinspect--class-static-methods class)) + (remhash (phpinspect--function-name-symbol method) (phpinspect--class-methods class))) + (cl-defmethod phpinspect--class-get-method-return-type ((class phpinspect--class) (method-name symbol)) (let ((method (phpinspect--class-get-method class method-name))) @@ -171,7 +220,8 @@ (cl-defmethod phpinspect--merge-method ((class-name phpinspect--type) (existing phpinspect--function) - (method phpinspect--function)) + (method phpinspect--function) + &optional extended) (let ((new-return-type (phpinspect--resolve-late-static-binding (phpinspect--function-return-type method) class-name))) @@ -180,49 +230,59 @@ (setf (phpinspect--function-return-type existing) new-return-type)) + (setf (phpinspect--function--inherited existing) + extended) + (setf (phpinspect--function-arguments existing) (phpinspect--function-arguments method))) existing) (cl-defmethod phpinspect--class-update-static-method ((class phpinspect--class) - (method phpinspect--function)) + (method phpinspect--function) + &optional extended) (let ((existing (gethash (phpinspect--function-name-symbol method) (phpinspect--class-static-methods class)))) (if existing (phpinspect--merge-method (alist-get 'class-name (phpinspect--class-index class)) - existing method) + existing method extended) + (setf (phpinspect--function--inherited method) extended) (phpinspect--class-set-static-method class method)))) (cl-defmethod phpinspect--class-update-method ((class phpinspect--class) - (method phpinspect--function)) + (method phpinspect--function) + &optional extended) (let* ((existing (gethash (phpinspect--function-name-symbol method) (phpinspect--class-methods class)))) (if existing (phpinspect--merge-method (alist-get 'class-name (phpinspect--class-index class)) - existing method) + existing method extended) + (setf (phpinspect--function--inherited method) extended) (phpinspect--class-set-method class method)))) +;; FIXME: Remove inherited methods when they no longer exist in parent classes +;; (and/or the current class in the case of abstract methods). (cl-defmethod phpinspect--class-incorporate ((class phpinspect--class) (other-class phpinspect--class)) - (dolist (method (phpinspect--class-get-method-list other-class)) - (phpinspect--class-update-method class method)) - - (dolist (method (phpinspect--class-get-static-method-list other-class)) - (phpinspect--class-update-static-method class method))) + (phpinspect--class-update-method class method 'extended)) + (dolist (method (phpinspect--class-get-static-method-list other-class)) + (phpinspect--class-update-static-method class method 'extended)) + (phpinspect--class-subscribe class other-class)) (cl-defmethod phpinspect--class-subscribe ((class phpinspect--class) (subscription-class phpinspect--class)) - (let ((update-function - (lambda (new-class) - (phpinspect--class-incorporate class new-class) - (phpinspect--class-trigger-update class)))) - (push update-function (phpinspect--class-subscriptions subscription-class)))) + (unless (gethash subscription-class (phpinspect--class-subscriptions class)) + (let ((update-function + (lambda (new-class) + (phpinspect--class-incorporate class new-class) + (phpinspect--class-trigger-update class)))) + (puthash subscription-class update-function + (phpinspect--class-subscriptions subscription-class))))) (provide 'phpinspect-class) ;;; phpinspect-class.el ends here diff --git a/phpinspect-completion.el b/phpinspect-completion.el index 59b7d7d..92e75ba 100644 --- a/phpinspect-completion.el +++ b/phpinspect-completion.el @@ -213,6 +213,8 @@ Returns list of `phpinspect--completion'." (buffer-map (phpinspect-buffer-parse-map buffer)) (rctx (phpinspect-get-resolvecontext buffer-map point)) (completion-list (phpinspect--make-completion-list))) + (phpinspect-buffer-update-project-index buffer) + (dolist (strategy phpinspect-completion-strategies) (when-let (region (phpinspect-comp-strategy-supports strategy query rctx)) (setf (phpinspect--completion-list-completion-start completion-list) diff --git a/phpinspect-eldoc.el b/phpinspect-eldoc.el index 8efa9b7..45db02e 100644 --- a/phpinspect-eldoc.el +++ b/phpinspect-eldoc.el @@ -123,8 +123,7 @@ be implemented for return values of `phpinspect-eld-strategy-execute'") enclosing-token) (setq left-sibling (phpinspect-meta-find-child-before-recursively - enclosing-token (phpinspect-eldoc-query-point q))) - (phpinspect-meta-overlaps-point left-sibling (phpinspect-eldoc-query-point q))) + enclosing-token (phpinspect-eldoc-query-point q)))) ;; Subject is inside an argument list ((and enclosing-token (phpinspect-list-p (phpinspect-meta-token enclosing-token))) @@ -250,6 +249,7 @@ also `phpinspect-eldoc-query-execute'.") (point (phpinspect-eldoc-query-point query)) (buffer-map (phpinspect-buffer-parse-map buffer)) (rctx (phpinspect-get-resolvecontext buffer-map point))) + (phpinspect-buffer-update-project-index buffer) (catch 'matched (dolist (strategy phpinspect-eldoc-strategies) (when (phpinspect-eld-strategy-supports strategy query rctx) diff --git a/phpinspect-imports.el b/phpinspect-imports.el index 5462f31..df37ec6 100644 --- a/phpinspect-imports.el +++ b/phpinspect-imports.el @@ -30,6 +30,7 @@ (require 'phpinspect-autoload) (require 'phpinspect-buffer) (require 'phpinspect-cache) +(require 'phpinspect-util) (defun phpinspect-insert-at-point (point data) (save-excursion @@ -113,12 +114,6 @@ buffer position to insert the use statement at." (defalias 'phpinspect-fix-uses-interactive #'phpinspect-fix-imports "Alias for backwards compatibility") -(defun phpinspect-namespace-name (namespace) - (or (and (phpinspect-namespace-p namespace) - (phpinspect-word-p (cadr namespace)) - (cadadr namespace)) - "")) - (defun phpinspect-add-use-statements-for-missing-types (types buffer imports project parent-token) (let (namespace namespace-name) (dolist (type types) diff --git a/phpinspect-index.el b/phpinspect-index.el index 7dc8df1..88e43ba 100644 --- a/phpinspect-index.el +++ b/phpinspect-index.el @@ -27,6 +27,7 @@ (require 'phpinspect-util) (require 'phpinspect-project) (require 'phpinspect-type) +(require 'phpinspect-parser) (defun phpinspect--function-from-scope (scope) (cond ((and (phpinspect-static-p (cadr scope)) @@ -108,6 +109,7 @@ function (think \"new\" statements, return types etc.)." (phpinspect--make-function :scope `(,(car scope)) + :token php-func :name (concat (if namespace (concat namespace "\\") "") (cadadr (cdr declaration))) :return-type (or type phpinspect--null-type) :arguments (phpinspect--index-function-arg-list @@ -115,11 +117,16 @@ function (think \"new\" statements, return types etc.)." (phpinspect-function-argument-list php-func) add-used-types)))) +(define-inline phpinspect--safe-cadr (list) + (inline-letevals (list) + (inline-quote + (when (listp ,list) (cadr ,list))))) + (defun phpinspect--index-const-from-scope (scope) (phpinspect--make-variable :scope `(,(car scope)) :mutability `(,(caadr scope)) - :name (cadr (cadr (cadr scope))))) + :name (phpinspect--safe-cadr (phpinspect--safe-cadr (phpinspect--safe-cadr scope))))) (defun phpinspect--var-annotations-from-token (token) (seq-filter #'phpinspect-var-annotation-p token)) @@ -184,6 +191,39 @@ function (think \"new\" statements, return types etc.)." methods))))) methods)) +(defun phpinspect--index-class-declaration (decl type-resolver) + ;; Find out what the class extends or implements + (let (encountered-extends encountered-implements encountered-class + class-name extends implements used-types) + (dolist (word decl) + (if (phpinspect-word-p word) + (cond ((string= (cadr word) "extends") + (phpinspect--log "Class %s extends other classes" class-name) + (setq encountered-extends t)) + ((string= (cadr word) "implements") + (setq encountered-extends nil) + (phpinspect--log "Class %s implements in interface" class-name) + (setq encountered-implements t)) + ((string= (cadr word) "class") + (setq encountered-class t)) + (t + (phpinspect--log "Calling Resolver from index-class on %s" (cadr word)) + (cond (encountered-extends + (push (funcall type-resolver (phpinspect--make-type + :name (cadr word))) + extends) + (push (cadr word) used-types)) + (encountered-implements + (push (funcall type-resolver (phpinspect--make-type + :name (cadr word))) + implements) + (push (cadr word) used-types)) + (encountered-class + (setq class-name (funcall type-resolver (phpinspect--make-type :name (cadr word))) + encountered-class nil))))))) + + (list class-name extends implements used-types))) + (defun phpinspect--index-class (imports type-resolver location-resolver class &optional doc-block) "Create an alist with relevant attributes of a parsed class." @@ -195,7 +235,7 @@ function (think \"new\" statements, return types etc.)." (constants) (extends) (implements) - (class-name (phpinspect--get-class-name-from-token class)) + (class-name) ;; Keep track of encountered comments to be able to use type ;; annotations. (comment-before) @@ -208,30 +248,9 @@ function (think \"new\" statements, return types etc.)." (nconc used-types additional-used-types) (setq used-types additional-used-types)))) - ;; Find out what the class extends or implements - (let ((enc-extends nil) - (enc-implements nil)) - (dolist (word (cadr class)) - (if (phpinspect-word-p word) - (cond ((string= (cadr word) "extends") - (phpinspect--log "Class %s extends other classes" class-name) - (setq enc-extends t)) - ((string= (cadr word) "implements") - (setq enc-extends nil) - (phpinspect--log "Class %s implements in interface" class-name) - (setq enc-implements t)) - (t - (phpinspect--log "Calling Resolver from index-class on %s" (cadr word)) - (cond (enc-extends - (push (funcall type-resolver (phpinspect--make-type - :name (cadr word))) - extends) - (push (cadr word) used-types)) - (enc-implements - (push (funcall type-resolver (phpinspect--make-type - :name (cadr word))) - implements) - (push (cadr word) used-types)))))))) + (pcase-setq `(,class-name ,extends ,implements ,used-types) + (phpinspect--index-class-declaration (cadr class) type-resolver)) + (dolist (token (caddr class)) (cond ((phpinspect-scope-p token) @@ -330,21 +349,22 @@ function (think \"new\" statements, return types etc.)." (setq methods (nconc methods (phpinspect--index-method-annotations type-resolver doc-block)))) - (let ((class-name (funcall type-resolver (phpinspect--make-type :name class-name)))) - `(,class-name . - (phpinspect--indexed-class - (class-name . ,class-name) - (location . ,(funcall location-resolver class)) - (imports . ,imports) - (methods . ,methods) - (static-methods . ,static-methods) - (static-variables . ,static-variables) - (variables . ,variables) - (constants . ,constants) - (extends . ,extends) - (implements . ,implements) - (used-types . ,(mapcar #'phpinspect-intern-name - (seq-uniq used-types #'string=)))))))) + `(,class-name . + (phpinspect--indexed-class + (complete . ,(not (phpinspect-incomplete-class-p class))) + (class-name . ,class-name) + (declaration . ,(seq-find #'phpinspect-declaration-p class)) + (location . ,(funcall location-resolver class)) + (imports . ,imports) + (methods . ,methods) + (static-methods . ,static-methods) + (static-variables . ,static-variables) + (variables . ,variables) + (constants . ,constants) + (extends . ,extends) + (implements . ,implements) + (used-types . ,(mapcar #'phpinspect-intern-name + (seq-uniq used-types #'string=))))))) (defsubst phpinspect-namespace-body (namespace) "Return the nested tokens in NAMESPACE tokens' body. @@ -503,7 +523,7 @@ Return value is a list of the types that are \"newed\"." tokens type-resolver-factory imports)))))) (t (phpinspect--log "phpinspect--index-tokens failed: %s. Enable debug-on-error for backtrace." err) - (when debug-on-error + (when (or debug-on-error phpinspect--debug) (require 'backtrace) (backtrace)) nil)) diff --git a/phpinspect-meta.el b/phpinspect-meta.el index e898371..a66e551 100644 --- a/phpinspect-meta.el +++ b/phpinspect-meta.el @@ -52,17 +52,40 @@ (define-inline phpinspect-meta-whitespace-before (meta) (inline-quote (car (cddddr ,meta)))) -(defun phpinspect-meta-start (meta) - (if (phpinspect-meta-parent meta) - (+ (phpinspect-meta-start (phpinspect-meta-parent meta)) - (phpinspect-meta-parent-offset meta)) - (phpinspect-meta-absolute-start meta))) +(define-inline phpinspect-meta-parent-start (meta) + "Calculate parent start position iteratively based on parent offsets." + (inline-letevals (meta) + (inline-quote + (let ((start (or (phpinspect-meta-parent-offset ,meta) 0)) + (current ,meta)) + (while (phpinspect-meta-parent current) + (setq current (phpinspect-meta-parent current) + start (+ start (or (phpinspect-meta-parent-offset current) 0)))) -(defun phpinspect-meta-end (meta) - (+ (phpinspect-meta-start meta) (phpinspect-meta-width meta))) + (+ (phpinspect-meta-absolute-start current) start))))) -(defsubst phpinspect-meta-width (meta) - (- (phpinspect-meta-absolute-end meta) (phpinspect-meta-absolute-start meta))) +(define-inline phpinspect-meta-start (meta) + "Calculate the start position of META." + (inline-quote + (if (phpinspect-meta-parent ,meta) + (+ (phpinspect-meta-parent-start (phpinspect-meta-parent ,meta)) + (phpinspect-meta-parent-offset ,meta)) + (phpinspect-meta-absolute-start ,meta)))) + +(define-inline phpinspect-meta-width (meta) + (inline-letevals (meta) + (inline-quote + (- (phpinspect-meta-absolute-end ,meta) (phpinspect-meta-absolute-start ,meta))))) + +(define-inline phpinspect-meta-end (meta) + (inline-letevals (meta) + (inline-quote + (+ (phpinspect-meta-start ,meta) (phpinspect-meta-width ,meta))))) + +(defsubst phpinspect-meta-find-root (meta) + (while (phpinspect-meta-parent meta) + (setq meta (phpinspect-meta-parent meta))) + meta) (defun phpinspect-meta-sort-width (meta1 meta2) (< (phpinspect-meta-width meta1) (phpinspect-meta-width meta2))) @@ -73,9 +96,12 @@ (define-inline phpinspect-meta-absolute-start (meta) (inline-quote (caddr ,meta))) -(defsubst phpinspect-meta-overlaps-point (meta point) - (and (> (phpinspect-meta-end meta) point) - (<= (phpinspect-meta-start meta) point))) +(define-inline phpinspect-meta-overlaps-point (meta point) + "Check if META's region overlaps POINT." + (inline-letevals (point meta) + (inline-quote + (and (> (phpinspect-meta-end ,meta) ,point) + (<= (phpinspect-meta-start ,meta) ,point))))) (defun phpinspect-meta-find-parent-matching-token (meta predicate) (if (funcall predicate (phpinspect-meta-token meta)) @@ -94,7 +120,9 @@ (setf (phpinspect-meta-parent-offset ,meta) (- (phpinspect-meta-start ,meta) (phpinspect-meta-start ,parent))) (phpinspect-meta-add-child ,parent ,meta)) - (setcar (cdr ,meta) ,parent))))) + (setcar (cdr ,meta) ,parent) + + ,meta)))) ;; Note: using defsubst here causes a byte code overflow (defun phpinspect-meta-add-child (meta child) @@ -138,7 +166,6 @@ (phpinspect-splayt-find-smallest-after (phpinspect-meta-children (phpinspect-meta-parent meta)) (phpinspect-meta-parent-offset meta)))) - (cl-defmethod phpinspect-meta-find-overlapping-child ((meta (head meta)) (point integer)) (let ((child (phpinspect-splayt-find-largest-before (phpinspect-meta-children meta) (phpinspect-meta--point-offset meta point)))) @@ -209,6 +236,5 @@ (phpinspect-meta-start meta) (phpinspect-meta-end meta) (phpinspect-meta-token meta)) "[nil]")) - (provide 'phpinspect-meta) ;;; phpinspect-meta.el ends here diff --git a/phpinspect-parse-context.el b/phpinspect-parse-context.el index fb2ae38..bc07444 100644 --- a/phpinspect-parse-context.el +++ b/phpinspect-parse-context.el @@ -36,6 +36,7 @@ parsing. Usually used in combination with (cl-defstruct (phpinspect-pctx (:constructor phpinspect-make-pctx)) "Parser Context" (incremental nil) + (meta-iterator nil) (interrupt-threshold (time-convert '(2 . 1000)) :documentation "After how much time `interrupt-predicate' diff --git a/phpinspect-parser.el b/phpinspect-parser.el index d3d70a3..451aa98 100644 --- a/phpinspect-parser.el +++ b/phpinspect-parser.el @@ -28,17 +28,21 @@ (require 'phpinspect-bmap) (require 'phpinspect-meta) (require 'phpinspect-parse-context) +(require 'phpinspect-token-predicates) (eval-when-compile (define-inline phpinspect--word-end-regex () (inline-quote "\\([[:blank:]]\\|[^0-9a-zA-Z_]\\)"))) -(defsubst phpinspect--strip-word-end-space (string) - (when phpinspect-parse-context - (phpinspect-pctx-register-whitespace - phpinspect-parse-context - (substring string (- (length string) 1) (length string)))) - (substring string 0 (- (length string) 1))) +(define-inline phpinspect--strip-word-end-space (string) + (inline-letevals (string) + (inline-quote + (progn + (when phpinspect-parse-context + (phpinspect-pctx-register-whitespace + phpinspect-parse-context + (substring ,string (- (length ,string) 1) (length ,string)))) + (substring ,string 0 (- (length ,string) 1)))))) (defsubst phpinspect-munch-token-without-attribs (string token-keyword) "Return a token of type TOKEN-KEYWORD with STRING as value. @@ -49,218 +53,6 @@ If STRING has text properties, they are stripped." (set-text-properties 0 length nil value) (list token-keyword value))) -(defsubst phpinspect-token-type-p (object type) - "Returns t if OBJECT is a token of type TYPE. -Type can be any of the token types returned by -`phpinspect-parse-buffer-until-point`" - (and (listp object) (eq (car object) type))) - -(defsubst phpinspect-object-attrib-p (token) - (phpinspect-token-type-p token :object-attrib)) - -(defsubst phpinspect-static-attrib-p (token) - (phpinspect-token-type-p token :static-attrib)) - -(defsubst phpinspect-attrib-p (token) - (or (phpinspect-object-attrib-p token) - (phpinspect-static-attrib-p token))) - -(defun phpinspect-html-p (token) - (phpinspect-token-type-p token :html)) - -(defun phpinspect-comma-p (token) - (phpinspect-token-type-p token :comma)) - -(defsubst phpinspect-terminator-p (token) - (phpinspect-token-type-p token :terminator)) - -(defsubst phpinspect-end-of-token-p (token) - (or (phpinspect-terminator-p token) - (phpinspect-comma-p token) - (phpinspect-html-p token))) - -(defsubst phpinspect-end-of-statement-p (token) - (or (phpinspect-end-of-token-p token) - (phpinspect-block-p token))) - -(defsubst phpinspect-incomplete-block-p (token) - (phpinspect-token-type-p token :incomplete-block)) - -(defsubst phpinspect-block-p (token) - (or (phpinspect-token-type-p token :block) - (phpinspect-incomplete-block-p token))) - -(defun phpinspect-end-of-use-p (token) - (or (phpinspect-block-p token) - (phpinspect-end-of-token-p token))) - -(defun phpinspect-static-p (token) - (phpinspect-token-type-p token :static)) - -(defsubst phpinspect-incomplete-const-p (token) - (phpinspect-token-type-p token :incomplete-const)) - -(defsubst phpinspect-const-p (token) - (or (phpinspect-token-type-p token :const) - (phpinspect-incomplete-const-p token))) - -(defsubst phpinspect-scope-p (token) - (or (phpinspect-token-type-p token :public) - (phpinspect-token-type-p token :private) - (phpinspect-token-type-p token :protected))) - -(defsubst phpinspect-namespace-p (object) - (phpinspect-token-type-p object :namespace)) - -(defun phpinspect-incomplete-class-p (token) - (and (phpinspect-class-p token) - (phpinspect-incomplete-block-p (car (last token))))) - -(defun phpinspect-incomplete-namespace-p (token) - (and (phpinspect-namespace-p token) - (or (phpinspect-incomplete-block-p (car (last token))) - (phpinspect-incomplete-class-p (car (last token)))))) - -(defun phpinspect-function-p (token) - (phpinspect-token-type-p token :function)) - - -(defun phpinspect-class-p (token) - (phpinspect-token-type-p token :class)) - -(defun phpinspect-incomplete-method-p (token) - (or (phpinspect-incomplete-function-p token) - (and (phpinspect-scope-p token) - (phpinspect-incomplete-function-p (car (last token)))) - (and (phpinspect-scope-p token) - (phpinspect-static-p (car (last token))) - (phpinspect-incomplete-function-p (car (last (car (last token)))))) - (and (phpinspect-scope-p token) - (phpinspect-function-p (car (last token)))))) - -(defun phpinspect-incomplete-function-p (token) - (and (phpinspect-function-p token) - (phpinspect-incomplete-block-p (car (last token))))) - -(defsubst phpinspect-incomplete-list-p (token) - (phpinspect-token-type-p token :incomplete-list)) - -(defsubst phpinspect-list-p (token) - (or (phpinspect-token-type-p token :list) - (phpinspect-incomplete-list-p token))) - -(defun phpinspect-declaration-p (token) - (phpinspect-token-type-p token :declaration)) - -(defsubst phpinspect-assignment-p (token) - (phpinspect-token-type-p token :assignment)) - -(defun phpinspect-function-argument-list (php-func) - "Get the argument list of a function" - (seq-find #'phpinspect-list-p (seq-find #'phpinspect-declaration-p php-func nil) nil)) - -(defun phpinspect-annotation-p (token) - (phpinspect-token-type-p token :annotation)) - -(defun phpinspect-method-annotation-p (token) - (phpinspect-token-type-p token :method-annotation)) - -(defun phpinspect-var-annotation-p (token) - (phpinspect-token-type-p token :var-annotation)) - -(defun phpinspect-return-annotation-p (token) - (phpinspect-token-type-p token :return-annotation)) - -(defsubst phpinspect-variable-p (token) - (phpinspect-token-type-p token :variable)) - -(defsubst phpinspect-word-p (token) - (phpinspect-token-type-p token :word)) - -(defsubst phpinspect-incomplete-array-p (token) - (phpinspect-token-type-p token :incomplete-array)) - -(defsubst phpinspect-array-p (token) - (or (phpinspect-token-type-p token :array) - (phpinspect-incomplete-array-p token))) - -(defsubst phpinspect-incomplete-root-p (token) - (and (phpinspect-root-p token) - (seq-find #'phpinspect-incomplete-token-p (cdr token)))) - -(defsubst phpinspect-incomplete-token-p (token) - (or (phpinspect-incomplete-root-p token) - (phpinspect-incomplete-class-p token) - (phpinspect-incomplete-block-p token) - (phpinspect-incomplete-list-p token) - (phpinspect-incomplete-array-p token) - (phpinspect-incomplete-const-p token) - (phpinspect-incomplete-function-p token) - (phpinspect-incomplete-method-p token) - (phpinspect-incomplete-namespace-p token))) - -(defun phpinspect--static-terminator-p (token) - (or (phpinspect-function-p token) - (phpinspect-end-of-token-p token))) - -(defun phpinspect--scope-terminator-p (token) - (or (phpinspect-function-p token) - (phpinspect-end-of-token-p token) - (phpinspect-const-p token) - (phpinspect-static-p token))) - -(defsubst phpinspect-enclosing-token-p (token) - "Returns t when a token can enclose other tokens" - (or - (phpinspect-list-p token) - (phpinspect-block-p token) - (phpinspect-class-p token) - (phpinspect-function-p token) - (phpinspect-array-p token) - (phpinspect-scope-p token) - (phpinspect-static-p token) - (phpinspect-const-p token))) - -(defun phpinspect-namespace-keyword-p (token) - (and (phpinspect-word-p token) (string= (car (last token)) "namespace"))) - -(defun phpinspect-use-keyword-p (token) - (and (phpinspect-word-p token) (string= (car (last token)) "use"))) - - -(defsubst phpinspect-root-p (object) - (phpinspect-token-type-p object :root)) - -(defsubst phpinspect-namespace-or-root-p (object) - (or (phpinspect-namespace-p object) - (phpinspect-root-p object))) - -(defun phpinspect-use-p (object) - (phpinspect-token-type-p object :use)) - -(defun phpinspect-comment-p (token) - (or (phpinspect-token-type-p token :comment) - (phpinspect-token-type-p token :doc-block))) - -(defsubst phpinspect-class-block (class) - (caddr class)) - -(define-inline phpinspect-namespace-is-blocked-p (namespace) - (inline-letevals (namespace) - (inline-quote - (and (= (length ,namespace) 3) (phpinspect-block-p (caddr ,namespace)))))) - -(defsubst phpinspect-namespace-block (namespace) - (when (phpinspect-namespace-is-blocked-p namespace) - (caddr namespace))) - -(defsubst phpinspect-function-block (php-func) - (caddr php-func)) - -(defsubst phpinspect-not-class-p (token) - "Apply inverse of `phpinspect-class-p' to TOKEN." - (not (phpinspect-class-p token))) - (defun phpinspect-handler-func-name (handler-name) (intern (concat "phpinspect--" (symbol-name handler-name) "-handler"))) @@ -715,6 +507,15 @@ parsing incrementally." (phpinspect-munch-token-without-attribs (match-string 0) :variable) (list :variable nil))) +(phpinspect-defhandler class-variable (start-token &rest _ignored) + "Handler for tokens indicating reference to a variable" + ((regexp . "\\$")) + (forward-char (length start-token)) + (if (looking-at (phpinspect-handler-regexp word)) + (phpinspect-munch-token-without-attribs (match-string 0) :class-variable) + (list :class-variable nil))) + + (phpinspect-defhandler whitespace (whitespace &rest _ignored) "Handler that discards whitespace" ((regexp . "[[:blank:]\n]+")) @@ -827,7 +628,7 @@ static keywords with the same meaning as in a class block." (phpinspect-defparser class-block :tree-keyword "block" - :handlers '(array tag equals list comma attribute-reference variable + :handlers '(array tag equals list comma attribute-reference class-variable assignment-operator whitespace scope-keyword static-keyword const-keyword use-keyword function-keyword word terminator here-doc string comment block)) @@ -961,19 +762,19 @@ nature like argument lists" (phpinspect-defparser scope-public :tree-keyword "public" - :handlers '(function-keyword static-keyword const-keyword variable here-doc + :handlers '(function-keyword static-keyword const-keyword class-variable here-doc string terminator tag comment) :delimiter-predicate #'phpinspect--scope-terminator-p) (phpinspect-defparser scope-private :tree-keyword "private" - :handlers '(function-keyword static-keyword const-keyword variable here-doc + :handlers '(function-keyword static-keyword const-keyword class-variable here-doc string terminator tag comment) :delimiter-predicate #'phpinspect--scope-terminator-p) (phpinspect-defparser scope-protected :tree-keyword "protected" - :handlers '(function-keyword static-keyword const-keyword variable here-doc + :handlers '(function-keyword static-keyword const-keyword class-variable here-doc string terminator tag comment) :delimiter-predicate #'phpinspect--scope-terminator-p) @@ -991,7 +792,7 @@ nature like argument lists" (phpinspect-defparser static :tree-keyword "static" - :handlers '(comment function-keyword variable array word terminator tag) + :handlers '(comment function-keyword class-variable array word terminator tag) :delimiter-predicate #'phpinspect--static-terminator-p) (phpinspect-defhandler static-keyword (start-token max-point) diff --git a/phpinspect-project.el b/phpinspect-project.el index 0df08d9..0eb3ac8 100644 --- a/phpinspect-project.el +++ b/phpinspect-project.el @@ -56,6 +56,7 @@ indexed classes in the project") :documentation "A hash able that contains all of the currently indexed functions in the project") + (function-token-index (make-hash-table :test 'eq :size 100 :rehash-size 1.5)) (fs nil :type phpinspect-fs :documentation @@ -66,7 +67,10 @@ can be accessed.") :documentation "The autoload object through which this project's type definitions can be retrieved") - (worker (phpinspect-make-dynamic-worker) + (worker (progn + (unless (featurep 'phpinspect-worker) + (require 'phpinspect-worker)) + (phpinspect-make-dynamic-worker)) :type phpinspect-worker :documentation "The worker that this project may queue tasks for") @@ -158,6 +162,10 @@ indexed by the absolute paths of the files they're watching.")) ((project phpinspect-project) (name symbol)) (gethash name (phpinspect-project-function-index project))) +(cl-defmethod phpinspect-project-delete-function + ((project phpinspect-project) (name symbol)) + (remhash name (phpinspect-project-function-index project))) + (cl-defmethod phpinspect-project-get-functions ((project phpinspect-project)) (let ((funcs)) (maphash @@ -173,6 +181,12 @@ indexed by the absolute paths of the files they're watching.")) (phpinspect--log "Adding import to index queue: %s" import) (phpinspect-project-enqueue-if-not-present project (cdr import))))) +(cl-defmethod phpinspect-project-delete-class ((project phpinspect-project) (class phpinspect--class)) + (phpinspect-project-delete-class project (phpinspect--class-name class))) + +(cl-defmethod phpinspect-project-delete-class ((project phpinspect-project) (class-name phpinspect--type)) + (remhash (phpinspect--type-name-symbol class-name) (phpinspect-project-class-index project))) + (cl-defmethod phpinspect-project-add-class ((project phpinspect-project) (indexed-class (head phpinspect--indexed-class)) &optional index-imports) (let* ((class-name (phpinspect--type-name-symbol @@ -203,11 +217,12 @@ indexed by the absolute paths of the files they're watching.")) class)) (cl-defmethod phpinspect-project-get-class-create - ((project phpinspect-project) (class-fqn phpinspect--type)) + ((project phpinspect-project) (class-fqn phpinspect--type) &optional no-enqueue) (let ((class (phpinspect-project-get-class project class-fqn))) (unless class (setq class (phpinspect-project-create-class project class-fqn)) - (phpinspect-project-enqueue-if-not-present project class-fqn)) + (unless no-enqueue + (phpinspect-project-enqueue-if-not-present project class-fqn))) class)) (defalias 'phpinspect-project-add-class-if-missing #'phpinspect-project-get-class-create) diff --git a/phpinspect-serialize.el b/phpinspect-serialize.el index 614dc21..dc72762 100644 --- a/phpinspect-serialize.el +++ b/phpinspect-serialize.el @@ -37,6 +37,7 @@ (cl-defmethod phpinspect--serialize-function ((func phpinspect--function)) `(phpinspect--make-function :name ,(phpinspect--function-name func) + :token (quote ,(phpinspect--function-token func)) :scope (quote ,(phpinspect--function-scope func)) :arguments ,(append '(list) (mapcar (lambda (arg) @@ -53,10 +54,11 @@ (phpinspect--variable-type var))) :scope (quote ,(phpinspect--variable-scope var)))) - (cl-defmethod phpinspect--serialize-indexed-class ((class (head phpinspect--indexed-class))) ``(phpinspect--indexed-class + (complete . ,,(alist-get 'complete class)) (class-name . ,,(phpinspect--serialize-type (alist-get 'class-name class))) + (declaration . ,(quote ,(alist-get 'declaration class))) (imports . ,,(append '(list) (mapcar #'phpinspect--serialize-import (alist-get 'imports class)))) diff --git a/phpinspect-splayt.el b/phpinspect-splayt.el index aa3751b..4bba874 100644 --- a/phpinspect-splayt.el +++ b/phpinspect-splayt.el @@ -88,10 +88,10 @@ apeared to be a little more performant than using `let'." (define-inline phpinspect-make-splayt (&optional root-node) (inline-quote - (cons ,root-node nil))) + (cons 'phpinspect-splayt ,root-node))) (define-inline phpinspect-splayt-root-node (splayt) - (inline-quote (car ,splayt))) + (inline-quote (cdr ,splayt))) (define-inline phpinspect-splayt-empty-p (splayt) (inline-quote (not (phpinspect-splayt-root-node ,splayt)))) @@ -166,10 +166,6 @@ apeared to be a little more performant than using `let'." (when (and ,splayt (eq ,node (phpinspect-splayt-root-node ,splayt))) (setf (phpinspect-splayt-root-node ,splayt) (phpinspect-splayt-node-parent ,node))))))) -(define-inline phpinspect-splayt-insert (splayt key value) - (inline-quote - (phpinspect-splayt-insert-node ,splayt (phpinspect-make-splayt-node ,key ,value)))) - (define-inline phpinspect-splayt-node-grandparent (node) (inline-quote (phpinspect-splayt-node-parent (phpinspect-splayt-node-parent ,node)))) @@ -261,7 +257,7 @@ apeared to be a little more performant than using `let'." (if ,reverse-sym (push ,current-sym ,stack-sym) - (setf ,place (phpinspect-splayt-node-value ,current-sym)) + (setf ,place ,current-sym) ,@body) (when (phpinspect-splayt-node-right ,current-sym) @@ -275,7 +271,7 @@ apeared to be a little more performant than using `let'." (when ,reverse-sym (while ,stack-sym (setq ,current-sym (pop ,stack-sym)) - (setf ,place (phpinspect-splayt-node-value ,current-sym)) + (setf ,place ,current-sym) ,@body)) (setq ,reverse-sym (not ,reverse-sym))) @@ -291,9 +287,15 @@ Traversal is breadth-first to take advantage of the splay trees main benefit: the most accessed interval of keys is likely to be near the top of the tee." (declare (indent 1)) - `(phpinspect-splayt-node-traverse - (,(car place-and-splayt) (phpinspect-splayt-root-node ,(cadr place-and-splayt))) - ,@body)) + (let* ((current (gensym)) + (code `(phpinspect-splayt-node-traverse + (,current (phpinspect-splayt-root-node ,(cadr place-and-splayt))) + (setf ,(car place-and-splayt) (phpinspect-splayt-node-value ,current)) + ,@body))) + (if (symbolp (car place-and-splayt)) + `(let (,(car place-and-splayt)) + ,code) + code))) (defmacro phpinspect-splayt-node-traverse-lr (place-and-node &rest body) (declare (indent 1)) @@ -309,7 +311,7 @@ near the top of the tee." (push ,current ,stack) (setq ,current (phpinspect-splayt-node-left ,current))) (setq ,current (pop ,stack)) - (setf ,place (phpinspect-splayt-node-value ,current)) + (setf ,place ,current) ,@body (setq ,current (phpinspect-splayt-node-right ,current))))))) @@ -319,9 +321,16 @@ near the top of the tee." The car of PLACE-AND-SPLAYT is assigned the value of each node. The cadr of PLACE-AND-SPLAYT is expected to be a splay tree." (declare (indent 1)) - `(phpinspect-splayt-node-traverse-lr - (,(car place-and-splayt) (phpinspect-splayt-root-node ,(cadr place-and-splayt))) - ,@body)) + (let* ((current (gensym)) + (code `(phpinspect-splayt-node-traverse-lr + (,current (phpinspect-splayt-root-node ,(cadr place-and-splayt))) + (setf ,(car place-and-splayt) (phpinspect-splayt-node-value ,current)) + ,@body))) + (if (symbolp (car place-and-splayt)) + `(let (,(car place-and-splayt)) + ,code) + code))) + (define-inline phpinspect-splayt-node-key-less-p (node key) (inline-quote (> ,key (phpinspect-splayt-node-key ,node)))) @@ -412,54 +421,89 @@ The cadr of PLACE-AND-SPLAYT is expected to be a splay tree." largest)))) -(defsubst phpinspect-splayt-find-all-after (splayt key) +(defun phpinspect-splayt-find-all-after (splayt key) "Find all values in SPLAYT with a key higher than KEY." - (let ((first (phpinspect-splayt-find-smallest-node-after splayt key)) - all) + (let* ((first (phpinspect-splayt-find-smallest-node-after splayt key)) + (all (cons nil nil)) + (all-rear all)) (while first - (push (phpinspect-splayt-node-value first) all) + (setq all-rear (setcdr all-rear (cons (phpinspect-splayt-node-value first) nil))) (phpinspect-splayt-node-traverse (sibling (phpinspect-splayt-node-right first)) - (setq all (nconc all (list sibling)))) + (setq all-rear (setcdr all-rear (cons (phpinspect-splayt-node-value sibling) nil)))) (if (and (phpinspect-splayt-node-parent first) (eq first (phpinspect-splayt-node-left (phpinspect-splayt-node-parent first)))) (setq first (phpinspect-splayt-node-parent first)) (setq first nil))) - all)) - -(defsubst phpinspect-splayt-find-all-before (splayt key) + (cdr all))) + +(defun phpinspect-splayt-find-all-between (splayt key-min key-max) + (let* ((first (phpinspect-splayt-find-smallest-node-after splayt key-min)) + (all (cons nil nil)) + (all-rear all)) + (catch 'return + (while first + (setq all-rear (setcdr all-rear (cons (phpinspect-splayt-node-value first) nil))) + + (phpinspect-splayt-node-traverse-lr (sibling (phpinspect-splayt-node-right first)) + (when (>= (phpinspect-splayt-node-key sibling) key-max) + (throw 'return all)) + (setq all-rear (setcdr all-rear (cons (phpinspect-splayt-node-value sibling) nil)))) + + (if (and (phpinspect-splayt-node-parent first) + (eq first (phpinspect-splayt-node-left (phpinspect-splayt-node-parent first)))) + (setq first (phpinspect-splayt-node-parent first)) + (setq first nil))) + (cdr all)))) + +(defun phpinspect-splayt-find-all-before (splayt key) "Find all values in SPLAYT with a key higher than KEY." - (let ((first (phpinspect-splayt-find-largest-node-before splayt key)) - all) + (let* ((first (phpinspect-splayt-find-largest-node-before splayt key)) + (all (cons nil nil)) + (all-rear all)) (while first - (push (phpinspect-splayt-node-value first) all) + (setq all-rear (setcdr all-rear (cons (phpinspect-splayt-node-value first) nil))) (phpinspect-splayt-node-traverse (sibling (phpinspect-splayt-node-left first)) - (setq all (nconc all (list sibling)))) + (setq all-rear (setcdr all-rear (cons (phpinspect-splayt-node-value sibling) nil)))) (if (and (phpinspect-splayt-node-parent first) (eq first (phpinspect-splayt-node-right (phpinspect-splayt-node-parent first)))) (setq first (phpinspect-splayt-node-parent first)) (setq first nil))) - all)) + (cdr all))) + +(defun phpinspect-splayt-to-list (tree) + "Convert TREE to an ordered list." + (let* ((list (cons nil nil)) + (rear list)) + (phpinspect-splayt-traverse-lr (val tree) + (setq rear (setcdr rear (cons val nil)))) + + (cdr list))) + +(cl-defmethod seq-do (func (tree (head phpinspect-splayt))) + (phpinspect-splayt-traverse-lr (val tree) + (funcall func val))) -(define-inline phpinspect-splayt-find-smallest-after (splayt key) +(defun phpinspect-splayt-find-smallest-after (splayt key) "Find value of node with smallest key that is higher than KEY in SPLAYT." - (inline-quote - (phpinspect-splayt-node-value - (phpinspect-splay - ,splayt (phpinspect-splayt-find-smallest-node-after ,splayt ,key))))) + (phpinspect-splayt-node-value + (phpinspect-splay + splayt (phpinspect-splayt-find-smallest-node-after splayt key)))) -(define-inline phpinspect-splayt-find-largest-before (splayt key) +(defun phpinspect-splayt-find-largest-before (splayt key) "Find value of node with smallest key that is higher than KEY in SPLAYT." - (inline-quote (phpinspect-splayt-node-value (phpinspect-splay - ,splayt (phpinspect-splayt-find-largest-node-before ,splayt ,key))))) - + splayt (phpinspect-splayt-find-largest-node-before splayt key)))) -(defsubst phpinspect-splayt-find (splayt key) +(defun phpinspect-splayt-find (splayt key) (phpinspect-splayt-node-value (phpinspect-splayt-find-node splayt key))) +(defun phpinspect-splayt-insert (tree key value) + "Insert KEY as VALUE into TREE." + (phpinspect-splayt-insert-node tree (phpinspect-make-splayt-node key value))) + (provide 'phpinspect-splayt) diff --git a/phpinspect-toc.el b/phpinspect-toc.el new file mode 100644 index 0000000..f27f6df --- /dev/null +++ b/phpinspect-toc.el @@ -0,0 +1,82 @@ +;;; phpinspect-toc.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-splayt) +(require 'phpinspect-parser) + +(defun phpinspect-make-toc (&optional tree) + (let ((table (make-hash-table :test #'eq :size 20 :rehash-size 2.0))) + (if tree + (phpinspect-splayt-traverse-lr (meta tree) + (puthash (phpinspect-meta-token meta) meta table)) + (setq tree (phpinspect-make-splayt))) + + (list tree table))) + +(define-inline phpinspect-toc-register (toc meta) + (inline-letevals (toc meta) + (inline-quote + (progn + (phpinspect-splayt-insert (phpinspect-toc-tree ,toc) (phpinspect-meta-start ,meta) ,meta) + (puthash (phpinspect-meta-token ,meta) ,meta (phpinspect-toc-table ,toc)))))) + +(define-inline phpinspect-toc-tree (toc) + (inline-quote (car ,toc))) + +(define-inline phpinspect-toc-table (toc) + (inline-quote (cadr ,toc))) + +(defun phpinspect-toc-update (toc new-tree current-root) + (let ((current-tree (phpinspect-toc-tree toc)) + (new-table (make-hash-table :test #'eq :size 20 :rehash-size 2.0)) + new deleted) + + (phpinspect-splayt-traverse-lr (meta new-tree) + (puthash (phpinspect-meta-token meta) meta new-table) + (push meta new)) + + (phpinspect-splayt-traverse-lr (meta current-tree) + (if (eq (phpinspect-meta-find-root meta) current-root) + (progn + (phpinspect-splayt-insert new-tree (phpinspect-meta-start meta) meta) + (puthash (phpinspect-meta-token meta) meta new-table)) + (push meta deleted))) + + (setf (phpinspect-toc-tree toc) new-tree) + (setf (phpinspect-toc-table toc) new-table) + + (list new deleted))) + +(defun phpinspect-toc-token-at-point (toc point) + (let ((result (phpinspect-splayt-find-largest-before (phpinspect-toc-tree toc) (+ point 1)))) + (and result (phpinspect-meta-overlaps-point result point) result))) + +(defun phpinspect-toc-token-at-or-after-point (toc point) + (phpinspect-splayt-find-smallest-after (phpinspect-toc-tree toc) (- point 1))) + +(defun phpinspect-toc-tokens-in-region (toc start end) + (phpinspect-splayt-find-all-between (phpinspect-toc-tree toc) start end)) + +(provide 'phpinspect-toc) diff --git a/phpinspect-token-predicates.el b/phpinspect-token-predicates.el new file mode 100644 index 0000000..f03883d --- /dev/null +++ b/phpinspect-token-predicates.el @@ -0,0 +1,250 @@ +;;; phpinspect-token-predicates.el --- Predicates for phpinspect-parser tokens types -*- 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: + + +(define-inline phpinspect-token-type-p (object type) + "Returns t if OBJECT is a token of type TYPE. +Type can be any of the token types returned by +`phpinspect-parse-buffer-until-point`" + (inline-letevals (object) + (inline-quote + (and (listp ,object) (eq (car ,object) ,type))))) + +(defsubst phpinspect-object-attrib-p (token) + (phpinspect-token-type-p token :object-attrib)) + +(defsubst phpinspect-static-attrib-p (token) + (phpinspect-token-type-p token :static-attrib)) + +(defsubst phpinspect-attrib-p (token) + (or (phpinspect-object-attrib-p token) + (phpinspect-static-attrib-p token))) + +(defun phpinspect-html-p (token) + (phpinspect-token-type-p token :html)) + +(defun phpinspect-comma-p (token) + (phpinspect-token-type-p token :comma)) + +(defsubst phpinspect-terminator-p (token) + (phpinspect-token-type-p token :terminator)) + +(defsubst phpinspect-end-of-token-p (token) + (or (phpinspect-terminator-p token) + (phpinspect-comma-p token) + (phpinspect-html-p token))) + +(defsubst phpinspect-end-of-statement-p (token) + (or (phpinspect-end-of-token-p token) + (phpinspect-block-p token))) + +(defsubst phpinspect-incomplete-block-p (token) + (phpinspect-token-type-p token :incomplete-block)) + +(defsubst phpinspect-block-p (token) + (or (phpinspect-token-type-p token :block) + (phpinspect-incomplete-block-p token))) + +(defun phpinspect-end-of-use-p (token) + (or (phpinspect-block-p token) + (phpinspect-end-of-token-p token))) + +(defun phpinspect-static-p (token) + (phpinspect-token-type-p token :static)) + +(defsubst phpinspect-incomplete-const-p (token) + (phpinspect-token-type-p token :incomplete-const)) + +(defsubst phpinspect-const-p (token) + (or (phpinspect-token-type-p token :const) + (phpinspect-incomplete-const-p token))) + +(define-inline phpinspect-scope-p (token) + (inline-letevals (token) + (inline-quote + (or (phpinspect-token-type-p ,token :public) + (phpinspect-token-type-p ,token :private) + (phpinspect-token-type-p ,token :protected))))) + +(define-inline phpinspect-namespace-p (object) + (inline-quote + (phpinspect-token-type-p ,object :namespace))) + +(defun phpinspect-incomplete-class-p (token) + (and (phpinspect-class-p token) + (phpinspect-incomplete-block-p (car (last token))))) + +(defun phpinspect-incomplete-namespace-p (token) + (and (phpinspect-namespace-p token) + (or (phpinspect-incomplete-block-p (car (last token))) + (phpinspect-incomplete-class-p (car (last token)))))) + +(define-inline phpinspect-function-p (token) + (inline-quote (phpinspect-token-type-p ,token :function))) + +(define-inline phpinspect-class-p (token) + (inline-quote (phpinspect-token-type-p ,token :class))) + +(defun phpinspect-incomplete-method-p (token) + (or (phpinspect-incomplete-function-p token) + (and (phpinspect-scope-p token) + (phpinspect-incomplete-function-p (car (last token)))) + (and (phpinspect-scope-p token) + (phpinspect-static-p (car (last token))) + (phpinspect-incomplete-function-p (car (last (car (last token)))))) + (and (phpinspect-scope-p token) + (phpinspect-function-p (car (last token)))))) + +(defun phpinspect-incomplete-function-p (token) + (and (phpinspect-function-p token) + (phpinspect-incomplete-block-p (car (last token))))) + +(defsubst phpinspect-incomplete-list-p (token) + (phpinspect-token-type-p token :incomplete-list)) + +(defsubst phpinspect-list-p (token) + (or (phpinspect-token-type-p token :list) + (phpinspect-incomplete-list-p token))) + +(define-inline phpinspect-declaration-p (token) + (inline-quote + (phpinspect-token-type-p ,token :declaration))) + +(defsubst phpinspect-assignment-p (token) + (phpinspect-token-type-p token :assignment)) + +(defun phpinspect-function-argument-list (php-func) + "Get the argument list of a function" + (seq-find #'phpinspect-list-p (seq-find #'phpinspect-declaration-p php-func nil) nil)) + +(defun phpinspect-annotation-p (token) + (phpinspect-token-type-p token :annotation)) + +(defun phpinspect-method-annotation-p (token) + (phpinspect-token-type-p token :method-annotation)) + +(defun phpinspect-var-annotation-p (token) + (phpinspect-token-type-p token :var-annotation)) + +(defun phpinspect-return-annotation-p (token) + (phpinspect-token-type-p token :return-annotation)) + +(define-inline phpinspect-class-variable-p (token) + (inline-quote (phpinspect-token-type-p ,token :class-variable))) + +(define-inline phpinspect-variable-p (token) + (inline-letevals (token) + (inline-quote + (or (phpinspect-token-type-p ,token :variable) + (phpinspect-token-type-p ,token :class-variable))))) + +(defsubst phpinspect-word-p (token) + (phpinspect-token-type-p token :word)) + +(defsubst phpinspect-incomplete-array-p (token) + (phpinspect-token-type-p token :incomplete-array)) + +(defsubst phpinspect-array-p (token) + (or (phpinspect-token-type-p token :array) + (phpinspect-incomplete-array-p token))) + +(defsubst phpinspect-incomplete-root-p (token) + (and (phpinspect-root-p token) + (seq-find #'phpinspect-incomplete-token-p (cdr token)))) + +(defsubst phpinspect-incomplete-token-p (token) + (or (phpinspect-incomplete-root-p token) + (phpinspect-incomplete-class-p token) + (phpinspect-incomplete-block-p token) + (phpinspect-incomplete-list-p token) + (phpinspect-incomplete-array-p token) + (phpinspect-incomplete-const-p token) + (phpinspect-incomplete-function-p token) + (phpinspect-incomplete-method-p token) + (phpinspect-incomplete-namespace-p token))) + +(defun phpinspect--static-terminator-p (token) + (or (phpinspect-function-p token) + (phpinspect-end-of-token-p token))) + +(defun phpinspect--scope-terminator-p (token) + (or (phpinspect-function-p token) + (phpinspect-end-of-token-p token) + (phpinspect-const-p token) + (phpinspect-static-p token))) + +(defsubst phpinspect-enclosing-token-p (token) + "Returns t when a token can enclose other tokens" + (or + (phpinspect-list-p token) + (phpinspect-block-p token) + (phpinspect-class-p token) + (phpinspect-function-p token) + (phpinspect-array-p token) + (phpinspect-scope-p token) + (phpinspect-static-p token) + (phpinspect-const-p token))) + +(defun phpinspect-namespace-keyword-p (token) + (and (phpinspect-word-p token) (string= (car (last token)) "namespace"))) + +(defun phpinspect-use-keyword-p (token) + (and (phpinspect-word-p token) (string= (car (last token)) "use"))) + + +(defsubst phpinspect-root-p (object) + (phpinspect-token-type-p object :root)) + +(defsubst phpinspect-namespace-or-root-p (object) + (or (phpinspect-namespace-p object) + (phpinspect-root-p object))) + +(define-inline phpinspect-use-p (object) + (inline-quote (phpinspect-token-type-p ,object :use))) + +(defun phpinspect-comment-p (token) + (or (phpinspect-token-type-p token :comment) + (phpinspect-token-type-p token :doc-block))) + +(defsubst phpinspect-class-block (class) + (caddr class)) + +(define-inline phpinspect-namespace-is-blocked-p (namespace) + (inline-letevals (namespace) + (inline-quote + (and (= (length ,namespace) 3) (phpinspect-block-p (caddr ,namespace)))))) + +(defsubst phpinspect-namespace-block (namespace) + (when (phpinspect-namespace-is-blocked-p namespace) + (caddr namespace))) + +(defsubst phpinspect-function-block (php-func) + (caddr php-func)) + +(defsubst phpinspect-not-class-p (token) + "Apply inverse of `phpinspect-class-p' to TOKEN." + (not (phpinspect-class-p token))) + +(provide 'phpinspect-token-predicates) diff --git a/phpinspect-type.el b/phpinspect-type.el index 8fc6006..fbc9415 100644 --- a/phpinspect-type.el +++ b/phpinspect-type.el @@ -206,6 +206,15 @@ NAMESPACE may be nil, or a string with a namespace FQN." :type symbol :documentation "A symbol associated with the name of the function") + (token nil + :type phpinspect-function-p + :documentation + "The tokens with which this function was declared.") + (-inherited nil + :type boolean + :documentation + "Whether this function has been incorporated into a class as +method of an extended class.") (scope nil :type phpinspect-scope :documentation diff --git a/phpinspect-util.el b/phpinspect-util.el index 190bfec..ca5b971 100644 --- a/phpinspect-util.el +++ b/phpinspect-util.el @@ -265,5 +265,16 @@ CONTINUE must be a condition-variable" (with-mutex mx (condition-wait continue)) (phpinspect--log "Thread '%s' continuing execution" (thread-name (current-thread)))) +(defun phpinspect-namespace-name (namespace) + (or (and (phpinspect-namespace-p namespace) + (phpinspect-word-p (cadr namespace)) + (cadadr namespace)) + "")) + + +(defsubst phpinspect-probably-token-p (token) + (and (listp token) + (keywordp (car token)))) + (provide 'phpinspect-util) ;;; phpinspect-util.el ends here diff --git a/phpinspect-worker.el b/phpinspect-worker.el index 0d42dd7..0a3e112 100644 --- a/phpinspect-worker.el +++ b/phpinspect-worker.el @@ -152,7 +152,7 @@ already present in the queue." (phpinspect-worker-skip-next-pause worker)) (phpinspect-thread-pause phpinspect-worker-pause-time mx continue)) (setf (phpinspect-worker-skip-next-pause worker) nil))) - (t (message "Phpinspect worker thread errored :%s" err)))) + (t (phpinspect--log "Phpinspect worker thread errored :%s" err)))) (phpinspect--log "Worker thread exiting") (message "phpinspect worker thread exited"))) diff --git a/phpinspect.el b/phpinspect.el index e42f92c..f52c985 100644 --- a/phpinspect.el +++ b/phpinspect.el @@ -79,10 +79,6 @@ (phpinspect-pctx-bmap context)))) -(defun phpinspect-after-change-function (start end pre-change-length) - (when phpinspect-current-buffer - (phpinspect-buffer-register-edit phpinspect-current-buffer start end pre-change-length))) - (defun phpinspect--init-mode () "Initialize the phpinspect minor mode for the current buffer." (phpinspect-ensure-worker) @@ -295,20 +291,6 @@ Example configuration for `company-mode': (phpinspect--completion-meta (phpinspect--completion-list-get-metadata phpinspect--last-completion-list arg))))) -(defun phpinspect-purge-cache () - "Assign a fresh, empty cache object to `phpinspect-cache'. -This effectively purges any cached code information from all -currently opened projects." - (interactive) - (when phpinspect-cache - ;; Allow currently known cached projects to cleanup after themselves - (maphash (lambda (_ project) - (phpinspect-project-purge project)) - (phpinspect--cache-projects phpinspect-cache))) - - ;; Assign a fresh cache object - (setq phpinspect-cache (phpinspect--make-cache))) - (defsubst phpinspect-insert-file-contents (&rest args) "Call `phpinspect-insert-file-contents-function' with ARGS as arguments." (apply phpinspect-insert-file-contents-function args)) diff --git a/test/fixtures/IncompleteClass.eld b/test/fixtures/IncompleteClass.eld index 67684e6..1962763 100644 --- a/test/fixtures/IncompleteClass.eld +++ b/test/fixtures/IncompleteClass.eld @@ -1 +1 @@ -(:root (:word "declare") (:list (:word "strict_types") (:assignment "=")) (:terminator ";") (:namespace (:word "App\\Controller") (:terminator ";") (:use (:word "Symfony\\Component\\HttpFoundation\\Response") (:terminator ";")) (:use (:word "App\\Entity\\Address") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\RedirectResponse") (:terminator ";")) (:use (:word "App\\Repository\\AddressRepository") (:terminator ";")) (:use (:word "App\\Repository\\UserRepository") (:terminator ";")) (:use (:word "Doctrine\\ORM\\EntityManagerInterface") (:terminator ";")) (:use (:word "Twig\\Environment") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\Request") (:terminator ";")) (:use (:word "Symfony\\Component\\Routing\\Annotation\\Route") (:terminator ";")) (:class (:declaration (:word "class") (:word "AddressController")) (:incomplete-block (:const (:word "A_CONSTANT_FOR_THE_SAKE_OF_HAVING_ONE") (:assignment "=") (:string "a value") (:terminator ";")) (:public (:const (:word "ARRAY_CONSTANT") (:assignment "=") (:array (:string "key") (:fat-arrow "=>") (:string "value") (:comma ",") (:string "key") (:fat-arrow "=>")) (:terminator ";"))) (:private (:variable "repo") (:terminator ";")) (:private (:variable "user_repo") (:terminator ";")) (:private (:variable "twig") (:terminator ";")) (:private (:variable "em") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "AddressRepository") (:variable "repo") (:comma ",") (:word "UserRepository") (:variable "user_repo") (:comma ",") (:word "Environment") (:variable "twig") (:comma ",") (:word "EntityManagerInterface") (:variable "em"))) (:block (:variable "this") (:object-attrib (:word "repo")) (:assignment "=") (:variable "repo") (:terminator ";") (:variable "this") (:object-attrib (:word "user_repo")) (:assignment "=") (:variable "user_repo") (:terminator ";") (:variable "this") (:object-attrib (:word "twig")) (:assignment "=") (:variable "twig") (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:assignment "=") (:variable "em") (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressPage") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "address/create.html.twig") (:comma ",") (:array (:string "user") (:fat-arrow "=>") (:variable "user") (:comma ",")))) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:variable "address_string") (:assignment "=") (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address")) (:terminator ";") (:variable "address") (:assignment "=") (:word "new") (:word "Address") (:list (:variable "user") (:comma ",") (:variable "address_string")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "persist")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "user") (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "deleteAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:incomplete-block (:variable "address") (:assignment "=") (:variable "this") (:object-attrib (:word "repo")) (:object-attrib (:word "find")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address"))) (:terminator ";") (:comment) (:comment) (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "remove")) (:incomplete-list (:variable "this") (:object-attrib (:word "em")) (:object-attrib nil))))))))) \ No newline at end of file +(:root (:word "declare") (:list (:word "strict_types") (:assignment "=")) (:terminator ";") (:namespace (:word "App\\Controller") (:terminator ";") (:use (:word "Symfony\\Component\\HttpFoundation\\Response") (:terminator ";")) (:use (:word "App\\Entity\\Address") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\RedirectResponse") (:terminator ";")) (:use (:word "App\\Repository\\AddressRepository") (:terminator ";")) (:use (:word "App\\Repository\\UserRepository") (:terminator ";")) (:use (:word "Doctrine\\ORM\\EntityManagerInterface") (:terminator ";")) (:use (:word "Twig\\Environment") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\Request") (:terminator ";")) (:use (:word "Symfony\\Component\\Routing\\Annotation\\Route") (:terminator ";")) (:class (:declaration (:word "class") (:word "AddressController")) (:incomplete-block (:const (:word "A_CONSTANT_FOR_THE_SAKE_OF_HAVING_ONE") (:assignment "=") (:string "a value") (:terminator ";")) (:public (:const (:word "ARRAY_CONSTANT") (:assignment "=") (:array (:string "key") (:fat-arrow "=>") (:string "value") (:comma ",") (:string "key") (:fat-arrow "=>")) (:terminator ";"))) (:private (:class-variable "repo") (:terminator ";")) (:private (:class-variable "user_repo") (:terminator ";")) (:private (:class-variable "twig") (:terminator ";")) (:private (:class-variable "em") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "AddressRepository") (:variable "repo") (:comma ",") (:word "UserRepository") (:variable "user_repo") (:comma ",") (:word "Environment") (:variable "twig") (:comma ",") (:word "EntityManagerInterface") (:variable "em"))) (:block (:variable "this") (:object-attrib (:word "repo")) (:assignment "=") (:variable "repo") (:terminator ";") (:variable "this") (:object-attrib (:word "user_repo")) (:assignment "=") (:variable "user_repo") (:terminator ";") (:variable "this") (:object-attrib (:word "twig")) (:assignment "=") (:variable "twig") (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:assignment "=") (:variable "em") (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressPage") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "address/create.html.twig") (:comma ",") (:array (:string "user") (:fat-arrow "=>") (:variable "user") (:comma ",")))) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:variable "address_string") (:assignment "=") (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address")) (:terminator ";") (:variable "address") (:assignment "=") (:word "new") (:word "Address") (:list (:variable "user") (:comma ",") (:variable "address_string")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "persist")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "user") (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "deleteAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:incomplete-block (:variable "address") (:assignment "=") (:variable "this") (:object-attrib (:word "repo")) (:object-attrib (:word "find")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address"))) (:terminator ";") (:comment) (:comment) (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "remove")) (:incomplete-list (:variable "this") (:object-attrib (:word "em")) (:object-attrib nil))))))))) \ No newline at end of file diff --git a/test/fixtures/IncompleteClassBlockedNamespace.eld b/test/fixtures/IncompleteClassBlockedNamespace.eld index 2bf9eaa..96c2489 100644 --- a/test/fixtures/IncompleteClassBlockedNamespace.eld +++ b/test/fixtures/IncompleteClassBlockedNamespace.eld @@ -1 +1 @@ -(:root (:word "declare") (:list (:word "strict_types") (:assignment "=")) (:terminator ";") (:namespace (:word "App\\Controller") (:incomplete-block (:use (:word "Symfony\\Component\\HttpFoundation\\Response") (:terminator ";")) (:use (:word "App\\Entity\\Address") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\RedirectResponse") (:terminator ";")) (:use (:word "App\\Repository\\AddressRepository") (:terminator ";")) (:use (:word "App\\Repository\\UserRepository") (:terminator ";")) (:use (:word "Doctrine\\ORM\\EntityManagerInterface") (:terminator ";")) (:use (:word "Twig\\Environment") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\Request") (:terminator ";")) (:use (:word "Symfony\\Component\\Routing\\Annotation\\Route") (:terminator ";")) (:class (:declaration (:word "class") (:word "AddressController")) (:incomplete-block (:const (:word "A_CONSTANT_FOR_THE_SAKE_OF_HAVING_ONE") (:assignment "=") (:string "a value") (:terminator ";")) (:public (:const (:word "ARRAY_CONSTANT") (:assignment "=") (:array (:string "key") (:fat-arrow "=>") (:string "value") (:comma ",") (:string "key") (:fat-arrow "=>")) (:terminator ";"))) (:private (:variable "repo") (:terminator ";")) (:private (:variable "user_repo") (:terminator ";")) (:private (:variable "twig") (:terminator ";")) (:private (:variable "em") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "AddressRepository") (:variable "repo") (:comma ",") (:word "UserRepository") (:variable "user_repo") (:comma ",") (:word "Environment") (:variable "twig") (:comma ",") (:word "EntityManagerInterface") (:variable "em"))) (:block (:variable "this") (:object-attrib (:word "repo")) (:assignment "=") (:variable "repo") (:terminator ";") (:variable "this") (:object-attrib (:word "user_repo")) (:assignment "=") (:variable "user_repo") (:terminator ";") (:variable "this") (:object-attrib (:word "twig")) (:assignment "=") (:variable "twig") (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:assignment "=") (:variable "em") (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressPage") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "address/create.html.twig") (:comma ",") (:array (:string "user") (:fat-arrow "=>") (:variable "user") (:comma ",")))) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:variable "address_string") (:assignment "=") (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address")) (:terminator ";") (:variable "address") (:assignment "=") (:word "new") (:word "Address") (:list (:variable "user") (:comma ",") (:variable "address_string")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "persist")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "user") (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "deleteAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:incomplete-block (:variable "address") (:assignment "=") (:variable "this") (:object-attrib (:word "repo")) (:object-attrib (:word "find")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address"))) (:terminator ";") (:comment) (:comment) (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "remove")) (:incomplete-list (:variable "this") (:object-attrib (:word "em")) (:object-attrib nil)))))))))) \ No newline at end of file +(:root (:word "declare") (:list (:word "strict_types") (:assignment "=")) (:terminator ";") (:namespace (:word "App\\Controller") (:incomplete-block (:use (:word "Symfony\\Component\\HttpFoundation\\Response") (:terminator ";")) (:use (:word "App\\Entity\\Address") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\RedirectResponse") (:terminator ";")) (:use (:word "App\\Repository\\AddressRepository") (:terminator ";")) (:use (:word "App\\Repository\\UserRepository") (:terminator ";")) (:use (:word "Doctrine\\ORM\\EntityManagerInterface") (:terminator ";")) (:use (:word "Twig\\Environment") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\Request") (:terminator ";")) (:use (:word "Symfony\\Component\\Routing\\Annotation\\Route") (:terminator ";")) (:class (:declaration (:word "class") (:word "AddressController")) (:incomplete-block (:const (:word "A_CONSTANT_FOR_THE_SAKE_OF_HAVING_ONE") (:assignment "=") (:string "a value") (:terminator ";")) (:public (:const (:word "ARRAY_CONSTANT") (:assignment "=") (:array (:string "key") (:fat-arrow "=>") (:string "value") (:comma ",") (:string "key") (:fat-arrow "=>")) (:terminator ";"))) (:private (:class-variable "repo") (:terminator ";")) (:private (:class-variable "user_repo") (:terminator ";")) (:private (:class-variable "twig") (:terminator ";")) (:private (:class-variable "em") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "AddressRepository") (:variable "repo") (:comma ",") (:word "UserRepository") (:variable "user_repo") (:comma ",") (:word "Environment") (:variable "twig") (:comma ",") (:word "EntityManagerInterface") (:variable "em"))) (:block (:variable "this") (:object-attrib (:word "repo")) (:assignment "=") (:variable "repo") (:terminator ";") (:variable "this") (:object-attrib (:word "user_repo")) (:assignment "=") (:variable "user_repo") (:terminator ";") (:variable "this") (:object-attrib (:word "twig")) (:assignment "=") (:variable "twig") (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:assignment "=") (:variable "em") (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressPage") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "address/create.html.twig") (:comma ",") (:array (:string "user") (:fat-arrow "=>") (:variable "user") (:comma ",")))) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:variable "address_string") (:assignment "=") (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address")) (:terminator ";") (:variable "address") (:assignment "=") (:word "new") (:word "Address") (:list (:variable "user") (:comma ",") (:variable "address_string")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "persist")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "user") (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "deleteAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:incomplete-block (:variable "address") (:assignment "=") (:variable "this") (:object-attrib (:word "repo")) (:object-attrib (:word "find")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address"))) (:terminator ";") (:comment) (:comment) (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "remove")) (:incomplete-list (:variable "this") (:object-attrib (:word "em")) (:object-attrib nil)))))))))) \ No newline at end of file diff --git a/test/fixtures/IncompleteClassMultipleNamespaces.eld b/test/fixtures/IncompleteClassMultipleNamespaces.eld index f978752..77449f5 100644 --- a/test/fixtures/IncompleteClassMultipleNamespaces.eld +++ b/test/fixtures/IncompleteClassMultipleNamespaces.eld @@ -1 +1 @@ -(:root (:word "declare") (:list (:word "strict_types") (:assignment "=")) (:terminator ";") (:namespace (:word "Circus\\Artist") (:block (:use (:word "Symfony\\Component\\HttpFoundation\\Response") (:terminator ";")) (:use (:word "App\\Entity\\Address") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\RedirectResponse") (:terminator ";")) (:use (:word "App\\Repository\\AddressRepository") (:terminator ";")) (:use (:word "App\\Repository\\UserRepository") (:terminator ";")) (:use (:word "Doctrine\\ORM\\EntityManagerInterface") (:terminator ";")) (:use (:word "Twig\\Environment") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\Request") (:terminator ";")) (:use (:word "Symfony\\Component\\Routing\\Annotation\\Route") (:terminator ";")) (:class (:declaration (:word "class") (:word "AddressController")) (:block (:const (:word "A_CONSTANT_FOR_THE_SAKE_OF_HAVING_ONE") (:assignment "=") (:string "a value") (:terminator ";")) (:public (:const (:word "ARRAY_CONSTANT") (:assignment "=") (:array (:string "key") (:fat-arrow "=>") (:string "value") (:comma ",") (:string "key") (:fat-arrow "=>")) (:terminator ";"))) (:private (:variable "repo") (:terminator ";")) (:private (:variable "user_repo") (:terminator ";")) (:private (:variable "twig") (:terminator ";")) (:private (:variable "em") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "AddressRepository") (:variable "repo") (:comma ",") (:word "UserRepository") (:variable "user_repo") (:comma ",") (:word "Environment") (:variable "twig") (:comma ",") (:word "EntityManagerInterface") (:variable "em"))) (:block (:variable "this") (:object-attrib (:word "repo")) (:assignment "=") (:variable "repo") (:terminator ";") (:variable "this") (:object-attrib (:word "user_repo")) (:assignment "=") (:variable "user_repo") (:terminator ";") (:variable "this") (:object-attrib (:word "twig")) (:assignment "=") (:variable "twig") (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:assignment "=") (:variable "em") (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressPage") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "address/create.html.twig") (:comma ",") (:array (:string "user") (:fat-arrow "=>") (:variable "user") (:comma ",")))) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:variable "address_string") (:assignment "=") (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address")) (:terminator ";") (:variable "address") (:assignment "=") (:word "new") (:word "Address") (:list (:variable "user") (:comma ",") (:variable "address_string")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "persist")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "user") (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "deleteAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "address") (:assignment "=") (:variable "this") (:object-attrib (:word "repo")) (:object-attrib (:word "find")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address"))) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "remove")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "address") (:object-attrib (:word "getUser")) (:list) (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))))))) (:namespace (:word "App\\Controller") (:incomplete-block (:use (:word "Symfony\\Component\\HttpFoundation\\Response") (:terminator ";")) (:use (:word "App\\Entity\\Address") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\RedirectResponse") (:terminator ";")) (:use (:word "App\\Repository\\AddressRepository") (:terminator ";")) (:use (:word "App\\Repository\\UserRepository") (:terminator ";")) (:use (:word "Doctrine\\ORM\\EntityManagerInterface") (:terminator ";")) (:use (:word "Twig\\Environment") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\Request") (:terminator ";")) (:use (:word "Symfony\\Component\\Routing\\Annotation\\Route") (:terminator ";")) (:class (:declaration (:word "class") (:word "AddressController")) (:incomplete-block (:const (:word "A_CONSTANT_FOR_THE_SAKE_OF_HAVING_ONE") (:assignment "=") (:string "a value") (:terminator ";")) (:public (:const (:word "ARRAY_CONSTANT") (:assignment "=") (:array (:string "key") (:fat-arrow "=>") (:string "value") (:comma ",") (:string "key") (:fat-arrow "=>")) (:terminator ";"))) (:private (:variable "repo") (:terminator ";")) (:private (:variable "user_repo") (:terminator ";")) (:private (:variable "twig") (:terminator ";")) (:private (:variable "em") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "AddressRepository") (:variable "repo") (:comma ",") (:word "UserRepository") (:variable "user_repo") (:comma ",") (:word "Environment") (:variable "twig") (:comma ",") (:word "EntityManagerInterface") (:variable "em"))) (:block (:variable "this") (:object-attrib (:word "repo")) (:assignment "=") (:variable "repo") (:terminator ";") (:variable "this") (:object-attrib (:word "user_repo")) (:assignment "=") (:variable "user_repo") (:terminator ";") (:variable "this") (:object-attrib (:word "twig")) (:assignment "=") (:variable "twig") (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:assignment "=") (:variable "em") (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressPage") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "address/create.html.twig") (:comma ",") (:array (:string "user") (:fat-arrow "=>") (:variable "user") (:comma ",")))) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:variable "address_string") (:assignment "=") (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address")) (:terminator ";") (:variable "address") (:assignment "=") (:word "new") (:word "Address") (:list (:variable "user") (:comma ",") (:variable "address_string")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "persist")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "user") (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "deleteAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:incomplete-block (:variable "address") (:assignment "=") (:variable "this") (:object-attrib (:word "repo")) (:object-attrib (:word "find")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address"))) (:terminator ";") (:comment) (:comment) (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "remove")) (:incomplete-list (:variable "this") (:object-attrib (:word "em")) (:object-attrib nil)))))))))) \ No newline at end of file +(:root (:word "declare") (:list (:word "strict_types") (:assignment "=")) (:terminator ";") (:namespace (:word "Circus\\Artist") (:block (:use (:word "Symfony\\Component\\HttpFoundation\\Response") (:terminator ";")) (:use (:word "App\\Entity\\Address") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\RedirectResponse") (:terminator ";")) (:use (:word "App\\Repository\\AddressRepository") (:terminator ";")) (:use (:word "App\\Repository\\UserRepository") (:terminator ";")) (:use (:word "Doctrine\\ORM\\EntityManagerInterface") (:terminator ";")) (:use (:word "Twig\\Environment") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\Request") (:terminator ";")) (:use (:word "Symfony\\Component\\Routing\\Annotation\\Route") (:terminator ";")) (:class (:declaration (:word "class") (:word "AddressController")) (:block (:const (:word "A_CONSTANT_FOR_THE_SAKE_OF_HAVING_ONE") (:assignment "=") (:string "a value") (:terminator ";")) (:public (:const (:word "ARRAY_CONSTANT") (:assignment "=") (:array (:string "key") (:fat-arrow "=>") (:string "value") (:comma ",") (:string "key") (:fat-arrow "=>")) (:terminator ";"))) (:private (:class-variable "repo") (:terminator ";")) (:private (:class-variable "user_repo") (:terminator ";")) (:private (:class-variable "twig") (:terminator ";")) (:private (:class-variable "em") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "AddressRepository") (:variable "repo") (:comma ",") (:word "UserRepository") (:variable "user_repo") (:comma ",") (:word "Environment") (:variable "twig") (:comma ",") (:word "EntityManagerInterface") (:variable "em"))) (:block (:variable "this") (:object-attrib (:word "repo")) (:assignment "=") (:variable "repo") (:terminator ";") (:variable "this") (:object-attrib (:word "user_repo")) (:assignment "=") (:variable "user_repo") (:terminator ";") (:variable "this") (:object-attrib (:word "twig")) (:assignment "=") (:variable "twig") (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:assignment "=") (:variable "em") (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressPage") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "address/create.html.twig") (:comma ",") (:array (:string "user") (:fat-arrow "=>") (:variable "user") (:comma ",")))) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:variable "address_string") (:assignment "=") (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address")) (:terminator ";") (:variable "address") (:assignment "=") (:word "new") (:word "Address") (:list (:variable "user") (:comma ",") (:variable "address_string")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "persist")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "user") (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "deleteAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "address") (:assignment "=") (:variable "this") (:object-attrib (:word "repo")) (:object-attrib (:word "find")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address"))) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "remove")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "address") (:object-attrib (:word "getUser")) (:list) (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))))))) (:namespace (:word "App\\Controller") (:incomplete-block (:use (:word "Symfony\\Component\\HttpFoundation\\Response") (:terminator ";")) (:use (:word "App\\Entity\\Address") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\RedirectResponse") (:terminator ";")) (:use (:word "App\\Repository\\AddressRepository") (:terminator ";")) (:use (:word "App\\Repository\\UserRepository") (:terminator ";")) (:use (:word "Doctrine\\ORM\\EntityManagerInterface") (:terminator ";")) (:use (:word "Twig\\Environment") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\Request") (:terminator ";")) (:use (:word "Symfony\\Component\\Routing\\Annotation\\Route") (:terminator ";")) (:class (:declaration (:word "class") (:word "AddressController")) (:incomplete-block (:const (:word "A_CONSTANT_FOR_THE_SAKE_OF_HAVING_ONE") (:assignment "=") (:string "a value") (:terminator ";")) (:public (:const (:word "ARRAY_CONSTANT") (:assignment "=") (:array (:string "key") (:fat-arrow "=>") (:string "value") (:comma ",") (:string "key") (:fat-arrow "=>")) (:terminator ";"))) (:private (:class-variable "repo") (:terminator ";")) (:private (:class-variable "user_repo") (:terminator ";")) (:private (:class-variable "twig") (:terminator ";")) (:private (:class-variable "em") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "AddressRepository") (:variable "repo") (:comma ",") (:word "UserRepository") (:variable "user_repo") (:comma ",") (:word "Environment") (:variable "twig") (:comma ",") (:word "EntityManagerInterface") (:variable "em"))) (:block (:variable "this") (:object-attrib (:word "repo")) (:assignment "=") (:variable "repo") (:terminator ";") (:variable "this") (:object-attrib (:word "user_repo")) (:assignment "=") (:variable "user_repo") (:terminator ";") (:variable "this") (:object-attrib (:word "twig")) (:assignment "=") (:variable "twig") (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:assignment "=") (:variable "em") (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressPage") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "address/create.html.twig") (:comma ",") (:array (:string "user") (:fat-arrow "=>") (:variable "user") (:comma ",")))) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:variable "address_string") (:assignment "=") (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address")) (:terminator ";") (:variable "address") (:assignment "=") (:word "new") (:word "Address") (:list (:variable "user") (:comma ",") (:variable "address_string")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "persist")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "user") (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "deleteAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:incomplete-block (:variable "address") (:assignment "=") (:variable "this") (:object-attrib (:word "repo")) (:object-attrib (:word "find")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address"))) (:terminator ";") (:comment) (:comment) (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "remove")) (:incomplete-list (:variable "this") (:object-attrib (:word "em")) (:object-attrib nil)))))))))) \ No newline at end of file diff --git a/test/fixtures/IndexClass1-indexed.eld b/test/fixtures/IndexClass1-indexed.eld index e819b26..8f4f9e8 100644 --- a/test/fixtures/IndexClass1-indexed.eld +++ b/test/fixtures/IndexClass1-indexed.eld @@ -1 +1 @@ -`(phpinspect--root-index (imports \, (list)) (classes \, (list (cons (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 "arrayReturn" :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\array" :collection t :contains (phpinspect--make-type :name "\\App\\Entity\\DateTime" :collection nil :contains nil :fully-qualified t) :fully-qualified t)) (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 +`(phpinspect--root-index (imports \, (list)) (classes \, (list (cons (phpinspect--make-type :name "\\App\\Entity\\AuthToken" :collection nil :contains nil :fully-qualified t) `(phpinspect--indexed-class (complete \, t) (class-name \, (phpinspect--make-type :name "\\App\\Entity\\AuthToken" :collection nil :contains nil :fully-qualified t)) (declaration \, '(:declaration (:word "class") (:word "AuthToken"))) (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 "arrayReturn" :token '(:function (:declaration (:word "function") (:word "arrayReturn") (:list) (:word "array")) (:block (:word "return") (:array (:word "new") (:word "\\DateTime") (:list)) (:terminator ";"))) :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\array" :collection t :contains (phpinspect--make-type :name "\\App\\Entity\\DateTime" :collection nil :contains nil :fully-qualified t) :fully-qualified t)) (phpinspect--make-function :name "getCreationTime" :token '(:function (:declaration (:word "function") (:word "getCreationTime") (:list) (:word "\\DateTime")) (:block (:word "return") (:variable "this") (:object-attrib (:word "creation_time")) (:terminator ";"))) :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\DateTime" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "isValid" :token '(:function (:declaration (:word "function") (:word "isValid") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "valid")) (:terminator ";"))) :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "hasStudentRole" :token '(:function (:declaration (:word "function") (:word "hasStudentRole") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "role_student")) (:terminator ";"))) :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "getUser" :token '(:function (:declaration (:word "function") (:word "getUser") (:list) (:word "User")) (:block (:word "return") (:variable "this") (:object-attrib (:word "user")) (:terminator ";"))) :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" :token '(:function (:declaration (:word "function") (:word "getToken") (:list) (:word "string")) (:block (:word "return") (:variable "this") (:object-attrib (:word "token")) (:terminator ";"))) :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\string" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "__construct" :token '(:function (:declaration (:word "function") (:word "__construct") (:list (:word "string") (:variable "token") (:comma ",") (:word "User") (:variable "user") (:comma ",") (:word "bool") (:variable "valid") (:assignment "=") (:word "false") (:comma ",") (:word "\\DateTime") (:variable "creation_time") (:assignment "=") (:word "null"))) (:block (:variable "this") (:object-attrib (:word "token")) (:assignment "=") (:variable "token") (:terminator ";") (:variable "this") (:object-attrib (:word "user")) (:assignment "=") (:variable "user") (:terminator ";") (:variable "this") (:object-attrib (:word "valid")) (:assignment "=") (:variable "valid") (:terminator ";") (:variable "this") (:object-attrib (:word "creation_time")) (:assignment "=") (:variable "creation_time") (:word "new") (:word "\\DateTime") (:list) (:terminator ";"))) :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/IndexClass1.eld b/test/fixtures/IndexClass1.eld index bbecd1c..b9fdeb1 100644 --- a/test/fixtures/IndexClass1.eld +++ b/test/fixtures/IndexClass1.eld @@ -1 +1 @@ -(:root (:word "declare") (:list (:word "strict_types") (:assignment "=")) (:terminator ";") (:namespace (:word "App\\Entity") (:terminator ";") (:use (:word "Doctrine\\ORM\\Mapping") (:word "as") (:word "ORM") (:terminator ";")) (:doc-block (:annotation "ORM\\Entity")) (:class (:declaration (:word "class") (:word "AuthToken")) (:block (:private (:variable "token") (:terminator ";")) (:doc-block (:var-annotation (:word "App\\\\Entity\\\\User"))) (:private (:variable "user") (:terminator ";")) (:doc-block (:var-annotation (:word "bool"))) (:private (:variable "valid") (:terminator ";")) (:doc-block (:var-annotation (:word "\\DateTime"))) (:private (:variable "creation_time") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "string") (:variable "token") (:comma ",") (:word "User") (:variable "user") (:comma ",") (:word "bool") (:variable "valid") (:assignment "=") (:word "false") (:comma ",") (:word "\\DateTime") (:variable "creation_time") (:assignment "=") (:word "null"))) (:block (:variable "this") (:object-attrib (:word "token")) (:assignment "=") (:variable "token") (:terminator ";") (:variable "this") (:object-attrib (:word "user")) (:assignment "=") (:variable "user") (:terminator ";") (:variable "this") (:object-attrib (:word "valid")) (:assignment "=") (:variable "valid") (:terminator ";") (:variable "this") (:object-attrib (:word "creation_time")) (:assignment "=") (:variable "creation_time") (:word "new") (:word "\\DateTime") (:list) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "getToken") (:list) (:word "string")) (:block (:word "return") (:variable "this") (:object-attrib (:word "token")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "getUser") (:list) (:word "User")) (:block (:word "return") (:variable "this") (:object-attrib (:word "user")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "hasStudentRole") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "role_student")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "isValid") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "valid")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "getCreationTime") (:list) (:word "\\DateTime")) (:block (:word "return") (:variable "this") (:object-attrib (:word "creation_time")) (:terminator ";")))) (:doc-block (:return-annotation (:word "DateTime[]"))) (:public (:function (:declaration (:word "function") (:word "arrayReturn") (:list) (:word "array")) (:block (:word "return") (:array (:word "new") (:word "\\DateTime") (:list)) (:terminator ";")))))))) \ No newline at end of file +(:root (:word "declare") (:list (:word "strict_types") (:assignment "=")) (:terminator ";") (:namespace (:word "App\\Entity") (:terminator ";") (:use (:word "Doctrine\\ORM\\Mapping") (:word "as") (:word "ORM") (:terminator ";")) (:doc-block (:annotation "ORM\\Entity")) (:class (:declaration (:word "class") (:word "AuthToken")) (:block (:private (:class-variable "token") (:terminator ";")) (:doc-block (:var-annotation (:word "App\\\\Entity\\\\User"))) (:private (:class-variable "user") (:terminator ";")) (:doc-block (:var-annotation (:word "bool"))) (:private (:class-variable "valid") (:terminator ";")) (:doc-block (:var-annotation (:word "\\DateTime"))) (:private (:class-variable "creation_time") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "string") (:variable "token") (:comma ",") (:word "User") (:variable "user") (:comma ",") (:word "bool") (:variable "valid") (:assignment "=") (:word "false") (:comma ",") (:word "\\DateTime") (:variable "creation_time") (:assignment "=") (:word "null"))) (:block (:variable "this") (:object-attrib (:word "token")) (:assignment "=") (:variable "token") (:terminator ";") (:variable "this") (:object-attrib (:word "user")) (:assignment "=") (:variable "user") (:terminator ";") (:variable "this") (:object-attrib (:word "valid")) (:assignment "=") (:variable "valid") (:terminator ";") (:variable "this") (:object-attrib (:word "creation_time")) (:assignment "=") (:variable "creation_time") (:word "new") (:word "\\DateTime") (:list) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "getToken") (:list) (:word "string")) (:block (:word "return") (:variable "this") (:object-attrib (:word "token")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "getUser") (:list) (:word "User")) (:block (:word "return") (:variable "this") (:object-attrib (:word "user")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "hasStudentRole") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "role_student")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "isValid") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "valid")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "getCreationTime") (:list) (:word "\\DateTime")) (:block (:word "return") (:variable "this") (:object-attrib (:word "creation_time")) (:terminator ";")))) (:doc-block (:return-annotation (:word "DateTime[]"))) (:public (:function (:declaration (:word "function") (:word "arrayReturn") (:list) (:word "array")) (:block (:word "return") (:array (:word "new") (:word "\\DateTime") (:list)) (:terminator ";")))))))) \ No newline at end of file diff --git a/test/fixtures/IndexClass2-indexed.eld b/test/fixtures/IndexClass2-indexed.eld index b67f78b..4edc186 100644 --- a/test/fixtures/IndexClass2-indexed.eld +++ b/test/fixtures/IndexClass2-indexed.eld @@ -1 +1 @@ -`(phpinspect--root-index (imports \, (list)) (classes \, (list (cons (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 +`(phpinspect--root-index (imports \, (list)) (classes \, (list (cons (phpinspect--make-type :name "\\App\\Entity\\AuthToken" :collection nil :contains nil :fully-qualified t) `(phpinspect--indexed-class (complete \, t) (class-name \, (phpinspect--make-type :name "\\App\\Entity\\AuthToken" :collection nil :contains nil :fully-qualified t)) (declaration \, '(:declaration (:word "class") (:word "AuthToken"))) (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" :token '(:function (:declaration (:word "function") (:word "getCreationTime") (:list) (:word "\\DateTime")) (:block (:word "return") (:variable "this") (:object-attrib (:word "creation_time")) (:terminator ";"))) :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\DateTime" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "anAddedFunction" :token '(:function (:declaration (:word "function") (:word "anAddedFunction") (:list)) (:block (:word "return") (:variable "this") (:object-attrib (:word "extra")) (:terminator ";"))) :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\null" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "isValid" :token '(:function (:declaration (:word "function") (:word "isValid") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "valid")) (:terminator ";"))) :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "hasStudentRole" :token '(:function (:declaration (:word "function") (:word "hasStudentRole") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "role_student")) (:terminator ";"))) :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "getUser" :token '(:function (:declaration (:word "function") (:word "getUser") (:list) (:word "User")) (:block (:word "return") (:variable "this") (:object-attrib (:word "user")) (:terminator ";"))) :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" :token '(:function (:declaration (:word "function") (:word "getToken") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "token")) (:terminator ";"))) :scope '(:public) :arguments (list) :return-type (phpinspect--make-type :name "\\bool" :collection nil :contains nil :fully-qualified t)) (phpinspect--make-function :name "__construct" :token '(:function (:declaration (:word "function") (:word "__construct") (:list (:word "string") (:variable "token") (:comma ",") (:word "User") (:variable "user") (:comma ",") (:word "bool") (:variable "valid") (:assignment "=") (:word "false") (:comma ",") (:word "\\DateTime") (:variable "creation_time") (:assignment "=") (:word "null"))) (:block (:variable "this") (:object-attrib (:word "token")) (:assignment "=") (:variable "token") (:terminator ";") (:variable "this") (:object-attrib (:word "user")) (:assignment "=") (:variable "user") (:terminator ";") (:variable "this") (:object-attrib (:word "valid")) (:assignment "=") (:variable "valid") (:terminator ";") (:variable "this") (:object-attrib (:word "creation_time")) (:assignment "=") (:variable "creation_time") (:word "new") (:word "\\DateTime") (:list) (:terminator ";"))) :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/fixtures/IndexClass2.eld b/test/fixtures/IndexClass2.eld index 37993cc..8505736 100644 --- a/test/fixtures/IndexClass2.eld +++ b/test/fixtures/IndexClass2.eld @@ -1 +1 @@ -(:root (:word "declare") (:list (:word "strict_types") (:assignment "=")) (:terminator ";") (:namespace (:word "App\\Entity") (:terminator ";") (:use (:word "Doctrine\\ORM\\Mapping") (:word "as") (:word "ORM") (:terminator ";")) (:doc-block (:annotation "ORM\\Entity")) (:class (:declaration (:word "class") (:word "AuthToken")) (:block (:private (:variable "token") (:terminator ";")) (:private (:variable "extra") (:terminator ";")) (:doc-block (:var-annotation (:word "App\\\\Entity\\\\User"))) (:private (:variable "user") (:terminator ";")) (:doc-block (:var-annotation (:word "bool"))) (:private (:variable "valid") (:terminator ";")) (:doc-block (:var-annotation (:word "\\DateTime"))) (:private (:variable "creation_time") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "string") (:variable "token") (:comma ",") (:word "User") (:variable "user") (:comma ",") (:word "bool") (:variable "valid") (:assignment "=") (:word "false") (:comma ",") (:word "\\DateTime") (:variable "creation_time") (:assignment "=") (:word "null"))) (:block (:variable "this") (:object-attrib (:word "token")) (:assignment "=") (:variable "token") (:terminator ";") (:variable "this") (:object-attrib (:word "user")) (:assignment "=") (:variable "user") (:terminator ";") (:variable "this") (:object-attrib (:word "valid")) (:assignment "=") (:variable "valid") (:terminator ";") (:variable "this") (:object-attrib (:word "creation_time")) (:assignment "=") (:variable "creation_time") (:word "new") (:word "\\DateTime") (:list) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "getToken") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "token")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "getUser") (:list) (:word "User")) (:block (:word "return") (:variable "this") (:object-attrib (:word "user")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "hasStudentRole") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "role_student")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "isValid") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "valid")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "anAddedFunction") (:list)) (:block (:word "return") (:variable "this") (:object-attrib (:word "extra")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "getCreationTime") (:list) (:word "\\DateTime")) (:block (:word "return") (:variable "this") (:object-attrib (:word "creation_time")) (:terminator ";")))))))) \ No newline at end of file +(:root (:word "declare") (:list (:word "strict_types") (:assignment "=")) (:terminator ";") (:namespace (:word "App\\Entity") (:terminator ";") (:use (:word "Doctrine\\ORM\\Mapping") (:word "as") (:word "ORM") (:terminator ";")) (:doc-block (:annotation "ORM\\Entity")) (:class (:declaration (:word "class") (:word "AuthToken")) (:block (:private (:class-variable "token") (:terminator ";")) (:private (:class-variable "extra") (:terminator ";")) (:doc-block (:var-annotation (:word "App\\\\Entity\\\\User"))) (:private (:class-variable "user") (:terminator ";")) (:doc-block (:var-annotation (:word "bool"))) (:private (:class-variable "valid") (:terminator ";")) (:doc-block (:var-annotation (:word "\\DateTime"))) (:private (:class-variable "creation_time") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "string") (:variable "token") (:comma ",") (:word "User") (:variable "user") (:comma ",") (:word "bool") (:variable "valid") (:assignment "=") (:word "false") (:comma ",") (:word "\\DateTime") (:variable "creation_time") (:assignment "=") (:word "null"))) (:block (:variable "this") (:object-attrib (:word "token")) (:assignment "=") (:variable "token") (:terminator ";") (:variable "this") (:object-attrib (:word "user")) (:assignment "=") (:variable "user") (:terminator ";") (:variable "this") (:object-attrib (:word "valid")) (:assignment "=") (:variable "valid") (:terminator ";") (:variable "this") (:object-attrib (:word "creation_time")) (:assignment "=") (:variable "creation_time") (:word "new") (:word "\\DateTime") (:list) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "getToken") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "token")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "getUser") (:list) (:word "User")) (:block (:word "return") (:variable "this") (:object-attrib (:word "user")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "hasStudentRole") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "role_student")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "isValid") (:list) (:word "bool")) (:block (:word "return") (:variable "this") (:object-attrib (:word "valid")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "anAddedFunction") (:list)) (:block (:word "return") (:variable "this") (:object-attrib (:word "extra")) (:terminator ";")))) (:public (:function (:declaration (:word "function") (:word "getCreationTime") (:list) (:word "\\DateTime")) (:block (:word "return") (:variable "this") (:object-attrib (:word "creation_time")) (:terminator ";")))))))) \ No newline at end of file diff --git a/test/fixtures/NamespacedClass.eld b/test/fixtures/NamespacedClass.eld index f536a1a..d8b6d51 100644 --- a/test/fixtures/NamespacedClass.eld +++ b/test/fixtures/NamespacedClass.eld @@ -1 +1 @@ -(:root (:word "declare") (:list (:word "strict_types") (:assignment "=")) (:terminator ";") (:namespace (:word "App\\Controller") (:terminator ";") (:use (:word "Symfony\\Component\\HttpFoundation\\Response") (:terminator ";")) (:use (:word "App\\Entity\\Address") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\RedirectResponse") (:terminator ";")) (:use (:word "App\\Repository\\AddressRepository") (:terminator ";")) (:use (:word "App\\Repository\\UserRepository") (:terminator ";")) (:use (:word "Doctrine\\ORM\\EntityManagerInterface") (:terminator ";")) (:use (:word "Twig\\Environment") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\Request") (:terminator ";")) (:use (:word "Symfony\\Component\\Routing\\Annotation\\Route") (:terminator ";")) (:doc-block (:method-annotation (:word "int") (:word "holdUp") (:list (:word "Something") (:variable "thing"))) (:method-annotation (:word "Potato") (:word "holdUp") (:list (:word "OtherThing") (:variable "thing"))) (:method-annotation (:word "noReturnType") (:list (:word "Thing") (:variable "thing")))) (:class (:declaration (:word "class") (:word "AddressController")) (:block (:const (:word "A_CONSTANT_FOR_THE_SAKE_OF_HAVING_ONE") (:assignment "=") (:string "a value") (:terminator ";")) (:public (:const (:word "ARRAY_CONSTANT") (:assignment "=") (:array (:string "key") (:fat-arrow "=>") (:string "value") (:comma ",") (:string "key") (:fat-arrow "=>")) (:terminator ";"))) (:private (:variable "repo") (:terminator ";")) (:private (:variable "user_repo") (:terminator ";")) (:private (:variable "twig") (:terminator ";")) (:private (:variable "em") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "AddressRepository") (:variable "repo") (:comma ",") (:word "UserRepository") (:variable "user_repo") (:comma ",") (:word "Environment") (:variable "twig") (:comma ",") (:word "EntityManagerInterface") (:variable "em"))) (:block (:variable "this") (:object-attrib (:word "repo")) (:assignment "=") (:variable "repo") (:terminator ";") (:variable "this") (:object-attrib (:word "user_repo")) (:assignment "=") (:variable "user_repo") (:terminator ";") (:variable "this") (:object-attrib (:word "twig")) (:assignment "=") (:variable "twig") (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:assignment "=") (:variable "em") (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressPage") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "address/create.html.twig") (:comma ",") (:array (:string "user") (:fat-arrow "=>") (:variable "user") (:comma ",")))) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:variable "address_string") (:assignment "=") (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address")) (:terminator ";") (:variable "address") (:assignment "=") (:word "new") (:word "Address") (:list (:variable "user") (:comma ",") (:variable "address_string")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "persist")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "user") (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "deleteAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "address") (:assignment "=") (:variable "this") (:object-attrib (:word "repo")) (:object-attrib (:word "find")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address"))) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "remove")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "address") (:object-attrib (:word "getUser")) (:list) (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))))))) \ No newline at end of file +(:root (:word "declare") (:list (:word "strict_types") (:assignment "=")) (:terminator ";") (:namespace (:word "App\\Controller") (:terminator ";") (:use (:word "Symfony\\Component\\HttpFoundation\\Response") (:terminator ";")) (:use (:word "App\\Entity\\Address") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\RedirectResponse") (:terminator ";")) (:use (:word "App\\Repository\\AddressRepository") (:terminator ";")) (:use (:word "App\\Repository\\UserRepository") (:terminator ";")) (:use (:word "Doctrine\\ORM\\EntityManagerInterface") (:terminator ";")) (:use (:word "Twig\\Environment") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\Request") (:terminator ";")) (:use (:word "Symfony\\Component\\Routing\\Annotation\\Route") (:terminator ";")) (:doc-block (:method-annotation (:word "int") (:word "holdUp") (:list (:word "Something") (:variable "thing"))) (:method-annotation (:word "Potato") (:word "holdUp") (:list (:word "OtherThing") (:variable "thing"))) (:method-annotation (:word "noReturnType") (:list (:word "Thing") (:variable "thing")))) (:class (:declaration (:word "class") (:word "AddressController")) (:block (:const (:word "A_CONSTANT_FOR_THE_SAKE_OF_HAVING_ONE") (:assignment "=") (:string "a value") (:terminator ";")) (:public (:const (:word "ARRAY_CONSTANT") (:assignment "=") (:array (:string "key") (:fat-arrow "=>") (:string "value") (:comma ",") (:string "key") (:fat-arrow "=>")) (:terminator ";"))) (:private (:class-variable "repo") (:terminator ";")) (:private (:class-variable "user_repo") (:terminator ";")) (:private (:class-variable "twig") (:terminator ";")) (:private (:class-variable "em") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "AddressRepository") (:variable "repo") (:comma ",") (:word "UserRepository") (:variable "user_repo") (:comma ",") (:word "Environment") (:variable "twig") (:comma ",") (:word "EntityManagerInterface") (:variable "em"))) (:block (:variable "this") (:object-attrib (:word "repo")) (:assignment "=") (:variable "repo") (:terminator ";") (:variable "this") (:object-attrib (:word "user_repo")) (:assignment "=") (:variable "user_repo") (:terminator ";") (:variable "this") (:object-attrib (:word "twig")) (:assignment "=") (:variable "twig") (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:assignment "=") (:variable "em") (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressPage") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "address/create.html.twig") (:comma ",") (:array (:string "user") (:fat-arrow "=>") (:variable "user") (:comma ",")))) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:variable "address_string") (:assignment "=") (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address")) (:terminator ";") (:variable "address") (:assignment "=") (:word "new") (:word "Address") (:list (:variable "user") (:comma ",") (:variable "address_string")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "persist")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "user") (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "deleteAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "address") (:assignment "=") (:variable "this") (:object-attrib (:word "repo")) (:object-attrib (:word "find")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address"))) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "remove")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "address") (:object-attrib (:word "getUser")) (:list) (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))))))) \ No newline at end of file diff --git a/test/phpinspect-test-env.el b/test/phpinspect-test-env.el new file mode 100644 index 0000000..6bb0aef --- /dev/null +++ b/test/phpinspect-test-env.el @@ -0,0 +1,41 @@ +;;; phpinspect-test-env.el --- Unit tests for phpinspect.el -*- lexical-binding: t; -*- + +(require 'phpinspect-worker) +(require 'phpinspect-cache) + +;; Make sure that the worker is running. TODO: fully encapsulate the worker the +;; data types that are used in tests so that we don't depend on some global +;; worker object for tests. +(phpinspect-ensure-worker) +(phpinspect-purge-cache) + +(defvar phpinspect-test-directory + (file-name-directory + (or load-file-name + buffer-file-name)) + "Directory that phpinspect tests reside in.") + + +(defvar phpinspect-test-php-file-directory + (concat + (file-name-directory + (or load-file-name + buffer-file-name)) + "/fixtures") + "Directory with syntax trees of example PHP files.") + +(defun phpinspect-test-read-fixture-data (name) + (with-temp-buffer + (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"))) + +(provide 'phpinspect-test-env) diff --git a/test/phpinspect-test.el b/test/phpinspect-test.el index a4e50bb..88f2070 100644 --- a/test/phpinspect-test.el +++ b/test/phpinspect-test.el @@ -26,40 +26,9 @@ (require 'ert) (require 'phpinspect) -;; Make sure that the worker is running. TODO: fully encapsulate the worker the -;; data types that are used in tests so that we don't depend on some global -;; worker object for tests. -(phpinspect-ensure-worker) -(phpinspect-purge-cache) - -(defvar phpinspect-test-directory - (file-name-directory - (or load-file-name - buffer-file-name)) - "Directory that phpinspect tests reside in.") - - -(defvar phpinspect-test-php-file-directory - (concat - (file-name-directory - (or load-file-name - buffer-file-name)) - "/fixtures") - "Directory with syntax trees of example PHP files.") - -(defun phpinspect-test-read-fixture-data (name) - (with-temp-buffer - (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"))) +(require 'phpinspect-test-env + (concat (file-name-directory (or load-file-name buffer-file-name)) + "phpinspect-test-env.el")) (ert-deftest phpinspect-get-variable-type-in-block () (let* ((code "class Foo { function a(\\Thing $baz) { $foo = new \\DateTime(); $bar = $foo; Whatever comes after don't matter.") @@ -544,6 +513,7 @@ class Thing (load-file (concat phpinspect-test-directory "/test-parse-context.el")) (load-file (concat phpinspect-test-directory "/test-splayt.el")) (load-file (concat phpinspect-test-directory "/test-pipeline.el")) +(load-file (concat phpinspect-test-directory "/test-toc.el")) (provide 'phpinspect-test) diff --git a/test/test-buffer.el b/test/test-buffer.el index eee4692..5376152 100644 --- a/test/test-buffer.el +++ b/test/test-buffer.el @@ -26,7 +26,9 @@ (require 'ert) (require 'phpinspect-parser) (require 'phpinspect-buffer) - +(require 'phpinspect-test-env + (concat (file-name-directory (or load-file-name buffer-file-name)) + "phpinspect-test-env.el")) (ert-deftest phpinspect-buffer-region-lookups () (let* ((parsed) @@ -285,3 +287,185 @@ class YYY { (setq parsed-after (phpinspect-buffer-parse buffer 'no-interrupt)) (should (equal parsed parsed-after)))) + + +(ert-deftest phpinspect-buffer-index-classes () + (let* ((buffer (phpinspect-make-buffer :project (phpinspect--make-project :autoload (phpinspect-make-autoloader)))) + (namespaces (phpinspect-make-splayt)) + (declarations (phpinspect-make-splayt)) + (classes (phpinspect-make-splayt)) + (root (phpinspect-make-meta nil 1 200 "" 'root))) + (phpinspect-splayt-insert + namespaces 1 (phpinspect-meta-set-parent + (phpinspect-make-meta nil 1 100 "" '(:namespace (:word "TestNamespace") (:terminator ";"))) + root)) + (phpinspect-splayt-insert + declarations 20 + (phpinspect-make-meta nil 20 40 "" '(:declaration (:word "class") (:word "TestClass") (:word "extends") (:word "OtherTestClass")))) + + + (phpinspect-splayt-insert classes 20 (phpinspect-make-meta nil 20 80 "" '(:class (:comment "bla") '(:declaration (:word "class") (:word "TestClass") (:word "extends") (:word "OtherTestClass"))))) + + (phpinspect-buffer-index-declarations buffer declarations) + (phpinspect-buffer-index-namespaces buffer namespaces) + (phpinspect-buffer-index-classes buffer classes) + + (should (phpinspect-project-get-class (phpinspect-buffer-project buffer) (phpinspect--make-type :name "\\TestNamespace\\TestClass"))) + + (should (= 2 (hash-table-count (phpinspect-project-class-index (phpinspect-buffer-project buffer))))) + (should (= 1 (length (phpinspect--class-extended-classes + (phpinspect-project-get-class + (phpinspect-buffer-project buffer) + (phpinspect--make-type :name "\\TestNamespace\\TestClass")))))) + + (let ((new-declarations (phpinspect-make-splayt)) + (new-classes (phpinspect-make-splayt))) + (phpinspect-splayt-insert + new-declarations + 20 + (phpinspect-meta-set-parent + (phpinspect-make-meta nil 20 40 "" '(:declaration (:word "class") (:word "TestClass"))) + root)) + + (phpinspect-splayt-insert + new-classes 20 + (phpinspect-meta-set-parent + (phpinspect-make-meta nil 20 80 "" '(:class (:comment "bla") '(:declaration (:word "class") (:word "TestClass")))) + root)) + + (setf (phpinspect-buffer-map buffer) (phpinspect-make-bmap :-root-meta root)) + + (phpinspect-buffer-index-declarations buffer new-declarations) + (phpinspect-buffer-index-classes buffer new-classes) + (should (phpinspect-project-get-class + (phpinspect-buffer-project buffer) + (phpinspect--make-type :name "\\TestNamespace\\TestClass"))) + + (should (= 0 (length (phpinspect--class-extended-classes + (phpinspect-project-get-class + (phpinspect-buffer-project buffer) + (phpinspect--make-type :name "\\TestNamespace\\TestClass"))))))) + + (let ((new-classes (phpinspect-make-splayt)) + (new-root (phpinspect-make-meta nil 1 400 "" 'new-root))) + (setf (phpinspect-bmap--root-meta (phpinspect-buffer-map buffer)) new-root) + (phpinspect-buffer-index-classes buffer new-classes) + + (should-not (phpinspect-project-get-class + (phpinspect-buffer-project buffer) + (phpinspect--make-type :name "\\TestNamespace\\TestClass"))) + + (should (= 1 (hash-table-count (phpinspect-project-class-index (phpinspect-buffer-project buffer)))))))) + +(ert-deftest phpinspect-buffer-index-functions () + (let ((buffer (phpinspect-make-buffer :project (phpinspect--make-project :autoload (phpinspect-make-autoloader)))) + (namespaces (phpinspect-make-splayt)) + (declarations (phpinspect-make-splayt)) + (classes (phpinspect-make-splayt)) + (functions (phpinspect-make-splayt))) + + (phpinspect-splayt-insert + namespaces 10 + (phpinspect-make-meta nil 10 200 "" '(:namespace (:word "NS") (:terminator ";")))) + + + (phpinspect-splayt-insert + declarations 20 + (phpinspect-make-meta nil 20 30 "" '(:declaration (:word "class") (:word "TestClass")))) + (phpinspect-splayt-insert + classes 20 + (phpinspect-make-meta nil 20 70 "" '(:class (:declaration (:word "class") (:word "TestClass"))))) + + + (phpinspect-splayt-insert + declarations 40 + (phpinspect-make-meta nil 40 45 "" '(:declaration (:word "testMethod") (:list) (:word "RelativeType")))) + + (phpinspect-splayt-insert + functions 40 + (phpinspect-make-meta nil 40 50 "" '(:function (:declaration (:word "testMethod") (:list) (:word "RelativeType"))))) + + (phpinspect-buffer-index-declarations buffer declarations) + (phpinspect-buffer-index-namespaces buffer namespaces) + (phpinspect-buffer-index-classes buffer classes) + + (phpinspect-buffer-index-functions buffer functions) + + (should (phpinspect-project-get-class + (phpinspect-buffer-project buffer) + (phpinspect--make-type :name "\\NS\\TestClass"))) + + (should (= 1 (hash-table-count (phpinspect--class-methods + (phpinspect-project-get-class + (phpinspect-buffer-project buffer) + (phpinspect--make-type :name "\\NS\\TestClass")))))) + + (setf (phpinspect-buffer-map buffer) (phpinspect-make-bmap :-root-meta (phpinspect-make-meta nil 1 400 "" 'root))) + + (phpinspect-buffer-index-functions buffer (phpinspect-make-splayt)) + + (should (= 0 (hash-table-count (phpinspect--class-methods + (phpinspect-project-get-class + (phpinspect-buffer-project buffer) + (phpinspect--make-type :name "\\NS\\TestClass")))))))) + +(ert-deftest phpinspect-buffer-index-class-variables () + (let ((buffer (phpinspect-make-buffer :project (phpinspect--make-project :autoload (phpinspect-make-autoloader)))) + (namespaces (phpinspect-make-splayt)) + (declarations (phpinspect-make-splayt)) + (classes (phpinspect-make-splayt)) + (functions (phpinspect-make-splayt)) + (variables (phpinspect-make-splayt))) + + (phpinspect-splayt-insert + functions 60 + (phpinspect-make-meta + nil 60 65 "" + (cadr (phpinspect-parse-string + "banana = $thing; }")))) + + + (phpinspect-splayt-insert + declarations 20 + (phpinspect-make-meta nil 20 30 "" '(:declaration (:word "class") (:word "TestClass")))) + (phpinspect-splayt-insert + classes 20 + (phpinspect-make-meta nil 20 70 "" '(:class (:declaration (:word "class") (:word "TestClass"))))) + + (phpinspect-splayt-insert + variables 33 + (phpinspect-make-meta nil 33 50 "" '(:class-variable "banana"))) + + (phpinspect-splayt-insert + variables 54 + (phpinspect-make-meta nil 54 60 "" '(:const (:word "CONSTANT")))) + + (phpinspect-buffer-index-declarations buffer declarations) + (phpinspect-buffer-index-namespaces buffer namespaces) + (phpinspect-buffer-index-classes buffer classes) + (phpinspect-buffer-index-functions buffer functions) + + (phpinspect-buffer-index-class-variables buffer variables) + + (should (phpinspect-project-get-class + (phpinspect-buffer-project buffer) + (phpinspect--make-type :name "\\TestClass"))) + + (should (= 2 (length (phpinspect--class-variables + (phpinspect-project-get-class + (phpinspect-buffer-project buffer) + (phpinspect--make-type :name "\\TestClass")))))) + + + (should (= 1 (length (phpinspect--class-get-constants + (phpinspect-project-get-class + (phpinspect-buffer-project buffer) + (phpinspect--make-type :name "\\TestClass")))))) + + (should (phpinspect--type= (phpinspect--make-type :name "\\array") + (phpinspect--variable-type + (phpinspect--class-get-variable + (phpinspect-project-get-class + (phpinspect-buffer-project buffer) + (phpinspect--make-type :name "\\TestClass")) + "banana")))))) diff --git a/test/test-class.el b/test/test-class.el index 4d69e86..0dbfb88 100644 --- a/test/test-class.el +++ b/test/test-class.el @@ -25,6 +25,11 @@ (require 'ert) (require 'phpinspect-class) +(require 'phpinspect-project) +(require 'subr-x) +(require 'phpinspect-worker) + +(phpinspect-ensure-worker) (ert-deftest phpinspect--merge-method-return-type () (let* ((class-name (phpinspect--make-type :name "\\Something")) @@ -40,3 +45,67 @@ (phpinspect--function-return-type result))) (should (phpinspect--type= (phpinspect--make-type :name "\\bool") (phpinspect--function-return-type method1))))) + +(ert-deftest phpinspect-class-incorporate () + (let ((class (phpinspect--make-class-generated)) + (other-class (phpinspect--make-class-generated))) + (phpinspect--class-set-index class `(phpinspect--indexed-class (class-name . ,(phpinspect--make-type :name "Class")))) + (phpinspect--class-set-index other-class `(phpinspect--indexed-class (class-name . ,(phpinspect--make-type :name "OtherClass")))) + (phpinspect--class-update-method + class (phpinspect--make-function :name "test" :return-type phpinspect--null-type)) + + (phpinspect--class-update-method + other-class (phpinspect--make-function :name "other-test" :return-type phpinspect--null-type)) + + (phpinspect--class-incorporate class other-class) + + (should (= 2 (length (hash-table-values (phpinspect--class-methods class))))) + (should (= 1 (length (hash-table-values (phpinspect--class-subscriptions other-class))))) + + (phpinspect--class-set-index + class + `(phpinspect--indexed-class + (complete . t) + (class-name . ,(phpinspect--make-type :name "Class")) + (methods . ,(list (phpinspect--make-function :name "test" :return-type phpinspect--null-type) + (phpinspect--make-function :name "foobar" :return-type phpinspect--null-type))))) + + (should (= 3 (length (hash-table-values (phpinspect--class-methods class))))) + + (phpinspect--class-incorporate class other-class) + (should (= 3 (length (hash-table-values (phpinspect--class-methods class))))) + + (phpinspect--class-set-index + class + `(phpinspect--indexed-class + (complete . t) + (class-name . ,(phpinspect--make-type :name "Class")) + (methods . ,(list (phpinspect--make-function :name "foobar" :return-type phpinspect--null-type))))) + + (should (= 2 (length (hash-table-values (phpinspect--class-methods class))))) + (should (phpinspect--class-get-method class (phpinspect-intern-name "other-test"))) + (should (phpinspect--class-get-method class (phpinspect-intern-name "foobar"))) + + (phpinspect--class-set-index + class + `(phpinspect--indexed-class + (complete . t) + (class-name . ,(phpinspect--make-type :name "Class")) + (methods))) + + (should (= 1 (length (hash-table-values (phpinspect--class-methods class))))) + (should (phpinspect--class-get-method class (phpinspect-intern-name "other-test"))) + + (phpinspect--class-incorporate class other-class) + (should (= 1 (length (hash-table-values (phpinspect--class-methods class))))) + (should (= 1 (length (hash-table-values (phpinspect--class-subscriptions other-class))))))) + +(ert-deftest phpinspect--class-update-declaration () + (let ((class (phpinspect--make-class-generated :project (phpinspect--make-project)))) + (phpinspect--class-update-declaration class '(:declaration (:word "class") (:word "TestClass") + (:word "extends") (:word "OtherClass") + (:word "implements") (:word "ImplClass")) + nil "NS") + (should (= 2 (length (phpinspect--class-extended-classes class)))) + (should (phpinspect--type= (phpinspect--make-type :name "\\NS\\TestClass" :fully-qualified t) + (phpinspect--class-name class))))) diff --git a/test/test-edtrack.el b/test/test-edtrack.el index 22db225..b12ddc8 100644 --- a/test/test-edtrack.el +++ b/test/test-edtrack.el @@ -1,3 +1,5 @@ +;;; test-edtrack.el --- Unit tests for phpinspect.el -*- lexical-binding: t; -*- + (require 'ert) (require 'phpinspect-edtrack) (require 'phpinspect-meta) diff --git a/test/test-index.el b/test/test-index.el index ab426f1..7bee75d 100644 --- a/test/test-index.el +++ b/test/test-index.el @@ -46,13 +46,22 @@ (classes (,(phpinspect--make-type :name"\\Potato" :fully-qualified t) phpinspect--indexed-class + (complete . t) (class-name . ,(phpinspect--make-type :name "\\Potato" :fully-qualified t)) + (declaration . (:declaration (:word "class") (:word "Potato"))) (location . (0 0)) (imports) (methods) (static-methods . (,(phpinspect--make-function :name "staticMethod" :scope '(:public) + :token '(:function (:declaration (:word "function") + (:word "staticMethod") + (:list (:variable "untyped") + (:comma) + (:word "array") + (:variable "things"))) + (:block)) :arguments `(("untyped" nil) ("things" ,(phpinspect--make-type :name "\\array" :collection t diff --git a/test/test-meta.el b/test/test-meta.el new file mode 100644 index 0000000..f20e3eb --- /dev/null +++ b/test/test-meta.el @@ -0,0 +1,67 @@ +;; test-meta.el --- Unit tests for phpinspect.el -*- lexical-binding: t; -*- + +;; Copyright (C) 2021 Free Software Foundation, Inc. + +;; Author: Hugo Thunnissen + +;; 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 'ert) +(require 'phpinspect-meta) + +(ert-deftest phpinspect-meta-start-relative-to-parent () + (let ((meta (phpinspect-make-meta nil 10 20 "" 'token)) + (parent1 (phpinspect-make-meta nil 9 22 "" 'token)) + (parent2 (phpinspect-make-meta nil 0 100 "" 'token))) + (phpinspect-meta-set-parent meta parent1) + (phpinspect-meta-set-parent parent1 parent2) + + (should (= 10 (phpinspect-meta-start meta))) + + (phpinspect-meta-shift parent2 20) + (should (= 30 (phpinspect-meta-start meta))) + + (should (phpinspect-meta-overlaps-point meta 30)))) + +(ert-deftest phpinspect-meta-iterator () + (let* ((meta (phpinspect-make-meta nil 10 20 "" 'token)) + (firstchild (phpinspect-make-meta nil 10 12 "" 'token)) + (secondchild (phpinspect-make-meta nil 13 15 "" 'token)) + (parent1 (phpinspect-make-meta nil 9 22 "" 'token)) + (sibling (phpinspect-make-meta nil 30 55 "" 'token)) + (parent2 (phpinspect-make-meta nil 0 100 "" 'token)) + iterator) + (phpinspect-meta-set-parent meta parent1) + (phpinspect-meta-set-parent parent1 parent2) + (phpinspect-meta-set-parent sibling parent2) + (phpinspect-meta-set-parent firstchild meta) + (phpinspect-meta-set-parent secondchild meta) + + (setq iterator (phpinspect-make-meta-iterator parent2)) + + (should (eq meta (phpinspect-meta-iterator-token-at-point iterator 10))) + (should (eq sibling (phpinspect-meta-iterator-token-at-point iterator 30))) + (should (eq meta (phpinspect-meta-iterator-token-at-point iterator 10))) + (should (eq firstchild (phpinspect-meta-iterator-token-at-point iterator 10))) + (should (eq secondchild (phpinspect-meta-iterator-token-at-point iterator 13))) + (should (eq meta (phpinspect-meta-iterator-token-at-point iterator 10))) + (should (eq firstchild (phpinspect-meta-iterator-token-at-point iterator 10))) + (should (eq sibling (phpinspect-meta-iterator-token-at-point iterator 30))))) diff --git a/test/test-splayt.el b/test/test-splayt.el index 7eacf7d..cf64dd5 100644 --- a/test/test-splayt.el +++ b/test/test-splayt.el @@ -163,3 +163,12 @@ (should (equal (sort '("eight" "nine" "eleven" "twelve") #'string-lessp) (sort (phpinspect-splayt-find-all-after tree 7) #'string-lessp))))) + +(ert-deftest phpinspect-splayt-to-list () + (let ((tree (phpinspect-make-splayt))) + (phpinspect-splayt-insert tree 3 "three") + (phpinspect-splayt-insert tree 1 "one") + (phpinspect-splayt-insert tree 2 "two") + + + (should (equal '("one" "two" "three") (phpinspect-splayt-to-list tree))))) diff --git a/test/test-toc.el b/test/test-toc.el new file mode 100644 index 0000000..99d7582 --- /dev/null +++ b/test/test-toc.el @@ -0,0 +1,50 @@ +;;; test-edtrack.el --- Unit tests for phpinspect.el -*- lexical-binding: t; -*- + +(require 'phpinspect-toc) +(require 'phpinspect-splayt) + +(ert-deftest phpinspect-make-toc () + (let ((tokens (phpinspect-make-splayt)) + toc) + (phpinspect-splayt-insert tokens 1 (phpinspect-make-meta nil 1 20 "" 'token1)) + (phpinspect-splayt-insert tokens 40 (phpinspect-make-meta nil 40 45 "" 'token2)) + (phpinspect-splayt-insert tokens 55 (phpinspect-make-meta nil 55 70 "" 'token3)) + + (setq toc (phpinspect-make-toc tokens)) + + (should (= 3 (hash-table-count (phpinspect-toc-table toc)))) + (should (= 3 (length (phpinspect-splayt-to-list (phpinspect-toc-tree toc))))))) + +(ert-deftest phpinspect-update-toc () + (let ((tokens (phpinspect-make-splayt)) + (root (phpinspect-make-meta nil 1 200 "" 'root)) + (new-root (phpinspect-make-meta nil 1 400 "" 'root)) + (tok1 (phpinspect-make-meta nil 1 20 "" 'token1)) + (tok2 (phpinspect-make-meta nil 40 45 "" 'token2)) + (tok3 (phpinspect-make-meta nil 55 70 "" 'token3)) + (tok4 (phpinspect-make-meta nil 71 91 "" 'token4)) + new-tokens toc) + + (phpinspect-meta-set-parent tok1 root) + (phpinspect-meta-set-parent tok2 root) + (phpinspect-meta-set-parent tok3 root) + + (phpinspect-splayt-insert tokens 1 tok1) + (phpinspect-splayt-insert tokens 40 tok2) + (phpinspect-splayt-insert tokens 55 tok3) + + (setq toc (phpinspect-make-toc tokens)) + + (phpinspect-meta-set-parent tok2 new-root) + (phpinspect-meta-set-parent tok3 new-root) + (phpinspect-meta-set-parent tok4 new-root) + + (setq new-tokens (phpinspect-make-splayt)) + (phpinspect-splayt-insert new-tokens 71 tok4) + + (pcase-let ((`(,result-new ,result-deleted) (phpinspect-toc-update toc new-tokens new-root))) + (should (= 1 (length result-new))) + (should (= 1 (length result-deleted))) + + (should (eq tok1 (car result-deleted))) + (should (eq tok4 (car result-new))))))