Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code.Fragment.container_cursor_to_quoted/1 can't return aliases when cursor at alias line. #12673

Closed
scottming opened this issue Jun 15, 2023 · 9 comments

Comments

@scottming
Copy link

Is this a bug?

iex(2)> s = "defmodule Mymodule do\n  alias Foo.Bar\n"                                     
"defmodule Mymodule do\n  alias Foo.Bar\n"
iex(3)> s |> Future.Code.Fragment.container_cursor_to_quoted
{:ok,
 {:defmodule, [line: 1],
  [
    {:__aliases__, [line: 1], [:Mymodule]},
    [
      do: {:__block__, [],
       [
         {:alias, [line: 2], [{:__aliases__, [line: 2], [:Foo, :Bar]}]},
         {:__cursor__, [line: 3], []}
       ]}
    ]
  ]}}
iex(4)> s = "defmodule MyModule do\n  alias Project.Structs.User"
"defmodule MyModule do\n  alias Project.Structs.User"
iex(5)> s |> Future.Code.Fragment.container_cursor_to_quoted     
{:ok,
 {:defmodule, [line: 1],
  [
    {:__aliases__, [line: 1], [:MyModule]},
    [do: {:alias, [line: 2], [{:__cursor__, [line: 2], []}]}]
  ]}}
iex(6)> 

I'm trying to copy some code to the Lexical repo: lexical-lsp/lexical#217

But I can't extract the aliases with this line: "defmodule MyModule do\n alias Project.Structs.User"

@josevalim
Copy link
Member

Can you tell me the macro task you are trying to do? The container cursor to quoted returns the parent, in this case the parent is the do block. cursor_context will tell you that you are in an alias. So you always look at cursor_context first, and then you use container to disambiguate or to get more context. Does that make sense?

@scottming
Copy link
Author

scottming commented Jun 15, 2023

o, I see; thanks for the quick reply. I'm trying to build an alias mapping, with your suggestion, I think I can use cursor_context + container_cursor_to_quoted to archive that.

@josevalim
Copy link
Member

Building the mapping is not something the Elixir tools will help, unfortunately. We want to tackle that in #12645.

if you want the AST until the current cursor, then you can always append a new line and call container_cursor_to_quoted. But using Elixir sense and private APIs may still be the best way to achieve that :(

@scottming
Copy link
Author

Yes, I have noticed this.

I cannot handle this defmodule MyModule do\n alias Project.Structs.User, as: MyUser with cursor_context + container_cursor_to_quoted. Let me try adding a new line first.):

@scottming
Copy link
Author

@josevalim
Hi, José, we already built our alias_mapping, and we think we found a bug.

iex(1)> Code.Fragment.container_cursor_to_quoted("%Struct{field: 1, fie\n")
{:error,
 {[line: 1, column: 17],
  "unexpected expression after keyword list. Keyword lists must always come last in lists and maps. Therefore, this is not allowed:\n\n    [some: :value, :another]\n    %{some: :value, another => value}\n\nInstead, reorder it to be the last entry:\n\n    [:another, some: :value]\n    %{another => value, some: :value}\n\nSyntax error after: ",
  "','"}}

%Struct{field: 1, fie\n this line should not fail the AST parsing, right?

@sabiwara
Copy link
Contributor

sabiwara commented Jul 8, 2023

%Struct{field: 1, fie\n this line should not fail the AST parsing, right?

I think\n is the issue here: keyword keys must be immediately followed by : without any whitespace. The following are syntax errors:

%{field : 1}
%{field
: 1}

@sabiwara
Copy link
Contributor

sabiwara commented Jul 8, 2023

Added to the syntax reference.

@scottming
Copy link
Author

@sabiwara

Thanks, but if this case cannot be handled by container_cursor_to_quoted, then we have to do something special for when the cursor is in struct arguments, like not adding a new line.

cc @scohen

@josevalim
Copy link
Member

IIRC, the new line is a temporary solution until #12645 is in place. My suggestion is for you to add a newline and then, if it fails to parse, try again without the newline.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants