From 8bba6d2c84e75a9215db041623036bc7fbee577a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mil=C3=A1n=20B=C3=B3r?= Date: Sun, 1 Dec 2024 15:47:58 +0100 Subject: [PATCH 01/18] add forbidden regex --- .../elvis_style/atom_naming_convention.md | 7 +- .../elvis_style/function_naming_convention.md | 3 + .../elvis_style/module_naming_convention.md | 3 + .../elvis_style/variable_naming_convention.md | 3 + src/elvis_style.erl | 113 ++++++++++++++---- .../forbidden_atom_naming_convention.erl | 14 +++ .../forbidden_function_naming_convention.erl | 31 +++++ .../forbidden_module_naming_convention_12.erl | 1 + .../forbidden_variable_naming_convention.erl | 22 ++++ test/style_SUITE.erl | 46 ++++++- 10 files changed, 216 insertions(+), 27 deletions(-) create mode 100644 test/examples/forbidden_atom_naming_convention.erl create mode 100644 test/examples/forbidden_function_naming_convention.erl create mode 100644 test/examples/forbidden_module_naming_convention_12.erl create mode 100644 test/examples/forbidden_variable_naming_convention.erl diff --git a/doc_rules/elvis_style/atom_naming_convention.md b/doc_rules/elvis_style/atom_naming_convention.md index 2e494e28..923f92c5 100644 --- a/doc_rules/elvis_style/atom_naming_convention.md +++ b/doc_rules/elvis_style/atom_naming_convention.md @@ -2,8 +2,9 @@ (since [1.0.0](https://github.com/inaka/elvis_core/releases/tag/1.0.0)) -All atoms should be named according to the regular expression provided. Atoms enclosed in -apostrophes have special meaning and are thus handled by a different configuration option (use +All atoms should be named according to the regular expression provided. +Except if it matches with a defined `forbidden_regex`. +Atoms enclosed in apostrophes have special meaning and are thus handled by a different configuration option (use `same` if you want the same value as `regex`). > Works on `.beam` file? Yes! @@ -14,6 +15,8 @@ apostrophes have special meaning and are thus handled by a different configurati - default: `"^([a-z][a-z0-9]*_?)*(_SUITE)?$"`. - `enclosed_atoms :: string()`. - default: `".*"`. +- `forbidden_regex :: string() | undefined`. + - default: `undefined`. ## Example diff --git a/doc_rules/elvis_style/function_naming_convention.md b/doc_rules/elvis_style/function_naming_convention.md index af91372a..7cf3e989 100644 --- a/doc_rules/elvis_style/function_naming_convention.md +++ b/doc_rules/elvis_style/function_naming_convention.md @@ -1,6 +1,7 @@ # Function Naming Convention All functions should be named according to the regular expression provided. +Except if it matches with a defined `forbidden_regex`. > Works on `.beam` file? Yes! @@ -8,6 +9,8 @@ All functions should be named according to the regular expression provided. - `regex :: string()`. - default: `"^[a-z](_?[a-z0-9]+)*$"`. +- `forbidden_regex :: string() | undefined`. + - default: `undefined`. ## Example diff --git a/doc_rules/elvis_style/module_naming_convention.md b/doc_rules/elvis_style/module_naming_convention.md index 3949ed8f..72550c1e 100644 --- a/doc_rules/elvis_style/module_naming_convention.md +++ b/doc_rules/elvis_style/module_naming_convention.md @@ -1,6 +1,7 @@ # Module Naming Convention All modules should be named according to the regular expression provided. +Except if it matches with a defined `forbidden_regex`. > Works on `.beam` file? Yes! @@ -8,6 +9,8 @@ All modules should be named according to the regular expression provided. - `regex :: string()`. - default: `"^[a-z](_?[a-z0-9]+)*(_SUITE)?$"`. +- `forbidden_regex :: string() | undefined`. + - default: `undefined`. ## Example diff --git a/doc_rules/elvis_style/variable_naming_convention.md b/doc_rules/elvis_style/variable_naming_convention.md index 40c9f2f7..7053375f 100644 --- a/doc_rules/elvis_style/variable_naming_convention.md +++ b/doc_rules/elvis_style/variable_naming_convention.md @@ -1,6 +1,7 @@ # Variable Naming Convention All variables should be named according to the regular expression provided. +Except if it matches with a defined `forbidden_regex`. > Works on `.beam` file? Yes! @@ -8,6 +9,8 @@ All variables should be named according to the regular expression provided. - `regex :: string()`. - default: `"^_?([A-Z][0-9a-zA-Z]*)$"`. +- `forbidden_regex :: string() | undefined`. + - default: `undefined`. ## Example diff --git a/src/elvis_style.erl b/src/elvis_style.erl index 36f274ed..3ee8adb9 100644 --- a/src/elvis_style.erl +++ b/src/elvis_style.erl @@ -72,14 +72,23 @@ -define(FUNCTION_NAMING_CONVENTION_MSG, "The function ~p does not respect the format defined by the " "regular expression '~p'."). +-define(FORBIDDEN_FUNCTION_NAMING_CONVENTION_MSG, + "The function ~p does written in a forbidden format" + "defined by the regular expression '~p'."). -define(VARIABLE_NAMING_CONVENTION_MSG, "The variable ~p on line ~p does not respect the format " "defined by the regular expression '~p'."). +-define(FORBIDDEN_VARIABLE_NAMING_CONVENTION_MSG, + "The variable ~p on line ~p does written in a forbidden the format " + "defined by the regular expression '~p'."). -define(CONSISTENT_VARIABLE_CASING_MSG, "Variable ~ts (first used in line ~p) is written in different ways within the module: ~p."). -define(MODULE_NAMING_CONVENTION_MSG, "The module ~p does not respect the format defined by the " "regular expression '~p'."). +-define(FORBIDDEN_MODULE_NAMING_CONVENTION_MSG, + "The module ~p does written in a forbidden format defined by the " + "regular expression '~p'."). -define(STATE_RECORD_MISSING_MSG, "This module implements an OTP behavior but is missing " "a 'state' record."). @@ -116,6 +125,9 @@ -define(ATOM_NAMING_CONVENTION_MSG, "Atom ~p on line ~p does not respect the format " "defined by the regular expression '~p'."). +-define(FORBIDDEN_ATOM_NAMING_CONVENTION_MSG, + "Atom ~p on line ~p does does written in a forbidden format " + "defined by the regular expression '~p'."). -define(NO_THROW_MSG, "Usage of throw/1 on line ~p is not recommended"). -define(NO_DOLLAR_SPACE_MSG, "'$ ' was found on line ~p. It's use is discouraged. " @@ -183,11 +195,11 @@ default(nesting_level) -> default(god_modules) -> #{limit => 25}; default(function_naming_convention) -> - #{regex => "^[a-z](_?[a-z0-9]+)*$"}; + #{regex => "^[a-z](_?[a-z0-9]+)*$", forbidden_regex => undefined}; default(variable_naming_convention) -> - #{regex => "^_?([A-Z][0-9a-zA-Z]*)$"}; + #{regex => "^_?([A-Z][0-9a-zA-Z]*)$", forbidden_regex => undefined}; default(module_naming_convention) -> - #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$"}; + #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", forbidden_regex => undefined}; default(dont_repeat_yourself) -> #{min_complexity => 10}; default(max_module_length) -> @@ -225,7 +237,9 @@ default(no_common_caveats_call) -> {timer, send_interval, 3}, {erlang, size, 1}]}; default(atom_naming_convention) -> - #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", enclosed_atoms => ".*"}; + #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", + enclosed_atoms => ".*", + forbidden_regex => undefined}; %% Not restrictive. Those who want more restrictions can set it like "^[^_]*$" default(numeric_format) -> #{regex => ".*", @@ -292,22 +306,35 @@ default(RuleWithEmptyDefault) [elvis_result:item()]. function_naming_convention(Config, Target, RuleConfig) -> Regex = option(regex, RuleConfig, function_naming_convention), + ForbiddenRegex = option(forbidden_regex, RuleConfig, function_naming_convention), Root = get_root(Config, Target, RuleConfig), FunctionNames0 = elvis_code:function_names(Root), - errors_for_function_names(Regex, FunctionNames0). + errors_for_function_names(Regex, ForbiddenRegex, FunctionNames0). -errors_for_function_names(_Regex, []) -> +errors_for_function_names(_Regex, _ForbiddenRegex, []) -> []; -errors_for_function_names(Regex, [FunctionName | RemainingFuncNames]) -> +errors_for_function_names(Regex, ForbiddenRegex, [FunctionName | RemainingFuncNames]) -> FunctionNameStr = unicode:characters_to_list(atom_to_list(FunctionName), unicode), case re:run(FunctionNameStr, Regex, [unicode]) of nomatch -> Msg = ?FUNCTION_NAMING_CONVENTION_MSG, Info = [FunctionNameStr, Regex], Result = elvis_result:new(item, Msg, Info, 1), - [Result | errors_for_function_names(Regex, RemainingFuncNames)]; + [Result | errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames)]; {match, _} -> - errors_for_function_names(Regex, RemainingFuncNames) + case ForbiddenRegex =/= undefined + andalso re:run(FunctionNameStr, ForbiddenRegex, [unicode]) + of + {match, _} -> + Msg = ?FORBIDDEN_FUNCTION_NAMING_CONVENTION_MSG, + Info = [FunctionNameStr, Regex], + Result = elvis_result:new(item, Msg, Info, 1), + [Result | errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames)]; + nomatch -> + errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames); + false -> + errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames) + end end. -type consistent_variable_casing_config() :: #{ignore => [ignorable()]}. @@ -362,9 +389,10 @@ check_variable_casing_consistency({_, [elvis_result:item()]. variable_naming_convention(Config, Target, RuleConfig) -> Regex = option(regex, RuleConfig, variable_naming_convention), + ForbiddenRegex = option(forbidden_regex, RuleConfig, variable_naming_convention), Root = get_root(Config, Target, RuleConfig), Vars = elvis_code:find(fun is_var/1, Root, #{traverse => all, mode => zipper}), - check_variables_name(Regex, Vars). + check_variables_name(Regex, ForbiddenRegex, Vars). -type macro_names_config() :: #{ignore => [ignorable()], regex => string()}. @@ -724,6 +752,7 @@ no_behavior_info(Config, Target, RuleConfig) -> [elvis_result:item()]. module_naming_convention(Config, Target, RuleConfig) -> Regex = option(regex, RuleConfig, module_naming_convention), + ForbiddenRegex = option(forbidden_regex, RuleConfig, module_naming_convention), IgnoreModules = option(ignore, RuleConfig, module_naming_convention), Root = get_root(Config, Target, RuleConfig), @@ -739,7 +768,19 @@ module_naming_convention(Config, Target, RuleConfig) -> Result = elvis_result:new(item, Msg, Info, 1), [Result]; {match, _} -> - [] + case ForbiddenRegex =/= undefined + andalso re:run(ModuleNameStr, ForbiddenRegex, [unicode]) + of + {match, _} -> + Msg = ?FORBIDDEN_MODULE_NAMING_CONVENTION_MSG, + Info = [ModuleNameStr, Regex], + Result = elvis_result:new(item, Msg, Info, 1), + [Result]; + nomatch -> + []; + false -> + [] + end end; true -> [] @@ -1118,10 +1159,11 @@ no_successive_maps(Config, Target, RuleConfig) -> atom_naming_convention(Config, Target, RuleConfig) -> Root = get_root(Config, Target, RuleConfig), Regex = option(regex, RuleConfig, atom_naming_convention), + ForbiddenRegex = option(forbidden_regex, RuleConfig, atom_naming_convention), RegexEnclosed = specific_or_default(option(enclosed_atoms, RuleConfig, atom_naming_convention), Regex), AtomNodes = elvis_code:find(fun is_atom_node/1, Root, #{traverse => all, mode => node}), - check_atom_names(Regex, RegexEnclosed, AtomNodes, []). + check_atom_names(Regex, ForbiddenRegex, RegexEnclosed, AtomNodes, []). -type no_init_lists_config() :: #{behaviours => [atom()]}. @@ -1659,9 +1701,13 @@ is_exception_or_non_reversible(_) -> false. %% @private -check_atom_names(_Regex, _RegexEnclosed, [] = _AtomNodes, Acc) -> +check_atom_names(_Regex, _, _RegexEnclosed, [] = _AtomNodes, Acc) -> Acc; -check_atom_names(Regex, RegexEnclosed, [AtomNode | RemainingAtomNodes], AccIn) -> +check_atom_names(Regex, + ForbiddenRegex, + RegexEnclosed, + [AtomNode | RemainingAtomNodes], + AccIn) -> AtomName0 = ktn_code:attr(text, AtomNode), ValueAtomName = ktn_code:attr(value, AtomNode), {IsEnclosed, AtomName} = string_strip_enclosed(AtomName0), @@ -1686,9 +1732,22 @@ check_atom_names(Regex, RegexEnclosed, [AtomNode | RemainingAtomNodes], AccIn) - Result = elvis_result:new(item, Msg, Info, Line), AccIn ++ [Result]; {match, _Captured} -> - AccIn + case ForbiddenRegex =/= undefined + andalso re:run( + unicode:characters_to_list(AtomName, unicode), ForbiddenRegex) + of + {match, _} -> + Msg = ?FORBIDDEN_ATOM_NAMING_CONVENTION_MSG, + Info = [AtomNode, Regex], + Result = elvis_result:new(item, Msg, Info, 1), + AccIn ++ [Result]; + nomatch -> + AccIn; + false -> + AccIn + end end, - check_atom_names(Regex, RegexEnclosed, RemainingAtomNodes, AccOut). + check_atom_names(Regex, ForbiddenRegex, RegexEnclosed, RemainingAtomNodes, AccOut). %% @private string_strip_enclosed([$' | Rest]) -> @@ -1714,21 +1773,33 @@ is_atom_node(MaybeAtom) -> %% Variables name %% @private -check_variables_name(_Regex, []) -> +check_variables_name(_Regex, _, []) -> []; -check_variables_name(Regex, [Variable | RemainingVars]) -> +check_variables_name(Regex, ForbiddenRegex, [Variable | RemainingVars]) -> VariableNameStr = atom_to_list(ktn_code:attr(name, Variable)), case re:run(VariableNameStr, Regex) of nomatch when VariableNameStr == "_" -> - check_variables_name(Regex, RemainingVars); + check_variables_name(Regex, ForbiddenRegex, RemainingVars); nomatch -> Msg = ?VARIABLE_NAMING_CONVENTION_MSG, {Line, _} = ktn_code:attr(location, Variable), Info = [VariableNameStr, Line, Regex], Result = elvis_result:new(item, Msg, Info, Line), - [Result | check_variables_name(Regex, RemainingVars)]; + [Result | check_variables_name(Regex, ForbiddenRegex, RemainingVars)]; {match, _} -> - check_variables_name(Regex, RemainingVars) + case ForbiddenRegex =/= undefined + andalso re:run(VariableNameStr, ForbiddenRegex, [unicode]) + of + {match, _} -> + Msg = ?FORBIDDEN_VARIABLE_NAMING_CONVENTION_MSG, + Info = [VariableNameStr, Regex], + Result = elvis_result:new(item, Msg, Info, 1), + [Result | check_variables_name(Regex, ForbiddenRegex, RemainingVars)]; + nomatch -> + check_variables_name(Regex, ForbiddenRegex, RemainingVars); + false -> + check_variables_name(Regex, ForbiddenRegex, RemainingVars) + end end. %% Result building diff --git a/test/examples/forbidden_atom_naming_convention.erl b/test/examples/forbidden_atom_naming_convention.erl new file mode 100644 index 00000000..c02341e4 --- /dev/null +++ b/test/examples/forbidden_atom_naming_convention.erl @@ -0,0 +1,14 @@ +-module(forbidden_atom_naming_convention). + +-export([for_test/0]). + +for_test() -> + this_is_an_ok_atom, + 'and_so_is_this', + 'and_this_1_too', + non_200, + '_', % used by ets/mnesia/etc. + non200, % valid, even without underscores + valid_200even_if_numb3rs_appear_between_letters, + blahblah_SUITE, + x. diff --git a/test/examples/forbidden_function_naming_convention.erl b/test/examples/forbidden_function_naming_convention.erl new file mode 100644 index 00000000..337ec594 --- /dev/null +++ b/test/examples/forbidden_function_naming_convention.erl @@ -0,0 +1,31 @@ +-module(forbidden_function_naming_convention). + +-dialyzer({nowarn_function, bad_names_inside/0}). + +-export([bad_names_inside/0]). + +%% Function names must use only lowercase characters. +%% Words in function names must be separated with _. + +%% Cf. https://github.com/inaka/erlang_guidelines#function-names + +bad_names_inside() -> + good_name(should, fail), + not_forbidden_but_still_bad____(should, fail), + no_numbers_1(should, fail), + fun2ms(should, fail). + +%% Private / hidden functions still checked + +good_name(Should, Fail) -> + [Should, Fail]. + +not_forbidden_but_still_bad____(Should, Fail) -> + [Should, Fail]. + +no_numbers_1(Should, Fail) -> + [Should, Fail]. + +fun2ms(Should, Fail) -> + [Should, Fail]. + diff --git a/test/examples/forbidden_module_naming_convention_12.erl b/test/examples/forbidden_module_naming_convention_12.erl new file mode 100644 index 00000000..36da17a2 --- /dev/null +++ b/test/examples/forbidden_module_naming_convention_12.erl @@ -0,0 +1 @@ +-module(forbidden_module_naming_convention_12). diff --git a/test/examples/forbidden_variable_naming_convention.erl b/test/examples/forbidden_variable_naming_convention.erl new file mode 100644 index 00000000..5f8f7460 --- /dev/null +++ b/test/examples/forbidden_variable_naming_convention.erl @@ -0,0 +1,22 @@ +-module(forbidden_variable_naming_convention). + +-export([should_pass/5]). +-export([should_pass/0, should_pass/1]). + +%% CamelCase must be used for variables. Don’t +%% separate words in variables with _. + +%% Cf. https://github.com/inaka/erlang_guidelines#variable-names + +should_pass(Should, Pass, Way2Home, Fun1, Fun2) -> + [_IgnoredVariable, _] = ["Ignored but valid", "also valid"], + Should = "Should", + Pass = "Pass", + Way2Home = "Way to home", + Fun1 = Should ++ Pass, + Fun2 = Fun1 ++ Way2Home. + +should_pass() -> + ?MODULE_STRING. + +should_pass(_) -> ?MODULE_STRING. diff --git a/test/style_SUITE.erl b/test/style_SUITE.erl index 6a9c3e41..9e1d04ff 100644 --- a/test/style_SUITE.erl +++ b/test/style_SUITE.erl @@ -184,7 +184,16 @@ verify_function_naming_convention(Config) -> elvis_style, function_naming_convention, RuleConfig4, - PathIgnored). + PathIgnored), + + % forbidden + PathForbidden = "forbidden_function_naming_convention." ++ Ext, + [_, _, _] = + elvis_core_apply_rule(Config, + elvis_style, + function_naming_convention, + #{regex => "^[a-z](_?[a-z0-9]+)*$", forbidden_regex => "[0-9]"}, + PathForbidden). -spec verify_variable_naming_convention(config()) -> any(). verify_variable_naming_convention(Config) -> @@ -210,7 +219,16 @@ verify_variable_naming_convention(Config) -> elvis_style, variable_naming_convention, RuleConfig, - PathFail). + PathFail), + + % forbidden + PathForbidden = "forbidden_variable_naming_convention." ++ Ext, + [_, _, _, _, _, _, _, _] = + elvis_core_apply_rule(Config, + elvis_style, + variable_naming_convention, + #{regex => "^_?([A-Z][0-9a-zA-Z]*)$", forbidden_regex => "[0-9]"}, + PathForbidden). -spec verify_consistent_variable_casing(config()) -> any(). verify_consistent_variable_casing(Config) -> @@ -694,7 +712,17 @@ verify_module_naming_convention(Config) -> elvis_style, module_naming_convention, RuleConfigIgnore, - PathFail). + PathFail), + + % forbidden + PathForbidden = "forbidden_module_naming_convention_12." ++ Ext, + [_] = + elvis_core_apply_rule(Config, + elvis_style, + module_naming_convention, + #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", + forbidden_regex => "[0-9]"}, + PathForbidden). -spec verify_state_record_and_type(config()) -> any(). verify_state_record_and_type(Config) -> @@ -1564,7 +1592,17 @@ verify_atom_naming_convention(Config) -> #{regex => KeepRegex, enclosed_atoms => "^([\\\\][\-a-z0-9A-Z_' \\\\]*)$"}, FailPath) - end. + end, + + % forbidden + PathForbidden = "forbidden_atom_naming_convention." ++ Ext, + [_, _, _, _] = + elvis_core_apply_rule(Config, + elvis_style, + atom_naming_convention, + #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", + forbidden_regex => "[0-9]"}, + PathForbidden). -spec verify_no_init_lists(config()) -> any(). verify_no_init_lists(Config) -> From 1171912dca1e97a14810284930f99da915fb94b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mil=C3=A1n=20B=C3=B3r?= Date: Sun, 1 Dec 2024 16:07:42 +0100 Subject: [PATCH 02/18] fix line length in md --- doc_rules/elvis_style/atom_naming_convention.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc_rules/elvis_style/atom_naming_convention.md b/doc_rules/elvis_style/atom_naming_convention.md index 923f92c5..8bc4055e 100644 --- a/doc_rules/elvis_style/atom_naming_convention.md +++ b/doc_rules/elvis_style/atom_naming_convention.md @@ -4,8 +4,8 @@ All atoms should be named according to the regular expression provided. Except if it matches with a defined `forbidden_regex`. -Atoms enclosed in apostrophes have special meaning and are thus handled by a different configuration option (use -`same` if you want the same value as `regex`). +Atoms enclosed in apostrophes have special meaning and are thus handled +by a different configuration option (use `same` if you want the same value as `regex`). > Works on `.beam` file? Yes! From 956491b5ca23860660c910ea18caad58c1977fff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mil=C3=A1n=20B=C3=B3r?= Date: Sun, 1 Dec 2024 22:24:00 +0100 Subject: [PATCH 03/18] fix error message --- src/elvis_style.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/elvis_style.erl b/src/elvis_style.erl index 3ee8adb9..f3ba2c8d 100644 --- a/src/elvis_style.erl +++ b/src/elvis_style.erl @@ -73,13 +73,13 @@ "The function ~p does not respect the format defined by the " "regular expression '~p'."). -define(FORBIDDEN_FUNCTION_NAMING_CONVENTION_MSG, - "The function ~p does written in a forbidden format" + "The function ~p is written in a forbidden format" "defined by the regular expression '~p'."). -define(VARIABLE_NAMING_CONVENTION_MSG, "The variable ~p on line ~p does not respect the format " "defined by the regular expression '~p'."). -define(FORBIDDEN_VARIABLE_NAMING_CONVENTION_MSG, - "The variable ~p on line ~p does written in a forbidden the format " + "The variable ~p on line ~p is written in a forbidden the format " "defined by the regular expression '~p'."). -define(CONSISTENT_VARIABLE_CASING_MSG, "Variable ~ts (first used in line ~p) is written in different ways within the module: ~p."). @@ -87,7 +87,7 @@ "The module ~p does not respect the format defined by the " "regular expression '~p'."). -define(FORBIDDEN_MODULE_NAMING_CONVENTION_MSG, - "The module ~p does written in a forbidden format defined by the " + "The module ~p is written in a forbidden format defined by the " "regular expression '~p'."). -define(STATE_RECORD_MISSING_MSG, "This module implements an OTP behavior but is missing " @@ -126,7 +126,7 @@ "Atom ~p on line ~p does not respect the format " "defined by the regular expression '~p'."). -define(FORBIDDEN_ATOM_NAMING_CONVENTION_MSG, - "Atom ~p on line ~p does does written in a forbidden format " + "Atom ~p on line ~p is written in a forbidden format " "defined by the regular expression '~p'."). -define(NO_THROW_MSG, "Usage of throw/1 on line ~p is not recommended"). -define(NO_DOLLAR_SPACE_MSG, From 5b31a55578b1b3f72fc57828dfa7129b04e1a5a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mil=C3=A1n=20B=C3=B3r?= Date: Thu, 5 Dec 2024 14:07:12 +0100 Subject: [PATCH 04/18] add forbidden for enclosed ones too --- .../elvis_style/atom_naming_convention.md | 3 ++ src/elvis_style.erl | 32 ++++++++++++++++--- test/style_SUITE.erl | 22 ++++++++++++- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/doc_rules/elvis_style/atom_naming_convention.md b/doc_rules/elvis_style/atom_naming_convention.md index 8bc4055e..72e2ade7 100644 --- a/doc_rules/elvis_style/atom_naming_convention.md +++ b/doc_rules/elvis_style/atom_naming_convention.md @@ -6,6 +6,7 @@ All atoms should be named according to the regular expression provided. Except if it matches with a defined `forbidden_regex`. Atoms enclosed in apostrophes have special meaning and are thus handled by a different configuration option (use `same` if you want the same value as `regex`). +For enclosed atoms we defined a different forbidden regex, called `forbidden_enclosed_regex`. > Works on `.beam` file? Yes! @@ -17,6 +18,8 @@ by a different configuration option (use `same` if you want the same value as `r - default: `".*"`. - `forbidden_regex :: string() | undefined`. - default: `undefined`. +- `forbidden_enclosed_regex :: string() | undefined`. + - default: `undefined`. ## Example diff --git a/src/elvis_style.erl b/src/elvis_style.erl index f3ba2c8d..e44b03ad 100644 --- a/src/elvis_style.erl +++ b/src/elvis_style.erl @@ -239,7 +239,8 @@ default(no_common_caveats_call) -> default(atom_naming_convention) -> #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", enclosed_atoms => ".*", - forbidden_regex => undefined}; + forbidden_regex => undefined, + forbidden_enclosed_regex => undefined}; %% Not restrictive. Those who want more restrictions can set it like "^[^_]*$" default(numeric_format) -> #{regex => ".*", @@ -1162,8 +1163,16 @@ atom_naming_convention(Config, Target, RuleConfig) -> ForbiddenRegex = option(forbidden_regex, RuleConfig, atom_naming_convention), RegexEnclosed = specific_or_default(option(enclosed_atoms, RuleConfig, atom_naming_convention), Regex), + ForbiddenEnclosedRegex = + specific_or_default(option(forbidden_enclosed_regex, RuleConfig, atom_naming_convention), + Regex), AtomNodes = elvis_code:find(fun is_atom_node/1, Root, #{traverse => all, mode => node}), - check_atom_names(Regex, ForbiddenRegex, RegexEnclosed, AtomNodes, []). + check_atom_names(Regex, + ForbiddenRegex, + RegexEnclosed, + ForbiddenEnclosedRegex, + AtomNodes, + []). -type no_init_lists_config() :: #{behaviours => [atom()]}. @@ -1701,11 +1710,12 @@ is_exception_or_non_reversible(_) -> false. %% @private -check_atom_names(_Regex, _, _RegexEnclosed, [] = _AtomNodes, Acc) -> +check_atom_names(_Regex, _, _RegexEnclosed, _, [] = _AtomNodes, Acc) -> Acc; check_atom_names(Regex, - ForbiddenRegex, + ForbiddenRegexNormal, RegexEnclosed, + ForbiddenRegexEnclosed, [AtomNode | RemainingAtomNodes], AccIn) -> AtomName0 = ktn_code:attr(text, AtomNode), @@ -1713,6 +1723,13 @@ check_atom_names(Regex, {IsEnclosed, AtomName} = string_strip_enclosed(AtomName0), IsExceptionClass = is_exception_or_non_reversible(ValueAtomName), RE = re_compile_for_atom_type(IsEnclosed, Regex, RegexEnclosed), + ForbiddenRegex = + case IsEnclosed of + true -> + ForbiddenRegexEnclosed; + false -> + ForbiddenRegexNormal + end, AccOut = case re:run( unicode:characters_to_list(AtomName, unicode), RE) @@ -1747,7 +1764,12 @@ check_atom_names(Regex, AccIn end end, - check_atom_names(Regex, ForbiddenRegex, RegexEnclosed, RemainingAtomNodes, AccOut). + check_atom_names(Regex, + ForbiddenRegexNormal, + RegexEnclosed, + ForbiddenRegexEnclosed, + RemainingAtomNodes, + AccOut). %% @private string_strip_enclosed([$' | Rest]) -> diff --git a/test/style_SUITE.erl b/test/style_SUITE.erl index 9e1d04ff..4d3dadb8 100644 --- a/test/style_SUITE.erl +++ b/test/style_SUITE.erl @@ -1596,12 +1596,32 @@ verify_atom_naming_convention(Config) -> % forbidden PathForbidden = "forbidden_atom_naming_convention." ++ Ext, + _ = case Group of + beam_files -> % 'or_THIS' getting stripped of enclosing ' + [_, _, _, _] = + elvis_core_apply_rule(Config, + elvis_style, + atom_naming_convention, + #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", + forbidden_regex => "[0-9]"}, + PathForbidden); + erl_files -> + [_, _, _] = + elvis_core_apply_rule(Config, + elvis_style, + atom_naming_convention, + #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", + forbidden_regex => "[0-9]"}, + PathForbidden) + end, + [_, _, _, _] = elvis_core_apply_rule(Config, elvis_style, atom_naming_convention, #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", - forbidden_regex => "[0-9]"}, + forbidden_regex => "[0-9]", + forbidden_enclosed_regex => "[0-9]"}, PathForbidden). -spec verify_no_init_lists(config()) -> any(). From a280eb113cc4d6e2dd0211f5117d9d10b788a1ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=B3r=20Mil=C3=A1n?= <71042542+bormilan@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:49:53 +0100 Subject: [PATCH 05/18] Update doc_rules/elvis_style/atom_naming_convention.md Co-authored-by: Brujo Benavides --- doc_rules/elvis_style/atom_naming_convention.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc_rules/elvis_style/atom_naming_convention.md b/doc_rules/elvis_style/atom_naming_convention.md index 72e2ade7..0268e154 100644 --- a/doc_rules/elvis_style/atom_naming_convention.md +++ b/doc_rules/elvis_style/atom_naming_convention.md @@ -6,7 +6,7 @@ All atoms should be named according to the regular expression provided. Except if it matches with a defined `forbidden_regex`. Atoms enclosed in apostrophes have special meaning and are thus handled by a different configuration option (use `same` if you want the same value as `regex`). -For enclosed atoms we defined a different forbidden regex, called `forbidden_enclosed_regex`. +To define forbidden enclosed atoms (like the ones in `forbidden_regex` apply for `regex`), use `forbidden_enclosed_regex`. > Works on `.beam` file? Yes! From 93dd0c70f0527dbb71f757c4cde9561474d5af3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=B3r=20Mil=C3=A1n?= <71042542+bormilan@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:15:59 +0100 Subject: [PATCH 06/18] Update src/elvis_style.erl Co-authored-by: Brujo Benavides --- src/elvis_style.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/elvis_style.erl b/src/elvis_style.erl index e44b03ad..553eca37 100644 --- a/src/elvis_style.erl +++ b/src/elvis_style.erl @@ -1165,7 +1165,7 @@ atom_naming_convention(Config, Target, RuleConfig) -> specific_or_default(option(enclosed_atoms, RuleConfig, atom_naming_convention), Regex), ForbiddenEnclosedRegex = specific_or_default(option(forbidden_enclosed_regex, RuleConfig, atom_naming_convention), - Regex), + ForbiddenRegex), AtomNodes = elvis_code:find(fun is_atom_node/1, Root, #{traverse => all, mode => node}), check_atom_names(Regex, ForbiddenRegex, From 9b5d2e232e6a4e4bfe11335baabb77d1e444fa49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mil=C3=A1n=20B=C3=B3r?= Date: Thu, 5 Dec 2024 16:27:23 +0100 Subject: [PATCH 07/18] test for same --- doc_rules/elvis_style/atom_naming_convention.md | 4 ++-- test/style_SUITE.erl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc_rules/elvis_style/atom_naming_convention.md b/doc_rules/elvis_style/atom_naming_convention.md index 0268e154..ef9f7249 100644 --- a/doc_rules/elvis_style/atom_naming_convention.md +++ b/doc_rules/elvis_style/atom_naming_convention.md @@ -6,7 +6,7 @@ All atoms should be named according to the regular expression provided. Except if it matches with a defined `forbidden_regex`. Atoms enclosed in apostrophes have special meaning and are thus handled by a different configuration option (use `same` if you want the same value as `regex`). -To define forbidden enclosed atoms (like the ones in `forbidden_regex` apply for `regex`), use `forbidden_enclosed_regex`. +To define forbidden enclosed atoms (like the ones in `forbidden_regex` apply for `regex`), use `forbidden_enclosed_regex`(use `same` if you want the same value as `forbidden_regex`). > Works on `.beam` file? Yes! @@ -18,7 +18,7 @@ To define forbidden enclosed atoms (like the ones in `forbidden_regex` apply for - default: `".*"`. - `forbidden_regex :: string() | undefined`. - default: `undefined`. -- `forbidden_enclosed_regex :: string() | undefined`. +- `forbidden_enclosed_regex :: string() | undefined | same`. - default: `undefined`. ## Example diff --git a/test/style_SUITE.erl b/test/style_SUITE.erl index 4d3dadb8..177902d6 100644 --- a/test/style_SUITE.erl +++ b/test/style_SUITE.erl @@ -1621,7 +1621,7 @@ verify_atom_naming_convention(Config) -> atom_naming_convention, #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", forbidden_regex => "[0-9]", - forbidden_enclosed_regex => "[0-9]"}, + forbidden_enclosed_regex => same}, PathForbidden). -spec verify_no_init_lists(config()) -> any(). From 6c95e0fb178064f2af75d5e7ad79ceac3c48b07e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mil=C3=A1n=20B=C3=B3r?= Date: Thu, 5 Dec 2024 16:28:49 +0100 Subject: [PATCH 08/18] fix markdown --- doc_rules/elvis_style/atom_naming_convention.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc_rules/elvis_style/atom_naming_convention.md b/doc_rules/elvis_style/atom_naming_convention.md index ef9f7249..5c0f8b2e 100644 --- a/doc_rules/elvis_style/atom_naming_convention.md +++ b/doc_rules/elvis_style/atom_naming_convention.md @@ -18,7 +18,7 @@ To define forbidden enclosed atoms (like the ones in `forbidden_regex` apply for - default: `".*"`. - `forbidden_regex :: string() | undefined`. - default: `undefined`. -- `forbidden_enclosed_regex :: string() | undefined | same`. +- `forbidden_enclosed_regex :: string() | undefined`. - default: `undefined`. ## Example From 40edae8e1d198c0014d8310d5390ad1ea3946053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mil=C3=A1n=20B=C3=B3r?= Date: Thu, 5 Dec 2024 16:31:07 +0100 Subject: [PATCH 09/18] fix markdown --- doc_rules/elvis_style/atom_naming_convention.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc_rules/elvis_style/atom_naming_convention.md b/doc_rules/elvis_style/atom_naming_convention.md index 5c0f8b2e..daf03b1c 100644 --- a/doc_rules/elvis_style/atom_naming_convention.md +++ b/doc_rules/elvis_style/atom_naming_convention.md @@ -6,7 +6,8 @@ All atoms should be named according to the regular expression provided. Except if it matches with a defined `forbidden_regex`. Atoms enclosed in apostrophes have special meaning and are thus handled by a different configuration option (use `same` if you want the same value as `regex`). -To define forbidden enclosed atoms (like the ones in `forbidden_regex` apply for `regex`), use `forbidden_enclosed_regex`(use `same` if you want the same value as `forbidden_regex`). +To define forbidden enclosed atoms (like the ones in `forbidden_regex` apply for `regex`), +use `forbidden_enclosed_regex`(use `same` if you want the same value as `forbidden_regex`). > Works on `.beam` file? Yes! From db6aa53544745b7a67d6fedad660cc5da51c0c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=B3r=20Mil=C3=A1n?= <71042542+bormilan@users.noreply.github.com> Date: Thu, 5 Dec 2024 17:34:54 +0100 Subject: [PATCH 10/18] Update src/elvis_style.erl Co-authored-by: Brujo Benavides --- src/elvis_style.erl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/elvis_style.erl b/src/elvis_style.erl index 553eca37..3d915741 100644 --- a/src/elvis_style.erl +++ b/src/elvis_style.erl @@ -323,18 +323,18 @@ errors_for_function_names(Regex, ForbiddenRegex, [FunctionName | RemainingFuncNa Result = elvis_result:new(item, Msg, Info, 1), [Result | errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames)]; {match, _} -> - case ForbiddenRegex =/= undefined - andalso re:run(FunctionNameStr, ForbiddenRegex, [unicode]) - of + case ForbiddenRegex of + undefined -> errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames); + ForbiddenRegex -> + case re:run(FunctionNameStr, ForbiddenRegex, [unicode]) of {match, _} -> Msg = ?FORBIDDEN_FUNCTION_NAMING_CONVENTION_MSG, Info = [FunctionNameStr, Regex], Result = elvis_result:new(item, Msg, Info, 1), [Result | errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames)]; nomatch -> - errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames); - false -> errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames) + end end end. From 86794b2f81e6511fc929ac6ae47a9699fc3745ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mil=C3=A1n=20B=C3=B3r?= Date: Thu, 5 Dec 2024 18:16:39 +0100 Subject: [PATCH 11/18] refactor andalso --- src/elvis_style.erl | 96 +++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/src/elvis_style.erl b/src/elvis_style.erl index 3d915741..cdd786dc 100644 --- a/src/elvis_style.erl +++ b/src/elvis_style.erl @@ -324,17 +324,20 @@ errors_for_function_names(Regex, ForbiddenRegex, [FunctionName | RemainingFuncNa [Result | errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames)]; {match, _} -> case ForbiddenRegex of - undefined -> errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames); + undefined -> + errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames); ForbiddenRegex -> case re:run(FunctionNameStr, ForbiddenRegex, [unicode]) of - {match, _} -> - Msg = ?FORBIDDEN_FUNCTION_NAMING_CONVENTION_MSG, - Info = [FunctionNameStr, Regex], - Result = elvis_result:new(item, Msg, Info, 1), - [Result | errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames)]; - nomatch -> - errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames) - end + {match, _} -> + Msg = ?FORBIDDEN_FUNCTION_NAMING_CONVENTION_MSG, + Info = [FunctionNameStr, Regex], + Result = elvis_result:new(item, Msg, Info, 1), + [Result | errors_for_function_names(Regex, + ForbiddenRegex, + RemainingFuncNames)]; + nomatch -> + errors_for_function_names(Regex, ForbiddenRegex, RemainingFuncNames) + end end end. @@ -769,24 +772,30 @@ module_naming_convention(Config, Target, RuleConfig) -> Result = elvis_result:new(item, Msg, Info, 1), [Result]; {match, _} -> - case ForbiddenRegex =/= undefined - andalso re:run(ModuleNameStr, ForbiddenRegex, [unicode]) - of - {match, _} -> - Msg = ?FORBIDDEN_MODULE_NAMING_CONVENTION_MSG, - Info = [ModuleNameStr, Regex], - Result = elvis_result:new(item, Msg, Info, 1), - [Result]; - nomatch -> + case ForbiddenRegex of + undefined -> []; - false -> - [] + ForbiddenRegex -> + is_forbidden_module_name(ModuleNameStr, + ForbiddenRegex, + ?FORBIDDEN_MODULE_NAMING_CONVENTION_MSG) end end; true -> [] end. +is_forbidden_module_name(Target, Regex, Message) -> + case re:run(Target, Regex, [unicode]) of + {match, _} -> + Msg = Message, + Info = [Target, Regex], + Result = elvis_result:new(item, Msg, Info, 1), + [Result]; + nomatch -> + [] + end. + -spec state_record_and_type(elvis_config:config(), elvis_file:file(), empty_rule_config()) -> @@ -1749,19 +1758,19 @@ check_atom_names(Regex, Result = elvis_result:new(item, Msg, Info, Line), AccIn ++ [Result]; {match, _Captured} -> - case ForbiddenRegex =/= undefined - andalso re:run( - unicode:characters_to_list(AtomName, unicode), ForbiddenRegex) - of - {match, _} -> - Msg = ?FORBIDDEN_ATOM_NAMING_CONVENTION_MSG, - Info = [AtomNode, Regex], - Result = elvis_result:new(item, Msg, Info, 1), - AccIn ++ [Result]; - nomatch -> + case ForbiddenRegex of + undefined -> AccIn; - false -> - AccIn + ForbiddenRegex -> + case re:run(AtomName, ForbiddenRegex, [unicode]) of + {match, _} -> + Msg = ?FORBIDDEN_ATOM_NAMING_CONVENTION_MSG, + Info = [AtomName, Regex], + Result = elvis_result:new(item, Msg, Info, 1), + AccIn ++ [Result]; + nomatch -> + AccIn + end end end, check_atom_names(Regex, @@ -1809,18 +1818,19 @@ check_variables_name(Regex, ForbiddenRegex, [Variable | RemainingVars]) -> Result = elvis_result:new(item, Msg, Info, Line), [Result | check_variables_name(Regex, ForbiddenRegex, RemainingVars)]; {match, _} -> - case ForbiddenRegex =/= undefined - andalso re:run(VariableNameStr, ForbiddenRegex, [unicode]) - of - {match, _} -> - Msg = ?FORBIDDEN_VARIABLE_NAMING_CONVENTION_MSG, - Info = [VariableNameStr, Regex], - Result = elvis_result:new(item, Msg, Info, 1), - [Result | check_variables_name(Regex, ForbiddenRegex, RemainingVars)]; - nomatch -> + case ForbiddenRegex of + undefined -> check_variables_name(Regex, ForbiddenRegex, RemainingVars); - false -> - check_variables_name(Regex, ForbiddenRegex, RemainingVars) + ForbiddenRegex -> + case re:run(VariableNameStr, ForbiddenRegex, [unicode]) of + {match, _} -> + Msg = ?FORBIDDEN_VARIABLE_NAMING_CONVENTION_MSG, + Info = [VariableNameStr, Regex], + Result = elvis_result:new(item, Msg, Info, 1), + [Result | check_variables_name(Regex, ForbiddenRegex, RemainingVars)]; + nomatch -> + check_variables_name(Regex, ForbiddenRegex, RemainingVars) + end end end. From 1802540bd8fd24a89c87676e8ecaab3eacf8f141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mil=C3=A1n=20B=C3=B3r?= Date: Thu, 5 Dec 2024 18:22:28 +0100 Subject: [PATCH 12/18] add same to the doc --- doc_rules/elvis_style/atom_naming_convention.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc_rules/elvis_style/atom_naming_convention.md b/doc_rules/elvis_style/atom_naming_convention.md index daf03b1c..35b6ae49 100644 --- a/doc_rules/elvis_style/atom_naming_convention.md +++ b/doc_rules/elvis_style/atom_naming_convention.md @@ -15,11 +15,11 @@ use `forbidden_enclosed_regex`(use `same` if you want the same value as `forbidd - `regex :: string()`. - default: `"^([a-z][a-z0-9]*_?)*(_SUITE)?$"`. -- `enclosed_atoms :: string()`. +- `enclosed_atoms :: string() | same`. - default: `".*"`. - `forbidden_regex :: string() | undefined`. - default: `undefined`. -- `forbidden_enclosed_regex :: string() | undefined`. +- `forbidden_enclosed_regex :: string() | undefined | same`. - default: `undefined`. ## Example From d3d9c0b84ef0efdb7217c9473dd329d8bac35866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=B3r=20Mil=C3=A1n?= <71042542+bormilan@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:50:35 +0100 Subject: [PATCH 13/18] Update doc_rules/elvis_style/atom_naming_convention.md Co-authored-by: Paulo F. Oliveira --- doc_rules/elvis_style/atom_naming_convention.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc_rules/elvis_style/atom_naming_convention.md b/doc_rules/elvis_style/atom_naming_convention.md index 35b6ae49..e4bbee4b 100644 --- a/doc_rules/elvis_style/atom_naming_convention.md +++ b/doc_rules/elvis_style/atom_naming_convention.md @@ -2,8 +2,8 @@ (since [1.0.0](https://github.com/inaka/elvis_core/releases/tag/1.0.0)) -All atoms should be named according to the regular expression provided. -Except if it matches with a defined `forbidden_regex`. +All atoms should be named according to the provided regular expression, +except if they match with a defined `forbidden_regex`. Atoms enclosed in apostrophes have special meaning and are thus handled by a different configuration option (use `same` if you want the same value as `regex`). To define forbidden enclosed atoms (like the ones in `forbidden_regex` apply for `regex`), From d1c9ea0f40ba9a8ba9d31e9c16e139df58d9a8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=B3r=20Mil=C3=A1n?= <71042542+bormilan@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:50:43 +0100 Subject: [PATCH 14/18] Update doc_rules/elvis_style/function_naming_convention.md Co-authored-by: Paulo F. Oliveira --- doc_rules/elvis_style/function_naming_convention.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc_rules/elvis_style/function_naming_convention.md b/doc_rules/elvis_style/function_naming_convention.md index 7cf3e989..1f53e733 100644 --- a/doc_rules/elvis_style/function_naming_convention.md +++ b/doc_rules/elvis_style/function_naming_convention.md @@ -1,7 +1,7 @@ # Function Naming Convention -All functions should be named according to the regular expression provided. -Except if it matches with a defined `forbidden_regex`. +All functions should be named according to the provided regular expression, +except if they match with a defined `forbidden_regex`. > Works on `.beam` file? Yes! From 43bb5fe9c149b731a78ecd89140103e26dc712db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=B3r=20Mil=C3=A1n?= <71042542+bormilan@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:50:49 +0100 Subject: [PATCH 15/18] Update doc_rules/elvis_style/module_naming_convention.md Co-authored-by: Paulo F. Oliveira --- doc_rules/elvis_style/module_naming_convention.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc_rules/elvis_style/module_naming_convention.md b/doc_rules/elvis_style/module_naming_convention.md index 72550c1e..d9340e60 100644 --- a/doc_rules/elvis_style/module_naming_convention.md +++ b/doc_rules/elvis_style/module_naming_convention.md @@ -1,7 +1,7 @@ # Module Naming Convention -All modules should be named according to the regular expression provided. -Except if it matches with a defined `forbidden_regex`. +All modules should be named according to the provided regular expression, +except if they match with a defined `forbidden_regex`. > Works on `.beam` file? Yes! From 25e9b73b351b0710d6cc6a9de63aaa163458c97f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=B3r=20Mil=C3=A1n?= <71042542+bormilan@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:50:55 +0100 Subject: [PATCH 16/18] Update doc_rules/elvis_style/variable_naming_convention.md Co-authored-by: Paulo F. Oliveira --- doc_rules/elvis_style/variable_naming_convention.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc_rules/elvis_style/variable_naming_convention.md b/doc_rules/elvis_style/variable_naming_convention.md index 7053375f..2e393d6e 100644 --- a/doc_rules/elvis_style/variable_naming_convention.md +++ b/doc_rules/elvis_style/variable_naming_convention.md @@ -1,7 +1,7 @@ # Variable Naming Convention -All variables should be named according to the regular expression provided. -Except if it matches with a defined `forbidden_regex`. +All variables should be named according to the provided regular expression, +except if they match with a defined `forbidden_regex`. > Works on `.beam` file? Yes! From 199ba15a81b202872de147c74c785e78c419caeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mil=C3=A1n=20B=C3=B3r?= Date: Mon, 9 Dec 2024 16:25:29 +0100 Subject: [PATCH 17/18] fix regexes --- test/style_SUITE.erl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/style_SUITE.erl b/test/style_SUITE.erl index 177902d6..317ce398 100644 --- a/test/style_SUITE.erl +++ b/test/style_SUITE.erl @@ -192,7 +192,7 @@ verify_function_naming_convention(Config) -> elvis_core_apply_rule(Config, elvis_style, function_naming_convention, - #{regex => "^[a-z](_?[a-z0-9]+)*$", forbidden_regex => "[0-9]"}, + #{regex => DefaultRegex, forbidden_regex => "[0-9]"}, PathForbidden). -spec verify_variable_naming_convention(config()) -> any(). @@ -200,6 +200,7 @@ verify_variable_naming_convention(Config) -> Ext = proplists:get_value(test_file_ext, Config, "erl"), RuleConfig = #{regex => "^_?([A-Z][0-9a-zA-Z]*)$"}, + #{regex := DefaultRegex} = elvis_style:default(variable_naming_convention), PathPass = "pass_variable_naming_convention." ++ Ext, [] = @@ -227,7 +228,7 @@ verify_variable_naming_convention(Config) -> elvis_core_apply_rule(Config, elvis_style, variable_naming_convention, - #{regex => "^_?([A-Z][0-9a-zA-Z]*)$", forbidden_regex => "[0-9]"}, + #{regex => DefaultRegex, forbidden_regex => "[0-9]"}, PathForbidden). -spec verify_consistent_variable_casing(config()) -> any(). @@ -720,8 +721,7 @@ verify_module_naming_convention(Config) -> elvis_core_apply_rule(Config, elvis_style, module_naming_convention, - #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", - forbidden_regex => "[0-9]"}, + #{regex => DefaultRegex, forbidden_regex => "[0-9]"}, PathForbidden). -spec verify_state_record_and_type(config()) -> any(). @@ -1465,6 +1465,8 @@ verify_atom_naming_convention(Config) -> Group = proplists:get_value(group, Config, erl_files), Ext = proplists:get_value(test_file_ext, Config, "erl"), + #{regex := DefaultRegex} = elvis_style:default(atom_naming_convention), + BaseRegex = "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", % pass @@ -1602,16 +1604,14 @@ verify_atom_naming_convention(Config) -> elvis_core_apply_rule(Config, elvis_style, atom_naming_convention, - #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", - forbidden_regex => "[0-9]"}, + #{regex => DefaultRegex, forbidden_regex => "[0-9]"}, PathForbidden); erl_files -> [_, _, _] = elvis_core_apply_rule(Config, elvis_style, atom_naming_convention, - #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", - forbidden_regex => "[0-9]"}, + #{regex => DefaultRegex, forbidden_regex => "[0-9]"}, PathForbidden) end, @@ -1619,7 +1619,7 @@ verify_atom_naming_convention(Config) -> elvis_core_apply_rule(Config, elvis_style, atom_naming_convention, - #{regex => "^[a-z](_?[a-z0-9]+)*(_SUITE)?$", + #{regex => DefaultRegex, forbidden_regex => "[0-9]", forbidden_enclosed_regex => same}, PathForbidden). From f92e859b75ccff5c7f934d1aa41ba8dcd905bce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mil=C3=A1n=20B=C3=B3r?= Date: Sat, 14 Dec 2024 12:41:44 +0100 Subject: [PATCH 18/18] change messages --- src/elvis_style.erl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/elvis_style.erl b/src/elvis_style.erl index cdd786dc..312f8d4c 100644 --- a/src/elvis_style.erl +++ b/src/elvis_style.erl @@ -70,24 +70,24 @@ "Use the '-callback' attribute instead of 'behavior_info/1' " "on line ~p."). -define(FUNCTION_NAMING_CONVENTION_MSG, - "The function ~p does not respect the format defined by the " + "The function ~p's name does not respect the format defined by the " "regular expression '~p'."). -define(FORBIDDEN_FUNCTION_NAMING_CONVENTION_MSG, - "The function ~p is written in a forbidden format" + "The function ~p's name is written in a forbidden format" "defined by the regular expression '~p'."). -define(VARIABLE_NAMING_CONVENTION_MSG, - "The variable ~p on line ~p does not respect the format " + "The variable ~p's name, on line ~p does not respect the format " "defined by the regular expression '~p'."). -define(FORBIDDEN_VARIABLE_NAMING_CONVENTION_MSG, - "The variable ~p on line ~p is written in a forbidden the format " + "The variable ~p's name on line ~p is written in a forbidden the format " "defined by the regular expression '~p'."). -define(CONSISTENT_VARIABLE_CASING_MSG, "Variable ~ts (first used in line ~p) is written in different ways within the module: ~p."). -define(MODULE_NAMING_CONVENTION_MSG, - "The module ~p does not respect the format defined by the " + "The module ~p's name does not respect the format defined by the " "regular expression '~p'."). -define(FORBIDDEN_MODULE_NAMING_CONVENTION_MSG, - "The module ~p is written in a forbidden format defined by the " + "The module ~p's name is written in a forbidden format defined by the " "regular expression '~p'."). -define(STATE_RECORD_MISSING_MSG, "This module implements an OTP behavior but is missing " @@ -123,10 +123,10 @@ -define(NO_SUCCESSIVE_MAPS_MSG, "Found map update after map construction/update at line ~p."). -define(ATOM_NAMING_CONVENTION_MSG, - "Atom ~p on line ~p does not respect the format " + "Atom ~p's name, on line ~p does not respect the format " "defined by the regular expression '~p'."). -define(FORBIDDEN_ATOM_NAMING_CONVENTION_MSG, - "Atom ~p on line ~p is written in a forbidden format " + "Atom ~p on line ~p's name is written in a forbidden format " "defined by the regular expression '~p'."). -define(NO_THROW_MSG, "Usage of throw/1 on line ~p is not recommended"). -define(NO_DOLLAR_SPACE_MSG,