Make parse context cancellable and restore state after interrupt

WIP-cache
Hugo Thunnissen 10 months ago
parent 111fa2f4b5
commit b68baaec83

@ -255,22 +255,23 @@ giving up. If not provided, this is 100."
(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)
(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)))
(phpinspect-meta-with-changeset token-meta
(phpinspect-meta-detach-parent token-meta)
(phpinspect-meta-shift token-meta pos-delta)
(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)

@ -105,8 +105,10 @@
(inline-quote
(when (phpinspect-meta-parent ,meta)
;; Update absolute start and end
(setf (phpinspect-meta-absolute-start ,meta) (phpinspect-meta-start ,meta))
(setf (phpinspect-meta-absolute-end ,meta) (phpinspect-meta-end ,meta))
;; Note: start should always be updated after end, as end is derived from
;; it.
(setf (phpinspect-meta-absolute-start ,meta) (phpinspect-meta-start ,meta))
(setf (phpinspect-meta-parent ,meta) nil)))))
(defun phpinspect-meta-shift (meta delta)
@ -114,16 +116,76 @@
(setf (phpinspect-meta-absolute-end meta) (+ (phpinspect-meta-end meta) delta)))
(defun phpinspect-meta-right-siblings (meta)
(mapcar #'phpinspect-meta-token
(sort
(phpinspect-splayt-find-all-after
(phpinspect-meta-children (phpinspect-meta-parent meta)) (phpinspect-meta-parent-offset meta))
#'phpinspect-meta-sort-start)))
(sort
(phpinspect-splayt-find-all-after
(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))))
(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-overlapping-child ((meta (head meta)) (point integer))
(let ((child (phpinspect-splayt-find-largest-before
(phpinspect-meta-children meta) (phpinspect-meta--point-offset meta point))))
(when (and child (phpinspect-meta-overlaps-point point))
child)))
(cl-defmethod phpinspect-meta-find-overlapping-children ((meta (head meta)) (point integer))
(let ((child meta)
children)
(while (and (setq child (phpinspect-meta-find-overlapping-child child point))
(phpinspect-meta-overlaps-point child point))
(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)))))
(cl-defmethod phpinspect-meta-find-child-before ((meta (head meta)) (point integer))
(phpinspect-splayt-find-largest-before
(phpinspect-meta-children meta) (phpinspect-meta--point-offset meta point)))
(cl-defmethod phpinspect-meta-find-child-before-recursively ((meta (head meta)) (point integer))
(let ((child meta)
last)
(while (setq child (phpinspect-meta-find-child-before child point))
(setq last child))
last))
(cl-defmethod phpinspect-meta-find-children-after ((meta (head meta)) (point integer))
(sort
(phpinspect-splayt-find-all-after
(phpinspect-meta-children meta) (phpinspect-meta--point-offset meta point))
#'phpinspect-meta-sort-start))
(cl-defmethod phpinspect-meta-find-children-before ((meta (head meta)) (point integer))
(sort (phpinspect-splayt-find-all-before
(phpinspect-meta-children meta) (phpinspect-meta--point-offset meta point))
#'phpinspect-meta-sort-start))
(defun phpinspect-meta-string (meta)
(format "[start: %d, end: %d, token: %s]"
(phpinspect-meta-start meta) (phpinspect-meta-end meta) (phpinspect-meta-token meta)))
(if meta
(format "[start: %d, end: %d, token: %s]"
(phpinspect-meta-start meta) (phpinspect-meta-end meta) (phpinspect-meta-token meta))
"[nil]"))
(provide 'phpinspect-meta)

@ -0,0 +1,182 @@
;;; phpinspect-parse-context.el --- PHP parsing context module -*- lexical-binding: t; -*-
;; Copyright (C) 2021 Free Software Foundation, Inc
;; Author: Hugo Thunnissen <devel@hugot.nl>
;; Keywords: php, languages, tools, convenience
;; Version: 0
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
(require 'phpinspect-util)
(require 'phpinspect-meta)
(require 'phpinspect-bmap)
(defvar phpinspect-parse-context nil
"An instance of `phpinspect-pctx' that is used when
parsing. Usually used in combination with
`phpinspect-with-parse-context'")
(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.")
(changesets nil
:type list
:documentation "Metadata change sets executed during this parse")
(edtrack nil
:type phpinspect-edtrack)
(bmap (phpinspect-make-bmap)
:type phpinspect-bmap)
(previous-bmap nil
:type phpinspect-bmap)
(whitespace-before ""
:type string))
(defmacro phpinspect-with-parse-context (ctx &rest body)
(declare (indent 1))
(let ((old-ctx (gensym))
(completed (gensym))
(result (gensym)))
`(let ((,old-ctx phpinspect-parse-context)
(,result)
(,completed))
(unwind-protect
(progn
(setq phpinspect-parse-context ,ctx
,result (progn ,@body)
,completed t)
,result)
(progn
(unless ,completed (phpinspect-pctx-cancel ,ctx))
(setq phpinspect-parse-context ,old-ctx))))))
(defmacro phpinspect-pctx-save-whitespace (pctx &rest body)
(declare (indent 1))
(let ((save-sym (gensym)))
`(let ((,save-sym (phpinspect-pctx-whitespace-before ,pctx)))
(unwind-protect
(progn
(setf (phpinspect-pctx-whitespace-before ,pctx) nil)
,@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-pctx-check-interrupt (pctx)
(inline-letevals (pctx)
(inline-quote
(progn
(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)))
(phpinspect-pctx-cancel ,pctx)
(throw 'phpinspect-parse-interrupted nil))))))
(define-inline phpinspect-pctx-register-token (pctx token start end)
(inline-letevals (pctx)
(inline-quote
(phpinspect-bmap-register
(phpinspect-pctx-bmap ,pctx) ,start ,end ,token (phpinspect-pctx-consume-whitespace ,pctx)))))
(define-inline phpinspect-pctx-register-whitespace (pctx whitespace)
(inline-quote
(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))
(define-inline phpinspect-make-changeset (meta)
(inline-letevals (meta)
(inline-quote
(list (phpinspect-meta-start ,meta) (phpinspect-meta-end ,meta)
(phpinspect-meta-parent ,meta) (phpinspect-meta-overlay ,meta)
(phpinspect-meta-parent-offset ,meta) ,meta))))
(define-inline phpinspect-changeset-start (set)
(inline-quote (car ,set)))
(define-inline phpinspect-changeset-end (set)
(inline-quote (cadr ,set)))
(define-inline phpinspect-changeset-parent (set)
(inline-quote (caddr ,set)))
(define-inline phpinspect-changeset-overlay (set)
(inline-quote (cadddr ,set)))
(define-inline phpinspect-changeset-parent-offset (set)
(inline-quote (car (cddddr ,set))))
(define-inline phpinspect-changeset-meta (set)
(inline-quote (car (nthcdr 5 ,set))))
(define-inline phpinspect-meta-with-changeset (meta &rest body)
(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-changeset-revert (changeset)
(inline-letevals (changeset)
(inline-quote
(progn
(setf (phpinspect-meta-parent (phpinspect-changeset-meta ,changeset))
(phpinspect-changeset-parent ,changeset))
(setf (phpinspect-meta-overlay (phpinspect-changeset-meta ,changeset))
(phpinspect-changeset-overlay ,changeset))
(setf (phpinspect-meta-absolute-start (phpinspect-changeset-meta ,changeset))
(phpinspect-changeset-start ,changeset))
(setf (phpinspect-meta-absolute-end (phpinspect-changeset-meta ,changeset))
(phpinspect-changeset-end ,changeset))
(setf (phpinspect-meta-parent-offset (phpinspect-changeset-meta ,changeset))
(phpinspect-changeset-parent-offset ,changeset))))))
(defun phpinspect-pctx-cancel (pctx)
(phpinspect--log "Cancelling parse context")
(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

@ -26,6 +26,7 @@
;;(require 'phpinspect-tree)
(require 'phpinspect-edtrack)
(require 'phpinspect-bmap)
(require 'phpinspect-parse-context)
(defvar phpinspect-parser-obarray (obarray-make)
"An obarray containing symbols for all phpinspect (sub)parsers.")
@ -37,68 +38,6 @@
(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))
@ -458,15 +397,6 @@ have any effect."
(setf (phpinspect-parser-incremental-func (symbol-value parser-symbol)) nil))
phpinspect-parser-obarray))
(defmacro phpinspect-pctx-save-whitespace (pctx &rest body)
(declare (indent 1))
(let ((save-sym (gensym)))
`(let ((,save-sym (phpinspect-pctx-whitespace-before ,pctx)))
(unwind-protect
(progn
(setf (phpinspect-pctx-whitespace-before ,pctx) nil)
,@body)
(setf (phpinspect-pctx-whitespace-before ,pctx) ,save-sym)))))
(defun phpinspect-make-parser-function (tree-type handler-list &optional delimiter-predicate)
"Create a parser function using the handlers by names defined in HANDLER-LIST.
@ -1139,5 +1069,20 @@ the properties of the class"
(current-buffer)
point nil 'root))))
(defun phpinspect-parse-current-buffer ()
(phpinspect-parse-buffer-until-point
(current-buffer)
(point-max)))
(defun phpinspect-parse-string (string)
(with-temp-buffer
(insert string)
(phpinspect-parse-current-buffer)))
(defun phpinspect-parse-file (file)
(with-temp-buffer
(insert-file-contents file)
(phpinspect-parse-current-buffer)))
(provide 'phpinspect-parser)
;;; phpinspect-parser.el ends here

@ -71,16 +71,6 @@ phpinspect")
project-root)
indexed-class)))
(defun phpinspect-parse-file (file)
(with-temp-buffer
(phpinspect-insert-file-contents file)
(phpinspect-parse-current-buffer)))
(defun phpinspect-parse-current-buffer ()
(phpinspect-parse-buffer-until-point
(current-buffer)
(point-max)))
(defun phpinspect-parse-string-to-bmap (string)
(with-temp-buffer
(insert string)
@ -91,11 +81,6 @@ phpinspect")
(phpinspect-pctx-bmap context))))
(defun phpinspect-parse-string (string)
(with-temp-buffer
(insert string)
(phpinspect-parse-current-buffer)))
(defun phpinspect-after-change-function (start end pre-change-length)
(when phpinspect-current-buffer
(phpinspect-buffer-register-edit phpinspect-current-buffer start end pre-change-length)))

@ -246,76 +246,6 @@
(should (equal expected assignments))))
(ert-deftest phpinspect-parse-namespaced-class ()
"Test phpinspect-parse on a namespaced class"
(should
(equal (phpinspect-test-read-fixture-data "NamespacedClass")
(phpinspect-test-parse-fixture-code "NamespacedClass"))))
(ert-deftest phpinspect-parse-block ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "Block")
(phpinspect-test-parse-fixture-code "Block"))))
(ert-deftest phpinspect-parse-functions ()
"Test phpinspect-parse for php functions"
(should
(equal (phpinspect-test-read-fixture-data "Functions")
(phpinspect-test-parse-fixture-code "Functions"))))
(ert-deftest phpinspect-parse-namespaced-functions ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "NamespacedFunctions")
(phpinspect-test-parse-fixture-code "NamespacedFunctions"))))
(ert-deftest phpinspect-parse-variable ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "Variable")
(phpinspect-test-parse-fixture-code "Variable"))))
(ert-deftest phpinspect-parse-word ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "Word")
(phpinspect-test-parse-fixture-code "Word"))))
(ert-deftest phpinspect-parse-array ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "Array")
(phpinspect-test-parse-fixture-code "Array"))))
(ert-deftest phpinspect-parse-short-function ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "ShortFunction")
(phpinspect-test-parse-fixture-code "ShortFunction"))))
(ert-deftest phpinspect-parse-two-short-functions ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "TwoShortFunctions")
(phpinspect-test-parse-fixture-code "TwoShortFunctions"))))
(ert-deftest phpinspect-parse-small-namespaced-class ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "SmallNamespacedClass")
(phpinspect-test-parse-fixture-code "SmallNamespacedClass"))))
;; If this test fails, the syntax tree has a breaking change in it. Regenerate the
;; fixtures and fix anything that is broken.
(ert-deftest phpinspect-syntax-tree-change ()
(let ((index (phpinspect--index-tokens
(phpinspect-test-parse-fixture-code "IndexClass1")))
(expected-result (phpinspect--index-tokens
(phpinspect-test-read-fixture-data "IndexClass1"))))
(should (equal index expected-result))))
(ert-deftest phpinspect-resolve-type-from-context ()
(let* ((pctx (phpinspect-make-pctx :incremental t))
@ -610,7 +540,10 @@ class Thing
(load-file (concat phpinspect-test-directory "/test-bmap.el"))
(load-file (concat phpinspect-test-directory "/test-edtrack.el"))
(load-file (concat phpinspect-test-directory "/test-resolvecontext.el"))
(load-file (concat phpinspect-test-directory "/test-parser.el"))
(load-file (concat phpinspect-test-directory "/test-parse-context.el"))
(load-file (concat phpinspect-test-directory "/test-splayt.el"))
(provide 'phpinspect-test)
;;; phpinspect-test.el ends here

@ -0,0 +1,52 @@
;;; phpinspect-test.el --- Unit tests for phpinspect.el -*- lexical-binding: t; -*-
;; Copyright (C) 2021 Free Software Foundation, Inc.
;; Author: Hugo Thunnissen <devel@hugot.nl>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'ert)
(require 'phpinspect-parse-context)
(require 'phpinspect-meta)
(ert-deftest phpinspect-pctx-cancel ()
(let ((meta (phpinspect-make-meta nil 10 20 " " 'token 'overlay nil))
(pctx (phpinspect-make-pctx)))
(phpinspect-with-parse-context pctx
(phpinspect-meta-with-changeset meta
(setf (phpinspect-meta-absolute-start meta) 222)
(setf (phpinspect-meta-absolute-end meta) 1234)
(phpinspect-meta-set-parent meta (phpinspect-make-meta nil 1 2000 "" 'parent-token))
(setf (phpinspect-meta-overlay meta) 'not-overlay)))
(should (= 222 (phpinspect-meta-start meta)))
(should (= 1234 (phpinspect-meta-end meta)))
(should (phpinspect-meta-parent meta))
(should (eq 'not-overlay (phpinspect-meta-overlay meta)))
(should (= 221 (phpinspect-meta-parent-offset meta)))
(phpinspect-pctx-cancel pctx)
(should (= 10 (phpinspect-meta-start meta)))
(should (= 20 (phpinspect-meta-end meta)))
(should-not (phpinspect-meta-parent meta))
(should-not (phpinspect-meta-parent-offset meta))
(should (eq 'overlay (phpinspect-meta-overlay meta)))))

@ -1,6 +1,46 @@
;; test-parser.el --- Unit tests for phpinspect.el -*- lexical-binding: t; -*-
;; Copyright (C) 2021 Free Software Foundation, Inc.
;; Author: Hugo Thunnissen <devel@hugot.nl>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'phpinspect-parser)
(defvar phpinspect-test-directory
(file-name-directory
(or load-file-name
buffer-file-name))
"Directory that phpinspect tests reside in.")
(defvar phpinspect-test-php-file-directory
(concat
(file-name-directory
(or load-file-name
buffer-file-name))
"/fixtures")
"Directory with syntax trees of example PHP files.")
(ert-deftest phpinspect-parse-bmap ()
(let* ((ctx (phpinspect-make-pctx :incremental t))
(code "
@ -30,3 +70,88 @@ class TestClass {
(setq parent (phpinspect-meta-parent (car enclosing)))
(should (phpinspect-list-p (phpinspect-meta-token parent)))
(should (phpinspect-block-p (phpinspect-meta-token (phpinspect-meta-parent parent)))))))
(ert-deftest phpinspect-parse-comma ()
(let* ((code "(,)")
(ctx (phpinspect-make-pctx :incremental t))
(parsed (phpinspect-with-parse-context ctx
(phpinspect-parse-string code)))
(comma (cadadr parsed))
(map (phpinspect-pctx-bmap ctx))
(comma-meta))
(should (equal '(:root (:list (:comma ","))) parsed))
(should (equal '(:comma ",") comma))
(should (setq comma-meta (phpinspect-bmap-token-meta map comma)))
(should (= 1 (phpinspect-meta-width comma-meta)))))
(ert-deftest phpinspect-parse-namespaced-class ()
"Test phpinspect-parse on a namespaced class"
(should
(equal (phpinspect-test-read-fixture-data "NamespacedClass")
(phpinspect-test-parse-fixture-code "NamespacedClass"))))
(ert-deftest phpinspect-parse-block ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "Block")
(phpinspect-test-parse-fixture-code "Block"))))
(ert-deftest phpinspect-parse-functions ()
"Test phpinspect-parse for php functions"
(should
(equal (phpinspect-test-read-fixture-data "Functions")
(phpinspect-test-parse-fixture-code "Functions"))))
(ert-deftest phpinspect-parse-namespaced-functions ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "NamespacedFunctions")
(phpinspect-test-parse-fixture-code "NamespacedFunctions"))))
(ert-deftest phpinspect-parse-variable ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "Variable")
(phpinspect-test-parse-fixture-code "Variable"))))
(ert-deftest phpinspect-parse-word ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "Word")
(phpinspect-test-parse-fixture-code "Word"))))
(ert-deftest phpinspect-parse-array ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "Array")
(phpinspect-test-parse-fixture-code "Array"))))
(ert-deftest phpinspect-parse-short-function ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "ShortFunction")
(phpinspect-test-parse-fixture-code "ShortFunction"))))
(ert-deftest phpinspect-parse-two-short-functions ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "TwoShortFunctions")
(phpinspect-test-parse-fixture-code "TwoShortFunctions"))))
(ert-deftest phpinspect-parse-small-namespaced-class ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-data "SmallNamespacedClass")
(phpinspect-test-parse-fixture-code "SmallNamespacedClass"))))
;; If this test fails, the syntax tree has a breaking change in it. Regenerate the
;; fixtures and fix anything that is broken.
(ert-deftest phpinspect-syntax-tree-change ()
(let ((index (phpinspect--index-tokens
(phpinspect-test-parse-fixture-code "IndexClass1")))
(expected-result (phpinspect--index-tokens
(phpinspect-test-read-fixture-data "IndexClass1"))))
(should (equal index expected-result))))

Loading…
Cancel
Save