Skip to content

Commit 1cf3bd9

Browse files
committed
fix: fallback to heuristics if workspace_folders is not set
1 parent 51ebda9 commit 1cf3bd9

File tree

2 files changed

+72
-8
lines changed

2 files changed

+72
-8
lines changed

apps/expert/lib/expert/state.ex

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,17 @@ defmodule Expert.State do
6363
response = initialize_result()
6464

6565
projects =
66-
for %{uri: uri} <- event.workspace_folders do
67-
Project.new(uri)
66+
case event.workspace_folders do
67+
nil ->
68+
find_projects(event.root_uri)
69+
70+
_ ->
71+
for %{uri: uri} <- event.workspace_folders,
72+
project = Project.new(uri),
73+
project.mix_project? do
74+
project
75+
end
6876
end
69-
|> Enum.filter(& &1.mix_project?)
7077

7178
ActiveProjects.set_projects(projects)
7279

@@ -89,6 +96,34 @@ defmodule Expert.State do
8996
Configuration.default(config)
9097
end
9198

99+
defp find_projects(root_uri) do
100+
root_path = Forge.Document.Path.from_uri(root_uri)
101+
root_mix_exs = Path.join(root_path, "mix.exs")
102+
103+
projects =
104+
if File.exists?(root_mix_exs) do
105+
[Project.new(root_uri)]
106+
else
107+
find_multiroot_projects(root_path)
108+
end
109+
110+
if projects == [], do: [Project.new(root_uri)], else: projects
111+
end
112+
113+
defp find_multiroot_projects(root_path) do
114+
mix_exs_blob = Path.join([root_path, "**", "mix.exs"])
115+
116+
for mix_exs_path <- Path.wildcard(mix_exs_blob),
117+
"deps" not in Path.split(mix_exs_path) do
118+
project_uri =
119+
mix_exs_path
120+
|> Path.dirname()
121+
|> Forge.Document.Path.to_uri()
122+
123+
Project.new(project_uri)
124+
end
125+
end
126+
92127
def apply(%__MODULE__{initialized?: false}, request) do
93128
Logger.error("Received #{request.method} before server was initialized")
94129
{:error, :not_initialized}

apps/expert/test/expert/expert_test.exs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,14 @@ defmodule ExpertTest do
6464

6565
def initialize_request(root_path, opts \\ []) do
6666
id = opts[:id] || 1
67-
projects = opts[:projects] || []
67+
projects = Keyword.get(opts, :projects, [])
68+
69+
workspace_folders =
70+
if not is_nil(projects) do
71+
Enum.map(projects, fn project ->
72+
%{uri: project.root_uri, name: Project.name(project)}
73+
end)
74+
end
6875

6976
%{
7077
method: "initialize",
@@ -78,10 +85,7 @@ defmodule ExpertTest do
7885
workspaceFolders: true
7986
}
8087
},
81-
workspaceFolders:
82-
Enum.map(projects, fn project ->
83-
%{uri: project.root_uri, name: Project.name(project)}
84-
end)
88+
workspaceFolders: workspace_folders
8589
}
8690
}
8791
end
@@ -232,6 +236,31 @@ defmodule ExpertTest do
232236
assert [] = Expert.ActiveProjects.projects()
233237
assert_project_stopped?(main_project)
234238
end
239+
240+
test "supports missing workspace_folders in the request", %{
241+
client: client,
242+
project_root: project_root,
243+
main_project: main_project,
244+
secondary_project: secondary_project
245+
} do
246+
assert :ok =
247+
request(
248+
client,
249+
initialize_request(project_root, id: 1, projects: nil)
250+
)
251+
252+
assert_result(1, %{
253+
"capabilities" => %{"workspace" => %{"workspaceFolders" => %{"supported" => true}}}
254+
})
255+
256+
assert [_, _] = projects = Expert.ActiveProjects.projects()
257+
258+
for project <- projects do
259+
assert project.root_uri in [main_project.root_uri, secondary_project.root_uri]
260+
261+
assert_project_alive?(project)
262+
end
263+
end
235264
end
236265

237266
describe "opening files" do

0 commit comments

Comments
 (0)