mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
docs(semantic): add doc comments for SymbolTester and SemanticTester (#4433)
This commit is contained in:
parent
4f5a7cbf3c
commit
871b3d6135
4 changed files with 76 additions and 1 deletions
|
|
@ -147,6 +147,9 @@ impl<'a> SemanticBuilder<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Enable or disable building a [`ControlFlowGraph`].
|
||||
///
|
||||
/// [`ControlFlowGraph`]: oxc_cfg::ControlFlowGraph
|
||||
#[must_use]
|
||||
pub fn with_cfg(mut self, cfg: bool) -> Self {
|
||||
self.cfg = if cfg { Some(ControlFlowGraphBuilder::default()) } else { None };
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ fn test_types_simple() {
|
|||
.has_some_symbol("T")
|
||||
.contains_flags(SymbolFlags::TypeParameter)
|
||||
.has_number_of_references(1)
|
||||
.has_number_of_references_where(1, oxc_semantic::Reference::is_type)
|
||||
.has_number_of_references_where(1, Reference::is_type)
|
||||
.test();
|
||||
|
||||
SemanticTester::ts("function foo<T>(a: T): void {}")
|
||||
|
|
|
|||
|
|
@ -15,9 +15,15 @@ pub use symbol_tester::SymbolTester;
|
|||
|
||||
#[must_use]
|
||||
pub struct SemanticTester<'a> {
|
||||
/// Memory arena that AST and [`Semantic`] will store data in.
|
||||
allocator: Allocator,
|
||||
/// Source type of the test case.
|
||||
source_type: SourceType,
|
||||
/// The source text of the test case.
|
||||
source_text: &'a str,
|
||||
/// Build a [`ControlFlowGraph`]?
|
||||
///
|
||||
/// [`ControlFlowGraph`]: oxc_cfg::ControlFlowGraph
|
||||
cfg: bool,
|
||||
/// Expect semantic analysis to produce errors.
|
||||
///
|
||||
|
|
@ -47,6 +53,10 @@ impl<'a> SemanticTester<'a> {
|
|||
Self::new(source_text, SourceType::default().with_module(true))
|
||||
}
|
||||
|
||||
/// Create a new tester for some source text.
|
||||
///
|
||||
/// You may find one of the other factory methods, like
|
||||
/// [`SemanticTester::ts`] or [`SemanticTester::js`], more convenient.
|
||||
pub fn new(source_text: &'a str, source_type: SourceType) -> Self {
|
||||
Self {
|
||||
allocator: Allocator::default(),
|
||||
|
|
@ -64,20 +74,27 @@ impl<'a> SemanticTester<'a> {
|
|||
}
|
||||
|
||||
/// Mark the [`SourceType`] as JSX
|
||||
///
|
||||
/// If the source is currently TypeScript, it will become TSX.
|
||||
pub fn with_jsx(mut self, yes: bool) -> Self {
|
||||
self.source_type = self.source_type.with_jsx(yes);
|
||||
self
|
||||
}
|
||||
|
||||
/// Mark the [`SourceType`] as an ESM module.
|
||||
pub fn with_module(mut self, yes: bool) -> Self {
|
||||
self.source_type = self.source_type.with_module(yes);
|
||||
self
|
||||
}
|
||||
|
||||
/// Enable or disable building a [`ControlFlowGraph`].
|
||||
///
|
||||
/// [`ControlFlowGraph`]: oxc_cfg::ControlFlowGraph
|
||||
pub fn with_cfg(mut self, yes: bool) -> Self {
|
||||
self.cfg = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// The program being tested is expected to produce errors during semantic analysis.
|
||||
///
|
||||
/// By default, programs are expected to be error-free.
|
||||
|
|
@ -201,6 +218,16 @@ impl<'a> SemanticTester<'a> {
|
|||
ClassTester::has_class(self.build(), name)
|
||||
}
|
||||
|
||||
/// Check if semantic analysis produces an error matching `message`.
|
||||
///
|
||||
/// Matching is done using `.contains()`.
|
||||
///
|
||||
/// ## Fails
|
||||
/// - If [`parsing`] produces errors
|
||||
/// - If [`SemanticBuilder`] finishes without producing any errors.
|
||||
/// - If [`SemanticBuilder`] finishes with errors, but none of them match `message`
|
||||
///
|
||||
/// [`parsing`]: oxc_parser::Parser::parse
|
||||
pub fn has_error(&self, message: &str) {
|
||||
let SemanticBuilderReturn { errors, .. } = self.build_with_errors();
|
||||
assert!(
|
||||
|
|
|
|||
|
|
@ -6,6 +6,30 @@ use oxc_span::CompactStr;
|
|||
|
||||
use super::{Expect, SemanticTester};
|
||||
|
||||
/// Test a symbol in the [`Semantic`] analysis results.
|
||||
///
|
||||
/// To use this, chain together assertions about the symbol, such as
|
||||
/// [`SymbolTester::contains_flags`], [`SymbolTester::has_number_of_reads`],
|
||||
/// etc., then finish the chain off with a call to [`SymbolTester::test`].
|
||||
///
|
||||
/// You will never create this struct manually. Instead, use one of
|
||||
/// [`SemanticTester`]'s factories, such as [`SemanticTester::has_root_symbol`].
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use oxc_semantic::{SymbolFlags, Semantic};
|
||||
/// use super::SemanticTester;
|
||||
///
|
||||
/// #[test]
|
||||
/// fn my_test() {
|
||||
/// SemanticTester::js("let x = 0; let foo = (0, x++)")
|
||||
/// .has_some_symbol("x") // find a symbol named "x" at any scope
|
||||
/// .contains_flags(SymbolFlags::Variable) // check that it's a variable
|
||||
/// .has_number_of_reads(1) // check read references
|
||||
/// .has_number_of_writes(1) // check write references
|
||||
/// .test(); // finish the test. Will panic if any assertions failed.
|
||||
/// }
|
||||
///```
|
||||
#[must_use]
|
||||
pub struct SymbolTester<'a> {
|
||||
parent: &'a SemanticTester<'a>,
|
||||
|
|
@ -131,18 +155,27 @@ impl<'a> SymbolTester<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Check that this symbol has a certain number of read [`Reference`]s
|
||||
///
|
||||
/// References that are both read and write are counted.
|
||||
pub fn has_number_of_reads(self, ref_count: usize) -> Self {
|
||||
self.has_number_of_references_where(ref_count, Reference::is_read)
|
||||
}
|
||||
|
||||
/// Check that this symbol has a certain number of write [`Reference`]s.
|
||||
///
|
||||
/// References that are both read and write are counted.
|
||||
pub fn has_number_of_writes(self, ref_count: usize) -> Self {
|
||||
self.has_number_of_references_where(ref_count, Reference::is_write)
|
||||
}
|
||||
|
||||
/// Check that this symbol has a certain number of [`Reference`]s of any kind.
|
||||
pub fn has_number_of_references(self, ref_count: usize) -> Self {
|
||||
self.has_number_of_references_where(ref_count, |_| true)
|
||||
}
|
||||
|
||||
/// Check that this symbol has a certain number of [`Reference`]s that meet
|
||||
/// some criteria established by a predicate.
|
||||
pub fn has_number_of_references_where<F>(mut self, ref_count: usize, filter: F) -> Self
|
||||
where
|
||||
F: FnMut(&Reference) -> bool,
|
||||
|
|
@ -170,6 +203,12 @@ impl<'a> SymbolTester<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Check that this symbol is exported.
|
||||
///
|
||||
/// Export status is checked using the symbol's [`SymbolFlags`], not by
|
||||
/// checking the [`oxc_semantic::ModuleRecord`].
|
||||
///
|
||||
/// For the inverse of this assertion, use [`SymbolTester::is_not_exported`].
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn is_exported(mut self) -> Self {
|
||||
self.test_result = match self.test_result {
|
||||
|
|
@ -188,6 +227,12 @@ impl<'a> SymbolTester<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Check that this symbol is not exported.
|
||||
///
|
||||
/// Export status is checked using the symbol's [`SymbolFlags`], not by
|
||||
/// checking the [`oxc_semantic::ModuleRecord`].
|
||||
///
|
||||
/// For the inverse of this assertion, use [`SymbolTester::is_exported`].
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn is_not_exported(mut self) -> Self {
|
||||
self.test_result = match self.test_result {
|
||||
|
|
|
|||
Loading…
Reference in a new issue