Skip to content

Commit e3ff6ff

Browse files
authored
let ZLS handle requests out of order (#25)
1 parent 93ca7d6 commit e3ff6ff

File tree

1 file changed

+128
-72
lines changed

1 file changed

+128
-72
lines changed

src/Fuzzer.zig

Lines changed: 128 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,15 @@ pub fn fuzz(fuzzer: *Fuzzer) !void {
219219
fuzzer.cycle += 1;
220220

221221
if (fuzzer.cycle % fuzzer.config.cycles_per_gen == 0) {
222+
var arena_allocator = std.heap.ArenaAllocator.init(fuzzer.allocator);
223+
defer arena_allocator.deinit();
224+
const arena = arena_allocator.allocator();
225+
226+
while (fuzzer.connection.callback_map.count() != 0) {
227+
_ = arena_allocator.reset(.retain_capacity);
228+
try fuzzer.connection.acceptUntilResponse(arena);
229+
}
230+
222231
while (true) {
223232
fuzzer.allocator.free(fuzzer.principal_file_source);
224233
fuzzer.principal_file_source = try fuzzer.mode.gen(fuzzer.allocator);
@@ -320,124 +329,171 @@ pub const WhatToFuzz = enum {
320329
rename,
321330
};
322331

332+
fn requestCallback(comptime method: []const u8) lsp.RequestCallback(Connection, method) {
333+
const Context = struct {
334+
pub fn res(_: *Connection, _: lsp.Result(method)) !void {}
335+
336+
pub fn err(_: *Connection, resperr: lsp_types.ResponseError) !void {
337+
return switch (resperr.code) {
338+
@intFromEnum(lsp_types.ErrorCodes.ParseError) => error.ParseError,
339+
@intFromEnum(lsp_types.ErrorCodes.InvalidRequest) => error.InvalidRequest,
340+
@intFromEnum(lsp_types.ErrorCodes.MethodNotFound) => error.MethodNotFound,
341+
@intFromEnum(lsp_types.ErrorCodes.InvalidParams) => error.InvalidParams,
342+
@intFromEnum(lsp_types.ErrorCodes.InternalError) => error.InternalError,
343+
@intFromEnum(lsp_types.ErrorCodes.ServerNotInitialized) => error.ServerNotInitialized,
344+
@intFromEnum(lsp_types.ErrorCodes.UnknownErrorCode) => error.UnknownErrorCode,
345+
else => error.InternalError,
346+
};
347+
}
348+
};
349+
return .{
350+
.onResponse = &Context.res,
351+
.onError = &Context.err,
352+
};
353+
}
354+
323355
pub fn fuzzFeatureRandom(
324356
fuzzer: *Fuzzer,
325357
file_uri: []const u8,
326358
file_data: []const u8,
327359
) !void {
328-
var arena_allocator = std.heap.ArenaAllocator.init(fuzzer.allocator);
329-
defer arena_allocator.deinit();
330-
const arena = arena_allocator.allocator();
331-
332360
const rand = fuzzer.random();
333361
const wtf = rand.enumValue(WhatToFuzz);
334362

335363
switch (wtf) {
336-
.completion => {
337-
_ = try fuzzer.connection.requestSync(arena, "textDocument/completion", .{
364+
.completion => try fuzzer.connection.request(
365+
"textDocument/completion",
366+
.{
338367
.textDocument = .{ .uri = file_uri },
339368
.position = utils.randomPosition(rand, file_data),
340-
});
341-
},
342-
.declaration => {
343-
_ = try fuzzer.connection.requestSync(arena, "textDocument/declaration", .{
369+
},
370+
requestCallback("textDocument/completion"),
371+
),
372+
.declaration => try fuzzer.connection.request(
373+
"textDocument/declaration",
374+
.{
344375
.textDocument = .{ .uri = file_uri },
345376
.position = utils.randomPosition(rand, file_data),
346-
});
347-
},
348-
.definition => {
349-
_ = try fuzzer.connection.requestSync(arena, "textDocument/definition", .{
377+
},
378+
requestCallback("textDocument/declaration"),
379+
),
380+
.definition => try fuzzer.connection.request(
381+
"textDocument/definition",
382+
.{
350383
.textDocument = .{ .uri = file_uri },
351384
.position = utils.randomPosition(rand, file_data),
352-
});
353-
},
354-
.type_definition => {
355-
_ = try fuzzer.connection.requestSync(arena, "textDocument/typeDefinition", .{
385+
},
386+
requestCallback("textDocument/definition"),
387+
),
388+
.type_definition => try fuzzer.connection.request(
389+
"textDocument/typeDefinition",
390+
.{
356391
.textDocument = .{ .uri = file_uri },
357392
.position = utils.randomPosition(rand, file_data),
358-
});
359-
},
360-
.implementation => {
361-
_ = try fuzzer.connection.requestSync(arena, "textDocument/implementation", .{
393+
},
394+
requestCallback("textDocument/typeDefinition"),
395+
),
396+
.implementation => try fuzzer.connection.request(
397+
"textDocument/implementation",
398+
.{
362399
.textDocument = .{ .uri = file_uri },
363400
.position = utils.randomPosition(rand, file_data),
364-
});
365-
},
366-
.references => {
367-
_ = try fuzzer.connection.requestSync(arena, "textDocument/references", .{
368-
.context = .{
369-
.includeDeclaration = rand.boolean(),
370-
},
401+
},
402+
requestCallback("textDocument/implementation"),
403+
),
404+
.references => try fuzzer.connection.request(
405+
"textDocument/references",
406+
.{
407+
.context = .{ .includeDeclaration = rand.boolean() },
371408
.textDocument = .{ .uri = file_uri },
372409
.position = utils.randomPosition(rand, file_data),
373-
});
374-
},
375-
.signature_help => {
376-
_ = try fuzzer.connection.requestSync(arena, "textDocument/signatureHelp", .{
410+
},
411+
requestCallback("textDocument/references"),
412+
),
413+
.signature_help => try fuzzer.connection.request(
414+
"textDocument/signatureHelp",
415+
.{
377416
.textDocument = .{ .uri = file_uri },
378417
.position = utils.randomPosition(rand, file_data),
379-
});
380-
},
381-
.hover => {
382-
_ = try fuzzer.connection.requestSync(arena, "textDocument/hover", .{
418+
},
419+
requestCallback("textDocument/signatureHelp"),
420+
),
421+
.hover => try fuzzer.connection.request(
422+
"textDocument/hover",
423+
.{
383424
.textDocument = .{ .uri = file_uri },
384425
.position = utils.randomPosition(rand, file_data),
385-
});
386-
},
387-
.semantic => {
388-
_ = try fuzzer.connection.requestSync(arena, "textDocument/semanticTokens/full", .{
389-
.textDocument = .{ .uri = file_uri },
390-
});
391-
},
392-
.document_symbol => {
393-
_ = try fuzzer.connection.requestSync(arena, "textDocument/documentSymbol", .{
394-
.textDocument = .{ .uri = file_uri },
395-
});
396-
},
426+
},
427+
requestCallback("textDocument/hover"),
428+
),
429+
.semantic => try fuzzer.connection.request(
430+
"textDocument/semanticTokens/full",
431+
.{ .textDocument = .{ .uri = file_uri } },
432+
requestCallback("textDocument/semanticTokens/full"),
433+
),
434+
.document_symbol => try fuzzer.connection.request(
435+
"textDocument/documentSymbol",
436+
.{ .textDocument = .{ .uri = file_uri } },
437+
requestCallback("textDocument/documentSymbol"),
438+
),
397439
.folding_range => {
398-
_ = try fuzzer.connection.requestSync(arena, "textDocument/foldingRange", .{
399-
.textDocument = .{ .uri = file_uri },
400-
});
440+
_ = try fuzzer.connection.request(
441+
"textDocument/foldingRange",
442+
.{ .textDocument = .{ .uri = file_uri } },
443+
requestCallback("textDocument/foldingRange"),
444+
);
401445
},
402-
.formatting => {
403-
_ = try fuzzer.connection.requestSync(arena, "textDocument/formatting", .{
446+
.formatting => try fuzzer.connection.request(
447+
"textDocument/formatting",
448+
.{
404449
.textDocument = .{ .uri = file_uri },
405450
.options = .{
406451
.tabSize = 4,
407452
.insertSpaces = true,
408453
},
409-
});
410-
},
411-
.document_highlight => {
412-
_ = try fuzzer.connection.requestSync(arena, "textDocument/documentHighlight", .{
454+
},
455+
requestCallback("textDocument/formatting"),
456+
),
457+
.document_highlight => try fuzzer.connection.request(
458+
"textDocument/documentHighlight",
459+
.{
413460
.textDocument = .{ .uri = file_uri },
414461
.position = utils.randomPosition(rand, file_data),
415-
});
416-
},
417-
.inlay_hint => {
418-
_ = try fuzzer.connection.requestSync(arena, "textDocument/inlayHint", .{
462+
},
463+
requestCallback("textDocument/documentHighlight"),
464+
),
465+
.inlay_hint => try fuzzer.connection.request(
466+
"textDocument/inlayHint",
467+
.{
419468
.textDocument = .{ .uri = file_uri },
420469
.range = utils.randomRange(rand, file_data),
421-
});
422-
},
470+
},
471+
requestCallback("textDocument/inlayHint"),
472+
),
423473
// TODO: Nest positions properly to avoid crash
424474
// .selection_range => {
425475
// var positions: [16]lsp_types.Position = undefined;
426476
// for (positions) |*pos| {
427477
// pos.* = utils.randomPosition(rand, file_data);
428478
// }
429-
// _ = try fuzzer.connection.requestSync(arena, "textDocument/selectionRange", .{
430-
// .textDocument = .{ .uri = file_uri, },
431-
// .positions = &positions,
432-
// });
479+
// try fuzzer.connection.request(
480+
// "textDocument/selectionRange",
481+
// .{
482+
// .textDocument = .{ .uri = file_uri },
483+
// .positions = &positions,
484+
// },
485+
// requestCallback("textDocument/selectionRange"),
486+
// );
433487
// },
434-
.rename => {
435-
_ = try fuzzer.connection.requestSync(arena, "textDocument/rename", .{
488+
.rename => try fuzzer.connection.request(
489+
"textDocument/rename",
490+
.{
436491
.textDocument = .{ .uri = file_uri },
437492
.position = utils.randomPosition(rand, file_data),
438493
.newName = "helloWorld",
439-
});
440-
},
494+
},
495+
requestCallback("textDocument/rename"),
496+
),
441497
}
442498
}
443499

0 commit comments

Comments
 (0)