refactor(sema): seal sema.zig as editor indexing only (A8.1)
Remove the last compiler dependency on sema as semantic truth and stop publishing as-you-type sema diagnostics from the LSP. - core.zig: drop dead `Compilation.analyze()`, the `sema_result` field, and the sema->diagnostics merge; drop the now-orphaned sema import. The CLI pipeline (parse -> resolveImports -> generateCode) never called analyze(), so this removes only dead code. - lsp/server.zig: rename `analyzeAndPublish` -> `refreshEditorIndex` and delete its sema-diagnostic publish (and the now-unused `semaToLspDiags`). The editor index (doc.sema) is still refreshed for nav/refs/completion/ tokens. On-save/on-open diagnostics still come solely from the canonical compiler pipeline in `runProjectCheck` (unchanged). - Document sema as an editor-indexing API (doc.sema field comment). Intended behavior change: as-you-type sema diagnostics no longer publish; on-save canonical diagnostics are the sole source. CLI compile output and the 361-example suite are unchanged (361/0, zero snapshot churn).
This commit is contained in:
14
src/core.zig
14
src/core.zig
@@ -2,7 +2,6 @@ const std = @import("std");
|
||||
const ast = @import("ast.zig");
|
||||
const parser = @import("parser.zig");
|
||||
const imports = @import("imports.zig");
|
||||
const sema = @import("sema.zig");
|
||||
const errors = @import("errors.zig");
|
||||
const c_import = @import("c_import.zig");
|
||||
const ir = @import("ir/ir.zig");
|
||||
@@ -27,7 +26,6 @@ pub const Compilation = struct {
|
||||
import_sources: std.StringHashMap([:0]const u8),
|
||||
module_scopes: std.StringHashMap(std.StringHashMap(void)),
|
||||
import_graph: std.StringHashMap(std.StringHashMap(void)),
|
||||
sema_result: ?sema.SemaResult = null,
|
||||
ir_emitter: ?ir.LLVMEmitter = null,
|
||||
/// Lowered IR module, kept alive past `generateCode` so post-link
|
||||
/// callbacks can re-enter the interpreter to invoke sx functions
|
||||
@@ -128,18 +126,6 @@ pub const Compilation = struct {
|
||||
self.resolved_root = new_root;
|
||||
}
|
||||
|
||||
pub fn analyze(self: *Compilation) !void {
|
||||
const root = self.resolved_root orelse self.root orelse return error.CompileError;
|
||||
var analyzer = sema.Analyzer.init(self.allocator);
|
||||
self.sema_result = analyzer.analyze(root) catch return error.CompileError;
|
||||
// Merge sema diagnostics into our list
|
||||
if (self.sema_result) |sr| {
|
||||
for (sr.diagnostics) |d| {
|
||||
self.diagnostics.add(d.level, d.message, d.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate code via the IR pipeline: lower AST → IR → LLVM.
|
||||
pub fn generateCode(self: *Compilation) !void {
|
||||
// Heap-allocate the IR module so its address is stable during emit
|
||||
|
||||
@@ -23,7 +23,9 @@ pub const Document = struct {
|
||||
version: i64,
|
||||
/// AST root for this file only (not merged).
|
||||
root: ?*sx.ast.Node,
|
||||
/// Sema results for this file (references are relative to this source).
|
||||
/// Editor index for this file — symbols/references/types for navigation,
|
||||
/// completion, and hover (references are relative to this source). Not a
|
||||
/// diagnostic source; see `sema.zig` module doc.
|
||||
sema: ?sx.sema.SemaResult,
|
||||
/// Last successful sema (preserved across parse failures for completions).
|
||||
last_good_sema: ?sx.sema.SemaResult = null,
|
||||
|
||||
@@ -158,7 +158,7 @@ pub const Server = struct {
|
||||
const text = jsonStr(jsonGet(td, "text") orelse return) orelse return;
|
||||
const version = jsonInt(jsonGet(td, "version") orelse return) orelse return;
|
||||
|
||||
try self.analyzeAndPublish(uri, text, version);
|
||||
try self.refreshEditorIndex(uri, text, version);
|
||||
self.runProjectCheck();
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ pub const Server = struct {
|
||||
const last = changes_arr[changes_arr.len - 1];
|
||||
const text = jsonStr(jsonGet(last, "text") orelse return) orelse return;
|
||||
|
||||
try self.analyzeAndPublish(uri, text, version);
|
||||
try self.refreshEditorIndex(uri, text, version);
|
||||
}
|
||||
|
||||
fn handleDidClose(_: *Server, params: std.json.Value) void {
|
||||
@@ -1919,41 +1919,16 @@ pub const Server = struct {
|
||||
|
||||
// ---- Core analysis pipeline ----
|
||||
|
||||
fn analyzeAndPublish(self: *Server, uri: []const u8, text: []const u8, version: i64) !void {
|
||||
/// Refresh the editor index for a document (symbols/references/types that
|
||||
/// power navigation, completion, hover, and token classification). Publishes
|
||||
/// no diagnostics — authoritative diagnostics come only from the canonical
|
||||
/// compiler pipeline in `runProjectCheck`.
|
||||
fn refreshEditorIndex(self: *Server, uri: []const u8, text: []const u8, version: i64) !void {
|
||||
const file_path = uriToFilePath(uri) orelse "";
|
||||
const source = try self.allocator.dupeZ(u8, text);
|
||||
|
||||
const doc = try self.documents.openOrUpdate(file_path, source, version);
|
||||
self.documents.analyzeDocument(doc) catch {};
|
||||
|
||||
// Publish diagnostics from sema
|
||||
if (doc.sema) |sema| {
|
||||
try self.sendDiagnostics(uri, semaToLspDiags(self.allocator, doc.source, sema.diagnostics));
|
||||
} else {
|
||||
try self.sendDiagnostics(uri, &.{});
|
||||
}
|
||||
}
|
||||
|
||||
fn semaToLspDiags(allocator: std.mem.Allocator, source: [:0]const u8, diags: []const sx.errors.Diagnostic) []const lsp.Diagnostic {
|
||||
var result = std.ArrayList(lsp.Diagnostic).empty;
|
||||
for (diags) |d| {
|
||||
const range = if (d.span) |span| spanToRange(source, span) else lsp.Range{
|
||||
.start = .{ .line = 0, .character = 0 },
|
||||
.end = .{ .line = 0, .character = 1 },
|
||||
};
|
||||
const severity: u32 = switch (d.level) {
|
||||
.err => 1,
|
||||
.warn => 2,
|
||||
.note => 3,
|
||||
.help => 4,
|
||||
};
|
||||
result.append(allocator, .{
|
||||
.range = range,
|
||||
.severity = severity,
|
||||
.message = d.message,
|
||||
}) catch continue;
|
||||
}
|
||||
return result.items;
|
||||
}
|
||||
|
||||
fn sendDiagnostics(self: *Server, uri: []const u8, diagnostics: []const lsp.Diagnostic) !void {
|
||||
@@ -2012,8 +1987,8 @@ pub const Server = struct {
|
||||
}
|
||||
|
||||
/// Drive the whole-program check from the workspace entry point and publish
|
||||
/// the real compiler's diagnostics per file (runs on save; the sema layer
|
||||
/// keeps live per-keystroke feedback).
|
||||
/// the real compiler's diagnostics per file. Runs on open and save; this is
|
||||
/// the sole source of LSP diagnostics (the editor index publishes none).
|
||||
fn runProjectCheck(self: *Server) void {
|
||||
if (self.root_path.len == 0) return;
|
||||
const entry_path = std.fmt.allocPrint(self.allocator, "{s}/main.sx", .{self.root_path}) catch return;
|
||||
|
||||
Reference in New Issue
Block a user