2022-08-26 15:53:44 +01:00
|
|
|
const std = @import("std");
|
|
|
|
const zls = @import("zls");
|
|
|
|
|
|
|
|
const Ast = std.zig.Ast;
|
|
|
|
|
2023-02-21 22:11:35 +00:00
|
|
|
const offsets = zls.offsets;
|
2022-08-26 15:53:44 +01:00
|
|
|
const translate_c = zls.translate_c;
|
|
|
|
|
|
|
|
const allocator: std.mem.Allocator = std.testing.allocator;
|
|
|
|
|
2023-05-30 00:59:46 +01:00
|
|
|
test "zig compile server - translate c" {
|
2023-06-23 16:47:54 +01:00
|
|
|
// FIXME: Disabled due to https://github.com/zigtools/zls/issues/1252
|
|
|
|
if (@import("builtin").os.tag == .windows) return error.SkipZigTest;
|
|
|
|
|
2023-05-30 00:59:46 +01:00
|
|
|
var result1 = try testTranslate(
|
|
|
|
\\void foo(int);
|
|
|
|
\\void bar(float*);
|
|
|
|
);
|
|
|
|
defer result1.deinit(allocator);
|
|
|
|
try std.testing.expect(result1 == .success);
|
|
|
|
|
|
|
|
// TODO the zig compiler doesn't seem to report error bundles for translate-c
|
|
|
|
// Hopefully I can fix that once llvm-16 finished compiling :)
|
|
|
|
|
|
|
|
var result2 = testTranslate(
|
|
|
|
\\#include <this_file_doesnt_exist>
|
|
|
|
);
|
|
|
|
defer if (result2) |*r| r.deinit(allocator) else |_| {};
|
|
|
|
try std.testing.expectError(error.Timeout, result2);
|
|
|
|
}
|
|
|
|
|
2022-08-26 15:53:44 +01:00
|
|
|
test "convertCInclude - empty" {
|
|
|
|
try testConvertCInclude("@cImport()", "");
|
|
|
|
try testConvertCInclude("@cImport({})", "");
|
|
|
|
try testConvertCInclude("@cImport({{}, {}})", "");
|
|
|
|
}
|
|
|
|
|
|
|
|
test "convertCInclude - cInclude" {
|
|
|
|
try testConvertCInclude(
|
|
|
|
\\@cImport(@cInclude("foo.zig"))
|
|
|
|
,
|
|
|
|
\\#include <foo.zig>
|
|
|
|
);
|
|
|
|
|
|
|
|
try testConvertCInclude(
|
|
|
|
\\@cImport(@cInclude("foo.zig"), @cInclude("bar.zig"))
|
|
|
|
,
|
|
|
|
\\#include <foo.zig>
|
|
|
|
\\#include <bar.zig>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-05-30 00:59:46 +01:00
|
|
|
test "convertCInclude - cDefine" {
|
2022-08-26 15:53:44 +01:00
|
|
|
try testConvertCInclude(
|
|
|
|
\\@cImport(@cDefine("FOO", "BAR"))
|
|
|
|
,
|
|
|
|
\\#define FOO BAR
|
|
|
|
);
|
|
|
|
try testConvertCInclude(
|
|
|
|
\\@cImport(@cDefine("FOO", {}))
|
|
|
|
,
|
|
|
|
\\#define FOO
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-05-30 00:59:46 +01:00
|
|
|
test "convertCInclude - cUndef" {
|
2022-08-26 15:53:44 +01:00
|
|
|
try testConvertCInclude(
|
|
|
|
\\@cImport(@cUndef("FOO"))
|
|
|
|
,
|
|
|
|
\\#undef FOO
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn testConvertCInclude(cimport_source: []const u8, expected: []const u8) !void {
|
|
|
|
const source: [:0]u8 = try std.fmt.allocPrintZ(allocator, "const c = {s};", .{cimport_source});
|
|
|
|
defer allocator.free(source);
|
|
|
|
|
2023-02-21 22:11:35 +00:00
|
|
|
var tree = try Ast.parse(allocator, source, .zig);
|
|
|
|
defer tree.deinit(allocator);
|
2022-08-26 15:53:44 +01:00
|
|
|
|
2023-02-21 22:11:35 +00:00
|
|
|
const node_tags = tree.nodes.items(.tag);
|
|
|
|
const main_tokens = tree.nodes.items(.main_token);
|
2022-08-26 15:53:44 +01:00
|
|
|
|
|
|
|
const node: Ast.Node.Index = blk: {
|
2023-02-21 22:11:35 +00:00
|
|
|
for (node_tags, main_tokens, 0..) |tag, token, i| {
|
2022-08-26 15:53:44 +01:00
|
|
|
switch (tag) {
|
|
|
|
.builtin_call_two,
|
|
|
|
.builtin_call_two_comma,
|
|
|
|
.builtin_call,
|
|
|
|
.builtin_call_comma,
|
|
|
|
=> {},
|
|
|
|
else => continue,
|
|
|
|
}
|
2022-12-27 06:47:57 +00:00
|
|
|
|
2023-02-21 22:11:35 +00:00
|
|
|
if (!std.mem.eql(u8, offsets.tokenToSlice(tree, token), "@cImport")) continue;
|
2022-08-26 15:53:44 +01:00
|
|
|
|
2023-02-21 22:11:35 +00:00
|
|
|
break :blk @intCast(Ast.Node.Index, i);
|
2022-08-26 15:53:44 +01:00
|
|
|
}
|
|
|
|
return error.TestUnexpectedResult; // source doesn't contain a cImport
|
|
|
|
};
|
|
|
|
|
2023-02-21 22:11:35 +00:00
|
|
|
const output = try translate_c.convertCInclude(allocator, tree, node);
|
2022-08-26 15:53:44 +01:00
|
|
|
defer allocator.free(output);
|
|
|
|
|
|
|
|
const trimmed_output = std.mem.trimRight(u8, output, &.{'\n'});
|
|
|
|
|
|
|
|
try std.testing.expectEqualStrings(expected, trimmed_output);
|
|
|
|
}
|
2023-05-30 00:59:46 +01:00
|
|
|
|
|
|
|
fn testTranslate(c_source: []const u8) !translate_c.Result {
|
|
|
|
if (!std.process.can_spawn) return error.SkipZigTest;
|
|
|
|
|
|
|
|
var config: zls.Config = .{};
|
2023-06-21 16:47:58 +01:00
|
|
|
defer zls.legacy_json.parseFree(zls.Config, allocator, config);
|
2023-05-30 00:59:46 +01:00
|
|
|
|
|
|
|
var runtime_zig_version: ?zls.ZigVersionWrapper = null;
|
|
|
|
defer if (runtime_zig_version) |*v| v.free();
|
|
|
|
|
|
|
|
try zls.configuration.configChanged(&config, &runtime_zig_version, allocator, null);
|
|
|
|
|
|
|
|
if (config.global_cache_path == null or
|
|
|
|
config.zig_exe_path == null or
|
|
|
|
config.zig_lib_path == null) return error.SkipZigTest;
|
|
|
|
|
|
|
|
const result = (try translate_c.translate(allocator, config, &.{}, c_source)).?;
|
|
|
|
|
|
|
|
switch (result) {
|
|
|
|
.success => |uri| {
|
|
|
|
const path = try zls.URI.parse(allocator, uri);
|
|
|
|
defer allocator.free(path);
|
|
|
|
try std.testing.expect(std.fs.path.isAbsolute(path));
|
|
|
|
},
|
|
|
|
.failure => |message| {
|
|
|
|
try std.testing.expect(message.len != 0);
|
|
|
|
},
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|