Skip to content

Commit

Permalink
add new version of max_function_clause_length
Browse files Browse the repository at this point in the history
  • Loading branch information
bormilan committed Oct 5, 2024
1 parent 0781bb7 commit 89e87ed
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 23 deletions.
93 changes: 72 additions & 21 deletions src/elvis_style.erl
Original file line number Diff line number Diff line change
Expand Up @@ -911,48 +911,99 @@ max_function_clause_length(Config, Target, RuleConfig) ->
{Src, _} = elvis_file:src(Target),
Lines = elvis_utils:split_all_lines(Src, [trim]),

IsClause = fun(Node) -> ktn_code:type(Node) == clause end,
Clauses0 = elvis_code:find(IsClause, Root),
IsFunction = fun(Node) -> ktn_code:type(Node) == function end,
Functions0 = elvis_code:find(IsFunction, Root),

% clause
FilterClause =
fun(Line) ->
(CountComments orelse not line_is_comment(Line))
andalso (CountWhitespace orelse not line_is_whitespace(Line))
end,

PairClause =
fun(ClauseNode, {Result, AccNum}) ->
Name = ktn_code:attr(text, ClauseNode),
fun(ClauseNode, {Result, PrevAccNum}) ->
{Min, Max} = node_line_limits(ClauseNode),
FunLines = lists:sublist(Lines, Min, Max - Min + 1),
FilteredLines = lists:filter(FilterClause, FunLines),
L = length(FilteredLines),
ClauseNumber = clause_num(Result, Name, AccNum + 1),
StringClauseNumber = parse_clause_num(ClauseNumber),
{[{Min, Name, StringClauseNumber, L} | Result], ClauseNumber}
AccNum = PrevAccNum + 1,
ClauseNumber = parse_clause_num(AccNum),
{[{Min, ClauseNumber, L} | Result], AccNum}
end,
{ClauseLenInfos, _} = lists:foldl(PairClause, {[], 0}, Clauses0),

MaxLengthPred = fun({_, _, _, L}) -> L > MaxLength end,
% fun
PairFun =
fun(FunctionNode) ->
Name = ktn_code:attr(name, FunctionNode),
Arity = ktn_code:attr(arity, FunctionNode),

IsClause = fun(Node) -> ktn_code:type(Node) == clause end,
Clauses = elvis_code:find(IsClause, FunctionNode),

{ClauseLenInfos, _} = lists:foldl(PairClause, {[], 0}, Clauses),

[{Name, Arity, Min, StringClauseNumber, L}
|| {Min, StringClauseNumber, L} <- ClauseLenInfos]
end,

ClauseLenInfos =
lists:append(
lists:map(PairFun, Functions0)),

MaxLengthPred = fun({_, _, _, _, L}) -> L > MaxLength end,
ClauseLenMaxPairs = lists:filter(MaxLengthPred, ClauseLenInfos),

ResultFun =
fun({StartPos, Name, ClauseNumber, L}) ->
Info = [ClauseNumber, Name, L, MaxLength],
fun({Name, Arity, StartPos, ClauseNumber, L}) ->
Info = [Name, Arity, ClauseNumber, L, MaxLength],
Msg = ?MAX_FUNCTION_CLAUSE_LENGTH,
elvis_result:new(item, Msg, Info, StartPos)
end,
lists:map(ResultFun, ClauseLenMaxPairs).

clause_num([], _, 1) ->
1;
clause_num([{_, LastClauseName, _, _}], Name, 2) ->
clause_num(LastClauseName, Name, 2);
clause_num([{_, LastClauseName, _, _} | _], Name, AccNum) ->
clause_num(LastClauseName, Name, AccNum);
clause_num(LastClauseName, Name, AccNum) when LastClauseName =:= Name ->
AccNum;
clause_num(_, _, _) ->
1.
% IsClause = fun(Node) -> ktn_code:type(Node) == clause end,
% Clauses0 = elvis_code:find(IsClause, Root),
% FilterClause =
% fun(Line) ->
% (CountComments orelse not line_is_comment(Line))
% andalso (CountWhitespace orelse not line_is_whitespace(Line))
% end,
%
% PairClause =
% fun(ClauseNode, {Result, AccNum}) ->
% Name = ktn_code:attr(text, ClauseNode),
% {Min, Max} = node_line_limits(ClauseNode),
% FunLines = lists:sublist(Lines, Min, Max - Min + 1),
% FilteredLines = lists:filter(FilterClause, FunLines),
% L = length(FilteredLines),
% ClauseNumber = clause_num(Result, Name, AccNum + 1),
% StringClauseNumber = parse_clause_num(ClauseNumber),
% {[{Min, Name, StringClauseNumber, L} | Result], ClauseNumber}
% end,
% {ClauseLenInfos, _} = lists:foldl(PairClause, {[], 0}, Clauses0),

% MaxLengthPred = fun({_, _, _, L}) -> L > MaxLength end,
% ClauseLenMaxPairs = lists:filter(MaxLengthPred, ClauseLenInfos),
%
% ResultFun =
% fun({StartPos, Name, ClauseNumber, L}) ->
% Info = [ClauseNumber, Name, L, MaxLength],
% Msg = ?MAX_FUNCTION_CLAUSE_LENGTH,
% elvis_result:new(item, Msg, Info, StartPos)
% end,
% lists:map(ResultFun, ClauseLenMaxPairs).

% clause_num([], _, 1) ->
% 1;
% clause_num([{_, LastClauseName, _, _}], Name, 2) ->
% clause_num(LastClauseName, Name, 2);
% clause_num([{_, LastClauseName, _, _} | _], Name, AccNum) ->
% clause_num(LastClauseName, Name, AccNum);
% clause_num(LastClauseName, Name, AccNum) when LastClauseName =:= Name ->
% AccNum;
% clause_num(_, _, _) ->
% 1.

parse_clause_num(Num) when Num rem 10 == 1 ->
integer_to_list(Num) ++ "st";
Expand Down
32 changes: 31 additions & 1 deletion test/examples/fail_max_function_clause_length.erl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
-module(fail_max_function_clause_length).

-export([f5/1, f6/1]).
-export([f5/1, f6/1, f7/1]).

f5(a) -> %% 1
%% 2
Expand Down Expand Up @@ -58,3 +58,33 @@ f6(e) -> %% 1
ok;
f6(f) -> %% 1
ok.

f7(a) -> 1;
f7(b) -> 2;
f7(c) -> 3;
f7(d) -> 4;
f7(e) -> 5;
f7(f) -> 6;
f7(aa) -> 7;
f7(bb) ->
8;
f7(cc) -> 9;
f7(dd) ->
10;
f7(ee) -> 11;
f7(ff) -> 12;
f7(aaa) -> 13;
f7(bbb) -> 14;
f7(ccc) -> 15;
f7(ddd) -> 16;
f7(eee) -> 17;
f7(fff) -> 18;
f7(aaaa) -> 19;
f7(bbbb) ->
20;
f7(cccc) -> 21;
f7(dddd) -> 22;
f7(eeee) -> 23;
f7(ffff) ->
24;
f7(aaaaa) -> 25.
11 changes: 10 additions & 1 deletion test/style_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,16 @@ verify_max_function_clause_length(Config) ->
elvis_style,
max_function_clause_length,
RuleConfig2,
PathExtraSuccess).
PathExtraSuccess),

RuleConfig3 = CountAllRuleConfig#{max_length => 1},

[_, _, _, _, _, _, _, _, _, _] =
elvis_core_apply_rule(Config,
elvis_style,
max_function_clause_length,
RuleConfig3,
PathFail).

-spec verify_no_debug_call(config()) -> any().
verify_no_debug_call(Config) ->
Expand Down

0 comments on commit 89e87ed

Please sign in to comment.