mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
docs(linter): add docs to no-unused-vars and Tester (#6558)
Misc doc changes made while authoring the previous PR in this stack.
This commit is contained in:
parent
1e7fab32fd
commit
557f94104e
3 changed files with 61 additions and 7 deletions
|
|
@ -25,6 +25,10 @@ fn fixme() {
|
||||||
Tester::new(NoUnusedVars::NAME, pass, fail).intentionally_allow_no_fix_tests().test();
|
Tester::new(NoUnusedVars::NAME, pass, fail).intentionally_allow_no_fix_tests().test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// !!!! STOP !!!
|
||||||
|
/// Are you fixing a bug in this rules and want to add a test case? Please put
|
||||||
|
/// it in `oxc.rs`. These are _only_ the test cases ported from the original
|
||||||
|
/// ESLint rule.
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
let pass = vec![
|
let pass = vec![
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,25 @@ use oxc_span::{GetSpan, Span};
|
||||||
use super::{ignored::FoundStatus, NoUnusedVars, Symbol};
|
use super::{ignored::FoundStatus, NoUnusedVars, Symbol};
|
||||||
|
|
||||||
impl<'s, 'a> Symbol<'s, 'a> {
|
impl<'s, 'a> Symbol<'s, 'a> {
|
||||||
|
// =========================================================================
|
||||||
|
// ==================== ENABLE/DISABLE USAGE SUB-CHECKS ====================
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
|
// NOTE(@don): all of these should be `#[inline]` and `const`. by inlining
|
||||||
|
// it, rustc should be able to detect redundant flag checks and optimize
|
||||||
|
// them away. Note that I haven't actually checked the assembly output to
|
||||||
|
// confirm this; if you are reading this and decide to do so, please let me
|
||||||
|
// know the results.
|
||||||
|
|
||||||
/// 1. Imported functions will never have calls to themselves within their
|
/// 1. Imported functions will never have calls to themselves within their
|
||||||
/// own declaration since they are declared outside the current module
|
/// own declaration since they are declared outside the current module
|
||||||
/// 2. Catch variables are always parameter-like and will therefore never have
|
/// 2. Catch variables are always parameter-like and will therefore never have
|
||||||
/// a function declaration.
|
/// a function declaration.
|
||||||
#[inline]
|
#[inline]
|
||||||
const fn is_maybe_callable(&self) -> bool {
|
const fn is_maybe_callable(&self) -> bool {
|
||||||
|
// NOTE: imports are technically callable, but that call will never
|
||||||
|
// occur within its own declaration since it's declared in another
|
||||||
|
// module.
|
||||||
const IMPORT: SymbolFlags = SymbolFlags::Import.union(SymbolFlags::TypeImport);
|
const IMPORT: SymbolFlags = SymbolFlags::Import.union(SymbolFlags::TypeImport);
|
||||||
// note: intetionally do not use `SymbolFlags::is_type` here, since that
|
// note: intetionally do not use `SymbolFlags::is_type` here, since that
|
||||||
// can return `true` for values
|
// can return `true` for values
|
||||||
|
|
@ -59,14 +72,26 @@ impl<'s, 'a> Symbol<'s, 'a> {
|
||||||
&& !f.contains(SymbolFlags::ConstVariable.union(SymbolFlags::Function))
|
&& !f.contains(SymbolFlags::ConstVariable.union(SymbolFlags::Function))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if this [`Symbol`] could be used as a type reference within its
|
||||||
|
/// own declaration.
|
||||||
|
///
|
||||||
|
/// This does _not_ imply this symbol is a type (negative cases include type
|
||||||
|
/// imports, type parameters, etc).
|
||||||
#[inline]
|
#[inline]
|
||||||
const fn could_have_type_reference_within_own_decl(&self) -> bool {
|
const fn could_have_type_reference_within_own_decl(&self) -> bool {
|
||||||
const TYPE_DECLS: SymbolFlags =
|
#[rustfmt::skip]
|
||||||
SymbolFlags::TypeAlias.union(SymbolFlags::Interface).union(SymbolFlags::Class);
|
const TYPE_DECLS: SymbolFlags = SymbolFlags::TypeAlias
|
||||||
|
.union(SymbolFlags::Interface)
|
||||||
|
.union(SymbolFlags::Class);
|
||||||
|
|
||||||
self.flags().intersects(TYPE_DECLS)
|
self.flags().intersects(TYPE_DECLS)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if this [`Symbol`] has an [`Reference`]s that are considered a usage.
|
// =========================================================================
|
||||||
|
// ============================= USAGE CHECKS ==============================
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
|
/// Check if this [`Symbol`] has any [`Reference`]s that are considered a usage.
|
||||||
pub fn has_usages(&self, options: &NoUnusedVars) -> bool {
|
pub fn has_usages(&self, options: &NoUnusedVars) -> bool {
|
||||||
// Use symbol flags to skip the usage checks we are certain don't need
|
// Use symbol flags to skip the usage checks we are certain don't need
|
||||||
// to be run.
|
// to be run.
|
||||||
|
|
@ -87,7 +112,8 @@ impl<'s, 'a> Symbol<'s, 'a> {
|
||||||
);
|
);
|
||||||
assert!(reference.symbol_id().is_some_and(|id| id == self.id()));
|
assert!(reference.symbol_id().is_some_and(|id| id == self.id()));
|
||||||
|
|
||||||
// Write usage checks
|
// ====================== Write usage checks =======================
|
||||||
|
|
||||||
if reference.is_write() {
|
if reference.is_write() {
|
||||||
if do_reassignment_checks
|
if do_reassignment_checks
|
||||||
&& (self.is_assigned_to_ignored_destructure(reference, options)
|
&& (self.is_assigned_to_ignored_destructure(reference, options)
|
||||||
|
|
@ -103,7 +129,8 @@ impl<'s, 'a> Symbol<'s, 'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type usage checks
|
// ======================= Type usage checks =======================
|
||||||
|
|
||||||
if reference.is_type() {
|
if reference.is_type() {
|
||||||
// e.g. `type Foo = Array<Foo>`
|
// e.g. `type Foo = Array<Foo>`
|
||||||
if do_type_self_usage_checks && self.is_type_self_usage(reference) {
|
if do_type_self_usage_checks && self.is_type_self_usage(reference) {
|
||||||
|
|
@ -112,7 +139,7 @@ impl<'s, 'a> Symbol<'s, 'a> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read usage checks
|
// ======================= Read usage checks =======================
|
||||||
|
|
||||||
// e.g. `let a = 0; a = a + 1`
|
// e.g. `let a = 0; a = a + 1`
|
||||||
if do_reassignment_checks && self.is_self_reassignment(reference) {
|
if do_reassignment_checks && self.is_self_reassignment(reference) {
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,30 @@ impl Tester {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the extension of the path
|
/// Change the extension of the path. Do not include the dot.
|
||||||
|
///
|
||||||
|
/// By default, the extension is `tsx`.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
/// ```ignore
|
||||||
|
/// use crate::tester::Tester;
|
||||||
|
/// use oxc_macros::declare_oxc_lint;
|
||||||
|
///
|
||||||
|
/// declare_oxc_lint! (
|
||||||
|
/// /// docs
|
||||||
|
/// MyRule,
|
||||||
|
/// correctness,
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// #[test]
|
||||||
|
/// fn test() {
|
||||||
|
/// let pass = vec!["let x = 1;"];
|
||||||
|
/// let fail = vec![];
|
||||||
|
/// Tester::new(MyRule::NAME, pass, fail)
|
||||||
|
/// .change_rule_path_extension("ts")
|
||||||
|
/// .test_and_snapshot();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
pub fn change_rule_path_extension(mut self, ext: &str) -> Self {
|
pub fn change_rule_path_extension(mut self, ext: &str) -> Self {
|
||||||
self.rule_path = self.rule_path.with_extension(ext);
|
self.rule_path = self.rule_path.with_extension(ext);
|
||||||
self
|
self
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue