pipes
This commit is contained in:
@@ -60,6 +60,30 @@ pub const DocumentStore = struct {
|
||||
return self.createDocument(path, source, -1);
|
||||
}
|
||||
|
||||
/// Try to list .sx files in a directory. Returns null if path is not a directory.
|
||||
pub fn listDirectoryFiles(self: *DocumentStore, dir_path: []const u8) ?[]const []const u8 {
|
||||
const dir = std.Io.Dir.openDir(.cwd(), self.io, dir_path, .{ .iterate = true }) catch return null;
|
||||
defer dir.close(self.io);
|
||||
|
||||
var file_paths = std.ArrayList([]const u8).empty;
|
||||
var it = dir.iterate();
|
||||
while (it.next(self.io) catch null) |entry| {
|
||||
if (entry.kind != .file) continue;
|
||||
if (!std.mem.endsWith(u8, entry.name, ".sx")) continue;
|
||||
const full_path = std.fmt.allocPrint(self.allocator, "{s}/{s}", .{ dir_path, entry.name }) catch continue;
|
||||
file_paths.append(self.allocator, full_path) catch continue;
|
||||
}
|
||||
|
||||
// Sort for deterministic order
|
||||
std.mem.sort([]const u8, file_paths.items, {}, struct {
|
||||
fn lessThan(_: void, a: []const u8, b: []const u8) bool {
|
||||
return std.mem.order(u8, a, b) == .lt;
|
||||
}
|
||||
}.lessThan);
|
||||
|
||||
return file_paths.toOwnedSlice(self.allocator) catch null;
|
||||
}
|
||||
|
||||
/// Create or update a document with editor-provided source (for didOpen/didChange).
|
||||
pub fn openOrUpdate(self: *DocumentStore, path: []const u8, source: [:0]const u8, version: i64) !*Document {
|
||||
if (self.by_path.get(path)) |doc| {
|
||||
@@ -125,7 +149,75 @@ pub const DocumentStore = struct {
|
||||
try cycle_guard.put(doc.path, {});
|
||||
|
||||
for (doc.imports) |imp| {
|
||||
const imp_doc = self.getOrLoad(imp.path) catch continue;
|
||||
// Try as file first; if that fails, try as directory import
|
||||
const imp_doc = self.getOrLoad(imp.path) catch {
|
||||
// Directory import: load each .sx file and merge their symbols
|
||||
const dir_files = self.listDirectoryFiles(imp.path) orelse continue;
|
||||
for (dir_files) |file_path| {
|
||||
const file_doc = self.getOrLoad(file_path) catch continue;
|
||||
if (cycle_guard.contains(file_path)) continue;
|
||||
if (file_doc.sema == null) {
|
||||
try cycle_guard.put(file_path, {});
|
||||
self.analyzeDocument(file_doc) catch {};
|
||||
_ = cycle_guard.remove(file_path);
|
||||
}
|
||||
const file_sema = file_doc.sema orelse continue;
|
||||
if (imp.ns) |ns_name| {
|
||||
// Only register namespace symbol once (first file)
|
||||
if (!analyzer.hasSymbol(ns_name)) {
|
||||
try analyzer.preRegisterSymbol(.{
|
||||
.name = ns_name,
|
||||
.kind = .namespace,
|
||||
.ty = null,
|
||||
.def_span = .{ .start = 0, .end = 0 },
|
||||
.scope_depth = 0,
|
||||
.origin = imp.path,
|
||||
});
|
||||
}
|
||||
var sig_it = file_sema.fn_signatures.iterator();
|
||||
while (sig_it.next()) |entry| {
|
||||
const prefixed = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ ns_name, entry.key_ptr.* });
|
||||
try analyzer.fn_signatures.put(prefixed, entry.value_ptr.*);
|
||||
}
|
||||
var struct_it = file_sema.struct_types.iterator();
|
||||
while (struct_it.next()) |entry| {
|
||||
const prefixed = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ ns_name, entry.key_ptr.* });
|
||||
try analyzer.struct_types.put(prefixed, entry.value_ptr.*);
|
||||
}
|
||||
var enum_it = file_sema.enum_types.iterator();
|
||||
while (enum_it.next()) |entry| {
|
||||
const prefixed = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ ns_name, entry.key_ptr.* });
|
||||
try analyzer.enum_types.put(prefixed, entry.value_ptr.*);
|
||||
}
|
||||
} else {
|
||||
for (file_sema.symbols) |sym| {
|
||||
if (sym.scope_depth == 0) {
|
||||
try analyzer.preRegisterSymbol(.{
|
||||
.name = sym.name,
|
||||
.kind = sym.kind,
|
||||
.ty = sym.ty,
|
||||
.def_span = sym.def_span,
|
||||
.scope_depth = 0,
|
||||
.origin = file_path,
|
||||
});
|
||||
}
|
||||
}
|
||||
var sig_it = file_sema.fn_signatures.iterator();
|
||||
while (sig_it.next()) |entry| {
|
||||
try analyzer.fn_signatures.put(entry.key_ptr.*, entry.value_ptr.*);
|
||||
}
|
||||
var struct_it = file_sema.struct_types.iterator();
|
||||
while (struct_it.next()) |entry| {
|
||||
try analyzer.struct_types.put(entry.key_ptr.*, entry.value_ptr.*);
|
||||
}
|
||||
var enum_it = file_sema.enum_types.iterator();
|
||||
while (enum_it.next()) |entry| {
|
||||
try analyzer.enum_types.put(entry.key_ptr.*, entry.value_ptr.*);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
};
|
||||
|
||||
// Cycle detection
|
||||
if (cycle_guard.contains(imp.path)) continue;
|
||||
|
||||
Reference in New Issue
Block a user