Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -2536,13 +2536,16 @@ func (p *Parser) methodName() string {
return t.Lit
}
switch t.Type {
// Operator methods called explicitly: 1.+(2), a.<=>(b), obj.&(x), …
// Operator methods called explicitly: 1.+(2), a.<=>(b), obj.&(x), … Each
// operator token names the method by its own spelling ("+", "<=>", "&", …).
case token.SPACESHIP, token.LT, token.GT, token.LE, token.GE, token.EQ, token.EQQ, token.NEQ,
token.SHOVEL, token.RSHIFT, token.PLUS, token.MINUS, token.STAR, token.SLASH, token.PERCENT, token.POW,
token.AMPER, token.PIPE, token.CARET, token.TILDE, token.MATCH, token.NMATCH, token.BANG,
token.XSTRING:
// XSTRING here is an empty backtick literal `` produced when `` ` `` names the
// backtick method (`def \`(cmd); end`, `obj.\``).
token.AMPER, token.PIPE, token.CARET, token.TILDE, token.MATCH, token.NMATCH, token.BANG:
p.advance()
return t.Type.String()
case token.XSTRING:
// An empty backtick literal `` produced when `` ` `` names the backtick
// method (`def \`(cmd); end`, `obj.\``).
p.advance()
return "`"
}
Expand Down
39 changes: 39 additions & 0 deletions round4_features_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,45 @@ func TestUnicodeIdentifiers(t *testing.T) {
parsesOK(t, "p ?é\n")
}

// TestOperatorMethodName asserts that an explicitly-called operator method
// (`recv.OP(arg)`) names the method by the operator's own spelling — not the
// backtick “ ` “ that only the empty-XSTRING backtick-method case yields.
func TestOperatorMethodName(t *testing.T) {
cases := []struct{ src, name string }{
{"1.+(2)", "+"},
{"1.-(2)", "-"},
{"1.*(2)", "*"},
{"1.**(2)", "**"},
{"a.<=>(b)", "<=>"},
{"a.<(b)", "<"},
{"a.>(b)", ">"},
{"a.<=(b)", "<="},
{"a.>=(b)", ">="},
{"a.==(b)", "=="},
{"a.===(b)", "==="},
{"a.!=(b)", "!="},
{"a.<<(b)", "<<"},
{"a.>>(b)", ">>"},
{"a.&(b)", "&"},
{"a.|(b)", "|"},
{"a.^(b)", "^"},
{"a.=~(b)", "=~"},
{"a.!~(b)", "!~"},
{"a.~", "~"},
{"a.!", "!"},
{"a.``(c)", "`"}, // the backtick method (empty XSTRING literal), still "`"
}
for _, c := range cases {
call, ok := parseOne(t, c.src).(*ast.Call)
if !ok {
t.Fatalf("Parse(%q): top node = %T, want *ast.Call", c.src, parseOne(t, c.src))
}
if call.Name != c.name {
t.Errorf("Parse(%q): method name = %q, want %q", c.src, call.Name, c.name)
}
}
}

// --- Feature 8: safe-navigation with an operator method ---

func TestSafeNavOperatorMethod(t *testing.T) {
Expand Down
Loading