From 42ba58df6c3071576f2ddc6e0a285db57b7e690b Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Tue, 1 Nov 2022 13:22:58 -0700 Subject: Simplify and correct angle bracket propertizing and macro argument detection. Fixes #465. When `rust-syntax-propertize` uses `rust-macro-scopes` to find ranges of text that are macro arguments, it ends up inadvertently poisoning the `syntax-ppss` cache by applying it to text that doesn't have the necessary `syntax-table` properties applied yet - the very job that `rust-syntax-propertize` is trying to do. However, `rust-macro-scopes` does much more work than necessary. Rather than producing a list of ranges of macro arguments, we can just use the list of enclosing opening parens provided by syntax-ppss, checking each paren to see if it seems to be a macro or `macro_rules` call. We have to keep syntax-ppss's cache accurate for other reasons anyway, so we might as well just use its data, rather than introducing another cache of our own - especially a problematic one (see #465). * rust-mode.el (rust-in-macro): Consult `syntax-ppss`'s list of enclosing parens, rather than using `rust-macro-scope`. Remove optional arguments, which were only used by tests. (rust-macro-scopes, rust-macro-scope): Delete. Now we just use `syntax-ppss`'s internal cache. (rust-syntax-propertize): Don't bind `rust-macro-scopes`. (rust-looking-back-macro-rules): New function. (rust-looking-back-macro): Support a space between macro name and `!`, by consulting `rust-expression-introducers`. (rust-expression-introducers): New constant. Use in `rust-looking-back-macro` and `rust-is-in-expression-context`. (rust-is-in-expression-context): Use `rust-expression-introducers`. (rust-looking-back-ident): Don't use `looking-back`. We've already moved to the correct spot for `looking-at`, within a `save-excursion`. * rust-mode-tests.el: Update tests. --- rust-mode-tests.el | 72 +++++++++++++++++------------------------------------- 1 file changed, 22 insertions(+), 50 deletions(-) (limited to 'rust-mode-tests.el') diff --git a/rust-mode-tests.el b/rust-mode-tests.el index e4949b2..abbfcb6 100644 --- a/rust-mode-tests.el +++ b/rust-mode-tests.el @@ -3116,7 +3116,7 @@ macro_c!{ (syntax-ppss)))) -(ert-deftest rust-test-in-macro-no-caching () +(ert-deftest rust-test-in-macro-around-opening () (should-not (with-temp-buffer (insert @@ -3125,66 +3125,38 @@ macro_c!{ struct Boo {} ") (rust-mode) - (search-backward "macro") - ;; do not use the cache - (let ((rust-macro-scopes nil)) - (rust-in-macro))))) - -(ert-deftest rust-test-in-macro-fake-cache () - (should - (with-temp-buffer - (insert - "fn foo(a:A) { - macro_c!{ - struct Boo {} -") - (rust-mode) - (search-backward "macro") - ;; make the cache lie to make the whole buffer in scope - ;; we need to be at paren level 1 for this to work - (let ((rust-macro-scopes `((,(point-min) ,(point-max))))) - (rust-in-macro))))) - -(ert-deftest rust-test-in-macro-broken-cache () - (should-error - (with-temp-buffer - (insert - "fn foo(a:A) { - macro_c!{ - struct Boo {} -") - (rust-mode) - (search-backward "Boo") - ;; do we use the cache at all - (let ((rust-macro-scopes '(I should break))) - (rust-in-macro))))) + (search-backward "macro_c") + (and + (not (rust-in-macro)) + (progn (forward-thing 'symbol 1) (not (rust-in-macro))) + (progn (forward-char 1) (rust-in-macro)) + (progn (goto-char (point-max)) (rust-in-macro)))))) (ert-deftest rust-test-in-macro-nested () - (should - (equal - (with-temp-buffer - (insert - "macro_rules! outer { + (with-temp-buffer + (insert + "macro_rules! outer { () => { vec![] }; }") - (rust-mode) - (rust-macro-scope (point-min) (point-max))) - '((38 40) (20 45))))) + (rust-mode) + (should (progn (goto-char 20) (not (rust-in-macro)))) + (should (progn (goto-char 21) (eq (rust-in-macro) 20))) + (should (progn (goto-char 38) (eq (rust-in-macro) 20))) + (should (progn (goto-char 39) (eq (rust-in-macro) 38))) + (should (progn (goto-char 40) (eq (rust-in-macro) 20))) + (should (progn (goto-char 44) (eq (rust-in-macro) 20))) + (should (progn (goto-char 45) (not (rust-in-macro)))))) (ert-deftest rust-test-in-macro-not-with-space () - (should - (equal - (with-temp-buffer - (insert + (with-temp-buffer + (insert "fn foo() { if !(mem::size_of::() > 8) { bar() } }") - (rust-mode) - (rust-macro-scope (point-min) (point-max))) - 'empty))) - + (rust-mode) + (should (progn (goto-char 24) (not (rust-in-macro)))))) (ert-deftest rust-test-paren-matching-type-with-module-name () (rust-test-matching-parens -- cgit v1.2.3