branch: externals/phpinspect commit 9846f7aa2389205e8268b65492140dd832becc0d Author: Hugo Thunnissen <de...@hugot.nl> Commit: Hugo Thunnissen <de...@hugot.nl>
Refactor parse context + fix compilation errors --- phpinspect-autoload.el | 2 +- phpinspect-buffer.el | 17 +++---- phpinspect-parse-context.el | 113 ++++++++++++++------------------------------ phpinspect-parser.el | 18 ++++--- phpinspect-pipeline.el | 6 +-- phpinspect-project.el | 3 +- phpinspect-thread.el | 29 +++++++----- 7 files changed, 75 insertions(+), 113 deletions(-) diff --git a/phpinspect-autoload.el b/phpinspect-autoload.el index 87a7643937..f71a780b4b 100644 --- a/phpinspect-autoload.el +++ b/phpinspect-autoload.el @@ -391,7 +391,7 @@ FILE-NAME does not contain any wildcards, instead of nil." (when-let ((pr (phpinspect-autoloader--progress-reporter al)) (i (cl-incf (phpinspect-autoloader--type-counter al))) ((= 0 (mod i phpinspect-autoload-progress-interval)))) - (progress-reporter-update pr i (format "%d types found" i))) + (progress-reporter-force-update pr i (format "%d types found" i))) (if bag (setcdr bag (cons type-fqn (cdr bag))) diff --git a/phpinspect-buffer.el b/phpinspect-buffer.el index 8116ee2beb..ec42ce6b75 100644 --- a/phpinspect-buffer.el +++ b/phpinspect-buffer.el @@ -136,7 +136,7 @@ linked with." (remhash old (phpinspect-buffer-token-index buffer)) (puthash new index (phpinspect-buffer-token-index buffer)))) -(defun phpinspect-get-buffer-index-reference-for-token (buffer token) +(defun phpinspect-buffer-get-index-reference-for-token (buffer token) (gethash token (phpinspect-buffer-token-index buffer))) (define-inline phpinspect--can-delete-buffer-index-for-token (token) @@ -229,7 +229,7 @@ tokens that have been deleted from a buffer." (phpinspect-buffer-reindex buffer) (error "invalid index location")))))))) -(defun phpinspect-delete-dynamic-prop-index-reference (buffer token) +(defun phpinspect-buffer--delete-dynamic-prop-index-reference (buffer token) (when-let ((ref (phpinspect-buffer-get-index-reference-for-token buffer token)) (typedef (phpinspect-project-get-typedef (phpinspect-buffer-project buffer) @@ -272,7 +272,7 @@ tokens that have been deleted from a buffer." (interactive (list (or phpinspect-current-buffer (error "Not a phpinspect buffer")))) (phpinspect-buffer-reset buffer) (phpi-shadow-enqueue-task (phpinspect-buffer-shadow buffer) 'parse-fresh) - (phpi-shadow-await-synced (phpi-buffer-shadow buffer)) + (phpi-shadow-await-synced (phpinspect-buffer-shadow buffer)) (phpinspect-buffer-tree buffer)) (defun phpinspect-buffer-reindex (buffer) @@ -709,8 +709,6 @@ If provided, PROJECT must be an instance of `phpinspect-project'." (defvar phpinspect--shadow-counter 0) (defvar phpinspect--shadow-run-sync nil) -(defvar phpinspect-shadow-pause-time 0.05) - (define-error 'phpinspect-wakeup-shadow "This error is used to wakeup the shadow thread.") @@ -774,9 +772,6 @@ If provided, PROJECT must be an instance of `phpinspect-project'." (lambda () (phpi-shadow-wakeup-thread shadow))) -(defun phpi-shadow--thread-make-parser-interrupt-predicate () - (lambda () (phpi-thread-yield) nil)) - (defun phpi-shadow-process-change (shadow change) (with-current-buffer (phpi-shadow-buffer shadow) (phpi-change-apply change (current-buffer)) @@ -787,7 +782,7 @@ If provided, PROJECT must be an instance of `phpinspect-project'." :previous-bmap (phpinspect-buffer-map buffer) :bmap (phpinspect-make-bmap) :change change - :interrupt-predicate (phpi-shadow--thread-make-parser-interrupt-predicate)))) + :collaborative t))) (let (result) ;; Parse new content @@ -808,7 +803,7 @@ If provided, PROJECT must be an instance of `phpinspect-project'." (pctx (phpinspect-make-pctx :incremental t :bmap (phpinspect-make-bmap) - :interrupt-predicate (phpi-shadow--thread-make-parser-interrupt-predicate)))) + :collaborative t))) (let (result) ;; Parse new content @@ -899,7 +894,7 @@ If provided, PROJECT must be an instance of `phpinspect-project'." (when-let ((additions (phpi-shadow--additions shadow)) (buffer (phpi-shadow-origin shadow))) (maphash - (lambda (token addition) + (lambda (_token addition) (phpi-progn (pcase (phpinspect-meta-token addition) ((pred phpinspect-class-declaration-p) diff --git a/phpinspect-parse-context.el b/phpinspect-parse-context.el index ec27eab706..ebe98dba7b 100644 --- a/phpinspect-parse-context.el +++ b/phpinspect-parse-context.el @@ -33,6 +33,7 @@ (require 'phpinspect-util) (require 'phpinspect-meta) (require 'phpinspect-changeset) +(require 'phpinspect-thread) (defvar phpinspect-parse-context nil "An instance of `phpinspect-pctx' that is used when @@ -52,33 +53,24 @@ parsing. Usually used in combination with "After how much time `interrupt-predicate' should be consulted. This is 2ms by default.") (-start-time + nil + :documentation + "The time at which the currently active parse cycle started.") + (collaborative nil - :documentation "The time at which the currently active parse cycle started. -This slot is for private use and does not always have a value.") - (change nil :type phpinspect-change) - (interrupt-predicate + :type boolean + :documentation + "When this is non-nil and the parser is not running in the main +thread, the thread will shortly yield before parsing a token. + +Only use this when the content of the buffer to be parsed is +guaranteed not to change while parsing.") + (change nil + :type phpinspect-change :documentation - "When non-nil, this should be a function. When the parse time -exceeds the configured interrupt-threshold, this function will be -called after each parsed token to make the final decision of -interrupting the parser. If this function returns a non-nil -value, the parse process is interrupted and the symbol -`phpinspect-parse-interrupted' is signaled.") -;; (changesets -;; nil -;; :type list -;; :documentation -;; "Restore points for metadata changes executed during this -;; parse. Usually populated through `phpinspect-meta-with-changeset'.") -;; (edtrack -;; nil -;; :type phpinspect-edtrack -;; :documentation -;; "When parsing incrementally, the edit tracker is used to determine -;; whether a token from a previous parse (in the buffer map that is -;; in the `previous-bmap' slot) can be recycled or is tainted/edited -;; and should not be recycled.") + "The change that happend after the parser produced + `phpinspect-pctx-previous-bmap'") (bmap nil :type phpinspect-bmap @@ -128,50 +120,6 @@ handled by the code using this macro." ,@body) (setf (phpinspect-pctx-whitespace-before ,pctx) ,save-sym))))) -;; (define-inline phpinspect-pctx-register-changeset (pctx changeset) -;; (inline-quote -;; (progn -;; (push ,changeset (phpinspect-pctx-changesets ,pctx))))) - -;; (define-inline phpinspect-meta-with-changeset (meta &rest body) -;; "Perform mutations on META in BODY, saving changes. - -;; Before BODY is executed, important slots of META are stored in a -;; changeset object and appended to the changesets slot of the -;; currently active parse context. The original state of META can be -;; restored by calling `phpinspect-pctx-cancel'." -;; (declare (indent 1)) -;; (inline-letevals (meta) -;; (push 'progn body) -;; (inline-quote -;; (progn -;; (when phpinspect-parse-context -;; (phpinspect-pctx-register-changeset -;; phpinspect-parse-context (phpinspect-make-changeset ,meta))) -;; ,body)))) - -(define-inline phpinspect-pctx-check-interrupt (pctx) - "Signal `phpinspect-parse-interrupted' when conditions are met. - -Parsing will be interrupted when the time passed since -`phpinspect--pctx-start-time' exceeds -`phpinspect-pctx-interrupt-threshold' and -`phpinspect-pctx-interrupt-predicate' returns non-nil. - -When parsing is interrupted, any changes made to buffer token -metadata will be reverted in a call to `pphinspect-pctx-cancel'." - (inline-letevals (pctx) - (inline-quote - (progn - (unless (phpinspect-pctx--start-time ,pctx) - (setf (phpinspect-pctx--start-time ,pctx) (time-convert nil t))) - - ;; 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)))))) - (define-inline phpinspect-pctx-register-whitespace (pctx whitespace) (inline-letevals (pctx) (inline-quote @@ -182,16 +130,27 @@ metadata will be reverted in a call to `pphinspect-pctx-cancel'." (setf (phpinspect-pctx-whitespace-before pctx) "") whitespace)) -;; (defun phpinspect-pctx-cancel (pctx) -;; "Cancel PCTX, revert all changes made during its lifetime. +(define-inline phpinspect-pctx-check-yield (pctx) + "Yield the current thread before each parsed token. + +If the current thread is the main thread, the thread will not be +yielded. + +The parser will start yielding before each parsed token when +`phpinspect--pctx-start-time' exceeds +`phpinspect-pctx-interrupt-threshold'." + (inline-letevals (pctx) + (inline-quote + (progn + (unless (phpinspect-pctx--start-time ,pctx) + (setf (phpinspect-pctx--start-time ,pctx) (time-convert nil t))) + + ;; Interrupt when blocking too long while input is pending. + (when (time-less-p (phpinspect-pctx-interrupt-threshold ,pctx) + (time-since (phpinspect-pctx--start-time ,pctx))) + (phpi-thread-yield)))))) + -;; Revert all changes made to the metadata tree while parsing -;; incrementally. This function is usually called by -;; `phpinspect-pctx-check-interrupt' when interrupt conditions are -;; met." -;; (dolist (changeset (phpinspect-pctx-changesets pctx)) -;; (phpinspect-changeset-revert changeset)) -;; (setf (phpinspect-pctx-changesets pctx) nil)) (provide 'phpinspect-parse-context) ;;; phpinspect-parse-context.el ends here diff --git a/phpinspect-parser.el b/phpinspect-parser.el index def9f99fe4..e282e11cee 100644 --- a/phpinspect-parser.el +++ b/phpinspect-parser.el @@ -229,11 +229,12 @@ of a statement. You can use `phpinspect-terminator-p` as 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) + `(defun ,(phpinspect-parser-func-name name "simple") (context 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) + (collaborative (when context (phpinspect-pctx-collaborative context))) token) (when skip-over (forward-char skip-over)) (while (and (< (point) max-point) @@ -244,6 +245,10 @@ token is \";\", which marks the end of a statement in PHP." (,delimiter-predicate (car (last tokens)))) `(,delimiter-predicate (car (last tokens)))) nil))) + + (when collaborative + (phpinspect-pctx-check-yield context)) + (cond ,@(mapcar (lambda (handler) `((looking-at (,(phpinspect-handler-regexp-func-name handler))) @@ -270,7 +275,7 @@ is able to reuse an already parsed tree." (root-start (point)) (previous-bmap (phpinspect-pctx-previous-bmap context)) (change (phpinspect-pctx-change context)) - (check-interrupt (phpinspect-pctx-interrupt-predicate context)) + (collaborative (phpinspect-pctx-collaborative context)) ;; Loop variables (start-position) @@ -291,12 +296,11 @@ is able to reuse an already parsed tree." (,delimiter-predicate (car (last tokens)))) `(,delimiter-predicate (car (last tokens)))) nil))) - (when check-interrupt - (phpinspect-pctx-check-interrupt context)) - (setq start-position (point)) + (when collaborative + (phpinspect-pctx-check-yield context)) - ;;(message "Start: %d" start-position) + (setq start-position (point)) (cond ((and-let* ((change) @@ -466,7 +470,7 @@ parsing incrementally." (if (and phpinspect-parse-context (phpinspect-pctx-incremental phpinspect-parse-context)) (,incremental-name phpinspect-parse-context buffer max-point skip-over continue-condition root) - (,simple-name buffer max-point skip-over continue-condition root))))) + (,simple-name phpinspect-parse-context buffer max-point skip-over continue-condition root))))) ) ;; End of eval-when-compile diff --git a/phpinspect-pipeline.el b/phpinspect-pipeline.el index 4893d853b5..5413bbc185 100644 --- a/phpinspect-pipeline.el +++ b/phpinspect-pipeline.el @@ -209,7 +209,7 @@ directories." result))) -(defun phpinspect--pipeline-fn-wrap-with-error-handler (fn step pipeline-ctx) +(defun phpinspect--pipeline-fn-wrap-with-error-handler (fn) (lambda (task) (condition-case err (funcall fn task) @@ -236,11 +236,11 @@ directories." (phpinspect--pipeline-step-name step) (phpinspect--pipeline-fn-wrap-with-ctx (phpinspect--pipeline-step-with-context step)) (phpinspect--pipeline-fn-wrap-with-read-pipeline step) - (phpinspect--pipeline-fn-wrap-with-error-handler step pipeline-ctx) + (phpinspect--pipeline-fn-wrap-with-error-handler) (phpinspect--pipeline-fn-wrap-with-emitter out-queue) (phpinspect--pipeline-fn-wrap-with-end-handler pipeline-ctx)))) (lambda (task) - (let ((result (funcall step-fn task))) + (prog1 (funcall step-fn task) (when (phpinspect-pipeline-end-p task) (phpi-job-queue-end)))))) diff --git a/phpinspect-project.el b/phpinspect-project.el index a895cd322b..ce8552e30c 100644 --- a/phpinspect-project.el +++ b/phpinspect-project.el @@ -341,7 +341,8 @@ before the search is executed." (let ((fs (phpinspect-project-fs project))) (with-temp-buffer (phpinspect-fs-insert-file-contents fs file-name 'prefer-async) - (phpinspect-index-current-buffer)))) + (phpinspect-with-parse-context (phpinspect-make-pctx :collaborative t) + (phpinspect-index-current-buffer))))) (cl-defmethod phpinspect-project-add-file-index ((project phpinspect-project) (file-name string)) (phpinspect-project-add-index project (phpinspect-project-index-file project file-name))) diff --git a/phpinspect-thread.el b/phpinspect-thread.el index d5449ed809..b55e45d470 100644 --- a/phpinspect-thread.el +++ b/phpinspect-thread.el @@ -89,19 +89,22 @@ ,thread-name))) -(defun phpi--main-thread-starving-p () - (if (or quit-flag (phpinspect--input-pending-p)) - 'yes - 'no)) +(define-inline phpi--main-thread-starving-p () + (inline-quote + (if (or quit-flag (phpinspect--input-pending-p)) + 'yes + 'no))) -(defun phpi-main-thread-starving-p () - (let ((starving (phpi--main-thread-starving-p))) - (when (eq 'yes starving) - (setf (phpi-condition-value phpinspect--main-thread-starving) starving) - t))) +(define-inline phpi-main-thread-starving-p () + (inline-quote + (let ((starving (phpi--main-thread-starving-p))) + (when (eq 'yes starving) + (setf (phpi-condition-value phpinspect--main-thread-starving) starving) + t)))) (defun phpi-await-main-thread-nourished () - (when (phpi-main-thread-startving-p) + (message "Waiting for the main thread to be nourished") + (when (phpi-main-thread-starving-p) (while (eq 'yes (phpi-condition-wait phpinspect--main-thread-starving))))) @@ -112,7 +115,7 @@ (defun phpi--notify-main-thread-nourished () (setf (phpi-condition-value phpinspect--main-thread-starving) 'no)) -(defvar phpinspect-main-thread-nourishment 0.1 +(defvar phpinspect-main-thread-nourishment 0.01 "Amount of seconds to pause all threads when input is pending.") (defvar phpinspect-main-thread-nourishment-timer @@ -155,7 +158,7 @@ If current thread is the main thread, this function does nothing." (while t (if-let ((job (phpinspect-queue-dequeue queue))) (phpi-progn - (condition-case err + (condition-case nil (funcall job-handler job) (phpinspect-job-queue-end ;; If job queue end is signaled, exit after queue has @@ -176,7 +179,7 @@ If current thread is the main thread, this function does nothing." (defun phpi-job-queue-kill (queue) (when (phpi-job-queue-live-p queue) - (phpi-kill-thread (phpi-job-queue-thread queue)))) + (phpi-thread-kill (phpi-job-queue-thread queue)))) (provide 'phpinspect-thread)