diff options
| author | Mattias EngdegÄrd | 2020-06-21 21:04:30 +0200 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2020-06-22 09:51:11 +0200 |
| commit | 73daab99914b4972a7cd167b03102be4c68e83e5 (patch) | |
| tree | 454a7f5d3c33b72c1ba0b7f3cffb453473386c30 | |
| parent | ce4ec1793041ae0f013234ef7189ed855b5227a3 (diff) | |
| download | emacs-73daab99914b4972a7cd167b03102be4c68e83e5.tar.gz emacs-73daab99914b4972a7cd167b03102be4c68e83e5.zip | |
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.
| -rw-r--r-- | lisp/progmodes/pascal.el | 51 | ||||
| -rw-r--r-- | test/lisp/progmodes/pascal-tests.el | 55 |
2 files changed, 82 insertions, 24 deletions
diff --git a/lisp/progmodes/pascal.el b/lisp/progmodes/pascal.el index 536a16dbb3c..b0191c029b9 100644 --- a/lisp/progmodes/pascal.el +++ b/lisp/progmodes/pascal.el | |||
| @@ -1170,26 +1170,27 @@ indent of the current line in parameterlist." | |||
| 1170 | 1170 | ||
| 1171 | (defun pascal-type-completion (pascal-str) | 1171 | (defun pascal-type-completion (pascal-str) |
| 1172 | "Calculate all possible completions for types." | 1172 | "Calculate all possible completions for types." |
| 1173 | (let ((start (point)) | 1173 | (save-excursion |
| 1174 | (pascal-all ()) | 1174 | (let ((start (point)) |
| 1175 | goon) | 1175 | (pascal-all ()) |
| 1176 | ;; Search for all reachable type declarations | 1176 | goon) |
| 1177 | (while (or (pascal-beg-of-defun) | 1177 | ;; Search for all reachable type declarations |
| 1178 | (setq goon (not goon))) | 1178 | (while (or (pascal-beg-of-defun) |
| 1179 | (save-excursion | 1179 | (setq goon (not goon))) |
| 1180 | (if (and (< start (prog1 (save-excursion (pascal-end-of-defun) | 1180 | (save-excursion |
| 1181 | (point)) | 1181 | (if (and (< start (prog1 (save-excursion (pascal-end-of-defun) |
| 1182 | (forward-char 1))) | 1182 | (point)) |
| 1183 | (re-search-forward | 1183 | (forward-char 1))) |
| 1184 | "\\<type\\>\\|\\<\\(begin\\|function\\|procedure\\)\\>" | 1184 | (re-search-forward |
| 1185 | start t) | 1185 | "\\<type\\>\\|\\<\\(begin\\|function\\|procedure\\)\\>" |
| 1186 | (not (match-end 1))) | 1186 | start t) |
| 1187 | ;; Check current type declaration | 1187 | (not (match-end 1))) |
| 1188 | (setq pascal-all | 1188 | ;; Check current type declaration |
| 1189 | (nconc (pascal-get-completion-decl pascal-str) | 1189 | (setq pascal-all |
| 1190 | pascal-all))))) | 1190 | (nconc (pascal-get-completion-decl pascal-str) |
| 1191 | pascal-all))))) | ||
| 1191 | 1192 | ||
| 1192 | pascal-all)) | 1193 | pascal-all))) |
| 1193 | 1194 | ||
| 1194 | (defun pascal-var-completion (prefix) | 1195 | (defun pascal-var-completion (prefix) |
| 1195 | "Calculate all possible completions for variables (or constants)." | 1196 | "Calculate all possible completions for variables (or constants)." |
| @@ -1263,11 +1264,13 @@ indent of the current line in parameterlist." | |||
| 1263 | (and (eq state 'defun) | 1264 | (and (eq state 'defun) |
| 1264 | (save-excursion | 1265 | (save-excursion |
| 1265 | (re-search-backward ")[ \t]*:" (point-at-bol) t)))) | 1266 | (re-search-backward ")[ \t]*:" (point-at-bol) t)))) |
| 1266 | (if (or (eq state 'paramlist) (eq state 'defun)) | 1267 | (save-excursion |
| 1267 | (pascal-beg-of-defun)) | 1268 | (if (or (eq state 'paramlist) (eq state 'defun)) |
| 1268 | (nconc | 1269 | (pascal-beg-of-defun)) |
| 1269 | (pascal-type-completion pascal-str) | 1270 | (nconc |
| 1270 | (pascal-keyword-completion pascal-type-keywords pascal-str))) | 1271 | (pascal-type-completion pascal-str) |
| 1272 | (pascal-keyword-completion pascal-type-keywords | ||
| 1273 | pascal-str)))) | ||
| 1271 | ( ;--Starting a new statement | 1274 | ( ;--Starting a new statement |
| 1272 | (and (not (eq state 'contexp)) | 1275 | (and (not (eq state 'contexp)) |
| 1273 | (save-excursion | 1276 | (save-excursion |
diff --git a/test/lisp/progmodes/pascal-tests.el b/test/lisp/progmodes/pascal-tests.el new file mode 100644 index 00000000000..10d6e0433d0 --- /dev/null +++ b/test/lisp/progmodes/pascal-tests.el | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | ;;; pascal-tests.el --- tests for pascal.el -*- lexical-binding: t -*- | ||
| 2 | |||
| 3 | ;; Copyright (C) 2020 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | ;; it under the terms of the GNU General Public License as published by | ||
| 9 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 10 | ;; (at your option) any later version. | ||
| 11 | |||
| 12 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | ;; GNU General Public License for more details. | ||
| 16 | |||
| 17 | ;; You should have received a copy of the GNU General Public License | ||
| 18 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 19 | |||
| 20 | (require 'ert) | ||
| 21 | (require 'pascal) | ||
| 22 | |||
| 23 | (ert-deftest pascal-completion () | ||
| 24 | ;; Bug#41740: completion functions must preserve point. | ||
| 25 | (let ((pascal-completion-cache nil)) | ||
| 26 | (with-temp-buffer | ||
| 27 | (pascal-mode) | ||
| 28 | (insert "program test; var") | ||
| 29 | (let* ((point-before (point)) | ||
| 30 | (completions (pascal-completion "var" nil 'metadata)) | ||
| 31 | (point-after (point))) | ||
| 32 | (should (equal completions nil)) | ||
| 33 | (should (equal point-before point-after))))) | ||
| 34 | |||
| 35 | (let ((pascal-completion-cache nil)) | ||
| 36 | (with-temp-buffer | ||
| 37 | (pascal-mode) | ||
| 38 | (insert "program test; function f(x : i") | ||
| 39 | (let* ((point-before (point)) | ||
| 40 | (completions (pascal-completion "i" nil 'metadata)) | ||
| 41 | (point-after (point))) | ||
| 42 | (should (equal completions nil)) | ||
| 43 | (should (equal point-before point-after))))) | ||
| 44 | |||
| 45 | (let ((pascal-completion-cache nil)) | ||
| 46 | (with-temp-buffer | ||
| 47 | (pascal-mode) | ||
| 48 | (insert "program test; function f(x : integer) : real") | ||
| 49 | (let* ((point-before (point)) | ||
| 50 | (completions (pascal-completion "real" nil 'metadata)) | ||
| 51 | (point-after (point))) | ||
| 52 | (should (equal completions nil)) | ||
| 53 | (should (equal point-before point-after)))))) | ||
| 54 | |||
| 55 | (provide 'pascal-tests) | ||