Skip to content

Commit

Permalink
Add empty_line_replacement to Credo.Code.Sigils
Browse files Browse the repository at this point in the history
  • Loading branch information
rrrene committed Dec 22, 2023
1 parent ccd7dbb commit c76a3a6
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 86 deletions.
180 changes: 94 additions & 86 deletions lib/credo/code/sigils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -72,259 +72,267 @@ defmodule Credo.Code.Sigils do
source_file,
replacement \\ " ",
interpolation_replacement \\ " ",
filename \\ "nofilename"
filename \\ "nofilename",
empty_line_replacement \\ ""
) do
{source, filename} = SourceFile.source_and_filename(source_file, filename)

source
|> InterpolationHelper.replace_interpolations(interpolation_replacement, filename)
|> parse_code("", replacement)
|> parse_code("", replacement, empty_line_replacement)
end

defp parse_code("", acc, _replacement) do
defp parse_code("", acc, _replacement, _empty_line_replacement) do
acc
end

defp parse_code(<<"\\\""::utf8, t::binary>>, acc, replacement) do
parse_code(t, acc <> "\\\"", replacement)
defp parse_code(<<"\\\""::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_code(t, acc <> "\\\"", replacement, empty_line_replacement)
end

defp parse_code(<<"\\\'"::utf8, t::binary>>, acc, replacement) do
parse_code(t, acc <> "\\\'", replacement)
defp parse_code(<<"\\\'"::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_code(t, acc <> "\\\'", replacement, empty_line_replacement)
end

defp parse_code(<<"?'"::utf8, t::binary>>, acc, replacement) do
parse_code(t, acc <> "?'", replacement)
defp parse_code(<<"?'"::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_code(t, acc <> "?'", replacement, empty_line_replacement)
end

defp parse_code(<<"'"::utf8, t::binary>>, acc, replacement) do
parse_charlist(t, acc <> "'", replacement)
defp parse_code(<<"'"::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_charlist(t, acc <> "'", replacement, empty_line_replacement)
end

defp parse_code(<<"?\""::utf8, t::binary>>, acc, replacement) do
parse_code(t, acc <> "?\"", replacement)
defp parse_code(<<"?\""::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_code(t, acc <> "?\"", replacement, empty_line_replacement)
end

defp parse_code(<<"#"::utf8, t::binary>>, acc, replacement) do
parse_comment(t, acc <> "#", replacement)
defp parse_code(<<"#"::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_comment(t, acc <> "#", replacement, empty_line_replacement)
end

for {sigil_start, sigil_end} <- removable_sigils do
defp parse_code(<<unquote(sigil_start)::utf8, t::binary>>, acc, replacement) do
defp parse_code(<<unquote(sigil_start)::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_removable_sigil(
t,
acc <> unquote(sigil_start),
unquote(sigil_end),
replacement
replacement, empty_line_replacement
)
end
end

for {sigil_start, sigil_end} <- all_heredocs_sigils do
defp parse_code(<<unquote(sigil_start)::utf8, t::binary>>, acc, replacement) do
defp parse_code(<<unquote(sigil_start)::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_heredoc(
t,
acc <> unquote(sigil_start),
replacement,
unquote(sigil_end)
unquote(sigil_end), empty_line_replacement
)
end
end

defp parse_code(<<"\"\"\""::utf8, t::binary>>, acc, replacement) do
parse_heredoc(t, acc <> ~s("""), replacement, ~s("""))
defp parse_code(<<"\"\"\""::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_heredoc(t, acc <> ~s("""), replacement, ~s("""), empty_line_replacement)
end

defp parse_code(<<"\'\'\'"::utf8, t::binary>>, acc, replacement) do
parse_heredoc(t, acc <> ~s('''), replacement, ~s('''))
defp parse_code(<<"\'\'\'"::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_heredoc(t, acc <> ~s('''), replacement, ~s('''), empty_line_replacement)
end

for {sigil_start, sigil_end} <- all_string_sigils do
defp parse_code(<<unquote(sigil_start)::utf8, t::binary>>, acc, replacement) do
defp parse_code(<<unquote(sigil_start)::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_removable_sigil(
t,
acc <> unquote(sigil_start),
unquote(sigil_end),
replacement
replacement, empty_line_replacement
)
end
end

defp parse_code(<<"\""::utf8, t::binary>>, acc, replacement) do
parse_string_literal(t, acc <> "\"", replacement)
defp parse_code(<<"\""::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_string_literal(t, acc <> "\"", replacement, empty_line_replacement)
end

defp parse_code(<<h::utf8, t::binary>>, acc, replacement) do
parse_code(t, acc <> <<h::utf8>>, replacement)
defp parse_code(<<h::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_code(t, acc <> <<h::utf8>>, replacement, empty_line_replacement)
end

defp parse_code(str, acc, replacement) when is_binary(str) do
defp parse_code(str, acc, replacement, empty_line_replacement) when is_binary(str) do
{h, t} = String.next_codepoint(str)

parse_code(t, acc <> h, replacement)
parse_code(t, acc <> h, replacement, empty_line_replacement)
end

#
# Charlists
#

defp parse_charlist("", acc, _replacement) do
defp parse_charlist("", acc, _replacement, _empty_line_replacement) do
acc
end

defp parse_charlist(<<"\\\\"::utf8, t::binary>>, acc, replacement) do
parse_charlist(t, acc <> "\\\\", replacement)
defp parse_charlist(<<"\\\\"::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_charlist(t, acc <> "\\\\", replacement, empty_line_replacement)
end

defp parse_charlist(<<"\\\'"::utf8, t::binary>>, acc, replacement) do
parse_charlist(t, acc <> "\\\'", replacement)
defp parse_charlist(<<"\\\'"::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_charlist(t, acc <> "\\\'", replacement, empty_line_replacement)
end

defp parse_charlist(<<"\'"::utf8, t::binary>>, acc, replacement) do
parse_code(t, acc <> "'", replacement)
defp parse_charlist(<<"\'"::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_code(t, acc <> "'", replacement, empty_line_replacement)
end

defp parse_charlist(<<"\n"::utf8, t::binary>>, acc, replacement) do
parse_charlist(t, acc <> "\n", replacement)
defp parse_charlist(<<"\n"::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_charlist(t, acc <> "\n", replacement, empty_line_replacement)
end

defp parse_charlist(str, acc, replacement) when is_binary(str) do
defp parse_charlist(str, acc, replacement, empty_line_replacement) when is_binary(str) do
{h, t} = String.next_codepoint(str)

parse_charlist(t, acc <> h, replacement)
parse_charlist(t, acc <> h, replacement, empty_line_replacement)
end

#
# Comments
#

defp parse_comment("", acc, _replacement) do
defp parse_comment("", acc, _replacement, _empty_line_replacement) do
acc
end

defp parse_comment(<<"\n"::utf8, t::binary>>, acc, replacement) do
parse_code(t, acc <> "\n", replacement)
defp parse_comment(<<"\n"::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_code(t, acc <> "\n", replacement, empty_line_replacement)
end

defp parse_comment(str, acc, replacement) when is_binary(str) do
defp parse_comment(str, acc, replacement, empty_line_replacement) when is_binary(str) do
{h, t} = String.next_codepoint(str)

parse_comment(t, acc <> h, replacement)
parse_comment(t, acc <> h, replacement, empty_line_replacement)
end

#
# String Literals
#

defp parse_string_literal("", acc, _replacement) do
defp parse_string_literal("", acc, _replacement, _empty_line_replacement) do
acc
end

defp parse_string_literal(<<"\\\\"::utf8, t::binary>>, acc, replacement) do
parse_string_literal(t, acc <> "\\\\", replacement)
defp parse_string_literal(<<"\\\\"::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_string_literal(t, acc <> "\\\\", replacement, empty_line_replacement)
end

defp parse_string_literal(<<"\\\""::utf8, t::binary>>, acc, replacement) do
parse_string_literal(t, acc <> "\\\"", replacement)
defp parse_string_literal(<<"\\\""::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_string_literal(t, acc <> "\\\"", replacement, empty_line_replacement)
end

defp parse_string_literal(<<"\""::utf8, t::binary>>, acc, replacement) do
parse_code(t, acc <> ~s("), replacement)
defp parse_string_literal(<<"\""::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_code(t, acc <> ~s("), replacement, empty_line_replacement)
end

defp parse_string_literal(<<"\n"::utf8, t::binary>>, acc, replacement) do
parse_string_literal(t, acc <> "\n", replacement)
defp parse_string_literal(<<"\n"::utf8, t::binary>>, acc, replacement, empty_line_replacement) do
parse_string_literal(t, acc <> "\n", replacement, empty_line_replacement)
end

defp parse_string_literal(str, acc, replacement) when is_binary(str) do
defp parse_string_literal(str, acc, replacement, empty_line_replacement) when is_binary(str) do
{h, t} = String.next_codepoint(str)
parse_string_literal(t, acc <> h, replacement)
parse_string_literal(t, acc <> h, replacement, empty_line_replacement)
end

#
# Sigils
#

for sigil_end <- removable_sigil_ends do
defp parse_removable_sigil("", acc, unquote(sigil_end), _replacement) do
defp parse_removable_sigil("", acc, unquote(sigil_end), _replacement, _empty_line_replacement) do
acc
end

defp parse_removable_sigil(
<<"\\"::utf8, s::binary>>,
acc,
unquote(sigil_end),
replacement
replacement, empty_line_replacement
) do
{_h, t} = String.next_codepoint(s)

parse_removable_sigil(t, acc <> replacement <> replacement, unquote(sigil_end), replacement)
parse_removable_sigil(t, acc <> replacement <> replacement, unquote(sigil_end), replacement, empty_line_replacement)
end

defp parse_removable_sigil(
# \\
<<"\\\\"::utf8, t::binary>>,
acc,
unquote(sigil_end),
replacement
replacement, empty_line_replacement
) do
parse_removable_sigil(t, acc <> replacement <> replacement, unquote(sigil_end), replacement)
parse_removable_sigil(t, acc <> replacement <> replacement, unquote(sigil_end), replacement, empty_line_replacement)
end

defp parse_removable_sigil(
<<unquote("\\#{sigil_end}")::utf8, t::binary>>,
acc,
unquote(sigil_end),
replacement
replacement, empty_line_replacement
) do
parse_removable_sigil(
t,
acc <> replacement <> replacement,
unquote(sigil_end),
replacement
replacement, empty_line_replacement
)
end

defp parse_removable_sigil(
<<unquote(sigil_end)::utf8, t::binary>>,
acc,
unquote(sigil_end),
replacement
replacement, empty_line_replacement
) do
parse_code(t, acc <> unquote(sigil_end), replacement)
parse_code(t, acc <> unquote(sigil_end), replacement, empty_line_replacement)
end

if sigil_end != "\"" do
defp parse_removable_sigil(
<<"\""::utf8, t::binary>>,
acc,
unquote(sigil_end),
replacement
replacement, empty_line_replacement
) do
parse_removable_sigil(t, acc <> replacement, unquote(sigil_end), replacement)
parse_removable_sigil(t, acc <> replacement, unquote(sigil_end), replacement, empty_line_replacement)
end
end

defp parse_removable_sigil(
<<"\n"::utf8, t::binary>>,
acc,
unquote(sigil_end),
replacement
replacement, empty_line_replacement
) do
parse_removable_sigil(t, acc <> "\n", unquote(sigil_end), replacement)
acc =
if String.last(acc) == "\n" do
acc <> empty_line_replacement
else
acc
end

parse_removable_sigil(t, acc <> "\n", unquote(sigil_end), replacement, empty_line_replacement)
end

defp parse_removable_sigil(
<<_::utf8, t::binary>>,
acc,
unquote(sigil_end),
replacement
replacement, empty_line_replacement
) do
parse_removable_sigil(
t,
acc <> replacement,
unquote(sigil_end),
replacement
replacement, empty_line_replacement
)
end
end
Expand All @@ -333,32 +341,32 @@ defmodule Credo.Code.Sigils do
# Heredocs
#

defp parse_heredoc(<<"\"\"\""::utf8, t::binary>>, acc, replacement, "\"\"\"") do
parse_code(t, acc <> "\"\"\"", replacement)
defp parse_heredoc(<<"\"\"\""::utf8, t::binary>>, acc, replacement, "\"\"\"", empty_line_replacement) do
parse_code(t, acc <> "\"\"\"", replacement, empty_line_replacement)
end

defp parse_heredoc(<<"\'\'\'"::utf8, t::binary>>, acc, replacement, "\'\'\'") do
parse_code(t, acc <> "\'\'\'", replacement)
defp parse_heredoc(<<"\'\'\'"::utf8, t::binary>>, acc, replacement, "\'\'\'", empty_line_replacement) do
parse_code(t, acc <> "\'\'\'", replacement, empty_line_replacement)
end

defp parse_heredoc("", acc, _replacement, _delimiter) do
defp parse_heredoc("", acc, _replacement, _delimiter, _empty_line_replacement) do
acc
end

defp parse_heredoc(<<"\\\\"::utf8, t::binary>>, acc, replacement, delimiter) do
parse_heredoc(t, acc <> "\\\\", replacement, delimiter)
defp parse_heredoc(<<"\\\\"::utf8, t::binary>>, acc, replacement, delimiter, empty_line_replacement) do
parse_heredoc(t, acc <> "\\\\", replacement, delimiter, empty_line_replacement)
end

defp parse_heredoc(<<"\\\""::utf8, t::binary>>, acc, replacement, delimiter) do
parse_heredoc(t, acc <> "\\\"", replacement, delimiter)
defp parse_heredoc(<<"\\\""::utf8, t::binary>>, acc, replacement, delimiter, empty_line_replacement) do
parse_heredoc(t, acc <> "\\\"", replacement, delimiter, empty_line_replacement)
end

defp parse_heredoc(<<"\n"::utf8, t::binary>>, acc, replacement, delimiter) do
parse_heredoc(t, acc <> "\n", replacement, delimiter)
defp parse_heredoc(<<"\n"::utf8, t::binary>>, acc, replacement, delimiter, empty_line_replacement) do
parse_heredoc(t, acc <> "\n", replacement, delimiter, empty_line_replacement)
end

defp parse_heredoc(str, acc, replacement, delimiter) when is_binary(str) do
defp parse_heredoc(str, acc, replacement, delimiter, empty_line_replacement) when is_binary(str) do
{h, t} = String.next_codepoint(str)
parse_heredoc(t, acc <> h, replacement, delimiter)
parse_heredoc(t, acc <> h, replacement, delimiter, empty_line_replacement)
end
end
Loading

0 comments on commit c76a3a6

Please sign in to comment.