Skip to content

Commit 8eefb7c

Browse files
authored
fix(extension/#3685): Fix nim activation error (#3709)
__Issue:__ The nim extension #3685 was failing to activate. __Defect:__ The extension is expecting the storage folder to be created, but this is failing. The folder should be created by the extension host here: https://github.com/microsoft/vscode/blob/fc0ee4e4bc28d8efe5d576827d3bacdd919f3e7f/src/vs/workbench/api/common/extHostStoragePaths.ts#L60 - however, the `$stat` result is not throwing an exception, as expected by that code. __Fix:__ When a file/folder is not available via `$stat`, send the response as an error, so it properly bubbles up to extensions as an extension. Fixes #3685
1 parent 8bc95f2 commit 8eefb7c

File tree

12 files changed

+118
-6
lines changed

12 files changed

+118
-6
lines changed

CHANGES_CURRENT.md

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
- #3692 - CodeLens: Fix delegated commands not executing (related #2380)
2929
- #3702 - OSX: Fix crash on open-with (fixes #3698)
3030
- #3703 - Sidebar: Fix window navigation to sidebar when closed or zen mode (related #3681)
31+
- #3709 - Extension: Fix activation error with nim extension (fixes #3685)
3132

3233
### Performance
3334

development_extensions/oni-test-extension/extension.js

+18
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,24 @@ function activate(context) {
4141
})();
4242
}),
4343
);
44+
45+
cleanup(
46+
vscode.commands.registerCommand("oni-test.exthost.runFileSystemTests", () => {
47+
48+
(async () => {
49+
// From docs: https://code.visualstudio.com/api/references/vscode-api#ExtensionContext
50+
// Given path might not exist - but parent directory will exist.
51+
const nonExistentPath = path.join(context.storagePath, "some-non-existent-path");
52+
const nonExistentUri = vscode.Uri.file(nonExistentPath);
53+
try {
54+
await vscode.workspace.fs.stat(nonExistentUri);
55+
fail("#3685: Non-existent path should not have successful stat")
56+
} catch (exn) {
57+
pass()
58+
}
59+
})();
60+
})
61+
);
4462
}
4563

4664
// this method is called when your extension is deactivated

development_extensions/oni-test-extension/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
},
99
"activationEvents": [
1010
"onCommand:oni-test.showMessage",
11-
"onCommand:oni-test.exthost.validateLogPathIsDirectory"
11+
"onCommand:oni-test.exthost.validateLogPathIsDirectory",
12+
"onCommand:oni-test.exthost.runFileSystemTests"
1213
],
1314
"main": "./extension.js",
1415
"contributes": {},
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
open Oni_Model;
2+
open Oni_IntegrationTestLib;
3+
4+
// This test validates:
5+
// - The 'oni-dev' extension gets activated
6+
// - When typing in an 'oni-dev' buffer, we get some completion results
7+
runTest(~name="ExtHostContextTest", ({dispatch, wait, _}) => {
8+
wait(~timeout=30.0, ~name="Exthost is initialized", (state: State.t) =>
9+
Feature_Exthost.isInitialized(state.exthost)
10+
);
11+
12+
// Wait until the extension is activated
13+
// Give some time for the exthost to start
14+
wait(
15+
~timeout=30.0,
16+
~name="Validate the 'oni-dev' extension gets activated",
17+
(state: State.t) =>
18+
List.exists(
19+
id => id == "oni-dev-extension",
20+
state.extensions |> Feature_Extensions.activatedIds,
21+
)
22+
);
23+
24+
// Kick off an oni-test command that should activate the oni-test-extension:
25+
dispatch(
26+
Actions.Extensions(
27+
Feature_Extensions.Msg.command(
28+
~command="oni-test.exthost.runFileSystemTests",
29+
~arguments=[],
30+
),
31+
),
32+
);
33+
34+
// Validate test passes
35+
wait(
36+
~timeout=30.0,
37+
~name="Validate test passes",
38+
(state: State.t) => {
39+
let notifications = Feature_Notification.all(state.notifications);
40+
notifications
41+
|> List.exists((notification: Feature_Notification.notification) => {
42+
notification.message == "PASS"
43+
});
44+
},
45+
);
46+
});

integration_test/dune

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
ExCommandKeybindingNormTest ExtConfigurationChangedTest ExtHostContextTest
1010
ExtHostBufferOpenTest ExtHostBufferUpdatesTest
1111
ExtHostCommandActivationTest ExtHostCompletionTest ExtHostDefinitionTest
12+
ExtHostFileSystemTest
1213
ExtHostFormatSingleEditTest ExtHostFormatFullEditTest
1314
ExtHostWorkspaceSearchTest FileWatcherTest FormatOnSaveTest
1415
KeybindingsInvalidJsonTest KeySequenceJJTest InputIgnoreTest
@@ -47,6 +48,7 @@
4748
ExtConfigurationChangedTest.exe ExtHostBufferOpenTest.exe
4849
ExtHostBufferUpdatesTest.exe ExtHostCommandActivationTest.exe
4950
ExtHostContextTest.exe ExtHostCompletionTest.exe ExtHostDefinitionTest.exe
51+
ExtHostFileSystemTest.exe
5052
ExtHostWorkspaceSearchTest.exe FileWatcherTest.exe FormatOnSaveTest.exe
5153
KeybindingsInvalidJsonTest.exe KeySequenceJJTest.exe InputIgnoreTest.exe
5254
InputContextKeysTest.exe InputRemapMotionTest.exe LanguageCssTest.exe

src/Exthost/Client.re

+10
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,16 @@ let start =
152152
)
153153
);
154154
send(Outgoing.ReplyError({requestId, error: message}));
155+
156+
| ErrorJson({error}) =>
157+
Log.tracef(m =>
158+
m(
159+
"Responding to request %d with error: %s",
160+
requestId,
161+
error |> Yojson.Safe.to_string,
162+
)
163+
);
164+
send(Outgoing.ReplyErrorJSON({requestId, error}));
155165
};
156166
};
157167

src/Exthost/Exthost.rei

+2
Original file line numberDiff line numberDiff line change
@@ -1890,6 +1890,8 @@ module Reply: {
18901890

18911891
let error: string => t;
18921892

1893+
let errorJson: Yojson.Safe.t => t;
1894+
18931895
let okEmpty: t;
18941896

18951897
let okJson: Yojson.Safe.t => t;

src/Exthost/Protocol/Exthost_Protocol.re

+10
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ module Message = {
157157
requestId: int,
158158
error: string,
159159
})
160+
| ReplyErrorJSON({
161+
requestId: int,
162+
error: Yojson.Safe.t,
163+
})
160164
| Terminate;
161165
};
162166

@@ -262,6 +266,7 @@ module Message = {
262266
| ReplyOKJSON({requestId, _}) => requestId
263267
| ReplyOKBuffer({requestId, _}) => requestId
264268
| ReplyError({requestId, _}) => requestId
269+
| ReplyErrorJSON({requestId, _}) => requestId
265270
| Terminate => Int.max_int;
266271
let requestId = getRequestId(msg) |> Int32.of_int;
267272

@@ -325,6 +330,11 @@ module Message = {
325330
writePreamble(~buffer, ~msgType=replyErrError, ~requestId);
326331
writeLongString(buffer, "\"" ++ error ++ "\"");
327332
bufferToPacket(~buffer);
333+
| ReplyErrorJSON({error, _}) =>
334+
writePreamble(~buffer, ~msgType=replyErrError, ~requestId);
335+
let err = error |> Yojson.Safe.to_string;
336+
writeLongString(buffer, err);
337+
bufferToPacket(~buffer);
328338
};
329339
};
330340
};

src/Exthost/Protocol/Exthost_Protocol.rei

+4
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ module Message: {
7272
requestId: int,
7373
error: string,
7474
})
75+
| ReplyErrorJSON({
76+
requestId: int,
77+
error: Yojson.Safe.t,
78+
})
7579
| Terminate;
7680
};
7781

src/Exthost/Reply.re

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ type t =
33
| OkEmpty
44
| OkBuffer({bytes: Bytes.t})
55
| OkJson({json: Yojson.Safe.t})
6+
| ErrorJson({error: Yojson.Safe.t})
67
| ErrorMessage({message: string});
78

89
let none = Nothing;
@@ -11,6 +12,8 @@ let okEmpty = OkEmpty;
1112

1213
let error = message => ErrorMessage({message: message});
1314

15+
let errorJson = json => ErrorJson({error: json});
16+
1417
let okBuffer = bytes => OkBuffer({bytes: bytes});
1518
let okJson = json => OkJson({json: json});
1619

@@ -22,4 +25,6 @@ let toDebugString =
2225
Printf.sprintf("OkBuffer(%s)", Bytes.to_string(bytes))
2326
| OkJson({json}) =>
2427
Printf.sprintf("OkJson(%s)", Yojson.Safe.to_string(json))
28+
| ErrorJson({error}) =>
29+
Printf.sprintf("ErrorMessage(%s)", Yojson.Safe.to_string(error))
2530
| ErrorMessage({message}) => Printf.sprintf("ErrorMessage(%s)", message);

src/Feature/FileSystem/Feature_FileSystem.re

+8-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ module Internal = {
88
v |> Json.Encode.encode_value(encoder) |> Reply.okJson;
99
};
1010

11+
let mapEncoderError = (encoder, v) => {
12+
v |> Json.Encode.encode_value(encoder) |> Reply.errorJson;
13+
};
14+
1115
let fileTypeFromStat: Luv.File.Stat.t => Files.FileType.t =
1216
(statResult: Luv.File.Stat.t) => {
1317
Luv.File.(
@@ -103,7 +107,7 @@ let update = (msg, model) => {
103107
Exthost.Files.FileSystemError.(
104108
make(Code.fileNotFound)
105109
|> Lwt.return
106-
|> Lwt.map(Internal.mapEncoder(encode))
110+
|> Lwt.map(Internal.mapEncoderError(encode))
107111
)
108112
},
109113
);
@@ -128,7 +132,7 @@ let update = (msg, model) => {
128132
Exthost.Files.FileSystemError.(
129133
make(Code.fileNotFound)
130134
|> Lwt.return
131-
|> Lwt.map(Internal.mapEncoder(encode))
135+
|> Lwt.map(Internal.mapEncoderError(encode))
132136
)
133137
},
134138
);
@@ -148,7 +152,7 @@ let update = (msg, model) => {
148152
Exthost.Files.FileSystemError.(
149153
make(Code.fileNotFound)
150154
|> Lwt.return
151-
|> Lwt.map(Internal.mapEncoder(encode))
155+
|> Lwt.map(Internal.mapEncoderError(encode))
152156
)
153157
},
154158
);
@@ -196,7 +200,7 @@ let update = (msg, model) => {
196200
Exthost.Files.FileSystemError.(
197201
make(Code.fileNotFound)
198202
|> Lwt.return
199-
|> Lwt.map(Internal.mapEncoder(encode))
203+
|> Lwt.map(Internal.mapEncoderError(encode))
200204
)
201205
},
202206
);

test/Exthost/FileSystemTest.re

+10-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,16 @@ describe("FileSystem", ({describe, _}) => {
7070

7171
let failHandler =
7272
fun
73-
| Msg.FileSystem(Stat(_)) => Lwt.fail_with("Error!")
73+
| Msg.FileSystem(Stat(_)) => {
74+
let err = Exthost.Files.FileSystemError.(make(Code.fileNotFound));
75+
Lwt.return(
76+
err
77+
|> Oni_Core.Json.Encode.encode_value(
78+
Exthost.Files.FileSystemError.encode,
79+
)
80+
|> Reply.errorJson,
81+
);
82+
}
7483
| _ => Lwt.return(Reply.okEmpty);
7584

7685
test("success case", _ => {

0 commit comments

Comments
 (0)