emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master c882b4ea02: ; cperl-mode.el: Detect prototypes in anonymous subro


From: Harald Jörg
Subject: master c882b4ea02: ; cperl-mode.el: Detect prototypes in anonymous subroutines
Date: Wed, 2 Feb 2022 16:42:58 -0500 (EST)

branch: master
commit c882b4ea02b705d866fbcdd886b577b9592479fe
Author: Harald Jörg <haj@posteo.de>
Commit: Harald Jörg <haj@posteo.de>

    ; 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
---
 lisp/progmodes/cperl-mode.el                       |  2 +-
 .../cperl-mode-resources/proto-and-attrs.pl        | 50 ++++++++++++++++++++++
 test/lisp/progmodes/cperl-mode-tests.el            | 49 +++++++++++++++++++++
 3 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index 8f33b3e3b7..94ecc45b15 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 0000000000..7138bf631d
--- /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 0124dad6f1..b8a3bd97d8 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 "\\_<sub_[[:digit:]]+" nil t)
+        (should (equal (get-text-property (match-beginning 0) 'face)
+                       'font-lock-function-name-face))
+        (let ((start-of-sub (match-beginning 0))
+              (end-of-sub (save-excursion (search-forward "}") (point))))
+
+          ;; Prototypes are shown as strings
+          (when (search-forward-regexp " ([$%@*]*) " end-of-sub t)
+            (should (equal (get-text-property (1+ (match-beginning 0)) 'face)
+                           'font-lock-string-face)))
+          (goto-char start-of-sub)
+          (when (search-forward-regexp "\\(:[a-z]+\\)\\((.*?)\\)?" end-of-sub 
t)
+            (should (equal (get-text-property (match-beginning 1) 'face)
+                           'font-lock-constant-face))
+            (when (match-beginning 2)
+              (should (equal (get-text-property (match-beginning 2) 'face)
+                             'font-lock-string-face))))
+          (goto-char end-of-sub)))
+
+      ;; Anonymous subroutines
+      (while (search-forward-regexp "= sub" nil t)
+        (let ((start-of-sub (match-beginning 0))
+              (end-of-sub (save-excursion (search-forward "}") (point))))
+
+          ;; Prototypes are shown as strings
+          (when (search-forward-regexp " ([$%@*]*) " end-of-sub t)
+            (should (equal (get-text-property (1+ (match-beginning 0)) 'face)
+                           'font-lock-string-face)))
+          (goto-char start-of-sub)
+          (when (search-forward-regexp "\\(:[a-z]+\\)\\((.*?)\\)?" end-of-sub 
t)
+            (should (equal (get-text-property (match-beginning 1) 'face)
+                           'font-lock-constant-face))
+            (when (match-beginning 2)
+              (should (equal (get-text-property (match-beginning 2) 'face)
+                             'font-lock-string-face))))
+          (goto-char end-of-sub))))))
+
 (ert-deftest cperl-test-fontify-special-variables ()
   "Test fontification of variables like $^T or ${^ENCODING}.
 These can occur as \"local\" aliases."



reply via email to

[Prev in Thread] Current Thread [Next in Thread]