Skip to content

Commit

Permalink
feat: formatting (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
mhanberg committed Jun 19, 2023
1 parent 4b53c71 commit 5f0c73c
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 8 deletions.
48 changes: 43 additions & 5 deletions lib/next_ls.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,23 @@ defmodule NextLS do
TextDocumentDidSave
}

alias GenLSP.Requests.{Initialize, Shutdown}
alias GenLSP.Requests.{
Initialize,
Shutdown,
TextDocumentFormatting
}

alias GenLSP.Structures.{
DidOpenTextDocumentParams,
InitializeParams,
InitializeResult,
Position,
Range,
SaveOptions,
ServerCapabilities,
TextDocumentItem,
TextDocumentSyncOptions
TextDocumentSyncOptions,
TextEdit
}

alias NextLS.Runtime
Expand Down Expand Up @@ -80,12 +87,35 @@ defmodule NextLS do
open_close: true,
save: %SaveOptions{include_text: true},
change: TextDocumentSyncKind.full()
}
},
document_formatting_provider: true
},
server_info: %{name: "NextLS"}
}, assign(lsp, root_uri: root_uri)}
end

def handle_request(%TextDocumentFormatting{params: %{text_document: %{uri: uri}}}, lsp) do
document = lsp.assigns.documents[uri]

working_dir = URI.parse(lsp.assigns.root_uri).path
{opts, _} = Code.eval_file(".formatter.exs", working_dir)
new_document = Code.format_string!(Enum.join(document, "\n"), opts) |> IO.iodata_to_binary()

{:reply,
[
%TextEdit{
new_text: new_document,
range: %Range{
start: %Position{line: 0, character: 0},
end: %Position{
line: length(document),
character: document |> List.last() |> String.length() |> Kernel.-(1) |> max(0)
}
}
}
], lsp}
end

def handle_request(%Shutdown{}, lsp) do
{:reply, nil, assign(lsp, exit_code: 0)}
end
Expand Down Expand Up @@ -172,13 +202,21 @@ defmodule NextLS do
{:noreply, lsp}
end

def handle_notification(%TextDocumentDidChange{}, lsp) do
def handle_notification(
%TextDocumentDidChange{
params: %{
text_document: %{uri: uri},
content_changes: [%{text: text}]
}
},
lsp
) do
for task <- Task.Supervisor.children(lsp.assigns.task_supervisor),
task != lsp.assigns.runtime_task.pid do
Process.exit(task, :kill)
end

{:noreply, lsp}
{:noreply, put_in(lsp.assigns.documents[uri], String.split(text, "\n"))}
end

def handle_notification(
Expand Down
4 changes: 1 addition & 3 deletions lib/next_ls/runtime.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ defmodule NextLS.Runtime do
end

def compile(server) do
GenServer.call(server, :compile)
GenServer.call(server, :compile, :infinity)
end

@impl GenServer
Expand Down Expand Up @@ -111,8 +111,6 @@ defmodule NextLS.Runtime do
def handle_call(:compile, _, %{node: node} = state) do
{_, errors} = :rpc.call(node, :_next_ls_private_compiler, :compile, [])

foo = "foo"

Registry.dispatch(state.extension_registry, :extension, fn entries ->
for {pid, _} <- entries do
send(pid, {:compiler, errors})
Expand Down
68 changes: 68 additions & 0 deletions test/next_ls_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -181,4 +181,72 @@ defmodule NextLSTest do
# }
# )
end

test "formats", %{client: client} do
assert :ok ==
notify(client, %{
method: "initialized",
jsonrpc: "2.0",
params: %{}
})

notify client, %{
method: "textDocument/didOpen",
jsonrpc: "2.0",
params: %{
textDocument: %{
uri: "file://lib/foo/bar.ex",
languageId: "elixir",
version: 1,
text: """
defmodule Foo.Bar do
def run() do
:ok
end
end
"""
}
}
}

request client, %{
method: "textDocument/formatting",
id: 2,
jsonrpc: "2.0",
params: %{
textDocument: %{
uri: "file://lib/foo/bar.ex"
},
options: %{
insertSpaces: true,
tabSize: 2
}
}
}

new_text =
"""
defmodule Foo.Bar do
def run() do
:ok
end
end
"""
|> String.trim()

assert_result(
2,
[
%{
"newText" => ^new_text,
"range" => %{
"start" => %{"character" => 0, "line" => 0},
"end" => %{"character" => 0, "line" => 8}
}
}
]
)
end
end

0 comments on commit 5f0c73c

Please sign in to comment.