[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
- [elpa] externals/phpinspect 153ff71fcf 048/126: WIP: Implement psr0 and psr4 autoload strategies, (continued)
- [elpa] externals/phpinspect 153ff71fcf 048/126: WIP: Implement psr0 and psr4 autoload strategies, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect e65b268cea 053/126: Implement @method annotation indexation, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect ae3acbdbe1 056/126: Disable auto-reindexing by default, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect e7b1f22e8c 068/126: Sort tokens by size when returning tokens around point, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 0e00d7e5a6 066/126: Wakeup worker when stop is requested and worker thread is paused, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect bb04e9a0f8 079/126: Implement strategy pattern for phpinspect-eldoc-function, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect f9f3440850 065/126: Make file contents insertion asynchronous in background threads, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect ad5ede01ad 071/126: Implement Incremental Parsing, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 9d6ce5726d 076/126: Use `phpinspect-edtrack-original-position-at-point' for edit end determination, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 58ad65932b 069/126: Add `phpinspect-parser' type and `phpinspect-defparser' macro, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 5548734ef7 075/126: Implement parser interruption on user input,
ELPA Syncer <=
- [elpa] externals/phpinspect 2049121810 097/126: Make edit delta lookup inclusive of current point, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 9a25959aad 095/126: Use metadata tree instead of hash table for token lookup, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 43310092ad 081/126: Clear tree and edit tracker when reparsing (to ensure full reparse), ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 8dd9bb07e4 080/126: Increase phpinspect-bmap-last-token-before-point backward search limit to 100, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 75562aab35 085/126: Add some tests for edit tracker + patch newly discovered bugs, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 135263c533 110/126: Add tests for incremental parsing + fix parser bugs that came to light, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect ea7795c76e 106/126: Remove commented code, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 9b82c0d0f6 111/126: Reimplement `phpinspect-fix-imports' using metadata objects, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect c20df819b8 114/126: Give `phpinspect-buffer' responsibility over buffer indexation, ELPA Syncer, 2023/08/12
- [elpa] externals/phpinspect 04606a4756 121/126: Fix test, ELPA Syncer, 2023/08/12