From 887539ed1aa84ee6f583156c7e239b974bcf1c31 Mon Sep 17 00:00:00 2001 From: Joseph Stahl <1269177+josephst@users.noreply.github.com> Date: Sun, 4 Dec 2022 16:44:22 -0500 Subject: [PATCH] Allocator.resize() does not adjust size of string allocated for URI to file path conversion (#806) * fix missing backslash * fix: zls escaping colon to %3A on URIs ZLS escapes a colon char ":" as "%3A" when encoding file paths to URIs When decoding, need to make the target string 2 character shorter to compensate for length decrease when replacing %3A with : * add new failing test because of resize() * revert changes to %3A handling - problem seems to be with allocator.resize * switch to realloc * Fix test failures, revert errdefer->defer * platform-specific URI tests URI parsing is highly platform-specific run Unix-style (file:///home/main.zig) on non-Windows test runners, run Windows-style (file://c%3A/main.zig) on Windows test runners --- src/uri.zig | 4 ++-- tests/utility/uri.zig | 53 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/uri.zig b/src/uri.zig index 95ce9a9..a1064d8 100644 --- a/src/uri.zig +++ b/src/uri.zig @@ -101,7 +101,7 @@ pub fn parse(allocator: std.mem.Allocator, str: []const u8) ![]u8 { if (str.len < 7 or !std.mem.eql(u8, "file://", str[0..7])) return error.UriBadScheme; var uri = try allocator.alloc(u8, str.len - (if (std.fs.path.sep == '\\') 8 else 7)); - defer allocator.free(uri); + errdefer allocator.free(uri); const path = if (std.fs.path.sep == '\\') str[8..] else str[7..]; @@ -125,5 +125,5 @@ pub fn parse(allocator: std.mem.Allocator, str: []const u8) ![]u8 { i -= 1; } - return try allocator.dupe(u8, uri[0..i]); + return allocator.realloc(uri, i); } diff --git a/tests/utility/uri.zig b/tests/utility/uri.zig index 4aeb3b4..a1a494c 100644 --- a/tests/utility/uri.zig +++ b/tests/utility/uri.zig @@ -1,16 +1,55 @@ const std = @import("std"); +const builtin = @import("builtin"); const zls = @import("zls"); const URI = zls.URI; const allocator = std.testing.allocator; -test "uri - pathRelative" { - const join1 = try URI.pathRelative(allocator, "file://project/zig", "/src/main+.zig"); - defer allocator.free(join1); - try std.testing.expectEqualStrings("file://project/zig/src/main%2B.zig", join1); +test "uri - parse (Windows)" { + if (builtin.os.tag == .windows) { + const parseWin = try URI.parse(allocator, "file:///c%3A/main.zig"); + defer allocator.free(parseWin); + try std.testing.expectEqualStrings("c:\\main.zig", parseWin); - const join2 = try URI.pathRelative(allocator, "file://project/zig/wow", "../]src]/]main.zig"); + const parseWin2 = try URI.parse(allocator, "file:///c%3A/main%2B.zig"); + defer allocator.free(parseWin2); + try std.testing.expectEqualStrings("c:\\main+.zig", parseWin2); + } +} + +test "uri - parse (Unix-style)" { + if (builtin.os.tag != .windows) { + const parseUnix = try URI.parse(allocator, "file:///home/main.zig"); + defer allocator.free(parseUnix); + try std.testing.expectEqualStrings("/home/main.zig", parseUnix); + + const parseUnix2 = try URI.parse(allocator, "file:///home/main%2B.zig"); + defer allocator.free(parseUnix2); + try std.testing.expectEqualStrings("/home/main+.zig", parseUnix2); + } +} + +test "uri - fromPath" { + if (builtin.os.tag == .windows) { + const fromPathWin = try URI.fromPath(allocator, "c:\\main.zig"); + defer allocator.free(fromPathWin); + try std.testing.expectEqualStrings("file:///c%3A/main.zig", fromPathWin); + } + + if (builtin.os.tag != .windows) { + const fromPathUnix = try URI.fromPath(allocator, "/home/main.zig"); + defer allocator.free(fromPathUnix); + try std.testing.expectEqualStrings("file:///home/main.zig", fromPathUnix); + } +} + +test "uri - pathRelative" { + const join1 = try URI.pathRelative(allocator, "file:///project/zig", "/src/main+.zig"); + defer allocator.free(join1); + try std.testing.expectEqualStrings("file:///project/zig/src/main%2B.zig", join1); + + const join2 = try URI.pathRelative(allocator, "file:///project/zig/wow", "../]src]/]main.zig"); defer allocator.free(join2); - try std.testing.expectEqualStrings("file://project/zig/%5Dsrc%5D/%5Dmain.zig", join2); -} \ No newline at end of file + try std.testing.expectEqualStrings("file:///project/zig/%5Dsrc%5D/%5Dmain.zig", join2); +}