emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/phpinspect 0af7d88fda 5/5: Improve performance of parse


From: ELPA Syncer
Subject: [elpa] externals/phpinspect 0af7d88fda 5/5: Improve performance of parser (and phpinspect-meta)
Date: Fri, 27 Sep 2024 21:58:42 -0400 (EDT)

branch: externals/phpinspect
commit 0af7d88fda438ea5d6b91f4419d1e7d144f98123
Author: Hugo Thunnissen <devel@hugot.nl>
Commit: Hugo Thunnissen <devel@hugot.nl>

    Improve performance of parser (and phpinspect-meta)
    
    - Add `phpinspect--recycle-token' which attempts to re-use all eligible
      righthand siblings.
    - Change important search functions of phpinspect-meta to inline functions 
and
      optimize their code.
    - Introduce `phpinspect-meta--point-offset-base' which see docstring.
---
 phpinspect-eldoc.el   |   8 +--
 phpinspect-imports.el |   6 +-
 phpinspect-meta.el    | 156 ++++++++++++++++++++++++++++++++++----------------
 phpinspect-parser.el  | 132 +++++++++++++++++++++++++++++++++---------
 test/test-meta.el     |  11 ++++
 5 files changed, 229 insertions(+), 84 deletions(-)

diff --git a/phpinspect-eldoc.el b/phpinspect-eldoc.el
index feb62e2edd..ee81d60434 100644
--- a/phpinspect-eldoc.el
+++ b/phpinspect-eldoc.el
@@ -167,8 +167,8 @@ be implemented for return values of 
`phpinspect-eld-strategy-execute'")
       (cond
        ;; Method call
        ((setq match-result (phpinspect--match-sequence (last statement 2)
-                             :f (phpinspect-meta-wrap-token-pred 
#'phpinspect-attrib-p)
-                             :f (phpinspect-meta-wrap-token-pred 
#'phpinspect-list-p)))
+                             :f (phpinspect-meta-token-predicate 
#'phpinspect-attrib-p)
+                             :f (phpinspect-meta-token-predicate 
#'phpinspect-list-p)))
         (phpinspect--log "Eldoc context is a method call")
 
         (setq arg-list (car (last match-result))
@@ -197,8 +197,8 @@ be implemented for return values of 
`phpinspect-eld-strategy-execute'")
           (when method
             (phpinspect-make-function-doc :fn method :arg-pos arg-pos))))
        ((setq match-result (phpinspect--match-sequence (last statement 2)
-                             :f (phpinspect-meta-wrap-token-pred 
#'phpinspect-word-p)
-                             :f (phpinspect-meta-wrap-token-pred 
#'phpinspect-list-p)))
+                             :f (phpinspect-meta-token-predicate 
#'phpinspect-word-p)
+                             :f (phpinspect-meta-token-predicate 
#'phpinspect-list-p)))
         (phpinspect--log "Eldoc context is a function call")
 
         (setq arg-list (car (last match-result))
diff --git a/phpinspect-imports.el b/phpinspect-imports.el
index 7031d9d8a2..0d4088ce9b 100644
--- a/phpinspect-imports.el
+++ b/phpinspect-imports.el
@@ -54,7 +54,7 @@ resulting in an unjust removal."
            (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))))
+     token-meta (phpinspect-meta-token-predicate #'phpinspect-use-p))))
 
 (defun phpinspect-add-use (fqn buffer &optional namespace-meta)
   "Add use statement for FQN to BUFFER.
@@ -80,12 +80,12 @@ buffer position to insert the use statement at."
             (phpinspect-insert-at-point
              (phpinspect-meta-end
               (phpinspect-meta-find-first-child-matching
-               namespace-meta (phpinspect-meta-wrap-token-pred 
#'phpinspect-terminator-p)))
+               namespace-meta (phpinspect-meta-token-predicate 
#'phpinspect-terminator-p)))
              (format "%c%cuse %s;%c" ?\n ?\n fqn ?\n)))))
     ;; else
     (let ((existing-use (phpinspect-meta-find-first-child-matching
                          (phpinspect-buffer-root-meta buffer)
-                        (phpinspect-meta-wrap-token-pred #'phpinspect-use-p))))
+                        (phpinspect-meta-token-predicate #'phpinspect-use-p))))
       (if existing-use
           (phpinspect-insert-at-point
            (phpinspect-meta-start existing-use)
diff --git a/phpinspect-meta.el b/phpinspect-meta.el
index a99ed95c21..2a989fb2b2 100644
--- a/phpinspect-meta.el
+++ b/phpinspect-meta.el
@@ -53,10 +53,30 @@
 
 (require 'phpinspect-splayt)
 
+(eval-and-compile
+  (defvar phpinspect-meta--point-offset-base nil
+    "This variable overrides `phpinspect-meta-start'. Normally,
+metadata objects derive their start position relative to their
+parents. This is at some performance cost because the start
+position is re-calculated each time it is accessed.
+
+There are scenarios, most notably when parsing incrementally,
+where the start position of the token is already known while
+interacting with the metadata object. In such cases this variable
+can be set to override the start position, preventing any
+additional calculations.
+
+Note: Use this sparingly in scenarios where performance is of
+significant importance. The code that uses this will be harder to
+maintain. It requires a lot of mental tracing to know when to
+set/unset this variable."))
+
 (define-inline phpinspect-make-meta
-  (parent start end whitespace-before token &optional overlay children 
parent-offset deleted)
-  (inline-quote (list 'meta ,parent ,start ,end ,whitespace-before ,token 
,overlay
-                      (or ,children (phpinspect-make-splayt)) ,parent-offset 
,deleted)))
+  (parent start end whitespace-before token &optional overlay children 
parent-offset)
+  "Create a metadata object for TOKEN."
+  (inline-letevals (start end)
+    (inline-quote (list 'meta ,parent ,start ,end ,whitespace-before ,token 
,overlay
+                        (or ,children (phpinspect-make-splayt)) 
,parent-offset))))
 
 (define-inline phpinspect-meta-p (meta)
   (inline-quote (eq 'meta (car-safe ,meta))))
@@ -82,9 +102,6 @@
 (define-inline phpinspect-meta-whitespace-before (meta)
   (inline-quote (car (cddddr ,meta))))
 
-(define-inline phpinspect-meta-deleted (meta)
-  (inline-quote (car (nthcdr 9 ,meta))))
-
 (define-inline phpinspect-meta-parent-start (meta)
   "Calculate parent start position iteratively based on parent offsets."
   (inline-letevals (meta)
@@ -97,13 +114,22 @@
 
        (+ (phpinspect-meta-absolute-start current) start)))))
 
-(define-inline phpinspect-meta-start (meta)
+(define-inline phpinspect-meta--start (meta)
   "Calculate the start position of META."
-  (inline-quote
+  (inline-letevals (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))))
+         (+ (phpinspect-meta-parent-start (phpinspect-meta-parent ,meta))
+            (phpinspect-meta-parent-offset ,meta))
+       (phpinspect-meta-absolute-start ,meta)))))
+
+(define-inline phpinspect-meta-start (meta)
+  "Start position of META.
+
+Either calculates relative to parent or returns
+`phpinspect-meta--point-offset-base' when that variable is set."
+  (inline-quote
+   (or phpinspect-meta--point-offset-base (phpinspect-meta--start ,meta))))
 
 (define-inline phpinspect-meta-width (meta)
   (inline-letevals (meta)
@@ -115,7 +141,8 @@
     (inline-quote
      (+ (phpinspect-meta-start ,meta) (phpinspect-meta-width ,meta)))))
 
-(defsubst phpinspect-meta-find-root (meta)
+(defun phpinspect-meta-find-root (meta)
+  "Find the root node of META's tree."
   (while (phpinspect-meta-parent meta)
     (setq meta (phpinspect-meta-parent meta)))
   meta)
@@ -154,8 +181,7 @@
          (setf (phpinspect-meta-parent-offset ,meta)
                (- (phpinspect-meta-start ,meta) (phpinspect-meta-start 
,parent)))
          (phpinspect-meta-add-child ,parent ,meta))
-       (setcar (cdr ,meta) ,parent)
-
+       (setf (phpinspect-meta-parent ,meta) ,parent)
        ,meta))))
 
 ;; Note: using defsubst here causes a byte code overflow
@@ -179,8 +205,15 @@
        (setf (phpinspect-meta-parent ,meta) nil)))))
 
 (defun phpinspect-meta-shift (meta delta)
+  "Move META by DELTA characters.
+
+Negative DELTA will move to the left. Positive DELTA will move to the right.
+
+All children are moved together (as they calculate their
+positions based on the parent)."
   (setf (phpinspect-meta-absolute-start meta) (+ (phpinspect-meta-start meta) 
delta))
-  (setf (phpinspect-meta-absolute-end meta) (+ (phpinspect-meta-end meta) 
delta)))
+  (setf (phpinspect-meta-absolute-end meta) (dlet 
((phpinspect-meta--point-offset-base nil))
+                                              (+ (phpinspect-meta-end meta) 
delta))))
 
 (defun phpinspect-meta-right-siblings (meta)
   (sort
@@ -196,6 +229,7 @@
     (cdr tokens)))
 
 (defun phpinspect-meta-token-with-left-siblings (meta)
+  "Return a list containing tokens of META and all of its left siblings."
   (nconc (phpinspect-meta-left-sibling-tokens meta) (list 
(phpinspect-meta-token meta))))
 
 (defun phpinspect-meta-left-siblings (meta)
@@ -204,30 +238,30 @@
     (phpinspect-meta-children (phpinspect-meta-parent meta)) 
(phpinspect-meta-parent-offset meta))
    #'phpinspect-meta-sort-start))
 
-(defun phpinspect-meta-wrap-token-pred (predicate)
-  (lambda (meta) (funcall predicate (phpinspect-meta-token meta))))
-
 (define-inline phpinspect-meta--point-offset (meta point)
   (inline-quote
-   (- ,point (phpinspect-meta-start ,meta))))
+   (- ,point (or phpinspect-meta--point-offset-base (phpinspect-meta-start 
,meta)))))
 
 (cl-defmethod phpinspect-meta-find-left-sibling ((meta (head meta)))
   (when (phpinspect-meta-parent meta)
     (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))))
+(define-inline phpinspect-meta-find-right-sibling (meta)
+  (inline-letevals (meta)
+    (inline-quote
+     (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)
-                ;; Use point +1 as a child starting at point still overlaps
-                (+ (phpinspect-meta--point-offset meta point) 1))))
-    (when (and child (phpinspect-meta-overlaps-point child point))
-      child)))
+(define-inline phpinspect-meta-find-overlapping-child (meta point)
+  (inline-letevals (meta point)
+    (inline-quote
+     (if-let ((child (phpinspect-splayt-find-largest-before
+                      (phpinspect-meta-children ,meta)
+                      ;; Use point +1 as a child starting at point still 
overlaps
+                      (+ (phpinspect-meta--point-offset ,meta ,point) 1))))
+         (and (phpinspect-meta-overlaps-point child ,point) child)))))
 
 (cl-defmethod phpinspect-meta-find-overlapping-children ((meta (head meta)) 
(point integer))
   (let ((child meta)
@@ -237,18 +271,30 @@
       (push child children))
     children))
 
-(cl-defmethod phpinspect-meta-find-child-starting-at ((meta (head meta)) 
(point integer))
-  (phpinspect-splayt-find (phpinspect-meta-children meta) 
(phpinspect-meta--point-offset meta point)))
-
-(cl-defmethod phpinspect-meta-find-child-starting-at-recursively ((meta (head 
meta)) (point integer))
-  (let ((child (phpinspect-meta-find-child-starting-at meta point)))
-    (if child
-        child
-      (setq child (phpinspect-meta-find-overlapping-child meta point))
-      (when child
-        (phpinspect-meta-find-child-starting-at-recursively child point)))))
+(define-inline  phpinspect-meta-find-child-starting-at (meta point)
+  (inline-letevals (meta point)
+    (inline-quote
+     (phpinspect-splayt-find (phpinspect-meta-children ,meta) 
(phpinspect-meta--point-offset ,meta ,point)))))
 
-(cl-defmethod phpinspect-meta-find-child-before ((meta (head meta)) (point 
integer))
+(define-inline phpinspect-meta-find-child-starting-at-recursively (meta point)
+  (inline-letevals (point)
+    (inline-quote
+     (catch 'phpinspect--return
+       (dlet ((phpinspect-meta--point-offset-base (phpinspect-meta-start 
,meta)))
+         (let ((meta ,meta))
+           (while meta
+             (if-let ((child (phpinspect-meta-find-child-starting-at meta 
,point)))
+                 (throw 'phpinspect--return child)
+               (setq meta
+                     (phpinspect-splayt-find-largest-before
+                      (phpinspect-meta-children meta)
+                      (phpinspect-meta--point-offset meta ,point))
+                     phpinspect-meta--point-offset-base
+                     (if meta (+ (phpinspect-meta-parent-offset meta) 
phpinspect-meta--point-offset-base)
+                       phpinspect-meta--point-offset-base))))))))))
+
+(defun phpinspect-meta-find-child-before (meta point)
+  "Find the last child of META before POINT."
   (phpinspect-splayt-find-largest-before
    (phpinspect-meta-children meta) (phpinspect-meta--point-offset meta point)))
 
@@ -256,6 +302,26 @@
   (phpinspect-splayt-find-smallest-after
    (phpinspect-meta-children meta) (phpinspect-meta--point-offset meta point)))
 
+(define-inline phpinspect-meta-find-child-after-recursively (meta point)
+  (inline-letevals (point)
+    (inline-quote
+     (catch 'phpinspect--return
+       (dlet ((phpinspect-meta--point-offset-base (phpinspect-meta-start 
,meta)))
+         (let ((meta ,meta))
+           (while meta
+             (if-let ((child (phpinspect-meta-find-child-after meta ,point)))
+                 (throw 'phpinspect--return child)
+               (setq meta
+                     (or (phpinspect-splayt-find-smallest-after
+                          (phpinspect-meta-children meta)
+                          (phpinspect-meta--point-offset meta ,point))
+                         (phpinspect-splayt-find-largest-before
+                          (phpinspect-meta-children meta)
+                          (phpinspect-meta--point-offset meta ,point)))
+                     phpinspect-meta--point-offset-base
+                     (if meta (+ (phpinspect-meta-parent-offset meta) 
phpinspect-meta--point-offset-base)
+                       phpinspect-meta--point-offset-base))))))))))
+
 (cl-defmethod phpinspect-meta-find-child-before-recursively ((meta (head 
meta)) (point integer))
   (let ((child meta)
         last)
@@ -295,7 +361,6 @@
         (push child result)))
     result))
 
-
 (defun phpinspect-meta-flatten (meta)
   "Flatten META and all its children into an unordered list."
   (when meta
@@ -309,13 +374,6 @@
 
       result)))
 
-(defun phpinspect-meta-delete (meta)
-  "Mark META and all of its children as deleted."
-  (named-let meta-delete ((meta meta))
-    (setf (phpinspect-meta-deleted meta) t)
-    (phpinspect-splayt-traverse-lr (child (phpinspect-meta-children meta))
-      (meta-delete child))))
-
 (cl-defmethod phpinspect-meta-last-child ((meta (head meta)))
   (phpinspect-meta-find-child-before meta (phpinspect-meta-end meta)))
 
diff --git a/phpinspect-parser.el b/phpinspect-parser.el
index 2c8a3418bb..f84dd264f3 100644
--- a/phpinspect-parser.el
+++ b/phpinspect-parser.el
@@ -127,15 +127,71 @@ You can purge the parser cache with 
\\[phpinspect-purge-parser-cache]."
        ,(if (alist-get 'inline attribute-alist)
             `(define-inline ,inline-name (,@arguments)
                ,docstring
+               (declare (speed 3))
                ,@body)
           `(defsubst ,inline-name (,@arguments)
              ,docstring
+             (declare (speed 3))
              ,@body))
 
        (put (quote ,inline-name) 'phpinspect--handler t)
        (put (quote ,inline-name) 'definition-name (quote ,name))
        (put (quote ,regexp-inline-name) 'definition-name (quote ,name)))))
 
+(defun phpinspect--recycle-token (context taint-iterator point original-point 
token-meta tokens-rear &optional delimiter-predicate)
+  "Attempt to re-use TOKEN-META and any of its eligible righthand siblings."
+  (declare (speed 3))
+
+  (when-let ((bmap (phpinspect-pctx-bmap context))
+             (first-iteration t))
+    (catch 'phpinspect--return
+      ;; Use while loop instead of recursion for better performance.
+      (while t
+        ;; Set point-offset-base for more efficient execution of
+        ;; `phpinspect-meta-start' and related functions.
+        (dlet ((phpinspect-meta--point-offset-base original-point))
+          (if (or (not token-meta)
+                  (phpinspect-taint-iterator-token-is-tainted-p taint-iterator 
token-meta))
+              ;; If the first passed token is tainted. Return tainted symbol to
+              ;; signal failure to parser loop. Otherwise return re-used 
tokens.
+              (throw 'phpinspect--return (if first-iteration 'tainted 
tokens-rear))
+
+            ;; Token is eligible for re-use.
+            (let ((parent-offset (phpinspect-meta-parent-offset token-meta))
+                  (delta (- point original-point))
+                  (current-end-position (+ point (phpinspect-meta-width 
token-meta)))
+                  (token (phpinspect-meta-token token-meta))
+                  (right-sibling (phpinspect-meta-find-right-sibling 
token-meta)))
+              ;; Note: recycling the token will update its parent and
+              ;; positions. Its properties should no longer be queried (aside
+              ;; from its width, which always stays the same)
+              (phpinspect-bmap-recycle
+               bmap token-meta delta (phpinspect-pctx-consume-whitespace 
context))
+
+              (goto-char current-end-position)
+              (setq tokens-rear (setcdr tokens-rear (cons token nil)))
+
+              ;; Override point-offset-base again, but this time for
+              ;; right-sibling
+              (dlet ((phpinspect-meta--point-offset-base nil))
+                (if-let (((not (and delimiter-predicate (funcall 
delimiter-predicate token))))
+                         (right-sibling right-sibling)
+                         ((setq phpinspect-meta--point-offset-base
+                                (+ original-point (- 
(phpinspect-meta-parent-offset right-sibling)
+                                                     parent-offset))))
+                         ((not (phpinspect-taint-iterator-region-is-tainted-p
+                                taint-iterator current-end-position (+ delta 
(phpinspect-meta-start right-sibling))))))
+                    (progn
+                      ;; There was a right sibling and it is eligible for
+                      ;; re-use. Set token-meta and "recurse".
+                      (setq first-iteration nil
+                            token-meta right-sibling
+                            point (+ delta (phpinspect-meta-start 
right-sibling))
+                            original-point (phpinspect-meta-start 
right-sibling)))
+
+                  ;; No eligible right sibling, break.
+                  (throw 'phpinspect--return tokens-rear))))))))))
+
 (eval-when-compile
   (defun phpinspect-make-parser-function (name tree-type handlers &optional 
delimiter-predicate delimiter-condition)
     "Create a parser function using the handlers by names defined in 
HANDLER-LIST.
@@ -157,6 +213,7 @@ delimiter predicate and have parsing stop when the last 
parsed
 token is \";\", which marks the end of a statement in PHP."
     (cl-assert (symbolp delimiter-predicate))
     `(defun ,(phpinspect-parser-func-name name "simple") (buffer max-point 
&optional skip-over continue-condition &rest _ignored)
+       (declare (speed 3))
        (with-current-buffer buffer
          (let* ((tokens (cons ,tree-type nil))
                 (tokens-rear tokens)
@@ -182,19 +239,18 @@ token is \";\", which marks the end of a statement in 
PHP."
            ;; Return
            tokens))))
 
-
-  (defun phpinspect-make-incremental-parser-function
+    (defun phpinspect-make-incremental-parser-function
       (name tree-type handlers &optional delimiter-predicate 
delimiter-condition)
     "Like `phpinspect-make-parser-function', but returned function
 is able to reuse an already parsed tree."
     (cl-assert (symbolp delimiter-predicate))
     `(defun ,(phpinspect-parser-func-name name "incremental")
          (context buffer max-point &optional skip-over continue-condition root)
+       (declare (speed 3))
        (with-current-buffer buffer
          (let* ((tokens (cons ,tree-type nil))
                 (tokens-rear tokens)
                 (root-start (point))
-                (bmap (phpinspect-pctx-bmap context))
                 (previous-bmap (phpinspect-pctx-previous-bmap context))
                 (edtrack (phpinspect-pctx-edtrack context))
                 (taint-iterator (when edtrack 
(phpinspect-edtrack-make-taint-iterator edtrack)))
@@ -203,9 +259,6 @@ is able to reuse an already parsed tree."
                 ;; Loop variables
                 (start-position)
                 (original-position)
-                (current-end-position)
-                (existing-meta)
-                (delta)
                 (token))
            (when skip-over (forward-char skip-over))
 
@@ -225,30 +278,52 @@ is able to reuse an already parsed tree."
                  (phpinspect-pctx-check-interrupt context))
 
                (setq start-position (point))
-               (cond ((and previous-bmap edtrack
-                           (setq existing-meta
-                                 (phpinspect-bmap-token-starting-at
-                                  previous-bmap
-                                  (setq original-position
-                                        
(phpinspect-edtrack-original-position-at-point edtrack start-position))))
-                           (not (or (phpinspect-root-p (phpinspect-meta-token 
existing-meta))
-                                    
(phpinspect-taint-iterator-token-is-tainted-p taint-iterator existing-meta))))
-                      (setq delta (- start-position original-position)
-                            current-end-position (+ (phpinspect-meta-end 
existing-meta) delta)
-                            token (phpinspect-meta-token existing-meta))
-
-                      ;;(message "Reusing token  %s at point %s" 
(phpinspect-meta-string existing-meta) (point))
-                      ;; Re-register existing token
-                      (phpinspect-bmap-overlay
-                       bmap previous-bmap existing-meta delta
-                       (phpinspect-pctx-consume-whitespace context))
-
-                      (goto-char current-end-position)
+
+               (cond ((and-let*
+                          ((edtrack)
+                           (previous-bmap)
+                           (result
+                            ;; Look for an already parsted token at POINT to
+                            ;; adopt into new tree.
+                            (or (phpinspect--recycle-token
+                                 context
+                                 taint-iterator
+                                 start-position
+                                 (setq original-position
+                                       
(phpinspect-edtrack-original-position-at-point edtrack start-position))
+                                 (phpinspect-bmap-token-starting-at 
previous-bmap original-position)
+                                 tokens-rear
+                                 ,(if delimiter-predicate `(quote 
,delimiter-predicate) 'nil))
+                                ;; There is no token at POINT exactly. Attempt
+                                ;; to find any other adoptable token after
+                                ;; POINT.
+                                (when-let
+                                    ((token-after 
(phpinspect-bmap-token-starting-after previous-bmap original-position))
+                                     (start (phpinspect-meta-start 
token-after))
+
+                                     ((not 
(phpinspect-taint-iterator-region-is-tainted-p
+                                            taint-iterator original-position 
start)))
+                                     (current-start (+ start-position (- start 
original-position))))
+                                  (goto-char current-start)
+                                  (phpinspect--recycle-token
+                                   context taint-iterator current-start start 
token-after tokens-rear
+                                   ,(if delimiter-predicate `(quote 
,delimiter-predicate) 'nil)))))
+
+                           ;; `phpinspect--recycle-token' will return the 
symbol
+                           ;; 'tainted' when the token that it tried to reuse
+                           ;; was tainted. When this happens, we know that we
+                           ;; can't re-use the token and we should continue
+                           ;; parsing.
+                           ((not (eq result 'tainted)))
+
+                           ;; Re-using tokens was a success, update tokens-rear
+                           ((setq tokens-rear result))))
 
                       ;; Skip over whitespace after so that we don't do a full
                       ;; run down all of the handlers during the next iteration
-                      (when (looking-at (phpinspect-handler-regexp whitespace))
-                        (,(phpinspect-handler-func-name 'whitespace) 
(match-string 0))))
+                      (when (looking-at 
(phpinspect--whitespace-handler-regexp))
+                        (phpinspect--whitespace-handler (match-string 0))))
+
                      ,@(mapcar
                         (lambda (handler)
                           `((looking-at (,(phpinspect-handler-regexp-func-name 
handler)))
@@ -785,7 +860,8 @@ static keywords with the same meaning as in a class block."
          (parsed (phpinspect--parse-class-block
                   (current-buffer) max-point (length start-token) 
continue-condition)))
     (if complete-block
-        (goto-char (+ complete-block 1))
+        (progn
+        (goto-char (+ complete-block 1)))
       (setcar parsed :incomplete-block))
     parsed))
 
diff --git a/test/test-meta.el b/test/test-meta.el
index 465413744b..3f07c07304 100644
--- a/test/test-meta.el
+++ b/test/test-meta.el
@@ -52,3 +52,14 @@
     (phpinspect-meta-detach-parent meta)
 
     (should (length= (phpinspect-meta-flatten parent) 1))))
+
+(ert-deftest phpinspect-meta-find-child-starting-at ()
+  (let ((grandchild (phpinspect-make-meta nil 14 16 "" 'grandchild))
+        (meta (phpinspect-make-meta nil 10 20 "" 'child))
+        (parent (phpinspect-make-meta nil 9 22 "" 'parent)))
+    (phpinspect-meta-set-parent meta parent)
+    (phpinspect-meta-set-parent grandchild meta)
+
+    (should (phpinspect-meta-find-child-starting-at parent 10))
+
+    (should (eq grandchild (phpinspect-meta-find-child-starting-at-recursively 
parent 14)))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]