mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
777f02ae10
## Summary Introduces `oxc_diagnostics::Diagnostics` — a `Vec<OxcDiagnostic>` newtype that knows the difference between errors and warnings — and makes it the standard diagnostics return value across oxc. - **New type**: `Diagnostics` with `has_errors()`, `has_warnings()`, `errors()`, `warnings()`, plus `Vec`-like ergonomics (Deref, `IntoIterator`, `Extend`, `From`/`Into<Vec>`) so most call sites are unchanged. - **Return types**: `ParserReturn`, `SemanticBuilderReturn`, `IsolatedDeclarationsReturn`, the React Compiler `TransformResult`/`LintResult`, and `TransformerReturn` now expose `diagnostics: Diagnostics` instead of `errors: Vec<OxcDiagnostic>` (the React Compiler's separate `errors`/`warnings` are merged into one severity-tagged list). - **Behaviour**: a React Compiler **error** now stops the transform (no output), while **warnings** flow through and the transform continues. `compile()` aborts codegen only when `diagnostics.has_errors()` — warnings alone no longer abort (previously any diagnostic did). ## Breaking change Consumers reading `*.errors` on these return values must read `*.diagnostics`. React Compiler consumers that read `.errors`/`.warnings` separately should use `diagnostics.has_errors()` / `diagnostics.errors()` / `diagnostics.warnings()`. Parser/semantic/isolated-declarations fatality is otherwise unchanged. Builds on the React Compiler transform feature (#23201). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
128 lines
4.0 KiB
Rust
128 lines
4.0 KiB
Rust
use std::path::Path;
|
|
|
|
use napi::{Task, bindgen_prelude::AsyncTask};
|
|
use napi_derive::napi;
|
|
|
|
use oxc::{
|
|
allocator::Allocator,
|
|
codegen::{Codegen, CodegenOptions, CommentOptions},
|
|
isolated_declarations::IsolatedDeclarations,
|
|
parser::Parser,
|
|
span::SourceType,
|
|
};
|
|
use oxc_napi::OxcError;
|
|
use oxc_sourcemap::napi::SourceMap;
|
|
|
|
#[napi(object)]
|
|
pub struct IsolatedDeclarationsResult {
|
|
pub code: String,
|
|
pub map: Option<SourceMap>,
|
|
pub errors: Vec<OxcError>,
|
|
}
|
|
|
|
#[napi(object)]
|
|
#[derive(Debug, Default, Clone, Copy)]
|
|
pub struct IsolatedDeclarationsOptions {
|
|
/// Do not emit declarations for code that has an @internal annotation in its JSDoc comment.
|
|
/// This is an internal compiler option; use at your own risk, because the compiler does not check that the result is valid.
|
|
///
|
|
/// Default: `false`
|
|
///
|
|
/// See <https://www.typescriptlang.org/tsconfig/#stripInternal>
|
|
pub strip_internal: Option<bool>,
|
|
|
|
pub sourcemap: Option<bool>,
|
|
}
|
|
|
|
impl From<IsolatedDeclarationsOptions> for oxc::isolated_declarations::IsolatedDeclarationsOptions {
|
|
fn from(options: IsolatedDeclarationsOptions) -> Self {
|
|
Self { strip_internal: options.strip_internal.unwrap_or_default() }
|
|
}
|
|
}
|
|
|
|
fn isolated_declaration_impl(
|
|
filename: &str,
|
|
source_text: &str,
|
|
options: Option<IsolatedDeclarationsOptions>,
|
|
) -> IsolatedDeclarationsResult {
|
|
let source_path = Path::new(filename);
|
|
let source_type = SourceType::from_path(source_path).unwrap_or_default().with_typescript(true);
|
|
let allocator = Allocator::default();
|
|
let options = options.unwrap_or_default();
|
|
|
|
let ret = Parser::new(&allocator, source_text, source_type).parse();
|
|
|
|
let transformed_ret = IsolatedDeclarations::new(
|
|
&allocator,
|
|
oxc::isolated_declarations::IsolatedDeclarationsOptions {
|
|
strip_internal: options.strip_internal.unwrap_or(false),
|
|
},
|
|
)
|
|
.build(&ret.program);
|
|
|
|
let source_map_path = match options.sourcemap {
|
|
Some(true) => Some(source_path.to_path_buf()),
|
|
_ => None,
|
|
};
|
|
let codegen_ret = Codegen::new()
|
|
.with_options(CodegenOptions {
|
|
comments: CommentOptions { jsdoc: true, ..CommentOptions::disabled() },
|
|
source_map_path,
|
|
..CodegenOptions::default()
|
|
})
|
|
.build(&transformed_ret.program);
|
|
|
|
let diagnostics =
|
|
ret.diagnostics.into_iter().chain(transformed_ret.diagnostics).collect::<Vec<_>>();
|
|
let errors = OxcError::from_diagnostics(filename, source_text, diagnostics);
|
|
|
|
IsolatedDeclarationsResult {
|
|
code: codegen_ret.code,
|
|
map: codegen_ret.map.map(SourceMap::from),
|
|
errors,
|
|
}
|
|
}
|
|
|
|
/// TypeScript Isolated Declarations for Standalone DTS Emit
|
|
#[allow(clippy::needless_pass_by_value, clippy::allow_attributes)]
|
|
#[napi]
|
|
pub fn isolated_declaration_sync(
|
|
filename: String,
|
|
source_text: String,
|
|
options: Option<IsolatedDeclarationsOptions>,
|
|
) -> IsolatedDeclarationsResult {
|
|
isolated_declaration_impl(&filename, &source_text, options)
|
|
}
|
|
|
|
pub struct IsolatedDeclarationTask {
|
|
filename: String,
|
|
source_text: String,
|
|
options: Option<IsolatedDeclarationsOptions>,
|
|
}
|
|
|
|
#[napi]
|
|
impl Task for IsolatedDeclarationTask {
|
|
type JsValue = IsolatedDeclarationsResult;
|
|
type Output = IsolatedDeclarationsResult;
|
|
|
|
fn compute(&mut self) -> napi::Result<Self::Output> {
|
|
Ok(isolated_declaration_impl(&self.filename, &self.source_text, self.options.take()))
|
|
}
|
|
|
|
fn resolve(&mut self, _: napi::Env, result: Self::Output) -> napi::Result<Self::JsValue> {
|
|
Ok(result)
|
|
}
|
|
}
|
|
|
|
/// TypeScript Isolated Declarations for Standalone DTS Emit (async)
|
|
///
|
|
/// Note: This function can be slower than `isolatedDeclarationSync` due to the overhead of spawning a thread.
|
|
#[napi]
|
|
pub fn isolated_declaration(
|
|
filename: String,
|
|
source_text: String,
|
|
options: Option<IsolatedDeclarationsOptions>,
|
|
) -> AsyncTask<IsolatedDeclarationTask> {
|
|
AsyncTask::new(IsolatedDeclarationTask { filename, source_text, options })
|
|
}
|