diff --git a/phpinspect-bmap.el b/phpinspect-bmap.el index 2b02211..44494ca 100644 --- a/phpinspect-bmap.el +++ b/phpinspect-bmap.el @@ -187,7 +187,7 @@ (gethash point (phpinspect-bmap-ends bmap))))) (defsubst phpinspect-bmap-overlay-at-point (bmap point) - (let ((overlay (phpinspect-splayt-find-smallest-after (phpinspect-bmap-overlays bmap) point))) + (let ((overlay (phpinspect-splayt-find-largest-before (phpinspect-bmap-overlays bmap) point))) (when (and overlay (phpinspect-overlay-overlaps-point overlay point)) overlay))) @@ -252,12 +252,25 @@ giving up. If not provided, this is 100." (let* ((overlays (phpinspect-bmap-overlays bmap)) (start (+ (phpinspect-meta-start token-meta) pos-delta)) (end (+ (phpinspect-meta-end token-meta) pos-delta)) - (overlay `(overlay ,start ,end ,pos-delta ,bmap-overlay ,token-meta))) + (overlay) + (last-overlay (phpinspect-splayt-node-value (phpinspect-splayt-root-node overlays)))) + (phpinspect-meta-detach-parent token-meta) (phpinspect-meta-shift token-meta pos-delta) - (setf (phpinspect-meta-overlay token-meta) overlay) - (phpinspect-bmap-register bmap start end (phpinspect-meta-token token-meta) whitespace-before token-meta) - (phpinspect-splayt-insert (phpinspect-bmap-overlays bmap) (phpinspect-overlay-end overlay) overlay))) + + (if (and last-overlay (= (- start (length whitespace-before)) (phpinspect-overlay-end last-overlay)) + (= pos-delta (phpinspect-overlay-delta last-overlay))) + (progn + (phpinspect--log "Expanding previous overlay from (%d,%d) to (%d,%d)" + (phpinspect-overlay-start last-overlay) (phpinspect-overlay-end last-overlay) + (phpinspect-overlay-start last-overlay) end) + (setf (phpinspect-overlay-end last-overlay) end) + (setf (phpinspect-meta-overlay token-meta) last-overlay)) + (phpinspect--log "Inserting new overlay at (%d,%d)" start end) + (setq overlay `(overlay ,start ,end ,pos-delta ,bmap-overlay ,token-meta)) + (setf (phpinspect-meta-overlay token-meta) overlay) + (phpinspect-splayt-insert (phpinspect-bmap-overlays bmap) (phpinspect-overlay-start overlay) overlay)) + (phpinspect-bmap-register bmap start end (phpinspect-meta-token token-meta) whitespace-before token-meta))) (defun phpinspect-bmap-make-location-resolver (bmap) (lambda (token) diff --git a/phpinspect-splayt.el b/phpinspect-splayt.el index a6e7475..fd8433e 100644 --- a/phpinspect-splayt.el +++ b/phpinspect-splayt.el @@ -355,6 +355,41 @@ near the top of the tee." (throw 'return smallest))) (t (throw 'return smallest))))))))) +(define-inline phpinspect-splayt-find-largest-node-before (splayt key) + (inline-letevals (splayt key) + (inline-quote + (let ((current (phpinspect-splayt-root-node ,splayt)) + largest) + + (catch 'break + (while current + (if (<= ,key (phpinspect-splayt-node-key current)) + (setf current (phpinspect-splayt-node-left current) + largest current) + (throw 'break nil)))) + + (catch 'return + (while current + (when (= (+ ,key 1) (phpinspect-splayt-node-key current)) + (throw 'return current)) + + (cond ((and (phpinspect-splayt-node-parent current) + (> ,key (phpinspect-splayt-node-key (phpinspect-splayt-node-parent current))) + (eq (phpinspect-splayt-node-left (phpinspect-splayt-node-parent current)) + current)) + (setf current (phpinspect-splayt-node-parent current) + largest current)) + ((phpinspect-splayt-node-right current) + (setf current (phpinspect-splayt-node-right current)) + (when (> ,key (phpinspect-splayt-node-key current)) + (setf largest current))) + ((<= ,key (phpinspect-splayt-node-key current)) + (if (phpinspect-splayt-node-left current) + (setf current (phpinspect-splayt-node-left current)) + (throw 'return largest))) + (t (throw 'return largest))))))))) + + (defsubst 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)) @@ -378,6 +413,14 @@ near the top of the tee." (phpinspect-splay ,splayt (phpinspect-splayt-find-smallest-node-after ,splayt ,key))))) +(define-inline 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))))) + + (defsubst phpinspect-splayt-find (splayt key) (phpinspect-splayt-node-value (phpinspect-splayt-find-node splayt key))) diff --git a/test/test-splayt.el b/test/test-splayt.el index 8bc9829..292fe96 100644 --- a/test/test-splayt.el +++ b/test/test-splayt.el @@ -115,6 +115,22 @@ (should (string= "nine" (phpinspect-splayt-find-smallest-after tree 8))) (should (string= "three" (phpinspect-splayt-find-smallest-after tree 1))))) + +(ert-deftest phpinspect-splayt-find-largest-before () + (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") + + + (should (string= "four" (phpinspect-splayt-find-largest-before tree 8))) + (should (string= "eleven" (phpinspect-splayt-find-largest-before tree 12))))) + + (ert-deftest phpinspect-splayt-find-all-after () (let ((tree (phpinspect-make-splayt))) (phpinspect-splayt-insert tree 9 "nine")