Skip to content

Commit

Permalink
Adds latin1 support for line_length and operator_spaces rules
Browse files Browse the repository at this point in the history
  • Loading branch information
tjarvstrand committed Feb 28, 2017
1 parent 722c090 commit a4aeef6
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 19 deletions.
7 changes: 6 additions & 1 deletion src/elvis_file.erl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ src(File = #{content := Content}) ->
src(File = #{path := Path}) ->
case file:read_file(Path) of
{ok, Content} ->
src(File#{content => Content});
Encoding = case epp:read_encoding_from_binary(Content) of
none -> utf8;
Enc -> Enc
end,
src(File#{content => Content,
encoding => Encoding});
Error -> Error
end;
src(File) ->
Expand Down
45 changes: 27 additions & 18 deletions src/elvis_style.erl
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ variable_naming_convention(Config, Target, RuleConfig) ->
line_length(_Config, Target, RuleConfig) ->
Limit = maps:get(limit, RuleConfig, 80),
SkipComments = maps:get(skip_comments, RuleConfig, false),
{Src, _} = elvis_file:src(Target),
Args = [Limit, SkipComments],
{Src, #{encoding := Encoding}} = elvis_file:src(Target),
Args = [Limit, SkipComments, Encoding],
elvis_utils:check_lines(Src, fun check_line_length/3, Args).

-spec no_tabs(elvis_config:config(),
Expand Down Expand Up @@ -253,13 +253,13 @@ macro_module_names(Config, Target, _RuleConfig) ->
[elvis_result:item()].
operator_spaces(Config, Target, RuleConfig) ->
Rules = maps:get(rules, RuleConfig, []),
{Src, _} = elvis_file:src(Target),
{Src, #{encoding := Encoding}} = elvis_file:src(Target),
{Root, _} = elvis_file:parse_tree(Config, Target),
Tokens = ktn_code:attr(tokens, Root),
Lines = binary:split(Src, <<"\n">>, [global]),
lists:flatmap(
fun(Rule) ->
check_operator_spaces(Lines, Tokens, Rule)
check_operator_spaces(Lines, Tokens, Rule, Encoding)
end,
Rules
).
Expand Down Expand Up @@ -720,18 +720,18 @@ remove_comment(Line) ->

-spec check_line_length(binary(), integer(), [term()]) ->
no_result | {ok, elvis_result:item()}.
check_line_length(Line, Num, [Limit, whole_line]) ->
check_line_length(Line, Num, [Limit, whole_line, Encoding]) ->
case line_is_comment(Line) of
false -> check_line_length(Line, Num, Limit);
false -> check_line_length(Line, Num, [Limit, Encoding]);
true -> no_result
end;
check_line_length(Line, Num, [Limit, any]) ->
check_line_length(Line, Num, [Limit, any, Encoding]) ->
LineWithoutComment = remove_comment(Line),
check_line_length(LineWithoutComment, Num, Limit);
check_line_length(Line, Num, [Limit|_]) ->
check_line_length(Line, Num, Limit);
check_line_length(Line, Num, Limit) ->
Chars = unicode:characters_to_list(Line),
check_line_length(LineWithoutComment, Num, [Limit, Encoding]);
check_line_length(Line, Num, [Limit, _, Encoding]) ->
check_line_length(Line, Num, [Limit, Encoding]);
check_line_length(Line, Num, [Limit, Encoding]) ->
Chars = unicode:characters_to_list(Line, Encoding),
case length(Chars) of
Large when Large > Limit ->
Msg = ?LINE_LENGTH_MSG,
Expand Down Expand Up @@ -888,9 +888,10 @@ has_remote_call_parent(Zipper) ->
%% Operator Spaces
-spec check_operator_spaces(Lines::[binary()],
Tokens::[map()],
Rule::{right | left, string()}) ->
Rule::{right | left, string()},
Encoding::latin1 | utf8) ->
[elvis_result:item()].
check_operator_spaces(Lines, Tokens, {Position, Operator}) ->
check_operator_spaces(Lines, Tokens, {Position, Operator}, Encoding) ->
Nodes = lists:filter(
fun(Node) -> ktn_code:attr(text, Node) =:= Operator end,
Tokens
Expand All @@ -899,7 +900,13 @@ check_operator_spaces(Lines, Tokens, {Position, Operator}) ->
lists:flatmap(
fun(Node) ->
Location = ktn_code:attr(location, Node),
case character_at_location(Position, Lines, Operator, Location) of
case
character_at_location(Position,
Lines,
Operator,
Location,
Encoding)
of
SpaceChar -> [];
_ ->
Msg = ?OPERATOR_SPACE_MSG,
Expand All @@ -915,9 +922,11 @@ check_operator_spaces(Lines, Tokens, {Position, Operator}) ->
-spec character_at_location(Position::atom(),
Lines::[binary()],
Operator::string(),
Location::{integer(), integer()}) -> char().
character_at_location(Position, Lines, Operator, {Line, Col}) ->
OperatorLineStr = unicode:characters_to_list(lists:nth(Line, Lines)),
Location::{integer(), integer()},
Encoding::latin1|utf8) -> char().
character_at_location(Position, Lines, Operator, {LineNo, Col}, Encoding) ->
Line = lists:nth(LineNo, Lines),
OperatorLineStr = unicode:characters_to_list(Line, Encoding),
ColToCheck = case Position of
left -> Col - 1;
right -> Col + length(Operator)
Expand Down
14 changes: 14 additions & 0 deletions test/examples/fail_line_length_latin1.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
%%% -*- coding: latin-1 -*-
-module(fail_line_length_latin1).

-export([
function_1/0,
function_2/0
]).

function_1() ->
io:format("Hellö").

function_2() ->
io:format("Hellö, This line is 81 characters long and should be detected, yeah!!!").

9 changes: 9 additions & 0 deletions test/examples/fail_operator_spaces_latin1.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
%%% -*- coding: latin-1 -*-
-module(fail_operator_spaces_latin1).

-export([
function_1/0
]).

function_1() ->
"ö"++"1".
29 changes: 29 additions & 0 deletions test/style_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@
verify_function_naming_convention/1,
verify_variable_naming_convention/1,
verify_line_length_rule/1,
verify_line_length_rule_latin1/1,
verify_unicode_line_length_rule/1,
verify_no_tabs_rule/1,
verify_no_spaces_rule/1,
verify_no_trailing_whitespace_rule/1,
verify_macro_names_rule/1,
verify_macro_module_names/1,
verify_operator_spaces/1,
verify_operator_spaces_latin1/1,
verify_nesting_level/1,
verify_god_modules/1,
verify_no_if_expression/1,
Expand Down Expand Up @@ -140,6 +142,19 @@ verify_line_length_rule(_Config) ->
skip_comments => any}),
6 = length(AnyResult).

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

File = "fail_line_length_latin1.erl",
{ok, Path} = elvis_test_utils:find_file(SrcDirs, File),

Result = elvis_style:line_length(ElvisConfig, Path, #{limit => 80}),
1 = length(Result),
#{info := Info, message := Msg} = lists:nth(1, Result),
<<"Line 13 is too long:", _/binary>> = list_to_binary(io_lib:format(Msg, Info)).

-spec verify_unicode_line_length_rule(config()) -> any().
verify_unicode_line_length_rule(_Config) ->
ElvisConfig = elvis_config:default(),
Expand Down Expand Up @@ -237,6 +252,20 @@ verify_operator_spaces(_Config) ->
[_, _, _, _, _, _] =
elvis_style:operator_spaces(ElvisConfig, Path, AllOptions).

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

File = "fail_operator_spaces_latin1.erl",
{ok, Path} = elvis_test_utils:find_file(SrcDirs, File),

[] = elvis_style:operator_spaces(ElvisConfig, Path, #{}),

AppendOptions = #{rules => [{right, "++"}, {left, "++"}]},
[_, _] = elvis_style:operator_spaces(ElvisConfig, Path, AppendOptions).


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

0 comments on commit a4aeef6

Please sign in to comment.