feat: add diagnostic system and improve CLI with check command
Implement comprehensive diagnostic reporting system: - Add Diagnostic struct with severity levels and span-based error tracking - Add diagnostic rendering with source context and caret positioning - Replace ParseError with diagnostic collection in lexer and parser - Add LexResult and ParseResult types to carry diagnostics Enhance driver crate with frontend output: - Replace CompileResult with FrontendOutput containing diagnostics - Add has_errors() and render_diagnostics() methods - Add AstSummary for
This commit is contained in:
@@ -1,41 +1,98 @@
|
||||
use std::fmt::Write;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use nxc_frontend::{Lexer, Module, ParseError, Parser, Token};
|
||||
use nxc_frontend::{
|
||||
has_errors, Diagnostic, Item, LexResult, Lexer, Module, ParseResult, Parser, Token,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CompileResult {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FrontendOutput {
|
||||
pub path: PathBuf,
|
||||
pub source: String,
|
||||
pub tokens: Vec<Token>,
|
||||
pub module: Module,
|
||||
pub diagnostics: Vec<Diagnostic>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CompileError {
|
||||
pub enum DriverError {
|
||||
Io(std::io::Error),
|
||||
Parse(ParseError),
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for CompileError {
|
||||
impl From<std::io::Error> for DriverError {
|
||||
fn from(value: std::io::Error) -> Self {
|
||||
Self::Io(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseError> for CompileError {
|
||||
fn from(value: ParseError) -> Self {
|
||||
Self::Parse(value)
|
||||
impl FrontendOutput {
|
||||
pub fn has_errors(&self) -> bool {
|
||||
has_errors(&self.diagnostics)
|
||||
}
|
||||
|
||||
pub fn summary(&self) -> AstSummary {
|
||||
let mut summary = AstSummary {
|
||||
items: self.module.items.len(),
|
||||
..AstSummary::default()
|
||||
};
|
||||
|
||||
for item in &self.module.items {
|
||||
match item {
|
||||
Item::Function(_) => summary.functions += 1,
|
||||
Item::Struct(_) => summary.structs += 1,
|
||||
}
|
||||
}
|
||||
|
||||
summary
|
||||
}
|
||||
|
||||
pub fn render_diagnostics(&self) -> String {
|
||||
let path = self.path.display().to_string();
|
||||
let mut out = String::new();
|
||||
for (index, diagnostic) in self.diagnostics.iter().enumerate() {
|
||||
if index > 0 {
|
||||
out.push('\n');
|
||||
out.push('\n');
|
||||
}
|
||||
let _ = write!(out, "{}", diagnostic.render(&path, &self.source));
|
||||
}
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compile_file(path: impl AsRef<Path>) -> Result<CompileResult, CompileError> {
|
||||
let source = fs::read_to_string(path)?;
|
||||
compile_source(&source)
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct AstSummary {
|
||||
pub items: usize,
|
||||
pub functions: usize,
|
||||
pub structs: usize,
|
||||
}
|
||||
|
||||
pub fn compile_source(source: &str) -> Result<CompileResult, CompileError> {
|
||||
let tokens = Lexer::new(source).tokenize();
|
||||
let mut parser = Parser::new(tokens.clone());
|
||||
let module = parser.parse_module()?;
|
||||
Ok(CompileResult { tokens, module })
|
||||
pub fn check_file(path: impl AsRef<Path>) -> Result<FrontendOutput, DriverError> {
|
||||
let path = path.as_ref().to_path_buf();
|
||||
let source = fs::read_to_string(&path)?;
|
||||
Ok(check_source(path, source))
|
||||
}
|
||||
|
||||
pub fn check_source(path: PathBuf, source: String) -> FrontendOutput {
|
||||
let LexResult {
|
||||
tokens,
|
||||
diagnostics: mut lexer_diagnostics,
|
||||
} = Lexer::new(&source).lex();
|
||||
|
||||
let ParseResult {
|
||||
module,
|
||||
diagnostics: parser_diagnostics,
|
||||
} = Parser::new(tokens.clone()).parse_module();
|
||||
|
||||
lexer_diagnostics.extend(parser_diagnostics);
|
||||
|
||||
FrontendOutput {
|
||||
path,
|
||||
source,
|
||||
tokens,
|
||||
module,
|
||||
diagnostics: lexer_diagnostics,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user