Skip to content

Commit

Permalink
Allow to restrict looking for the mix.exs in the current workspace ro…
Browse files Browse the repository at this point in the history
…ot only, closes #424 (#425)

Co-authored-by: Łukasz Samson <[email protected]>
  • Loading branch information
vheathen and lukaszsamson committed Aug 3, 2024
1 parent 91a0602 commit fc90e3c
Show file tree
Hide file tree
Showing 14 changed files with 186 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
### Unreleased

#### Improvements

- It is possible to restrict `mix.exs` search (projectDir) to the current root folder only, so in multi-root workspace configurations ElixirLS won't start in the outermost containing the `mix.exs` folder

### v0.22.1: 10 July 2024

#### Improvements
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ If you run into issues with the extension, try these debugging steps:
- After stopping your editor, remove the entire `.elixir_ls` directory, then restart your editor.
- NOTE: This will cause you to have to re-run the entire dialyzer build

You may need to set `elixirLS.mixEnv`, `elixirLS.mixTarget`, and `elixirLS.projectDir` if your project requires it. By default, ElixirLS compiles code with `MIX_ENV=test`, `MIX_TARGET=host`, and assumes that `mix.exs` is located in the workspace root directory.
You may need to set `elixirLS.mixEnv`, `elixirLS.mixTarget`, `elixirLS.projectDir` and/or `elixirLS.useCurrentRootFolderAsProjectDir` if your project requires it. By default, ElixirLS compiles code with `MIX_ENV=test`, `MIX_TARGET=host`, and assumes that `mix.exs` is located in the workspace root directory.

If you get an error like the following immediately on startup:

Expand Down
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@
"minLength": 0,
"default": ""
},
"elixirLS.useCurrentRootFolderAsProjectDir": {
"scope": "resource",
"type": "boolean",
"description": "Don't try to look for mix.exs in parent directories",
"default": false
},
"elixirLS.fetchDeps": {
"scope": "resource",
"type": "boolean",
Expand Down Expand Up @@ -682,4 +688,4 @@
"@vscode/extension-telemetry": "^0.9.0",
"vscode-languageclient": "^9.0.0"
}
}
}
9 changes: 8 additions & 1 deletion src/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,16 @@ export class WorkspaceTracker {
uri = uri + "/";
}

const useCurrentRootFolderAsProjectDir = vscode.workspace
.getConfiguration("elixirLS", folder)
.get<boolean>("useCurrentRootFolderAsProjectDir");


let outermostFolder: vscode.WorkspaceFolder | null = null;

for (const element of this.sortedWorkspaceFolders()) {
const sortedWorkspaceFolders = useCurrentRootFolderAsProjectDir ? [uri] : this.sortedWorkspaceFolders();

for (const element of sortedWorkspaceFolders) {
if (uri.startsWith(element)) {
const foundFolder = vscode.workspace.getWorkspaceFolder(
vscode.Uri.parse(element)
Expand Down
28 changes: 28 additions & 0 deletions src/test-fixtures/containing_folder_with_mix/mix.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
defmodule SingleFolderMix.MixProject do
use Mix.Project

def project do
[
app: :containing_folder_with_mix,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end

# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end

# Run "mix help deps" to learn about dependencies.
defp deps do
[
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where third-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore package tarball (built via "mix hex.build").
single_folder_mix-*.tar

# Temporary files, for example, from tests.
/tmp/
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# SingleFolderMix

**TODO: Add description**

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `single_folder_mix` to your list of dependencies in `mix.exs`:

```elixir
def deps do
[
{:single_folder_mix, "~> 0.1.0"}
]
end
```

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/single_folder_mix>.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule SingleFolderMix do
@moduledoc """
Documentation for `SingleFolderMix`.
"""

@doc """
Hello world.
## Examples
iex> SingleFolderMix.hello()
:world
"""
def hello do
:world
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
defmodule SingleFolderMix.MixProject do
use Mix.Project

def project do
[
app: :single_folder_mix,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end

# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end

# Run "mix help deps" to learn about dependencies.
defp deps do
[
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
defmodule SingleFolderMixTest do
use ExUnit.Case
doctest SingleFolderMix

test "greets the world" do
assert SingleFolderMix.hello() == :world
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ExUnit.start()
32 changes: 32 additions & 0 deletions src/test/multiRoot/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,36 @@ suite("Multi root workspace tests", () => {
)
);
}).timeout(30000);

test("extension starts first client on the same folder with mix.exs if useCurrentRootFolderAsProjectDir is true", async () => {
vscode.workspace.getConfiguration("elixirLS").update("useCurrentRootFolderAsProjectDir", true, vscode.ConfigurationTarget.WorkspaceFolder);

const fileUri = vscode.Uri.file(
path.join(
fixturesPath,
"containing_folder",
"single_folder_mix",
"mix.exs"
)
);

const workspaceFolderUri = vscode.Uri.file(
path.join(fixturesPath, "containing_folder", "single_folder_mix")
);

await waitForLanguageClientManagerUpdate(extension, async () => {
const document = await vscode.workspace.openTextDocument(fileUri);
await vscode.window.showTextDocument(document);
});

assert.ok(!extension.exports.languageClientManager.defaultClient);
assert.equal(extension.exports.languageClientManager.clients.size, 3);

assert.equal(
extension.exports.languageClientManager.getClientByUri(fileUri),
extension.exports.languageClientManager.clients.get(
workspaceFolderUri.toString()
)
);
}).timeout(30000);
});
1 change: 1 addition & 0 deletions telemetry.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
},
"lsp_config": {
"elixir_ls.projectDir": {"classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Is project dir overriden"},
"elixir_ls.useCurrentRootFolderAsProjectDir": {"classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Is project dir set to the current root in multi-root workspace"},
"elixir_ls.autoBuild": {"classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Is auto build enabled"},
"elixir_ls.dialyzerEnabled": {"classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Is dialyzer enabled"},
"elixir_ls.fetchDeps": {"classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Is auto fetching of dependencies enabled"},
Expand Down

0 comments on commit fc90e3c

Please sign in to comment.