aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Jörg2022-02-02 22:30:09 +0100
committerHarald Jörg2022-02-02 22:42:05 +0100
commitc882b4ea02b705d866fbcdd886b577b9592479fe (patch)
treedec72b06371f6e7ac460410ad800573be39e6ff7
parentaa795a6223c31ec8804f2824c435dba3091c115f (diff)
downloademacs-c882b4ea02b705d866fbcdd886b577b9592479fe.tar.gz
emacs-c882b4ea02b705d866fbcdd886b577b9592479fe.zip
; cperl-mode.el: Detect prototypes in anonymous subroutines
My commit 3d49ad73e5a from 2021-09-143 had a flaw causing bad fontification and indentation after anonymous subroutines with a prototype. * lisp/progmodes/cperl-mode.el (cperl-find-pods-heres): Correctly process prototypes in anonymous subroutines * test/lisp/progmodes/cperl-mode-tests.el (cperl-test-fontify-attrs-and-signatures): new tests for various combinations of attributes, prototypes, and signatures * test/lisp/progmodes/cperl-mode-resources/proto-and-attrs.pl: new test source
-rw-r--r--lisp/progmodes/cperl-mode.el2
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/proto-and-attrs.pl50
-rw-r--r--test/lisp/progmodes/cperl-mode-tests.el49
3 files changed, 100 insertions, 1 deletions
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index 8f33b3e3b73..94ecc45b15f 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -3834,7 +3834,7 @@ recursive calls in starting lines of here-documents."
3834 "\\<" cperl-sub-regexp "\\>" ; sub with proto/attr 3834 "\\<" cperl-sub-regexp "\\>" ; sub with proto/attr
3835 "\\(" 3835 "\\("
3836 cperl-white-and-comment-rex 3836 cperl-white-and-comment-rex
3837 (rx (group (eval cperl--normal-identifier-rx))) 3837 (rx (opt (group (eval cperl--normal-identifier-rx))))
3838 "\\)" 3838 "\\)"
3839 "\\(" 3839 "\\("
3840 cperl-maybe-white-and-comment-rex 3840 cperl-maybe-white-and-comment-rex
diff --git a/test/lisp/progmodes/cperl-mode-resources/proto-and-attrs.pl b/test/lisp/progmodes/cperl-mode-resources/proto-and-attrs.pl
new file mode 100644
index 00000000000..7138bf631df
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/proto-and-attrs.pl
@@ -0,0 +1,50 @@
1# The next two lines are required as of 2022, but obsolescent
2# as soon as signatures leave their "experimental" state
3use feature 'signatures';
4no warnings 'experimental::signatures';
5
6# Tests for subroutine prototypes, signatures and the like
7
8# Prototypes have syntactical properties different from "normal" Perl:
9# Perl has a variable $), so ($)) is not an unbalanced parenthesis.
10# On the other hand, in a prototype ($) is _not_ an open paren
11# followed by the variable $), so the parens are balanced. Prototypes
12# are somewhat frowned upon most of the times, but they are required
13# for some Perl magic
14
15# FIXME: 2022-02-02 CPerl mode does not handle subroutine signatures.
16# In simple cases it mistakes them as prototypes, when attributes are
17# present, it doesn't handle them at all. Variables in signatures
18# SHOULD be fontified like variable declarations.
19
20# Part 1: Named subroutines
21# A prototype and a trivial subroutine attribute
22{
23 no feature 'signatures'; # that's a prototype, not a signature
24 sub sub_1 ($) :lvalue { local $); }
25}
26
27# A prototype as an attribute (how it should be written these days)
28sub sub_2 :prototype($) { ...; }
29
30# A signature (these will soon-ish leave the experimental state)
31sub sub_3 ($foo,$bar) { ...; }
32
33# Attribute plus signature FIXME: Not yet supported
34sub bad_sub_4 :prototype($$$) ($foo,$bar,$baz) { ...; }
35
36# Part 2: Same constructs for anonymous subs
37# A prototype and a trivial subroutine attribute
38{
39 no feature 'signatures'; # that's a prototype, not a signature
40 my $subref_1 = sub ($) :lvalue { local $); };
41}
42
43# A prototype as an attribute (how it should be written these days)
44my $subref_2 = sub :prototype($) { ...; };
45
46# A signature (these will soon-ish leave the experimental state)
47my $subref_3 = sub ($foo,$bar) { ...; };
48
49# Attribute plus signature
50my $subref_4 = sub :prototype($$$) ($foo,$bar,$baz) { ...; };
diff --git a/test/lisp/progmodes/cperl-mode-tests.el b/test/lisp/progmodes/cperl-mode-tests.el
index 0124dad6f17..b8a3bd97d8d 100644
--- a/test/lisp/progmodes/cperl-mode-tests.el
+++ b/test/lisp/progmodes/cperl-mode-tests.el
@@ -154,6 +154,55 @@ point in the distant past, and is still broken in perl-mode. "
154 (should (equal (get-text-property (match-beginning 0) 'face) 154 (should (equal (get-text-property (match-beginning 0) 'face)
155 'font-lock-keyword-face)))) 155 'font-lock-keyword-face))))
156 156
157(ert-deftest cperl-test-fontify-attrs-and-signatures ()
158 "Test fontification of the various combinations of subroutine
159attributes, prototypes and signatures."
160 (skip-unless (eq cperl-test-mode #'cperl-mode))
161 (let ((file (ert-resource-file "proto-and-attrs.pl")))
162 (with-temp-buffer
163 (insert-file-contents file)
164 (goto-char (point-min))
165 (funcall cperl-test-mode)
166 (font-lock-ensure)
167
168 ;; Named subroutines
169 (while (search-forward-regexp "\\_<sub_[[:digit:]]+" nil t)
170 (should (equal (get-text-property (match-beginning 0) 'face)
171 'font-lock-function-name-face))
172 (let ((start-of-sub (match-beginning 0))
173 (end-of-sub (save-excursion (search-forward "}") (point))))
174
175 ;; Prototypes are shown as strings
176 (when (search-forward-regexp " ([$%@*]*) " end-of-sub t)
177 (should (equal (get-text-property (1+ (match-beginning 0)) 'face)
178 'font-lock-string-face)))
179 (goto-char start-of-sub)
180 (when (search-forward-regexp "\\(:[a-z]+\\)\\((.*?)\\)?" end-of-sub t)
181 (should (equal (get-text-property (match-beginning 1) 'face)
182 'font-lock-constant-face))
183 (when (match-beginning 2)
184 (should (equal (get-text-property (match-beginning 2) 'face)
185 'font-lock-string-face))))
186 (goto-char end-of-sub)))
187
188 ;; Anonymous subroutines
189 (while (search-forward-regexp "= sub" nil t)
190 (let ((start-of-sub (match-beginning 0))
191 (end-of-sub (save-excursion (search-forward "}") (point))))
192
193 ;; Prototypes are shown as strings
194 (when (search-forward-regexp " ([$%@*]*) " end-of-sub t)
195 (should (equal (get-text-property (1+ (match-beginning 0)) 'face)
196 'font-lock-string-face)))
197 (goto-char start-of-sub)
198 (when (search-forward-regexp "\\(:[a-z]+\\)\\((.*?)\\)?" end-of-sub t)
199 (should (equal (get-text-property (match-beginning 1) 'face)
200 'font-lock-constant-face))
201 (when (match-beginning 2)
202 (should (equal (get-text-property (match-beginning 2) 'face)
203 'font-lock-string-face))))
204 (goto-char end-of-sub))))))
205
157(ert-deftest cperl-test-fontify-special-variables () 206(ert-deftest cperl-test-fontify-special-variables ()
158 "Test fontification of variables like $^T or ${^ENCODING}. 207 "Test fontification of variables like $^T or ${^ENCODING}.
159These can occur as \"local\" aliases." 208These can occur as \"local\" aliases."