I think for the dot we don't need end_of_expression, we just update the
outer meta to include the outer identifier.

For aliases, I guess we can reuse closing? Or maybe last_dot? And what
happens when the alias has no dot? We don't set it?

On Fri, Jun 4, 2021 at 10:02 PM i Dorgan <[email protected]> wrote:

> > The dot one is easy, I think we can have the outer meta be the meta of
> the call identifier. A PR is welcome.
> Great! I will prepare a PR soon
>
> > One alternative is to have something similar to [end: ...] that we have
> for constructs like do-blocks, so we can at least say where the whole alias
> extends to? WDYT?
> Sounds reasonable to me. It would also be way less noisy.
> I think what's most valuable is to be able to tell the boundaries of a
> node, not so much what happens in between.
>
> Regarding the naming of the fields, do you think end_of_expression would
> be fine for both? It is described as "denotes when the end of expression
> effectively happens", which is what we would be adding here. Moreover, they
> would be the same positions that are already added in such field if the
> expression is part of a block.
> El viernes, 4 de junio de 2021 a las 16:13:11 UTC-3, José Valim escribió:
>
>> The dot one is easy, I think we can have the outer meta be the meta of
>> the call identifier. A PR is welcome.
>>
>> For aliases, it is trickier, as you said. One alternative is to have
>> something similar to [end: ...] that we have for constructs like do-blocks,
>> so we can at least say where the whole alias extends to? WDYT?
>>
>> On Fri, Jun 4, 2021 at 6:00 PM i Dorgan <[email protected]> wrote:
>>
>>> Hi all,
>>>
>>> I'm writing a function that takes a quoted expression and calculates the
>>> start and end positions of the node in the source code. So for example for
>>> this expression:
>>>
>>> :"foo#{
>>>   2
>>> }bar"
>>>
>>> It would tell us that it starts at line: 1, column: 1 and ends at line:
>>> 3, column: 6. The idea is that by knowing the boundaries of a node, a
>>> refactoring tool can say things like "replace the code between these
>>> positions with this other code".
>>>
>>> The issue I'm facing is that there are two cases where the AST does not
>>> contain enough information to calculate those positions, the first one is
>>> qualified identifiers:
>>>
>>> foo
>>> .
>>> bar
>>>
>>> which produces the ast:
>>>
>>> {{:., [line: 2, column: 1],
>>>   [
>>>     {:foo, [line: 1, column: 1], nil},
>>>     :bar
>>>   ]},
>>>  [no_parens: true, line: 2, column: 1], []}
>>>
>>> Note that we don't have any information about the location of :bar,
>>> only for the dot. This makes it impossible to accurately calculate the
>>> ending location for the expression, and we are forced to assume :bar is
>>> at the same line as the dot.
>>>
>>> The second case happens with aliases:
>>>
>>> Foo.
>>> Bar
>>> .Baz
>>>
>>> produces:
>>>
>>> {:__aliases__, [line: 1, column: 1], [:Foo, :Bar, :Baz]}
>>>
>>> Here we have even less information, we know nothing about dots or
>>> segments location, and we are forced to assume everything happens at the
>>> same line.
>>>
>>> I looked into the parser and this information is being discarded in the
>>> build_dot function for qualified identifiers and in build_dot_alias for
>>> aliases.
>>>
>>> My proposal is to keep that information in the ast metadata instead of
>>> discarding it when the :token_metadata option is true, similarly to how
>>> it is done with do/end, closing and end_of_expression.
>>>
>>> The quoted form of the first example would be something like this:
>>>
>>> {{:.,
>>>   [
>>>     identifier_location: [line: 3, column: 1],
>>>     line: 2,
>>>     column: 1
>>>   ],
>>>   [
>>>     {:foo, [line: 1, column: 1], nil},
>>>     :bar
>>>   ]},
>>>  [no_parens: true, line: 2, column: 1], []}
>>>
>>> For the aliases it would be a bit more involved, because there are two
>>> kind of locations that would need to be preserved: dots and segments. I've
>>> considered something like this to keep only the segments:
>>>
>>> {:__aliases__,
>>>  [
>>>    line: 1,
>>>    column: 1,
>>>    alias_segments: [
>>>      [token: :Foo, line: 1, column: 1],
>>>      [token: :Bar, line: 2, column: 1],
>>>      [token: :Baz, line: 4, column: 1]
>>>    ]
>>>  ], [:Foo, :Bar, :Baz]}
>>>
>>> I already have a working version, so I will gladly submit a PR if you
>>> consider this to be viable. I'm still unsure on how to tackle the dots
>>> positions in a meaningful way. While just knowing the segments positions is
>>> enough for my use cases, I figure dot positions may also need to be
>>> preserved for the sake of completeness.
>>>
>>> I'd like to know your thoughts!
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "elixir-lang-core" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to [email protected].
>>> To view this discussion on the web visit
>>> https://groups.google.com/d/msgid/elixir-lang-core/815d3113-dae6-4e99-8427-a873a704c4aan%40googlegroups.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/815d3113-dae6-4e99-8427-a873a704c4aan%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/ffd16955-f791-40b8-bd40-1cf37322995an%40googlegroups.com
> <https://groups.google.com/d/msgid/elixir-lang-core/ffd16955-f791-40b8-bd40-1cf37322995an%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4KvfE1bUy4c4TDG--xXZ6Yzv2EaHAvy4jBnFngu0ruZ_A%40mail.gmail.com.

Reply via email to