Skip to content

Commit

Permalink
Strip top-level calls from .exs files before compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
zachallaun committed Jul 23, 2024
1 parent 6572a6a commit 2618593
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ defmodule Lexical.RemoteControl.Build.Document.Compilers.Elixir do
@behaviour Build.Document.Compiler

@impl true
def recognizes?(%Document{language_id: "elixir"}), do: true
def recognizes?(_), do: false
def recognizes?(%Document{} = doc) do
doc.language_id in ["elixir", "elixir-script"]
end

@impl true
def enabled?, do: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ defmodule Lexical.RemoteControl.Build.Document.Compilers.Quoted do
def compile(%Document{} = document, quoted_ast, compiler_name) do
prepare_compile(document.path)

quoted_ast =
if document.language_id == "elixir-script" do
wrap_top_level_forms(quoted_ast)
else
quoted_ast
end

{status, diagnostics} =
if Features.with_diagnostics?() do
do_compile(quoted_ast, document)
Expand Down Expand Up @@ -130,4 +137,39 @@ defmodule Lexical.RemoteControl.Build.Document.Compilers.Quoted do
defp replace_source(result, source) do
Map.put(result, :source, source)
end

defp wrap_top_level_forms({:__block__, meta, nodes}) do
chunks =
nodes
|> Enum.chunk_by(&should_wrap?/1)
|> Enum.with_index(fn [node | _] = nodes, i ->
if should_wrap?(node) do
wrap_nodes(nodes, i)
else
nodes
end
end)

{:__block__, meta, chunks}
end

defp wrap_top_level_forms(ast) do
wrap_top_level_forms({:__block__, [], [ast]})
end

defp wrap_nodes(nodes, i) do
module_name = :"lexical_wrapper_#{i}"

quote do
defmodule unquote(module_name) do
def __lexical_wrapper__ do
(unquote_splicing(nodes))
end
end
end
end

@allowed_top_level [:defmodule, :alias, :import, :require, :use]
defp should_wrap?({allowed, _, _}) when allowed in @allowed_top_level, do: false
defp should_wrap?(_), do: true
end
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ defmodule Lexical.BuildTest do
project
|> Project.root_path()
|> Path.join(to_string(sequence))
|> Path.join("file.exs")
|> Path.join("file.ex")
|> Document.Path.to_uri()
end

Expand Down
9 changes: 7 additions & 2 deletions projects/lexical_shared/lib/lexical/document.ex
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ defmodule Lexical.Document do
uri = DocumentPath.ensure_uri(maybe_uri)
path = DocumentPath.from_uri(uri)

language_id = language_id || language_id_from_path(path)
language_id =
if String.ends_with?(path, ".exs") do
"elixir-script"
else
language_id || language_id_from_path(path)
end

%__MODULE__{
uri: uri,
Expand Down Expand Up @@ -233,7 +238,7 @@ defmodule Lexical.Document do
"elixir"

".exs" ->
"elixir"
"elixir-script"

".eex" ->
"eex"
Expand Down

0 comments on commit 2618593

Please sign in to comment.