Adapt resolvecontext to use metadata tree

WIP-incremental-parsing
Hugo Thunnissen 10 months ago
parent 35a89eb554
commit 292b4ca123

@ -768,13 +768,13 @@ executing.")
(doc-block (save-restriction
(goto-char region-start)
(narrow-to-region region-start region-end)
(funcall parser (current-buffer) (point-max)))))
(funcall parser (current-buffer) (point-max) nil 'root))))
(forward-char 2)
doc-block))
(t
(let ((parser (phpinspect-get-parser-func 'comment))
(end-position (line-end-position)))
(funcall parser (current-buffer) end-position)))))
(funcall parser (current-buffer) end-position nil 'root)))))
(phpinspect-defhandler variable (start-token &rest _ignored)
"Handler for tokens indicating reference to a variable"
@ -818,7 +818,7 @@ executing.")
(forward-char (length start-token))
(let ((parser (phpinspect-get-parser-func 'use)))
(funcall parser (current-buffer) max-point)))
(funcall parser (current-buffer) max-point nil 'root)))
(phpinspect-defhandler attribute-reference (start-token &rest _ignored)
"Handler for references to object attributes, or static class attributes."
@ -864,7 +864,7 @@ executing.")
(setq start-token (phpinspect--strip-word-end-space start-token))
(forward-char (length start-token))
(let* ((parser (phpinspect-get-parser-func 'const))
(token (funcall parser (current-buffer) max-point)))
(token (funcall parser (current-buffer) max-point nil 'root)))
(when (phpinspect-incomplete-token-p (car (last token)))
(setcar token :incomplete-const))
token))
@ -890,7 +890,7 @@ static keywords with the same meaning as in a class block."
(continue-condition (lambda ()
(not (and (char-equal (char-after) ?})
(setq complete-block t)))))
(parsed (funcall parser (current-buffer) max-point continue-condition)))
(parsed (funcall parser (current-buffer) max-point continue-condition 'root)))
(if complete-block
(forward-char)
(setcar parsed :incomplete-block))
@ -912,7 +912,7 @@ static keywords with the same meaning as in a class block."
(continue-condition (lambda ()
(not (and (char-equal (char-after) ?})
(setq complete-block t)))))
(parsed (funcall parser (current-buffer) max-point continue-condition)))
(parsed (funcall parser (current-buffer) max-point continue-condition 'root)))
(if complete-block
(forward-char)
(setcar parsed :incomplete-block))

@ -73,9 +73,42 @@ list it was called on."
(cl-defstruct (phpinspect-slice (:constructor phpinspect-make-slice))
"A window to a subsection of a (`phpinspect-llnode') linked list. "
(reversed nil
:type bool
:documentation
"Whether the slice should be iterated in reverse")
(start nil)
(end nil))
(defmacro phpinspect-doslice (place-and-slice &rest body)
(declare (indent defun))
(let ((list (gensym))
(slice-end (gensym))
(normal-next-function #'phpinspect-llnode-right)
(reverse-next-function #'phpinspect-llnode-left))
`(if (phpinspect-slice-reversed ,(cadr place-and-slice))
(let ((,list (phpinspect-slice-end ,(cadr place-and-slice)))
(,slice-end (phpinspect-llnode-left
(phpinspect-slice-start ,(cadr place-and-slice)))))
(when (phpinspect-llnode-value ,list)
(while (and ,list (not (eq ,slice-end ,list)))
(let ((,(car place-and-slice) (phpinspect-llnode-value ,list)))
,@body)
(setq ,list (,reverse-next-function ,list)))))
(let ((,list (phpinspect-slice-start ,(cadr place-and-slice)))
(,slice-end (phpinspect-llnode-right
(phpinspect-slice-end ,(cadr place-and-slice)))))
(while (and ,list (not (eq ,slice-end ,list)))
(let ((,(car place-and-slice) (phpinspect-llnode-value ,list)))
,@body)
(setq ,list (,normal-next-function ,list)))))))
(cl-defmethod seq-reverse ((slice phpinspect-slice))
(setf (phpinspect-slice-reversed slice) (not (phpinspect-slice-reversed slice)))
slice)
(cl-defmethod phpinspect-slice-detach ((slice phpinspect-slice))
"Detach underlying link range from the linked list that it
belongs to. Return resulting linked list."
@ -237,30 +270,8 @@ belongs to. Return resulting linked list."
(setq list (phpinspect-llnode-right list)))))
(cl-defmethod seq-do (fn (slice phpinspect-slice))
(let ((list (phpinspect-slice-start slice))
(slice-end (phpinspect-llnode-right (phpinspect-slice-end slice))))
(when (phpinspect-llnode-value list)
(while (and list (not (eq slice-end list)))
(funcall fn (phpinspect-llnode-value list))
(setq list (phpinspect-llnode-right list))))))
(cl-defmethod seq-map (fn (list phpinspect-llnode))
(when (phpinspect-llnode-value list)
(let ((values))
(while list
(push (funcall fn (phpinspect-llnode-value list)) values)
(setq list (phpinspect-llnode-right list)))
(nreverse values))))
(cl-defmethod seq-map (fn (slice phpinspect-slice))
(let ((list (phpinspect-slice-start slice))
(end (phpinspect-llnode-right (phpinspect-slice-end slice))))
(when (phpinspect-llnode-value list)
(let ((values))
(while (and list (not (eq end list)))
(push (funcall fn (phpinspect-llnode-value list)) values)
(setq list (phpinspect-llnode-right list)))
(nreverse values)))))
(phpinspect-doslice (val slice)
(funcall fn val)))
(cl-defmethod seq-take-while (pred (list phpinspect-llnode))
(when (phpinspect-llnode-value list)
@ -273,17 +284,15 @@ belongs to. Return resulting linked list."
(phpinspect-make-slice :start start :end end))))
(cl-defmethod seq-take-while (pred (slice phpinspect-slice))
(let ((list (phpinspect-slice-start slice))
(slice-end (phpinspect-llnode-right (phpinspect-slice-end slice))))
(when (phpinspect-llnode-value list)
(let ((start list)
(end list))
(while (and list (not (eq slice-end list))
(funcall pred (phpinspect-llnode-value list)))
(setq end list)
(setq list (phpinspect-llnode-right list)))
(let ((start (phpinspect-slice-start slice))
(end (phpinspect-slice-start slice)))
(catch 'break
(phpinspect-doslice (val slice)
(if (funcall pred val)
(setq end (phpinspect-ll-link start val))
(throw 'break nil))))
(phpinspect-make-slice :start start :end end)))))
(phpinspect-make-slice :start start :end end)))
(cl-defmethod seq-length ((list phpinspect-llnode))
(let ((count 0))
@ -306,25 +315,28 @@ belongs to. Return resulting linked list."
count))
(cl-defmethod seq-into ((list phpinspect-llnode) type)
(let ((destination)
(list (phpinspect-ll-last list)))
(while list
(push (phpinspect-llnode-value list) destination)
(setq list (phpinspect-llnode-left list)))
(cond ((eq 'vector type) (vconcat destination))
((eq 'list type) destination)
((eq 'string type) (concat destination))
(t (error "Not a sequence type name: %S" type)))))
(cl-defmethod seq-into ((slice phpinspect-slice) type)
(if (eq 'slice type)
(phpinspect-make-slice :start list :end (phpinspect-ll-last list))
(let ((destination)
(list (phpinspect-slice-end slice))
(slice-start (phpinspect-llnode-left (phpinspect-slice-start slice))))
(while (and list (not (eq slice-start list)))
(list (phpinspect-ll-last list)))
(while list
(push (phpinspect-llnode-value list) destination)
(setq list (phpinspect-llnode-left list)))
(cond ((eq 'vector type) (vconcat destination))
((eq 'list type) destination)
((eq 'string type) (concat destination))
(t (error "Not a sequence type name: %S" type))))))
(cl-defmethod seq-into ((slice phpinspect-slice) type)
(let ((destination))
(unwind-protect
(progn
(seq-reverse slice)
(phpinspect-doslice (val slice)
(push val destination)))
(seq-reverse slice))
(cond ((eq 'vector type) (vconcat destination))
((eq 'list type) destination)
((eq 'string type) (concat destination))
@ -341,17 +353,12 @@ belongs to. Return resulting linked list."
default))
(cl-defmethod seq-find (pred (slice phpinspect-slice) &optional default)
(let ((list (phpinspect-slice-start slice))
(end (phpinspect-llnode-right (phpinspect-slice-end slice))))
(if (phpinspect-llnode-value list)
(while (and list (not (eq end list))
(not (funcall pred (phpinspect-llnode-value list))))
(setq list (phpinspect-llnode-right list)))
(setq list nil))
(if list
(phpinspect-llnode-value list)
default)))
(or
(catch 'found
(phpinspect-doslice (val slice)
(when (funcall pred val)
(throw 'found val))))
default))
(cl-defmethod phpinspect-ll-pp ((list phpinspect-llnode))
(message "(phpinspect-ll %s)"
@ -673,10 +680,17 @@ Returns the newly created and inserted node."
(when parent
(let ((parent-link (phpinspect-ll-link (phpinspect-tree-children parent)
tree)))
;; (unless parent-link
;; (message "No parent link for node %s, parent: %s"
;; (phpinspect-meta-token (phpinspect-tree-value tree)) (phpinspect-tree-value parent)))
(phpinspect-llnode-detach parent-link)
(unless parent-link
(phpinspect--log "No parent link for node, trying to find it manually")
(setq parent-link
(seq-find (lambda (child) (eq child tree))
(phpinspect-tree-children parent))))
(if parent-link
(phpinspect-llnode-detach parent-link)
(phpinspect--log "[WARNING] No parent link for node."))
(setf (phpinspect-tree-parent tree) nil)))
tree))

@ -128,7 +128,54 @@ candidate. Candidates can be indexed functions and variables.")
(push enclosing-token (phpinspect--resolvecontext-enclosing-tokens
resolvecontext)))
(defun phpinspect--get-resolvecontext (token &optional resolvecontext)
(cl-defmethod phpinspect-find-statement-before-point
((tree phpinspect-tree) (point integer))
(let ((children (seq-reverse (seq-into (phpinspect-tree-children tree) 'slice))))
(let ((previous-siblings))
(catch 'break
(seq-doseq (child children)
(when (phpinspect-end-of-statement-p (phpinspect-tree-meta-token child))
(throw 'break nil))
(when (< (phpinspect-tree-start child) point)
(push child previous-siblings))))
previous-siblings)))
(cl-defmethod phpinspect-get-resolvecontext
((tree phpinspect-tree) (point integer))
(let* ((enclosing (phpinspect-tree-traverse-overlapping
tree (phpinspect-make-region (- point 1) point)))
(subject (car enclosing))
(siblings))
(when enclosing
(phpinspect--log "Initial resolvecontext subject: %s" (phpinspect-meta-token subject))
(let ((parent (phpinspect-tree-meta-token (phpinspect-tree-parent (phpinspect-meta-tree subject)))))
(phpinspect--log "Parent: %s" parent))
(if (phpinspect-block-or-list-p (phpinspect-meta-token subject))
(setq subject (mapcar #'phpinspect-tree-meta-token
(phpinspect-find-statement-before-point
(phpinspect-meta-tree subject) point)))
(setq subject (mapcar #'phpinspect-tree-meta-token
(phpinspect-find-statement-before-point
(phpinspect-tree-parent
(phpinspect-meta-tree subject))
point)))))
(phpinspect--make-resolvecontext :subject subject
:enclosing-tokens (mapcar #'phpinspect-meta-token enclosing)
:project-root (phpinspect-current-project-root))))
(defun phpinspect-subject-at-point ()
(interactive)
(unless phpinspect-current-buffer
(setq phpinspect-current-buffer (phpinspect-make-buffer :buffer (current-buffer))))
(phpinspect-get-resolvecontext (phpinspect-buffer-parse-tree phpinspect-current-buffer) (point)))
(cl-defmethod phpinspect--get-resolvecontext (token &optional resolvecontext)
"Find the deepest nested incomplete token in TOKEN.
If RESOLVECONTEXT is nil, it is created. Returns RESOLVECONTEXT
of type `phpinspect--resolvecontext' containing the last
@ -324,9 +371,8 @@ TODO:
- Respect `eldoc-echo-area-use-multiline-p`
- This function is too big and has repetitive code. Split up and simplify.
"
(phpinspect--log "Starting eldoc function execution")
(let* ((token-tree (phpinspect-parse-buffer-until-point (current-buffer) (point)))
(resolvecontext (phpinspect--get-resolvecontext token-tree))
(let* ((token-tree (phpinspect-buffer-parse-tree phpinspect-current-buffer))
(resolvecontext (phpinspect-get-resolvecontext token-tree (point)))
(incomplete-token (car (phpinspect--resolvecontext-enclosing-tokens
resolvecontext)))
(enclosing-token (cadr (phpinspect--resolvecontext-enclosing-tokens
@ -794,10 +840,14 @@ more recent"
(phpinspect--log "Failed to find methods for class %s :(" class))
methods))
(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."
(setq phpinspect-current-buffer (phpinspect-make-buffer :buffer (current-buffer)))
(add-hook 'after-change-functions #'phpinspect-after-change-function)
(make-local-variable 'company-backends)
(add-to-list 'company-backends #'phpinspect-company-backend)
@ -1098,8 +1148,8 @@ static variables and static methods."
(defun phpinspect--suggest-at-point ()
(phpinspect--log "Entering suggest at point." )
(let* ((token-tree (phpinspect-parse-buffer-until-point (current-buffer) (point)))
(resolvecontext (phpinspect--get-resolvecontext token-tree))
(let* ((token-tree (phpinspect-buffer-parse-tree phpinspect-current-buffer))
(resolvecontext (phpinspect-get-resolvecontext token-tree (point)))
(last-tokens (last (phpinspect--resolvecontext-subject resolvecontext) 2)))
(phpinspect--log "Subject: %s" (phpinspect--resolvecontext-subject
resolvecontext))

@ -478,6 +478,8 @@ class Thing
(should (string= "getThis: ($moment DateTime, $thing Thing, $other): Thing"
(with-temp-buffer
(insert php-code)
(setq-local phpinspect-current-buffer
(phpinspect-make-buffer :buffer (current-buffer)))
(phpinspect-eldoc-function))))))
(ert-deftest phpinspect-eldoc-function-for-static-method ()
@ -504,6 +506,8 @@ class Thing
(should (string= "doThing: ($moment DateTime, $thing Thing, $other): Thing"
(with-temp-buffer
(insert php-code)
(setq-local phpinspect-current-buffer
(phpinspect-make-buffer :buffer (current-buffer)))
(phpinspect-eldoc-function))))))

@ -250,7 +250,9 @@ the start of the list."
(should (string= "abc" (apply #'concat (seq-into detached-list 'list))))
(should-not (phpinspect-ll-link list val1))
(should (phpinspect-ll-link list d))))
(should (phpinspect-ll-link list d))
(should (phpinspect-ll-link detached-list val1))
(should (phpinspect-ll-link detached-list val2))))
(ert-deftest phpinspect-slice-detach-single-member ()
(let ((list (phpinspect-make-ll))

Loading…
Cancel
Save