Skip to content

Commit

Permalink
feat(cli): add pretty error reporting (DonIsaac#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
DonIsaac authored Sep 18, 2024
1 parent 97e53b5 commit 4373fc6
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 28 deletions.
8 changes: 4 additions & 4 deletions src/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ pub struct CompiledOutput {
pub fn compile(
options: &CompileOptions,
source_path: &Path,
source_text: &str,
) -> Result<CompiledOutput, Vec<OxcDiagnostic>> {
let source_text = fs::read_to_string(source_path).unwrap();
// is this js? ts? tsx?
let source_type = SourceType::from_path(source_path).unwrap();
// get the name as a pretty string
Expand All @@ -51,7 +51,7 @@ pub fn compile(
trivias,
mut errors,
panicked,
} = Parser::new(&allocator, &source_text, source_type).parse();
} = Parser::new(&allocator, source_text, source_type).parse();

if panicked {
debug_assert!(!errors.is_empty());
Expand All @@ -61,7 +61,7 @@ pub fn compile(
let SemanticBuilderReturn {
semantic,
errors: semantic_errors,
} = SemanticBuilder::new(&source_text)
} = SemanticBuilder::new(source_text)
.with_trivias(trivias.clone())
.with_check_syntax_error(true)
.build(&program);
Expand All @@ -79,7 +79,7 @@ pub fn compile(
} = isolated_declarations(
&allocator,
&program,
&source_text,
source_text,
source_name,
trivias.clone(),
)?;
Expand Down
25 changes: 20 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,38 @@
mod cli;
mod compiler;
mod options;
mod reporter;
mod walk;

use std::{thread, time::Instant};

use miette::Result;
use std::time::Instant;

use cli::{cli, CliOptions};
use options::OxbuildOptions;
use crate::{
cli::{cli, CliOptions},
options::OxbuildOptions,
reporter::{DiagnosticSender, Reporter},
};

#[allow(clippy::print_stdout)]
fn main() -> Result<()> {
let matches = cli();
let opts = CliOptions::new(matches).and_then(OxbuildOptions::new)?;
let num_threads = opts.num_threads.get();

let (mut reporter, report_sender) = Reporter::new();

let start = Instant::now();
let mut walker = walk::WalkerBuilder::new(opts);
walker.walk(num_threads);

let handle = thread::spawn(move || {
let mut walker = walk::WalkerBuilder::new(opts, report_sender.clone());
walker.walk(num_threads);
report_sender.send(None).unwrap();
});

reporter.run();
handle.join().unwrap();

let duration = start.elapsed();

println!(
Expand Down
4 changes: 2 additions & 2 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl OxbuildOptions {
.with_context(|| {
format!("Failed to read TSConfig at {}", tsconfig_path.display())
})
.and_then(TsConfig::new)
.and_then(TsConfig::parse)
})
.transpose()?;

Expand Down Expand Up @@ -116,7 +116,7 @@ struct TsConfigCompilerOptions {
}

impl TsConfig {
pub fn new(mut source_text: String) -> Result<Self> {
pub fn parse(mut source_text: String) -> Result<Self> {
json_strip_comments::strip(&mut source_text).unwrap();

serde_json::from_str(&source_text).into_diagnostic()
Expand Down
21 changes: 21 additions & 0 deletions src/reporter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use oxc::diagnostics::DiagnosticService;

// re-export in case we want to modify/wrap/replace/whatever in the future
pub use oxc::diagnostics::DiagnosticSender;

#[must_use]
pub struct Reporter {
inner: DiagnosticService,
}

impl Reporter {
pub fn new() -> (Self, DiagnosticSender) {
let inner = DiagnosticService::default();
let sender = inner.sender().clone();
(Self { inner }, sender)
}

pub fn run(&mut self) {
self.inner.run();
}
}
51 changes: 34 additions & 17 deletions src/walk.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,32 @@
use std::ops::Deref;
use std::{
fs,
ops::Deref,
path::{Path, PathBuf},
sync::{Arc, Mutex},
sync::Arc,
};

use ignore::{DirEntry, Error as WalkError, ParallelVisitor, ParallelVisitorBuilder, WalkState};
use oxc::diagnostics::OxcDiagnostic;
use oxc::diagnostics::{Error, NamedSource, OxcDiagnostic};

use crate::{
compiler::{compile, CompileOptions, CompiledOutput},
OxbuildOptions,
DiagnosticSender, OxbuildOptions,
};

pub struct WalkerBuilder {
options: Arc<OxbuildOptions>,
compile_options: Arc<CompileOptions>,
state: Arc<Mutex<State>>,
}
#[derive(Debug, Default)]
struct State {
errors: Vec<OxcDiagnostic>,
sender: DiagnosticSender,
}

impl WalkerBuilder {
pub fn new(options: OxbuildOptions) -> Self {
pub fn new(options: OxbuildOptions, sender: DiagnosticSender) -> Self {
let compile_options = CompileOptions::new(options.root.deref().to_path_buf())
.with_d_ts(options.isolated_declarations);
Self {
compile_options: Arc::new(compile_options),
options: Arc::new(options),
state: Default::default(),
sender,
}
}

Expand All @@ -51,15 +47,15 @@ impl<'s> ParallelVisitorBuilder<'s> for WalkerBuilder {
Box::new(Walker {
options: Arc::clone(&self.options),
compile_options: Arc::clone(&self.compile_options),
state: Arc::clone(&self.state),
sender: self.sender.clone(),
})
}
}

pub struct Walker {
options: Arc<OxbuildOptions>,
compile_options: Arc<CompileOptions>,
state: Arc<Mutex<State>>,
sender: DiagnosticSender,
}

impl Walker {
Expand All @@ -73,11 +69,32 @@ impl Walker {

#[must_use]
fn compile(&self, path: &Path) -> Option<CompiledOutput> {
match compile(&self.compile_options, path) {
let source_text = match fs::read_to_string(path) {
Ok(text) => text,
Err(e) => {
let error = OxcDiagnostic::error(format!(
"Failed to open source file at '{}': {}",
path.display(),
e
));
self.sender
.send(Some((path.to_path_buf(), vec![Error::new(error)])))
.unwrap();
return None;
}
};

match compile(&self.compile_options, path, &source_text) {
Ok(output) => Some(output),
Err(errors) => {
let mut state = self.state.lock().unwrap();
state.errors.extend(errors);
Err(diagnostics) => {
let source = Arc::new(NamedSource::new(path.to_string_lossy(), source_text));
let errors = diagnostics
.into_iter()
.map(|diagnostic| diagnostic.with_source_code(Arc::clone(&source)))
.collect();
self.sender
.send(Some((path.to_path_buf(), errors)))
.unwrap();
None
}
}
Expand Down

0 comments on commit 4373fc6

Please sign in to comment.