Skip to content

Commit

Permalink
[#153] Max function length rule
Browse files Browse the repository at this point in the history
  • Loading branch information
jfacorro committed Aug 28, 2015
1 parent 9642bbe commit 86291a5
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 1 deletion.
45 changes: 44 additions & 1 deletion src/elvis_style.erl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
state_record_and_type/3,
no_spec_with_records/3,
dont_repeat_yourself/3,
max_module_length/3
max_module_length/3,
max_function_length/3
]).

-define(LINE_LENGTH_MSG, "Line ~p is too long: ~s.").
Expand Down Expand Up @@ -91,6 +92,10 @@
"The code for module ~p has ~p lines which exceeds the "
"maximum of ~p.").

-define(MAX_FUNCTION_LENGTH,
"The code for function ~p has ~p lines which exceeds the "
"maximum of ~p.").

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Rules
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Expand Down Expand Up @@ -407,6 +412,44 @@ max_module_length(Config, Target, RuleConfig) ->
[]
end.

-spec max_function_length(elvis_config:config(),
elvis_file:file(),
empty_rule_config()) ->
[elvis_result:item()].
max_function_length(Config, Target, RuleConfig) ->
MaxLength = maps:get(max_length, RuleConfig, 30),

{Root, _} = elvis_file:parse_tree(Config, Target),

IsFunction = fun(Node) -> ktn_code:type(Node) == function end,
Functions = elvis_code:find(IsFunction, Root),
PairFun =
fun(FunctionNode) ->
Name = ktn_code:attr(name, FunctionNode),
L = function_line_length(FunctionNode),
{Name, L}
end,
FunLenPairs = lists:map(PairFun, Functions),
MaxLengthPred = fun({_, L}) -> L > MaxLength end,
FunLenMaxPairs = lists:filter(MaxLengthPred, FunLenPairs),

ResultFun =
fun({Name, L}) ->
Info = [Name, L, MaxLength],
Msg = ?MAX_FUNCTION_LENGTH,
elvis_result:new(item, Msg, Info, 0)
end,
lists:map(ResultFun, FunLenMaxPairs).

-spec function_line_length(ktn_code:tree_node())-> [{atom(), integer()}].
function_line_length(FunctionNode) ->
Zipper = elvis_code:code_zipper(FunctionNode),
LineFun = fun(N) -> {L, _} = ktn_code:attr(location, N), L end,
LineNums = zipper:map(LineFun, Zipper),
Max = lists:max(LineNums),
Min = lists:min(LineNums),
(Max - Min) + 1.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Private
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Expand Down
36 changes: 36 additions & 0 deletions test/examples/fail_max_function_length.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
-module(fail_max_function_length).

-export([f5/1, f10/1, f15/1]).

f5(_) -> %% 1
%% 2
%% 3
%% 4
ok. %% 5

f10(_) -> %% 1
%% 2
%% 3
%% 4
%% 5
%% 6
%% 7
%% 8
%% 9
ok.

f15(_) -> %% 1
%% 2
%% 3
%% 4
%% 5
%% 6
%% 7
%% 8
%% 9
%% 10
%% 11
%% 12
%% 13
%% 14
ok.
22 changes: 22 additions & 0 deletions test/style_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
verify_no_spec_with_records/1,
verify_dont_repeat_yourself/1,
verify_max_module_length/1,
verify_max_function_length/1,
%% Non-rule
results_are_ordered_by_line/1
]).
Expand Down Expand Up @@ -351,6 +352,27 @@ verify_max_module_length(_Config) ->
RuleConfig2 = #{max_length => 15},
[] = elvis_style:max_module_length(ElvisConfig, FileFail, RuleConfig2).

-spec verify_max_function_length(config()) -> any().
verify_max_function_length(_Config) ->
ElvisConfig = elvis_config:default(),
SrcDirs = elvis_config:dirs(ElvisConfig),

PathFail = "fail_max_function_length.erl",
{ok, FileFail} = elvis_test_utils:find_file(SrcDirs, PathFail),
RuleConfig = #{max_length => 4},
[_, _, _] =
elvis_style:max_function_length(ElvisConfig, FileFail, RuleConfig),

RuleConfig1 = #{max_length => 9},
[_, _] =
elvis_style:max_function_length(ElvisConfig, FileFail, RuleConfig1),

RuleConfig2 = #{max_length => 14},
[_] = elvis_style:max_function_length(ElvisConfig, FileFail, RuleConfig2),

RuleConfig3 = #{max_length => 15},
[] = elvis_style:max_function_length(ElvisConfig, FileFail, RuleConfig3).

-spec results_are_ordered_by_line(config()) -> any().
results_are_ordered_by_line(_Config) ->
ElvisConfig = elvis_config:default(),
Expand Down

0 comments on commit 86291a5

Please sign in to comment.