Reimplement `phpinspect-fix-imports' using metadata objects

WIP-cache
Hugo Thunnissen 10 months ago
parent 135263c533
commit 9b82c0d0f6

@ -35,7 +35,14 @@
(goto-char point)
(insert data)))
(defun phpinspect-add-use (fqn buffer &optional namespace-token)
(defun phpinspect-find-first-use (token-meta)
(if (and (phpinspect-namespace-p (phpinspect-meta-token token-meta))
(phpinspect-namespace-is-blocked-p (phpinspect-meta-token token-meta)))
(phpinspect-find-first-use (phpinspect-meta-last-child token-meta))
(phpinspect-meta-find-first-child-matching
token-meta (phpinspect-meta-wrap-token-pred #'phpinspect-use-p))))
(defun phpinspect-add-use (fqn buffer &optional namespace-meta)
"Add use statement for FQN to BUFFER.
If NAMESPACE-TOKEN is non-nil, it is assumed to be a token that
@ -44,46 +51,47 @@ buffer position to insert the use statement at."
(when (string-match "^\\\\" fqn)
(setq fqn (string-trim-left fqn "\\\\")))
(if namespace-token
(let* ((meta (phpinspect-bmap-token-meta
(phpinspect-buffer-map buffer) namespace-token))
(existing-use (seq-find #'phpinspect-use-p
(phpinspect-namespace-body namespace-token)))
(namespace-block (phpinspect-namespace-block namespace-token)))
(if namespace-meta
(let* ((namespace-block (and (phpinspect-namespace-is-blocked-p
(phpinspect-meta-token namespace-meta))
(phpinspect-meta-last-child namespace-meta)))
(existing-use (phpinspect-find-first-use namespace-meta)))
(if existing-use
(phpinspect-insert-at-point
(phpinspect-meta-start
(phpinspect-buffer-token-meta buffer existing-use))
(format "use %s;%c" fqn ?\n))
(phpinspect-meta-start existing-use) (format "use %s;%c" fqn ?\n))
(if namespace-block
(phpinspect-insert-at-point
(+ 1 (phpinspect-meta-start
(phpinspect-buffer-token-meta buffer namespace-block)))
(+ 1 (phpinspect-meta-start namespace-block))
(format "%c%cuse %s;%c" ?\n ?\n fqn ?\n))
(phpinspect-insert-at-point
(phpinspect-meta-end
(phpinspect-buffer-token-meta
buffer (seq-find #'phpinspect-terminator-p namespace-token)))
(phpinspect-meta-find-first-child-matching
namespace-meta (phpinspect-meta-wrap-token-pred #'phpinspect-terminator-p)))
(format "%c%cuse %s;%c" ?\n ?\n fqn ?\n)))))
;; else
(let ((existing-use (seq-find #'phpinspect-use-p
(phpinspect-buffer-tree buffer))))
(let ((existing-use (phpinspect-meta-find-first-child-matching
(phpinspect-buffer-root-meta buffer)
(phpinspect-meta-wrap-token-pred #'phpinspect-use-p))))
(if existing-use
(phpinspect-insert-at-point
(phpinspect-meta-start
(phpinspect-buffer-token-meta buffer existing-use))
(phpinspect-meta-start existing-use)
(format "use %s;%c" fqn ?\n))
(let ((first-token (cadr (phpinspect-buffer-tree buffer))))
(if (and (phpinspect-word-p first-token)
(string= "declare" (cadr first-token)))
(let* ((first-token (phpinspect-meta-first-child (phpinspect-buffer-root-meta buffer)))
token-after)
(message "First token %s" (phpinspect-meta-string first-token))
(when (and (phpinspect-word-p (phpinspect-meta-token first-token))
(string= "declare" (cadr (phpinspect-meta-token first-token))))
(progn
(setq token-after first-token)
(while (and token-after (not (phpinspect-terminator-p
(phpinspect-meta-token token-after))))
(setq token-after (phpinspect-meta-find-right-sibling token-after))
(message "Token after: %s" (phpinspect-meta-string token-after)))))
(if token-after
(phpinspect-insert-at-point
(phpinspect-meta-end
(phpinspect-buffer-token-meta
buffer (seq-find #'phpinspect-terminator-p (phpinspect-buffer-tree buffer))))
(format "%c%cuse %s;%c" ?\n ?\n fqn ?\n))
(phpinspect-meta-end token-after) (format "%c%cuse %s;%c" ?\n ?\n fqn ?\n))
(phpinspect-insert-at-point
(phpinspect-meta-start
(phpinspect-buffer-token-meta buffer first-token))
(phpinspect-meta-start first-token)
(format "%c%cuse %s;%c%c" ?\n ?\n fqn ?\n ?\n))))))))
(defun phpinspect-add-use-interactive (typename buffer project &optional namespace-token)
@ -109,10 +117,10 @@ buffer position to insert the use statement at."
that there are import (\"use\") statements for them."
(interactive)
(if phpinspect-current-buffer
(let* ((tree (phpinspect-buffer-parse phpinspect-current-buffer))
(let* ((buffer phpinspect-current-buffer)
(tree (phpinspect-buffer-parse buffer))
(index (phpinspect--index-tokens
tree nil (phpinspect-buffer-location-resolver
phpinspect-current-buffer)))
tree nil (phpinspect-buffer-location-resolver buffer)))
(classes (alist-get 'classes index))
(imports (alist-get 'imports index))
(project (phpinspect--cache-get-project-create
@ -122,20 +130,23 @@ that there are import (\"use\") statements for them."
(let* ((class-imports (alist-get 'imports class))
(used-types (alist-get 'used-types class))
(class-name (alist-get 'class-name class))
(region))
(dolist (type used-types)
;; Retrieve latest version of class location data changes with
;; each added use statement + reindex.
(setq region
(alist-get 'location
(phpinspect-index-get-class
index class-name)))
(let ((namespace
(seq-find (lambda (meta) (phpinspect-namespace-p (phpinspect-meta-token meta)))
(phpinspect-buffer-tokens-enclosing-point
phpinspect-current-buffer (phpinspect-region-start region)))))
(region (alist-get 'location class))
token-meta namespace)
(message "Region: %s" region)
(message "index: %s" index)
(setq token-meta (phpinspect-meta-find-parent-matching-token
(phpinspect-bmap-last-token-before-point
(phpinspect-buffer-map buffer)
(+ (phpinspect-region-start region) 1))
#'phpinspect-class-p))
(unless token-meta
(error "Unable to find token for class %s" class-name))
(dolist (type used-types)
(setq namespace (phpinspect-meta-find-parent-matching-token
token-meta #'phpinspect-namespace-p))
;; Add use statements for types that aren't imported.
(unless (or (or (alist-get type class-imports)
(alist-get type imports))
@ -147,14 +158,7 @@ that there are import (\"use\") statements for them."
(phpinspect-autoloader-types
(phpinspect-project-autoload project))))
(phpinspect-add-use-interactive
type phpinspect-current-buffer project (phpinspect-meta-token namespace))
;; Buffer has been modified by adding type, update buffer map
;; and index for correct location data.
(setq index
(phpinspect--index-tokens
(phpinspect-buffer-parse phpinspect-current-buffer)
nil
(phpinspect-buffer-location-resolver
phpinspect-current-buffer)))))))))))
type buffer project namespace)
(phpinspect-buffer-parse buffer 'no-interrupt))))))))
(provide 'phpinspect-imports)

@ -133,6 +133,12 @@
(phpinspect-splayt-find-largest-before (phpinspect-meta-children (phpinspect-meta-parent meta))
(phpinspect-meta-parent-offset meta))))
(cl-defmethod phpinspect-meta-find-right-sibling ((meta (head meta)))
(when (phpinspect-meta-parent meta)
(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))))
@ -162,6 +168,10 @@
(phpinspect-splayt-find-largest-before
(phpinspect-meta-children meta) (phpinspect-meta--point-offset meta point)))
(cl-defmethod phpinspect-meta-find-child-after ((meta (head meta)) (point integer))
(phpinspect-splayt-find-smallest-after
(phpinspect-meta-children meta) (phpinspect-meta--point-offset meta point)))
(cl-defmethod phpinspect-meta-find-child-before-recursively ((meta (head meta)) (point integer))
(let ((child meta)
last)
@ -180,6 +190,18 @@
(phpinspect-meta-children meta) (phpinspect-meta--point-offset meta point))
#'phpinspect-meta-sort-start))
(cl-defmethod phpinspect-meta-find-first-child-matching ((meta (head meta)) predicate)
(catch 'return
(phpinspect-splayt-traverse-lr (child (phpinspect-meta-children meta))
(when (funcall predicate child)
(throw 'return child)))))
(cl-defmethod phpinspect-meta-last-child ((meta (head meta)))
(phpinspect-meta-find-child-before meta (phpinspect-meta-end meta)))
(cl-defmethod phpinspect-meta-first-child ((meta (head meta)))
(phpinspect-meta-find-child-after meta (- (phpinspect-meta-start meta) 1)))
(defun phpinspect-meta-string (meta)
(if meta

@ -93,6 +93,9 @@ apeared to be a little more performant than using `let'."
(define-inline phpinspect-splayt-root-node (splayt)
(inline-quote (car ,splayt)))
(define-inline phpinspect-splayt-empty-p (splayt)
(inline-quote (not (phpinspect-splayt-root-node ,splayt))))
(define-inline phpinspect-splayt-node-rotate-right (node &optional splayt)
(inline-letevals (node splayt)
(inline-quote
@ -216,7 +219,7 @@ apeared to be a little more performant than using `let'."
(define-inline phpinspect-splayt-insert-node (splayt node)
(inline-letevals (splayt node (parent (inline-quote (phpinspect-splayt-node-temp-store ,node))))
(inline-quote
(if (not (phpinspect-splayt-root-node ,splayt))
(if (phpinspect-splayt-empty-p ,splayt)
(setf (phpinspect-splayt-root-node ,splayt) ,node)
(progn
(setf ,parent (phpinspect-splayt-find-insertion-node ,splayt (phpinspect-splayt-node-key ,node)))
@ -292,6 +295,33 @@ near the top of the tee."
(,(car place-and-splayt) (phpinspect-splayt-root-node ,(cadr place-and-splayt)))
,@body))
(defmacro phpinspect-splayt-node-traverse-lr (place-and-node &rest body)
(declare (indent 1))
(let ((place (car place-and-node))
(current (gensym))
(stack (gensym)))
`(let* ((,current ,(cadr place-and-node))
,stack
,@(if (symbolp place) (list place)))
(while (or ,stack ,current)
(if ,current
(progn
(push ,current ,stack)
(setq ,current (phpinspect-splayt-node-left ,current)))
(setq ,current (pop ,stack))
(setf ,place (phpinspect-splayt-node-value ,current))
,@body
(setq ,current (phpinspect-splayt-node-right ,current)))))))
(defmacro phpinspect-splayt-traverse-lr (place-and-splayt &rest body)
"Traverse splay tree in cadr of PLACE-AND-SPLAYT depth-first from left to right, executing BODY.
The car of PLACE-AND-SPLAYT is assigned the value of each node."
(declare (indent 1))
`(phpinspect-splayt-node-traverse-lr
(,(car place-and-splayt) (phpinspect-splayt-root-node ,(cadr place-and-splayt)))
,@body))
(define-inline phpinspect-splayt-node-key-less-p (node key)
(inline-quote (> ,key (phpinspect-splayt-node-key ,node))))

@ -101,6 +101,23 @@
(should (equal expected result)))))
(ert-deftest phpinspect-splayt-traverse-lr ()
(let ((tree (phpinspect-make-splayt)))
(phpinspect-splayt-insert tree 9 "nine")
(phpinspect-splayt-insert tree 3 "three")
(phpinspect-splayt-insert tree 11 "eleven")
(phpinspect-splayt-insert tree 8 "eight")
(phpinspect-splayt-insert tree 12 "twelve")
(phpinspect-splayt-insert tree 4 "four")
(phpinspect-splayt-insert tree 1 "one")
(let ((expected '("one" "three" "four" "eight" "nine" "eleven" "twelve"))
result)
(phpinspect-splayt-traverse-lr (item tree)
(setq result (nconc result (list item))))
(should (equal expected result)))))
(ert-deftest phpinspect-splayt-find-smallest-after ()
(let ((tree (phpinspect-make-splayt)))
(phpinspect-splayt-insert tree 9 "nine")

Loading…
Cancel
Save