Started working on build file logic
This commit is contained in:
parent
4542abf145
commit
155c5b2a95
@ -5,12 +5,25 @@ const analysis = @import("analysis.zig");
|
|||||||
|
|
||||||
const DocumentStore = @This();
|
const DocumentStore = @This();
|
||||||
|
|
||||||
|
const BuildFile = struct {
|
||||||
|
const Pkg = struct {
|
||||||
|
name: []const u8,
|
||||||
|
uri: []const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
uri: []const u8,
|
||||||
|
packages: std.ArrayListUnmanaged(Pkg),
|
||||||
|
};
|
||||||
|
|
||||||
pub const Handle = struct {
|
pub const Handle = struct {
|
||||||
document: types.TextDocument,
|
document: types.TextDocument,
|
||||||
count: usize,
|
count: usize,
|
||||||
import_uris: std.ArrayList([]const u8),
|
import_uris: std.ArrayList([]const u8),
|
||||||
tree: *std.zig.ast.Tree,
|
tree: *std.zig.ast.Tree,
|
||||||
|
|
||||||
|
associated_build_file: ?*BuildFile,
|
||||||
|
is_build_file: ?*BuildFile,
|
||||||
|
|
||||||
pub fn uri(handle: Handle) []const u8 {
|
pub fn uri(handle: Handle) []const u8 {
|
||||||
return handle.document.uri;
|
return handle.document.uri;
|
||||||
}
|
}
|
||||||
@ -18,16 +31,21 @@ pub const Handle = struct {
|
|||||||
|
|
||||||
allocator: *std.mem.Allocator,
|
allocator: *std.mem.Allocator,
|
||||||
handles: std.StringHashMap(*Handle),
|
handles: std.StringHashMap(*Handle),
|
||||||
|
has_zig: bool,
|
||||||
|
build_files: std.ArrayListUnmanaged(*BuildFile),
|
||||||
|
|
||||||
pub fn init(self: *DocumentStore, allocator: *std.mem.Allocator) !void {
|
pub fn init(self: *DocumentStore, allocator: *std.mem.Allocator, has_zig: bool) !void {
|
||||||
self.allocator = allocator;
|
self.allocator = allocator;
|
||||||
self.handles = std.StringHashMap(*Handle).init(allocator);
|
self.handles = std.StringHashMap(*Handle).init(allocator);
|
||||||
errdefer self.handles.deinit();
|
self.has_zig = has_zig;
|
||||||
|
self.build_files = .{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NewDocumentError = std.fs.File.ReadError || URI.UriParseError || error{StreamTooLong};
|
||||||
|
|
||||||
/// This function asserts the document is not open yet and takes ownership
|
/// This function asserts the document is not open yet and takes ownership
|
||||||
/// of the uri and text passed in.
|
/// of the uri and text passed in.
|
||||||
fn newDocument(self: *DocumentStore, uri: []const u8, text: []u8) !*Handle {
|
fn newDocument(self: *DocumentStore, uri: []const u8, text: []u8) NewDocumentError!*Handle {
|
||||||
std.debug.warn("Opened document: {}\n", .{uri});
|
std.debug.warn("Opened document: {}\n", .{uri});
|
||||||
|
|
||||||
var handle = try self.allocator.create(Handle);
|
var handle = try self.allocator.create(Handle);
|
||||||
@ -42,8 +60,67 @@ fn newDocument(self: *DocumentStore, uri: []const u8, text: []u8) !*Handle {
|
|||||||
.mem = text,
|
.mem = text,
|
||||||
},
|
},
|
||||||
.tree = try std.zig.parse(self.allocator, text),
|
.tree = try std.zig.parse(self.allocator, text),
|
||||||
|
.associated_build_file = null,
|
||||||
|
.is_build_file = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (std.mem.endsWith(u8, uri, "build.zig") and self.has_zig) {
|
||||||
|
std.debug.warn("Document is a build file, extracting packages...\n", .{});
|
||||||
|
// This is a build file.
|
||||||
|
// @TODO Here copy the runner, run `zig run`, parse the output,
|
||||||
|
// make a BuildFile pointer called build_file
|
||||||
|
var build_file = try self.allocator.create(BuildFile);
|
||||||
|
|
||||||
|
build_file.* = .{
|
||||||
|
.uri = try std.mem.dupe(self.allocator, u8, uri),
|
||||||
|
.packages = .{},
|
||||||
|
};
|
||||||
|
|
||||||
|
handle.is_build_file = build_file;
|
||||||
|
} else if (self.has_zig) associate_build_file: {
|
||||||
|
// Look into build files to see if we already have one that fits
|
||||||
|
for (self.build_files.items) |build_file| {
|
||||||
|
// @TODO: Check if this is correct
|
||||||
|
const build_file_base_uri = build_file.uri[0 .. std.mem.lastIndexOfScalar(u8, build_file.uri, '/').? + 1];
|
||||||
|
|
||||||
|
if (std.mem.startsWith(u8, uri, build_file_base_uri)) {
|
||||||
|
std.debug.warn("Found an associated build file: {}\n", .{build_file.uri});
|
||||||
|
handle.associated_build_file = build_file;
|
||||||
|
break :associate_build_file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Otherwise, try to find a build file.
|
||||||
|
var curr_path = try URI.parse(self.allocator, uri);
|
||||||
|
defer self.allocator.free(curr_path);
|
||||||
|
while (true) {
|
||||||
|
// @TODO Add temporary traces to see what is going on.
|
||||||
|
|
||||||
|
// std.fs.path.sep
|
||||||
|
if (std.mem.lastIndexOfScalar(u8, curr_path[0 .. curr_path.len - 1], std.fs.path.sep)) |idx| {
|
||||||
|
// This includes the last separator
|
||||||
|
curr_path = curr_path[0..idx + 1];
|
||||||
|
var candidate_path = try std.mem.concat(self.allocator, u8, &[_][]const u8 { curr_path, "build.zig" });
|
||||||
|
defer self.allocator.free(candidate_path);
|
||||||
|
// Try to open the file, read it and add the new document if we find it.
|
||||||
|
var file = std.fs.cwd().openFile(candidate_path, .{ .read = true, .write = false }) catch continue;
|
||||||
|
defer file.close();
|
||||||
|
|
||||||
|
const build_file_text = try file.inStream().readAllAlloc(self.allocator, std.math.maxInt(usize));
|
||||||
|
errdefer self.allocator.free(build_file_text);
|
||||||
|
|
||||||
|
const build_file_uri = try URI.fromPath(self.allocator, candidate_path);
|
||||||
|
errdefer self.allocator.free(build_file_uri);
|
||||||
|
|
||||||
|
const build_file_handle = try self.newDocument(build_file_uri, build_file_text);
|
||||||
|
handle.associated_build_file = build_file_handle.is_build_file;
|
||||||
|
break;
|
||||||
|
} else break :associate_build_file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @TODO: Handle the text refresh if we have a is_build_file
|
||||||
|
// @TODO: Handle package imports if we have an associated_build_file
|
||||||
|
|
||||||
try self.handles.putNoClobber(uri, handle);
|
try self.handles.putNoClobber(uri, handle);
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -891,6 +891,8 @@ pub fn main() anyerror!void {
|
|||||||
// Find the zig executable in PATH
|
// Find the zig executable in PATH
|
||||||
var has_zig = false;
|
var has_zig = false;
|
||||||
|
|
||||||
|
// TODO: Should we just spawn a child process that calls "zig version" or something
|
||||||
|
// and check that way?
|
||||||
find_zig: {
|
find_zig: {
|
||||||
const env_path = std.process.getEnvVarOwned(allocator, "PATH") catch |err| switch (err) {
|
const env_path = std.process.getEnvVarOwned(allocator, "PATH") catch |err| switch (err) {
|
||||||
error.EnvironmentVariableNotFound => {
|
error.EnvironmentVariableNotFound => {
|
||||||
@ -901,16 +903,18 @@ pub fn main() anyerror!void {
|
|||||||
};
|
};
|
||||||
defer allocator.free(env_path);
|
defer allocator.free(env_path);
|
||||||
|
|
||||||
var it = std.mem.tokenize(env_path,&[_]u8{std.fs.path.delimiter});
|
|
||||||
const exe_extension = @as(std.zig.CrossTarget, .{}).exeFileExt();
|
const exe_extension = @as(std.zig.CrossTarget, .{}).exeFileExt();
|
||||||
const zig_exe = try std.fmt.allocPrint(allocator, "zig{}", .{exe_extension});
|
const zig_exe = try std.fmt.allocPrint(allocator, "zig{}", .{exe_extension});
|
||||||
defer allocator.free(zig_exe);
|
defer allocator.free(zig_exe);
|
||||||
|
|
||||||
|
var it = std.mem.tokenize(env_path,&[_]u8{std.fs.path.delimiter});
|
||||||
while (it.next()) |path| {
|
while (it.next()) |path| {
|
||||||
const full_path = try std.fs.path.join(allocator, &[_][]const u8{
|
const full_path = try std.fs.path.join(allocator, &[_][]const u8{
|
||||||
path,
|
path,
|
||||||
zig_exe,
|
zig_exe,
|
||||||
});
|
});
|
||||||
|
defer allocator.free(full_path);
|
||||||
|
|
||||||
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
|
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
|
||||||
const zig_path = std.os.realpath(full_path, &buf) catch continue;
|
const zig_path = std.os.realpath(full_path, &buf) catch continue;
|
||||||
std.debug.warn("Found zig in PATH: {}\n", .{zig_path});
|
std.debug.warn("Found zig in PATH: {}\n", .{zig_path});
|
||||||
@ -919,7 +923,7 @@ pub fn main() anyerror!void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try document_store.init(allocator);
|
try document_store.init(allocator, has_zig);
|
||||||
defer document_store.deinit();
|
defer document_store.deinit();
|
||||||
|
|
||||||
workspace_folder_configs = std.StringHashMap(?Config).init(allocator);
|
workspace_folder_configs = std.StringHashMap(?Config).init(allocator);
|
||||||
|
@ -41,6 +41,13 @@ pub fn fromPath(allocator: *std.mem.Allocator, path: []const u8) ![]const u8 {
|
|||||||
return buf.toOwnedSlice();
|
return buf.toOwnedSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const UriParseError = error {
|
||||||
|
UriBadScheme,
|
||||||
|
UriBadHexChar,
|
||||||
|
UriBadEscape,
|
||||||
|
OutOfMemory,
|
||||||
|
};
|
||||||
|
|
||||||
// Original code: https://github.com/andersfr/zig-lsp/blob/master/uri.zig
|
// Original code: https://github.com/andersfr/zig-lsp/blob/master/uri.zig
|
||||||
fn parseHex(c: u8) !u8 {
|
fn parseHex(c: u8) !u8 {
|
||||||
return switch (c) {
|
return switch (c) {
|
||||||
|
Loading…
Reference in New Issue
Block a user