From b25a4bbc6d616d5ea574ca7c974fb061fbeed5e2 Mon Sep 17 00:00:00 2001 From: Ilya Klyuchnikov Date: Sat, 12 Feb 2022 22:43:45 +0000 Subject: [PATCH] allow custom attributes everywhere 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 #5689. --- lib/stdlib/src/erl_lint.erl | 14 +++++++++++--- lib/stdlib/test/erl_lint_SUITE.erl | 9 ++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 95e2ed884751..287d7eb76a4e 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -900,10 +900,18 @@ function_state({attribute,A,opaque,{TypeName,TypeDef,Args}}, St) -> type_def(opaque, A, TypeName, TypeDef, Args, St); function_state({attribute,A,spec,{Fun,Types}}, St) -> spec_decl(A, Fun, Types, St); -function_state({attribute,_A,dialyzer,_Val}, St) -> - St; -function_state({attribute,Aa,Attr,_Val}, St) -> +function_state({attribute,Aa,Attr,_Val}, St) when Attr =:= module; + Attr =:= export; + Attr =:= export_type; + Attr =:= import; + Attr =:= behaviour; + Attr =:= behavior; + Attr =:= callback; + Attr =:= optional_callbacks; + Attr =:= on_load -> add_error(Aa, {attribute,Attr}, St); +function_state({attribute,_A,_Key,_Val}, St) -> + St; function_state({function,Anno,N,A,Cs}, St) -> function(Anno, N, A, Cs, St); function_state({eof,Location}, St) -> eof(Location, St). diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 7e89b5f8912b..3f7e67760fd8 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -3643,7 +3643,7 @@ basic_errors(Config) -> <<"f() -> ok. -attr(x).">>, [], - {errors,[{{2,17},erl_lint,{attribute,attr}}],[]}}, + []}, {redefine_function, <<"f() -> ok. @@ -4280,12 +4280,9 @@ stacktrace_syntax(Config) -> otp_14285(Config) -> %% A small sample of all the errors and warnings in module erl_lint. E1 = {redefine_function,{'кирилли́ческий атом',0}}, - E2 = {attribute,'кирилли́ческий атом'}, E3 = {undefined_record,'кирилли́ческий атом'}, E4 = {undefined_bittype,'кирилли́ческий атом'}, "function 'кирилли́ческий атом'/0 already defined" = format_error(E1), - "attribute 'кирилли́ческий атом' after function definitions" = - format_error(E2), "record 'кирилли́ческий атом' undefined" = format_error(E3), "bit type 'кирилли́ческий атом' undefined" = format_error(E4), Ts = [{otp_14285_1, @@ -4301,9 +4298,7 @@ otp_14285(Config) -> -'кирилли́ческий атом'(a). "/utf8>>, [], - {errors, - [{{2,16},erl_lint,E2}], - []}}, + []}, {otp_14285_3, <<"'кирилли́ческий атом'() -> #'кирилли́ческий атом'{}. "/utf8>>,