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

Attributes mixed with functions #5689

Closed
elbrujohalcon opened this issue Feb 7, 2022 · 3 comments · Fixed by #5712
Closed

Attributes mixed with functions #5689

elbrujohalcon opened this issue Feb 7, 2022 · 3 comments · Fixed by #5712
Assignees
Labels
enhancement team:VM Assigned to OTP team VM

Comments

@elbrujohalcon
Copy link
Contributor

Is your feature request related to a problem? Please describe.

I would like to implement AdRoll/rebar3_format#244 using attributes to surround code blocks that the formatter should ignore. To do that, I would like to be able to write code as…

-module my_mod.

-export [my_fun/0].

my_fun() ->
    my_fun(something, something).

-format_block ignore.
my_fun(something, something) -> [
  this
  , function
    , should
      , not be:formatted()
        ].
-format_bock.

But the compiler now tells me that…

my_mod.erl:#:#: attribute format_block after function definitions

Describe the solution you'd like

I would like to have a compiler option available to disable that check.

Describe alternatives you've considered

A brutal alternative would be to remove that check entirely, but I don't really know if there are scenarios where it's really needed.
Another one would be to allow some (i.e. a list of) attributes to be interleaved, but that list should either be configurable or otherwise properly maintained.
Another alternative is to preserve the check but only for OTP attributes… user attributes can be interleaved at will. That would be my favorite choice, but again… I'm not really aware of the consequences.

@ilya-klyuchnikov
Copy link
Contributor

ilya-klyuchnikov commented Feb 12, 2022

there are tools (like code linters and analysers) that would also benefit from an ability to specify how particular functions should be handled, - similar to how dialyzer relies on -dialyzer(...) attributes.

It is possible to do this via putting custom attributes in the beginning of a file and mention the function foo/1 explicitly, like this:

-my_tool({ignore, {foo, 1}}).

-spec ...
bar1(..) ->

bar2(..) ->

foo(Arg) -> 
...

But it is very sub-optimal from the ergonomics and usability points of view - since for developers it is important to keep the locality of "annotations" - keep annotations close to the code they affect.

ilya-klyuchnikov added a commit to ilya-klyuchnikov/otp that referenced this issue Feb 13, 2022
This makes Erlang surface syntax more friendly to tooling
like formatters, linters, analyzers.
Currently, the `-dialyzer(...)` attribute is the only annotating
(that is, not affecting semantics) attribute that can be placed
everywhere.

There is no reason to ban other custom attributes
from being placed between functions.

The logic that certain `erlc` attributes cannot be placed
after functions is preserved

This also closes erlang#5689.
ilya-klyuchnikov added a commit to ilya-klyuchnikov/otp that referenced this issue Feb 13, 2022
This makes Erlang surface syntax more friendly to tooling
like formatters, linters, analyzers.
Currently, the `-dialyzer(...)` attribute is the only annotating
(that is, not affecting semantics) attribute that can be placed
everywhere.

There is no reason to ban other custom attributes
from being placed between functions.

The logic that certain `erlc` attributes cannot be placed
after functions is preserved

This also closes erlang#5689.
@paulo-ferraz-oliveira
Copy link
Contributor

Code editors would potentially also benefit from the possibility to expand/collapse code, as eg.:

-module(example).
-export([a/0, b/0, c/0]).

-region Public API.
a() -> a_int().
b() -> b_int().
c() -> c_int().
-endregion.

-region Internal functions.
a_int() -> a().
b_int() -> b().
c_int() -> c().
-endregion.

would look like this when collapsed (the + is just "visual").

-module(example).
-export([a/0, b/0, c/0]).

+Public API

+Internal functions

This is actually something I've missed from my C# days. It could also probably be achieved with comments, though, but it would be trickier to validate, I imagine.

Hm... I think I might have mentioned this in rebar3_format somewhere, already. 😄

@elbrujohalcon
Copy link
Contributor Author

Any chance we can re-surface this idea, OTP Team? As a maintainer for Elvis, Hank, and rebar3_format (among others) I found myself linking to this ticket time and time again, lately. I still wonder how bad it could be to allow custom attributes to be placed after the first function declaration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement team:VM Assigned to OTP team VM
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants