;;; wisi-run-indent-test.el --- utils for automating indentation and casing tests
;;
;; Copyright (C) 2018 - 2020 Free Software Foundation, Inc.
;;
;; This file is part of GNU Emacs.
;;
;; GNU Emacs 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.
;;
;; GNU Emacs 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 GNU Emacs. If not, see .
(require 'wisi-tests)
(require 'wisi-prj)
;; user can set these to t in an EMACSCMD
(defvar skip-cmds nil)
(defvar skip-reindent-test nil)
(defvar skip-recase-test nil)
(defvar skip-write nil)
(defun test-in-comment-p ()
(nth 4 (syntax-ppss)))
(defun test-face (token face)
"Test if all of TOKEN in next code line has FACE.
FACE may be a list."
(save-excursion
(when (test-in-comment-p)
(beginning-of-line); forward-comment doesn't move if inside a comment!
(forward-comment (point-max)))
(condition-case err
(search-forward token (line-end-position 5))
(error
(error "can't find '%s'" token)))
(save-match-data
(wisi-validate-cache (line-beginning-position) (line-end-position) nil 'face)
(font-lock-ensure (line-beginning-position) (line-end-position)))
;; We don't use face-at-point, because it doesn't respect
;; font-lock-face set by the parser! And we want to check for
;; conflicts between font-lock-keywords and the parser.
;; font-lock-keywords sets 'face property, parser sets 'font-lock-face.
;; In emacs < 27, if we use (get-text-property (point) 'face), we
;; also get 'font-lock-face, but not vice-versa. So we have to use
;; text-properties-at to check for both.
(let* ((token (match-string 0))
(props (text-properties-at (match-beginning 0)))
key
token-face)
(cond
((plist-get props 'font-lock-face)
(setq key 'font-lock-face)
(setq token-face (plist-get props 'font-lock-face)))
((plist-get props 'face)
(setq key 'face)
(setq token-face (plist-get props 'face)))
)
(when (and (memq 'font-lock-face props)
(memq 'face props))
(describe-text-properties (match-beginning 0))
(error "mixed font-lock-keyword and parser faces for '%s'" token))
(unless (not (text-property-not-all 0 (length token) key token-face token))
(error "mixed faces, expecting %s for '%s'" face token))
(unless (or (and (listp face)
(memq token-face face))
(eq token-face face))
(error "found face %s, expecting %s for '%s'" token-face face token))
)))
(defun test-face-1 (search token face)
"Move to end of comment, search for SEARCH, call `test-face'."
(save-excursion
(when (test-in-comment-p)
(beginning-of-line); forward-comment doesn't move if inside a comment!
(forward-comment (point-max)))
(search-forward search)
(test-face token face)
))
(defun test-cache-class (token class)
"Test if TOKEN in next code line has wisi-cache with class CLASS."
(save-excursion
(wisi-validate-cache (line-beginning-position 0) (line-end-position 3) nil 'navigate)
(beginning-of-line); forward-comment doesn't move if inside a comment!
(forward-comment (point-max))
(condition-case err
(search-forward token (line-end-position 5))
(error
(error "can't find '%s'" token)))
(let ((cache (get-text-property (match-beginning 0) 'wisi-cache)))
(unless cache (error "no cache"))
(unless (eq (wisi-cache-class cache) class)
(error "expecting class %s, found '%s'" class (wisi-cache-class cache)))
)))
(defun test-cache-containing (containing contained)
"Test if CONTAINING in next code line has wisi-cache with that contains CONTAINED."
(save-excursion
(wisi-validate-cache (line-beginning-position 0) (line-end-position 3) nil 'navigate)
(beginning-of-line)
(forward-comment (point-max))
(let (containing-pos contained-cache)
(search-forward containing (line-end-position 5))
(setq containing-pos (match-beginning 0))
(search-forward contained (line-end-position 5))
(setq contained-cache (get-text-property (match-beginning 0) 'wisi-cache))
(unless contained-cache (error "no cache on %s" contained))
(unless (= containing-pos (wisi-cache-containing contained-cache))
(error "expecting %d, got %d" containing-pos (wisi-cache-containing contained-cache)))
)))
(defvar test-refactor-markers nil
"Stores positions altered by `test-refactor-1' for `test-refactor-2'.
Each item is a list (ACTION PARSE-BEGIN PARSE-END EDIT-BEGIN)")
(defun test-refactor-1 (action inverse-action search-string refactor-string)
(beginning-of-line)
(forward-comment (point-max)) ;; forward-comment does not work from inside comment
(search-forward search-string (line-end-position 7))
(wisi-validate-cache (line-end-position -7) (line-end-position 7) t 'navigate)
(search-forward refactor-string (line-end-position 7))
(let* ((edit-begin (match-beginning 0))
(cache (wisi-goto-statement-start))
(parse-begin (point))
(parse-end (wisi-cache-end cache)))
(setq parse-end (+ parse-end (wisi-cache-last (wisi-get-cache (wisi-cache-end cache)))))
(push (list
inverse-action
(copy-marker parse-begin nil)
(copy-marker parse-end nil)
(copy-marker edit-begin nil))
test-refactor-markers)
(wisi-refactor wisi--parser action parse-begin parse-end edit-begin)
))
(defun test-refactor-inverse ()
"Reverse refactors done by recent set of `test-refactor-1'."
(save-excursion
(condition-case-unless-debug nil
(dolist (item test-refactor-markers)
(wisi-refactor wisi--parser
(nth 0 item)
(marker-position (nth 1 item))
(marker-position (nth 2 item))
(marker-position (nth 3 item))))
(error nil))
(setq test-refactor-markers nil)))
(defun run-test-here ()
"Run an indentation and casing test on the current buffer."
(interactive)
(setq indent-tabs-mode nil)
(setq jit-lock-context-time 0.0);; for test-face
;; Test files use wisi-prj-select-cached to parse and select a project file.
(setq project-find-functions (list #'wisi-prj-current-cached))
(setq xref-backend-functions (list #'wisi-prj-xref-backend))
(let ((error-count 0)
(test-buffer (current-buffer))
cmd-line
last-result last-cmd expected-result)
;; Look for EMACS* comments in the file:
;;
;; EMACSCMD: