diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 4ac289d529..d20e5e9b51 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -134,6 +134,12 @@ ruby-symbol-chars (defconst ruby-symbol-re (concat "[" ruby-symbol-chars "]") "Regexp to match symbols.") +(defconst ruby-endless-method-head-re + (format " *\\(self\\.\\)?%s+[?!]? *\\(([^()]*)\\)? *=" ruby-symbol-re) + "Regexp to match the beginning of an endless method definition. + +It should match the part after \"def\" and until \"=\".") + (defvar ruby-use-smie t) (make-obsolete-variable 'ruby-use-smie nil "28.1") @@ -351,7 +357,8 @@ ruby-smie-grammar (exp (exp1) (exp "," exp) (exp "=" exp) (id " @ " exp)) (exp1 (exp2) (exp2 "?" exp1 ":" exp1)) - (exp2 (exp3) (exp3 "." exp3)) + (exp2 (exp3) (exp3 "." exp3) + (exp3 "def=" exp3)) (exp3 ("def" insts "end") ("begin" insts-rescue-insts "end") ("do" insts "end") @@ -528,6 +535,9 @@ ruby-smie--forward-token (ruby-smie--forward-token)) ;Fully redundant. (t ";"))) ((equal tok "&.") ".") + ((and (equal tok "def") + (looking-at ruby-endless-method-head-re)) + "def=") (t tok))))))))) (defun ruby-smie--backward-token () @@ -575,6 +585,9 @@ ruby-smie--backward-token (ruby-smie--backward-token)) ;Fully redundant. (t ";"))) ((equal tok "&.") ".") + ((and (equal tok "def") + (looking-at (concat "def" ruby-endless-method-head-re))) + "def=") (t tok))))))) (defun ruby-smie--indent-to-stmt () @@ -641,9 +654,11 @@ ruby-smie-rules (unless (or (eolp) (forward-comment 1)) (cons 'column (current-column))))) ('(:before . " @ ") - (save-excursion - (skip-chars-forward " \t") - (cons 'column (current-column)))) + (if (smie-rule-parent-p "def=") + (smie-rule-parent) + (save-excursion + (skip-chars-forward " \t") + (cons 'column (current-column))))) ('(:before . "do") (ruby-smie--indent-to-stmt)) ('(:before . ".") (if (smie-rule-sibling-p) @@ -672,6 +687,9 @@ ruby-smie-rules (and (smie-rule-parent-p ";" nil) (smie-indent--hanging-p) ruby-indent-level)) + (`(:before . "=") + (and (smie-rule-parent-p " @ ") + (smie-rule-parent ruby-indent-level))) (`(:after . ,(or "?" ":")) ruby-indent-level) (`(:before . ,(guard (memq (intern-soft token) ruby-alignable-keywords))) (when (not (ruby--at-indentation-p)) @@ -1631,7 +1649,7 @@ ruby-add-log-current-method (while (and (re-search-backward definition-re nil t) (if (if (string-equal "def" (match-string 1)) ;; We're inside a method. - (if (ruby-block-contains-point start) + (if (ruby-block-contains-point (1- start)) t ;; Try to match a method only once. (setq definition-re module-re) diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby.rb b/test/lisp/progmodes/ruby-mode-resources/ruby.rb index f39489071e..2e087393a8 100644 --- a/test/lisp/progmodes/ruby-mode-resources/ruby.rb +++ b/test/lisp/progmodes/ruby-mode-resources/ruby.rb @@ -500,3 +500,25 @@ def resolve(**args) member.call(**args) end + +# Endless methods. +class Bar + def foo(abc) = + bar + + bar + .baz + + def self.bar = + 123 + + 4 + + def request_params = { + headers: request_headers, + body: request_body + } +end + +class Foo + def foo(...) = z + def bar = y +end diff --git a/test/lisp/progmodes/ruby-mode-tests.el b/test/lisp/progmodes/ruby-mode-tests.el index e90a9e4075..9be01dc78f 100644 --- a/test/lisp/progmodes/ruby-mode-tests.el +++ b/test/lisp/progmodes/ruby-mode-tests.el @@ -605,6 +605,18 @@ ruby-add-log-current-method-after-inner-class-outside-methods-with-text (search-backward "FOO") (should (string= (ruby-add-log-current-method) "M::C")))) +(ert-deftest ruby-add-log-current-method-after-endless-method () + (ruby-with-temp-buffer (ruby-test-string + "module M + | class C + | def foo = + | 4_ + | end + |end") + (search-backward "_") + (delete-char 1) + (should (string= (ruby-add-log-current-method) "M::C#foo")))) + (defvar ruby-block-test-example (ruby-test-string "class C