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

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

[elpa] externals/phpinspect 5548734ef7 075/126: Implement parser interru


From: ELPA Syncer
Subject: [elpa] externals/phpinspect 5548734ef7 075/126: Implement parser interruption on user input
Date: Sat, 12 Aug 2023 00:58:45 -0400 (EDT)

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

    Implement parser interruption on user input
---
 phpinspect-buffer.el |  11 +++
 phpinspect-parser.el | 113 +++++++++++++++++++----------
 phpinspect.el        | 197 +++++++++++++++++++++++++--------------------------
 3 files changed, 183 insertions(+), 138 deletions(-)

diff --git a/phpinspect-buffer.el b/phpinspect-buffer.el
index 56df0c22e3..f16cecd65a 100644
--- a/phpinspect-buffer.el
+++ b/phpinspect-buffer.el
@@ -55,6 +55,7 @@ linked with."
         (let* ((map (phpinspect-make-bmap))
                (buffer-map (phpinspect-buffer-map buffer))
                (ctx (phpinspect-make-pctx
+                     :interrupt-predicate #'input-pending-p
                      :bmap map
                      :incremental t
                      :previous-bmap buffer-map
@@ -81,6 +82,16 @@ linked with."
 
 (cl-defmethod phpinspect-buffer-register-edit
   ((buffer phpinspect-buffer) (start integer) (end integer) (pre-change-length 
integer))
+  "Mark a region of the buffer as edited."
+
+  ;; Take into account "atoms" (tokens without clear delimiters like words,
+  ;; variables and object attributes. The meaning of these tokens will change 
as
+  ;; they grow or shrink, so their ful regions need to be marked for a 
reparse).
+  (save-excursion
+    (goto-char start)
+    (when (looking-back "\\($->|::\\)?[^][)(}{[:blank:]\n;'\"]+" nil t)
+      (setq start (- start (length (match-string 0))))))
+
   (phpinspect-edtrack-register-edit
    (phpinspect-buffer-edit-tracker buffer) start end pre-change-length))
 
diff --git a/phpinspect-parser.el b/phpinspect-parser.el
index 9d9e557056..e5fa194e80 100644
--- a/phpinspect-parser.el
+++ b/phpinspect-parser.el
@@ -37,6 +37,69 @@
   (define-inline phpinspect--word-end-regex ()
     (inline-quote "\\([[:blank:]]\\|[^0-9a-zA-Z_]\\)")))
 
+(defvar phpinspect-parse-context nil
+  "An instance of `phpinspect-pctx' that is used when
+parsing. Usually used in combination with
+`phpinspect-with-parse-context'")
+
+(defmacro phpinspect-with-parse-context (ctx &rest body)
+  (declare (indent 1))
+  (let ((old-ctx phpinspect-parse-context))
+    `(unwind-protect
+         (progn
+           (setq phpinspect-parse-context ,ctx)
+           ,@body)
+       (setq phpinspect-parse-context ,old-ctx))))
+
+(cl-defstruct (phpinspect-pctx (:constructor phpinspect-make-pctx))
+  "Parser Context"
+  (incremental nil)
+  (interrupt-threshold (time-convert '(2 . 1000))
+                       :documentation
+                       "After how much time `interrupt-predicate'
+should be polled. This is 2ms by default.")
+  (-start-time nil
+               :documentation "The time at which the parse started.
+This variable is for private use and not always set.")
+  (interrupt-predicate nil
+                      :documentation
+                      "A function that is called in intervals during parsing 
when
+set. If this function returns a non-nil value, the parse process
+is interrupted and the symbol `phpinspect-parse-interrupted' is
+thrown.")
+  (edtrack nil
+           :type phpinspect-edtrack)
+  (bmap (phpinspect-make-bmap)
+        :type phpinspect-bmap)
+  (previous-bmap nil
+                 :type phpinspect-bmap)
+  (whitespace-before ""
+                     :type string))
+
+(defsubst phpinspect-pctx-check-interrupt (pctx)
+  (unless (phpinspect-pctx--start-time pctx)
+    (setf (phpinspect-pctx--start-time pctx) (time-convert nil)))
+
+  ;; Interrupt when blocking too long while input is pending.
+  (when (and (time-less-p (phpinspect-pctx-interrupt-threshold pctx)
+                          (time-since (phpinspect-pctx--start-time pctx)))
+             (funcall (phpinspect-pctx-interrupt-predicate pctx)))
+    (throw 'phpinspect-parse-interrupted nil)))
+
+
+
+(defsubst phpinspect-pctx-register-token (pctx token start end)
+  (phpinspect-bmap-register
+   (phpinspect-pctx-bmap pctx) start end token 
(phpinspect-pctx-consume-whitespace pctx)))
+
+(defsubst phpinspect-pctx-register-whitespace (pctx whitespace)
+  (setf (phpinspect-pctx-whitespace-before pctx) whitespace))
+
+(defsubst phpinspect-pctx-consume-whitespace (pctx)
+  (let ((whitespace (phpinspect-pctx-whitespace-before pctx)))
+    (setf (phpinspect-pctx-whitespace-before pctx) "")
+    whitespace))
+
 (defun phpinspect-list-handlers ()
   (let ((handlers))
     (mapatoms (lambda (handler)
@@ -370,9 +433,14 @@ parser function is then returned in byte-compiled form."
 
     (if (and phpinspect-parse-context
              (phpinspect-pctx-incremental phpinspect-parse-context))
+
         (let ((func (phpinspect-parser-compile-incremental (symbol-value 
parser-symbol))))
-          (lambda (&rest arguments)
-            (apply func phpinspect-parse-context arguments)))
+          (if (phpinspect-pctx-interrupt-predicate phpinspect-parse-context)
+              (lambda (&rest arguments)
+                (phpinspect-pctx-check-interrupt phpinspect-parse-context)
+                (apply func phpinspect-parse-context arguments))
+            (lambda (&rest arguments)
+              (apply func phpinspect-parse-context arguments))))
       (or (symbol-function parser-symbol)
           (defalias parser-symbol
             (phpinspect-parser-compile (symbol-value parser-symbol)))))))
@@ -457,43 +525,6 @@ token is \";\", which marks the end of a statement in PHP."
            ;; Return
            tokens)))))
 
-(defvar phpinspect-parse-context nil
-  "An instance of `phpinspect-pctx' that is used when
-parsing. Usually used in combination with
-`phpinspect-with-parse-context'")
-
-(defmacro phpinspect-with-parse-context (ctx &rest body)
-  (declare (indent 1))
-  (let ((old-ctx phpinspect-parse-context))
-    `(unwind-protect
-         (progn
-           (setq phpinspect-parse-context ,ctx)
-           ,@body)
-       (setq phpinspect-parse-context ,old-ctx))))
-
-(cl-defstruct (phpinspect-pctx (:constructor phpinspect-make-pctx))
-  "Parser Context"
-  (incremental nil)
-  (edtrack nil
-           :type phpinspect-edtrack)
-  (bmap (phpinspect-make-bmap)
-        :type phpinspect-bmap)
-  (previous-bmap nil
-                 :type phpinspect-bmap)
-  (whitespace-before ""
-                     :type string))
-
-(defsubst phpinspect-pctx-register-token (pctx token start end)
-  (phpinspect-bmap-register
-   (phpinspect-pctx-bmap pctx) start end token 
(phpinspect-pctx-consume-whitespace pctx)))
-
-(defsubst phpinspect-pctx-register-whitespace (pctx whitespace)
-  (setf (phpinspect-pctx-whitespace-before pctx) whitespace))
-
-(defsubst phpinspect-pctx-consume-whitespace (pctx)
-  (let ((whitespace (phpinspect-pctx-whitespace-before pctx)))
-    (setf (phpinspect-pctx-whitespace-before pctx) "")
-    whitespace))
 
 (defun phpinspect-make-incremental-parser-function (tree-type handler-list 
&optional delimiter-predicate)
   "Like `phpinspect-make-parser-function', but returned function is able to 
reuse an already parsed tree."
@@ -516,6 +547,7 @@ parsing. Usually used in combination with
                 (previous-bmap (phpinspect-pctx-previous-bmap context))
                 (edtrack (phpinspect-pctx-edtrack context))
                 (taint-iterator (when edtrack 
(phpinspect-edtrack-make-taint-iterator edtrack)))
+                (check-interrupt (phpinspect-pctx-interrupt-predicate context))
 
                 ;; Loop variables
                 (start-position)
@@ -551,6 +583,9 @@ parsing. Usually used in combination with
 
                      (goto-char current-end-position)
 
+                     (when check-interrupt
+                       (phpinspect-pctx-check-interrupt context))
+
                      ;; 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))
diff --git a/phpinspect.el b/phpinspect.el
index 0816ca3299..481796dbc5 100644
--- a/phpinspect.el
+++ b/phpinspect.el
@@ -282,87 +282,88 @@ TODO:
  - Respect `eldoc-echo-area-use-multiline-p`
  - This function is too big and has repetitive code. Split up and simplify.
 "
-  (let* ((token-map (phpinspect-buffer-parse-map phpinspect-current-buffer))
-         (resolvecontext (phpinspect-get-resolvecontext token-map (point)))
-         (parent-token (car (phpinspect--resolvecontext-enclosing-tokens
-                                      resolvecontext)))
-         (enclosing-token (cadr (phpinspect--resolvecontext-enclosing-tokens
-                                 resolvecontext)))
-         (statement (phpinspect--resolvecontext-subject resolvecontext))
-         (arg-list)
-         (type-resolver (phpinspect--make-type-resolver-for-resolvecontext
-                               resolvecontext))
-         (static))
-
-    (phpinspect--log  "Eldoc statement before checking outside list: %s" 
statement)
-    (when (and (phpinspect-list-p parent-token) enclosing-token)
-      (setq statement
-            (phpinspect-find-statement-before-point
-             token-map (phpinspect-bmap-token-meta token-map enclosing-token)
-             (phpinspect-meta-end
-              (phpinspect-bmap-token-meta token-map parent-token)))))
-
-    (phpinspect--log "Enclosing token: %s" enclosing-token)
-    (phpinspect--log  "Eldoc statement: %s" statement)
-
-    (setq arg-list (seq-find #'phpinspect-list-p (reverse statement)))
-
-    (when (and (phpinspect-list-p arg-list)
-               enclosing-token
-               (or (phpinspect-object-attrib-p (car (last statement 2)))
-                   (setq static (phpinspect-static-attrib-p (car (last 
statement 2))))))
-
-      ;; Set resolvecontext subject to the last statement in the enclosing 
token, minus
-      ;; the method name. The last enclosing token is an incomplete list, so 
point is
-      ;; likely to be at a location inside a method call like 
"$a->b->doSomething(". The
-      ;; resulting subject would be "$a->b".
-      (setf (phpinspect--resolvecontext-subject resolvecontext)
-            (phpinspect--get-last-statement-in-token (butlast statement 2)))
-
-      (let* ((type-of-previous-statement
-              (phpinspect-resolve-type-from-context resolvecontext 
type-resolver))
-             (method-name-sym (phpinspect-intern-name (cadr (cadar (last 
statement 2)))))
-             (class (phpinspect-project-get-class-create
-                     (phpinspect--cache-get-project-create
-                      (phpinspect--get-or-create-global-cache)
-                      (phpinspect--resolvecontext-project-root resolvecontext))
-                     type-of-previous-statement))
-             (method (when class
-                       (if static
-                           (phpinspect--class-get-static-method class 
method-name-sym)
+  (catch 'phpinspect-parse-interrupted
+    (let* ((token-map (phpinspect-buffer-parse-map phpinspect-current-buffer))
+           (resolvecontext (phpinspect-get-resolvecontext token-map (point)))
+           (parent-token (car (phpinspect--resolvecontext-enclosing-tokens
+                               resolvecontext)))
+           (enclosing-token (cadr (phpinspect--resolvecontext-enclosing-tokens
+                                   resolvecontext)))
+           (statement (phpinspect--resolvecontext-subject resolvecontext))
+           (arg-list)
+           (type-resolver (phpinspect--make-type-resolver-for-resolvecontext
+                           resolvecontext))
+           (static))
+
+      (phpinspect--log  "Eldoc statement before checking outside list: %s" 
statement)
+      (when (and (phpinspect-list-p parent-token) enclosing-token)
+        (setq statement
+              (phpinspect-find-statement-before-point
+               token-map (phpinspect-bmap-token-meta token-map enclosing-token)
+               (phpinspect-meta-end
+                (phpinspect-bmap-token-meta token-map parent-token)))))
+
+      (phpinspect--log "Enclosing token: %s" enclosing-token)
+      (phpinspect--log  "Eldoc statement: %s" statement)
+
+      (setq arg-list (seq-find #'phpinspect-list-p (reverse statement)))
+
+      (when (and (phpinspect-list-p arg-list)
+                 enclosing-token
+                 (or (phpinspect-object-attrib-p (car (last statement 2)))
+                     (setq static (phpinspect-static-attrib-p (car (last 
statement 2))))))
+
+        ;; Set resolvecontext subject to the last statement in the enclosing 
token, minus
+        ;; the method name. The last enclosing token is an incomplete list, so 
point is
+        ;; likely to be at a location inside a method call like 
"$a->b->doSomething(". The
+        ;; resulting subject would be "$a->b".
+        (setf (phpinspect--resolvecontext-subject resolvecontext)
+              (phpinspect--get-last-statement-in-token (butlast statement 2)))
+
+        (let* ((type-of-previous-statement
+                (phpinspect-resolve-type-from-context resolvecontext 
type-resolver))
+               (method-name-sym (phpinspect-intern-name (cadr (cadar (last 
statement 2)))))
+               (class (phpinspect-project-get-class-create
+                       (phpinspect--cache-get-project-create
+                        (phpinspect--get-or-create-global-cache)
+                        (phpinspect--resolvecontext-project-root 
resolvecontext))
+                       type-of-previous-statement))
+               (method (when class
+                         (if static
+                             (phpinspect--class-get-static-method class 
method-name-sym)
                            (phpinspect--class-get-method class 
method-name-sym)))))
-        (phpinspect--log "Eldoc method name: %s" method-name-sym)
-        (phpinspect--log "Eldoc type of previous statement: %s"
-                         type-of-previous-statement)
-        (phpinspect--log "Eldoc method: %s" method)
-        (when method
-          (let ((arg-count -1)
-                (comma-count
-                 (length (seq-filter #'phpinspect-comma-p arg-list))))
-            (concat (truncate-string-to-width
-                     (phpinspect--function-name method) 
phpinspect-eldoc-word-width) ": ("
-                     (mapconcat
-                      (lambda (arg)
-                        (setq arg-count (+ arg-count 1))
-                        (if (= arg-count comma-count)
-                            (propertize (concat
-                                         "$"
-                                         (truncate-string-to-width
-                                          (car arg)
-                                          phpinspect-eldoc-word-width)
-                                         " "
-                                         (phpinspect--format-type-name (or 
(cadr arg) "")))
-                                        'face 
'eldoc-highlight-function-argument)
-                          (concat "$"
-                                  (truncate-string-to-width (car arg)
-                                                            
phpinspect-eldoc-word-width)
-                                  (if (cadr arg) " " "")
-                                  (phpinspect--format-type-name (or (cadr arg) 
"")))))
-                      (phpinspect--function-arguments method)
-                      ", ")
-                     "): "
-                     (phpinspect--format-type-name
-                      (phpinspect--function-return-type method)))))))))
+          (phpinspect--log "Eldoc method name: %s" method-name-sym)
+          (phpinspect--log "Eldoc type of previous statement: %s"
+                           type-of-previous-statement)
+          (phpinspect--log "Eldoc method: %s" method)
+          (when method
+            (let ((arg-count -1)
+                  (comma-count
+                   (length (seq-filter #'phpinspect-comma-p arg-list))))
+              (concat (truncate-string-to-width
+                       (phpinspect--function-name method) 
phpinspect-eldoc-word-width) ": ("
+                       (mapconcat
+                        (lambda (arg)
+                          (setq arg-count (+ arg-count 1))
+                          (if (= arg-count comma-count)
+                              (propertize (concat
+                                           "$"
+                                           (truncate-string-to-width
+                                            (car arg)
+                                            phpinspect-eldoc-word-width)
+                                           " "
+                                           (phpinspect--format-type-name (or 
(cadr arg) "")))
+                                          'face 
'eldoc-highlight-function-argument)
+                            (concat "$"
+                                    (truncate-string-to-width (car arg)
+                                                              
phpinspect-eldoc-word-width)
+                                    (if (cadr arg) " " "")
+                                    (phpinspect--format-type-name (or (cadr 
arg) "")))))
+                        (phpinspect--function-arguments method)
+                        ", ")
+                       "): "
+                       (phpinspect--format-type-name
+                        (phpinspect--function-return-type method))))))))))
 
 (cl-defstruct (phpinspect--assignment
                (:constructor phpinspect--make-assignment))
@@ -974,9 +975,6 @@ level of a token. Nested variables are ignored."
     (resolvecontext &optional static)
   "Suggest object or class attributes at point.
 
-TOKEN-TREE must be a syntax tree containing enough context to
-infer the types of the preceding statements
-
 RESOLVECONTEXT must be a structure of the type
 `phpinspect--resolvecontext'.  The PHP type of its subject is
 resolved to provide completion candidates.
@@ -1097,22 +1095,23 @@ static variables and static methods."
                           arg)))
       (insert "(")))
    ((eq command 'candidates)
-    (let ((completion-list (phpinspect--make-completion-list))
-          (candidates))
-      (dolist (completion (phpinspect--suggest-at-point))
-        (phpinspect--completion-list-add
-         completion-list
-         (phpinspect--make-completion completion)))
-
-      (setq candidates
-            (seq-filter (lambda (completion)
-                          (when completion
-                            (string-match (concat "^" (regexp-quote arg))
-                                          completion)))
-                        (phpinspect--completion-list-strings
-                                   completion-list)))
-      (setq phpinspect--last-completion-list completion-list)
-      candidates))
+    (catch 'phpinspect-parse-interrupted
+      (let ((completion-list (phpinspect--make-completion-list))
+            (candidates))
+        (dolist (completion (phpinspect--suggest-at-point))
+          (phpinspect--completion-list-add
+           completion-list
+           (phpinspect--make-completion completion)))
+
+        (setq candidates
+              (seq-filter (lambda (completion)
+                            (when completion
+                              (string-match (concat "^" (regexp-quote arg))
+                                            completion)))
+                          (phpinspect--completion-list-strings
+                           completion-list)))
+        (setq phpinspect--last-completion-list completion-list)
+        candidates)))
    ((eq command 'annotation)
     (concat " " (phpinspect--completion-annotation
                  (phpinspect--completion-list-get-metadata



reply via email to

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