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

Error when Module Attribute in Docstring #289

Closed
aj-foster opened this issue Mar 5, 2024 · 4 comments
Closed

Error when Module Attribute in Docstring #289

aj-foster opened this issue Mar 5, 2024 · 4 comments

Comments

@aj-foster
Copy link
Contributor

Hello there 👋🏼

When a module attribute is used in a docstring, elixir_sense appears to raise an error while building metadata for function definitions. A reduced test case is available here. Anecdotally, this issue affects an entire project when any function utilizes module attributes in this way.

  • Elixir 1.16.0
  • ElixirLS 0.20.0
  • VS Code 1.87.0
  • elixir_sense 2.0.0
diff --git a/lib/test.ex b/lib/test.ex
index d0c8c5b..61f44c5 100644
--- a/lib/test.ex
+++ b/lib/test.ex
@@ -1,10 +1,12 @@
 defmodule Test do
+  @some_attribute 42
+
   @moduledoc """
   Documentation for `Test`.
   """
 
   @doc """
-  Hello world.
+  Hello world. #{@some_attribute}
 
   ## Examples
 

The error:

[Warn  - 6:20:06 PM] ** (ErlangError) Erlang error: "Protocol.UndefinedError during metadata build pre:\nprotocol String.Chars not implemented for {%ArgumentError{message: \"cannot invoke @/1 outside module\"}, [{Kernel, :assert_module_scope, 3, [file: ~c\"lib/kernel.ex\", line: 6555]}, {Kernel, :@, 1, [file: ~c\"expanding macro\"]}, {:elixir_compiler_0, :__FILE__, 1, [file: ~c\"nofile\", line: 9]}, {Kernel, :to_string, 1, [file: ~c\"expanding macro\"]}, {:elixir_compiler_0, :__FILE__, 1, [file: ~c\"nofile\", line: 9]}]} of type Tuple\nast node: {:def, [do: [line: 17, column: 13], end: [line: 19, column: 3], line: 17, column: 3], [{:hello, [line: 17, column: 7], nil}, [do: :world]]}"
    (elixir 1.16.0) lib/string/chars.ex:3: String.Chars.impl_for!/1
    (elixir 1.16.0) lib/string/chars.ex:22: String.Chars.to_string/1
    (elixir_sense 2.0.0) lib/elixir_sense/core/state.ex:1547: ElixirSense.Core.State.format_doc_arg/1
    (elixir_sense 2.0.0) lib/elixir_sense/core/state.ex:1504: anonymous fn/2 in ElixirSense.Core.State.reduce_doc_context/1
    (elixir 1.16.0) lib/enum.ex:2528: Enum."-reduce/3-lists^foldl/2-0-"/3
    (elixir_sense 2.0.0) lib/elixir_sense/core/state.ex:1492: ElixirSense.Core.State.consume_doc_context/1
    (elixir_sense 2.0.0) lib/elixir_sense/core/state.ex:842: ElixirSense.Core.State.add_func_to_index/7
    (elixir_sense 2.0.0) lib/elixir_sense/core/metadata_builder.ex:309: ElixirSense.Core.MetadataBuilder.pre_func/6
    (elixir_sense 2.0.0) lib/elixir_sense/core/metadata_builder.ex:102: ElixirSense.Core.MetadataBuilder.safe_call_pre/2
    (elixir 1.16.0) lib/macro.ex:637: anonymous fn/4 in Macro.do_traverse_args/4
    (stdlib 3.17.1) lists.erl:1358: :lists.mapfoldl/3
    (stdlib 3.17.1) lists.erl:1359: :lists.mapfoldl/3
    (elixir 1.16.0) lib/macro.ex:602: Macro.do_traverse/4
    (elixir 1.16.0) lib/macro.ex:617: Macro.do_traverse/4
    (stdlib 3.17.1) lists.erl:1358: :lists.mapfoldl/3
    (elixir 1.16.0) lib/macro.ex:622: Macro.do_traverse/4
@lukaszsamson
Copy link
Collaborator

@aj-foster That's not a common thing to do. Please send a PR fixing that. You would need to expand @ macro before trying to get the string out of the @doc attribute in format_doc_arg. Otherwise the minimal solution is to catch the error and return a dummy ""

@aj-foster
Copy link
Contributor Author

@lukaszsamson See #291 for a PR that solves the immediate issue (the rescue block raised an unrelated error because it failed to interpolate the exception).

I would love to expand @, however, I'm not sure how to reconstruct the Macro.Env necessary to do so. It seems like all of the necessary information is in the state, but I'm unsure how to safely transform it. Do you have any advice?

We are currently discussing this in the context of module attributes, but will this same issue occur for any non-primitive interpolation (ex. a function or macro call)? I'm concerned about the way doc ASTs are evaluated out of context.

Finally, I'm confused about the cause of this issue: did a recent change introduce it? I've certainly used module attributes in docstrings before, with accurate intellisense in VS Code.

@lukaszsamson
Copy link
Collaborator

I would love to expand @, however, I'm not sure how to reconstruct the Macro.Env necessary to do so. It seems like all of the necessary information is in the state, but I'm unsure how to safely transform it. Do you have any advice?

There is a plan to add Macro.Env building in elixir 1.17. Meanwhile here is the code doing use expansion

We are currently discussing this in the context of module attributes, but will this same issue occur for any non-primitive interpolation (ex. a function or macro call)?

Most of those non standard AST branches are simply omitted. In particular everything in quote is omitted. elixir_sense is not a full blown compiler.

Finally, I'm confused about the cause of this issue: did a recent change introduce it?

Yes, this is an unexpected side effect of #288

@lukaszsamson
Copy link
Collaborator

Since MetadataBuilder has been reimplemented this should no longer be an issue. The AST expansion continues and only a warning is emitted.

Unable to format docstring expression: ...
** (ArgumentError) cannot invoke @/1 outside module

@aj-foster please let me know if your project is still affected

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

No branches or pull requests

2 participants