Skip to content

Commit 39b5b3b

Browse files
authored
fix: be more resilient to invalid config files (#273)
1 parent 5202de5 commit 39b5b3b

23 files changed

Lines changed: 1130 additions & 38 deletions

.vscode-test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,25 @@ module.exports = defineConfig([
5959
timeout: 60_000,
6060
},
6161
},
62+
{
63+
label: "broken-config",
64+
files: "src/e2e-tests/broken-config/*.e2e.ts",
65+
workspaceFolder: path.join(fixturesPath, "broken-config-workspace"),
66+
env: {
67+
MISE_CEILING_PATHS: fixturesPath,
68+
MISE_LOCKED: "0",
69+
MISE_TRUSTED_CONFIG_PATHS: fixturesPath,
70+
MISE_GLOBAL_CONFIG_FILE: path.join(
71+
fixturesPath,
72+
"broken-config-workspace",
73+
"global-config.toml",
74+
),
75+
},
76+
mocha: {
77+
require: ["tsx/cjs"],
78+
timeout: 60_000,
79+
},
80+
},
6281
{
6382
label: "command-injection",
6483
files: "src/e2e-tests/command-injection/*.e2e.ts",

docs/src/content/docs/reference/Environment-variables.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ variable to find where it's defined.
1212

1313
![env-list.png](../../../assets/env-1.png)
1414

15+
While a config file does not parse, the list keeps showing the previous
16+
values. See [While a config file is being edited](/mise-vscode/reference/misetoml-language-support/#while-a-config-file-is-being-edited).
17+
1518
## Loading environment variables
1619

1720
`mise-vscode` will automatically load all the environment variables provided by

docs/src/content/docs/reference/Tasks.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ Click on a task to navigate to the file where the task is defined.
2020
Using the command palette: `cmd|ctrl+shift+p` and search for
2121
`Mise: Open task definition`.
2222

23+
While a config file does not parse, the task list and the code lens actions
24+
keep showing the previous tasks. See [While a config file is being edited](/mise-vscode/reference/misetoml-language-support/#while-a-config-file-is-being-edited).
25+
2326
## Running a task
2427

2528
You have several ways to run a task with the extension:

docs/src/content/docs/reference/Tools.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ in the current project. You can also the list of global tools.
2323

2424
![img.png](../../../assets/tools-activity-bar.png)
2525

26+
A config file that does not parse is marked in the explorer. Its tools are the
27+
ones from the last time the file parsed. See [While a config file is being edited](/mise-vscode/reference/misetoml-language-support/#while-a-config-file-is-being-edited).
28+
2629
## Tools list
2730

2831
Use the list `List all tools` button to list all installed tools.

docs/src/content/docs/reference/mise.toml-language-support.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,31 @@ If you are using [multi-lines task script](https://mise.jdx.dev/tasks/toml-tasks
137137
The following languages are supported: Python, Node.js, Deno, Bun, Deno, Ruby, Bash, and Shell.
138138

139139
![screenshot showing syntax highlighting support when shebang is used](./syntax-highlighting-shebang.png)
140+
141+
### While a config file is being edited
142+
143+
With auto save enabled, a config file is written while you are still typing it.
144+
mise cannot read a file that does not parse, so every command fails until it
145+
does.
146+
147+
Instead of clearing the panels, the extension keeps showing the last state it
148+
could read. The status bar shows a warning while this is the case, and config
149+
files that do not parse are marked in the activity bar.
150+
151+
If a command never succeeded, its error is shown as usual. Opening a project
152+
with a config file that is already broken shows errors.
153+
154+
Running or watching a task is refused while a config file does not parse. You
155+
get a message pointing at the file, instead of a mise error about a task that
156+
does not exist.
157+
158+
The kept state is dropped when:
159+
160+
- the file parses again
161+
- you save it yourself with `Cmd`/`Ctrl`+`S`
162+
- you reload the configuration from the activity bar, the status bar or the
163+
command palette
164+
165+
Reloads the extension does on its own, for example after running a task, do not
166+
drop it. There is no timeout: the state is kept for as long as the file does not
167+
parse.

package.json

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@
617617
"viewsWelcome": [
618618
{
619619
"view": "miseTasksView",
620-
"contents": "[Tasks](https://mise.jdx.dev/tasks/) will be displayed here. ([refresh](command:mise.refreshEntry))\n[Add task](command:mise.createTomlTask)",
620+
"contents": "[Tasks](https://mise.jdx.dev/tasks/) will be displayed here. ([refresh](command:mise.reloadConfiguration))\n[Add task](command:mise.createTomlTask)",
621621
"when": "config.mise.binPath && config.mise.enable && !mise.tasksProviderError"
622622
},
623623
{
@@ -627,7 +627,7 @@
627627
},
628628
{
629629
"view": "miseTasksView",
630-
"contents": "[Install mise](https://mise.jdx.dev/getting-started.html) to get started.\nOnce mise is installed, click reload.\n[Reload](command:mise.refreshEntry)\n[Configure](command:mise.openExtensionSettings)",
630+
"contents": "[Install mise](https://mise.jdx.dev/getting-started.html) to get started.\nOnce mise is installed, click reload.\n[Reload](command:mise.reloadConfiguration)\n[Configure](command:mise.openExtensionSettings)",
631631
"when": "!config.mise.binPath"
632632
},
633633
{
@@ -709,6 +709,11 @@
709709
"commands": [
710710
{
711711
"command": "mise.refreshEntry",
712+
"title": "Mise: Reload configuration (internal)",
713+
"enablement": "!isWeb"
714+
},
715+
{
716+
"command": "mise.reloadConfiguration",
712717
"title": "Mise: Reload configuration",
713718
"icon": "$(refresh)",
714719
"enablement": "!isWeb"
@@ -999,6 +1004,10 @@
9991004
],
10001005
"menus": {
10011006
"commandPalette": [
1007+
{
1008+
"command": "mise.refreshEntry",
1009+
"when": "false"
1010+
},
10021011
{
10031012
"command": "mise.showTaskCacheMenu",
10041013
"when": "false"
@@ -1111,7 +1120,7 @@
11111120
"group": "navigation@3"
11121121
},
11131122
{
1114-
"command": "mise.refreshEntry",
1123+
"command": "mise.reloadConfiguration",
11151124
"when": "view == miseTasksView || view == miseToolsView || view == miseEnvsView || view == miseBootstrapView",
11161125
"group": "navigation@4"
11171126
}

src/commands.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ export const MISE_OPEN_EXTENSION_SETTINGS = "mise.openExtensionSettings";
3030
export const MISE_OPEN_TASK_DEFINITION = "mise.openTaskDefinition";
3131
export const MISE_OPEN_TOOL_DEFINITION = "mise.openToolDefinition";
3232
export const MISE_RELOAD = "mise.refreshEntry";
33+
/**
34+
* The reload the user asks for, from the sidebar, the status bar or the palette.
35+
* `MISE_RELOAD` is also fired internally after tasks, settings and workspace
36+
* changes, so only this one drops the state kept while a config does not parse.
37+
*/
38+
export const MISE_RELOAD_FROM_USER = "mise.reloadConfiguration";
3339
export const MISE_REMOVE_TOOL = "mise.removeTool";
3440
export const MISE_OPEN_BOOTSTRAP_ENTRY_DEFINITION =
3541
"mise.openBootstrapEntryDefinition";

src/e2e-tests/bootstrap/bootstrap.e2e.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ suite("Bootstrap Test Suite", function () {
7676
"mise.runBootstrapDryRun",
7777
"mise.runBootstrapPlan",
7878
"mise.showBootstrap",
79+
"mise.reloadConfiguration",
80+
"mise.refreshEntry",
7981
"mise.openBootstrapEntryDefinition",
8082
]) {
8183
assert.ok(

0 commit comments

Comments
 (0)