Skip to content

Accessing the = location in an attribute write #3656

@amomchilov

Description

@amomchilov

There's currently no easy way to get the location of the = in an "attribute write" like:

self.attr_name = :value
#              ^

Notice that the PM_CALL_NODE's name has the = (name: :attr_name=), but the message_loc only spans the message (message_loc: (1,5)-(1,14) = "attr_name"):

Example Prism AST
> Prism.parse("self.attr_name = :value").value
@ ProgramNode (location: (1,0)-(1,23))
├── flags: 
├── locals: []
└── statements:
    @ StatementsNode (location: (1,0)-(1,23))
    ├── flags: 
    └── body: (length: 1)
        └── @ CallNode (location: (1,0)-(1,23))
            ├── flags: newline, attribute_write, ignore_visibility
            ├── receiver:
               @ SelfNode (location: (1,0)-(1,4))
               └── flags: 
            ├── call_operator_loc: (1,4)-(1,5) = "."
            ├── name: :attr_name=
            ├── message_loc: (1,5)-(1,14) = "attr_name"
            ├── opening_loc: 
            ├── arguments:
               @ ArgumentsNode (location: (1,17)-(1,23))
               ├── flags: 
               └── arguments: (length: 1)
                   └── @ SymbolNode (location: (1,17)-(1,23))
                       ├── flags: static_literal, forced_us_ascii_encoding
                       ├── opening_loc: (1,17)-(1,18) = ":"
                       ├── value_loc: (1,18)-(1,23) = "value"
                       ├── closing_loc: 
                       └── unescaped: "value"
            ├── closing_loc: 
            └── block: 

I ran into this while fixing a bug in Sorbet (PR). Sorbet's pipeline needs me to provide a location that spans the whole method name up to (and including) the = (including any amount of possible whitespace in between), like so:

self.attr_name = :value
#    ^^^^^^^^^^^

The closest thing I could do is start at the end of the message_loc, and scan right until hitting the next =. This works, but it would be nicer to get the value from Prism.

@jez suggests that we could repurpose the opening_loc field, which would otherwise always be null for "attribute write" cases like this.

We'd be happy to implement this, if the approach sounds good. Thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions