From: Harald Jörg Date: Wed, 2 Feb 2022 21:30:09 +0000 (+0100) Subject: ; cperl-mode.el: Detect prototypes in anonymous subroutines X-Git-Tag: emacs-29.0.90~2571 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=c882b4ea02b705d866fbcdd886b577b9592479fe;p=emacs.git ; 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 --- 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." "\\<" cperl-sub-regexp "\\>" ; sub with proto/attr "\\(" cperl-white-and-comment-rex - (rx (group (eval cperl--normal-identifier-rx))) + (rx (opt (group (eval cperl--normal-identifier-rx)))) "\\)" "\\(" 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 @@ +# The next two lines are required as of 2022, but obsolescent +# as soon as signatures leave their "experimental" state +use feature 'signatures'; +no warnings 'experimental::signatures'; + +# Tests for subroutine prototypes, signatures and the like + +# Prototypes have syntactical properties different from "normal" Perl: +# Perl has a variable $), so ($)) is not an unbalanced parenthesis. +# On the other hand, in a prototype ($) is _not_ an open paren +# followed by the variable $), so the parens are balanced. Prototypes +# are somewhat frowned upon most of the times, but they are required +# for some Perl magic + +# FIXME: 2022-02-02 CPerl mode does not handle subroutine signatures. +# In simple cases it mistakes them as prototypes, when attributes are +# present, it doesn't handle them at all. Variables in signatures +# SHOULD be fontified like variable declarations. + +# Part 1: Named subroutines +# A prototype and a trivial subroutine attribute +{ + no feature 'signatures'; # that's a prototype, not a signature + sub sub_1 ($) :lvalue { local $); } +} + +# A prototype as an attribute (how it should be written these days) +sub sub_2 :prototype($) { ...; } + +# A signature (these will soon-ish leave the experimental state) +sub sub_3 ($foo,$bar) { ...; } + +# Attribute plus signature FIXME: Not yet supported +sub bad_sub_4 :prototype($$$) ($foo,$bar,$baz) { ...; } + +# Part 2: Same constructs for anonymous subs +# A prototype and a trivial subroutine attribute +{ + no feature 'signatures'; # that's a prototype, not a signature + my $subref_1 = sub ($) :lvalue { local $); }; +} + +# A prototype as an attribute (how it should be written these days) +my $subref_2 = sub :prototype($) { ...; }; + +# A signature (these will soon-ish leave the experimental state) +my $subref_3 = sub ($foo,$bar) { ...; }; + +# Attribute plus signature +my $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. " (should (equal (get-text-property (match-beginning 0) 'face) 'font-lock-keyword-face)))) +(ert-deftest cperl-test-fontify-attrs-and-signatures () + "Test fontification of the various combinations of subroutine +attributes, prototypes and signatures." + (skip-unless (eq cperl-test-mode #'cperl-mode)) + (let ((file (ert-resource-file "proto-and-attrs.pl"))) + (with-temp-buffer + (insert-file-contents file) + (goto-char (point-min)) + (funcall cperl-test-mode) + (font-lock-ensure) + + ;; Named subroutines + (while (search-forward-regexp "\\_