Preserve point in pascal-mode completion (bug#41740)

Failure to do so caused errors in several cases.
Reported by Shinichi Sakata.

* lisp/progmodes/pascal.el (pascal-type-completion)
(pascal-completion): Wrap code that may move point in save-excursion.
* test/lisp/progmodes/pascal-tests.el: New file.
This commit is contained in:
Mattias Engdegård 2020-06-21 21:04:30 +02:00
parent ce4ec17930
commit 73daab9991
2 changed files with 82 additions and 24 deletions

View file

@ -1170,26 +1170,27 @@ indent of the current line in parameterlist."
(defun pascal-type-completion (pascal-str)
"Calculate all possible completions for types."
(let ((start (point))
(pascal-all ())
goon)
;; Search for all reachable type declarations
(while (or (pascal-beg-of-defun)
(setq goon (not goon)))
(save-excursion
(if (and (< start (prog1 (save-excursion (pascal-end-of-defun)
(point))
(forward-char 1)))
(re-search-forward
"\\<type\\>\\|\\<\\(begin\\|function\\|procedure\\)\\>"
start t)
(not (match-end 1)))
;; Check current type declaration
(setq pascal-all
(nconc (pascal-get-completion-decl pascal-str)
pascal-all)))))
(save-excursion
(let ((start (point))
(pascal-all ())
goon)
;; Search for all reachable type declarations
(while (or (pascal-beg-of-defun)
(setq goon (not goon)))
(save-excursion
(if (and (< start (prog1 (save-excursion (pascal-end-of-defun)
(point))
(forward-char 1)))
(re-search-forward
"\\<type\\>\\|\\<\\(begin\\|function\\|procedure\\)\\>"
start t)
(not (match-end 1)))
;; Check current type declaration
(setq pascal-all
(nconc (pascal-get-completion-decl pascal-str)
pascal-all)))))
pascal-all))
pascal-all)))
(defun pascal-var-completion (prefix)
"Calculate all possible completions for variables (or constants)."
@ -1263,11 +1264,13 @@ indent of the current line in parameterlist."
(and (eq state 'defun)
(save-excursion
(re-search-backward ")[ \t]*:" (point-at-bol) t))))
(if (or (eq state 'paramlist) (eq state 'defun))
(pascal-beg-of-defun))
(nconc
(pascal-type-completion pascal-str)
(pascal-keyword-completion pascal-type-keywords pascal-str)))
(save-excursion
(if (or (eq state 'paramlist) (eq state 'defun))
(pascal-beg-of-defun))
(nconc
(pascal-type-completion pascal-str)
(pascal-keyword-completion pascal-type-keywords
pascal-str))))
( ;--Starting a new statement
(and (not (eq state 'contexp))
(save-excursion

View file

@ -0,0 +1,55 @@
;;; pascal-tests.el --- tests for pascal.el -*- lexical-binding: t -*-
;; Copyright (C) 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 <https://www.gnu.org/licenses/>.
(require 'ert)
(require 'pascal)
(ert-deftest pascal-completion ()
;; Bug#41740: completion functions must preserve point.
(let ((pascal-completion-cache nil))
(with-temp-buffer
(pascal-mode)
(insert "program test; var")
(let* ((point-before (point))
(completions (pascal-completion "var" nil 'metadata))
(point-after (point)))
(should (equal completions nil))
(should (equal point-before point-after)))))
(let ((pascal-completion-cache nil))
(with-temp-buffer
(pascal-mode)
(insert "program test; function f(x : i")
(let* ((point-before (point))
(completions (pascal-completion "i" nil 'metadata))
(point-after (point)))
(should (equal completions nil))
(should (equal point-before point-after)))))
(let ((pascal-completion-cache nil))
(with-temp-buffer
(pascal-mode)
(insert "program test; function f(x : integer) : real")
(let* ((point-before (point))
(completions (pascal-completion "real" nil 'metadata))
(point-after (point)))
(should (equal completions nil))
(should (equal point-before point-after))))))
(provide 'pascal-tests)