Skip to content

Commit

Permalink
feat(noConfusingVoidType): improve doc & code style & use can_cast in…
Browse files Browse the repository at this point in the history
…stead of cast_ref
  • Loading branch information
shulandmimi committed Sep 8, 2023
1 parent ab743e0 commit f7db11e
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rome_analyze::{declare_rule, Ast, Rule, RuleDiagnostic};
use rome_analyze::{context::RuleContext, declare_rule, Ast, Rule, RuleDiagnostic};
use rome_console::markup;
use rome_js_syntax::{
AnyTsType, TsDefaultTypeClause, TsIntersectionTypeElementList, TsParenthesizedType,
Expand All @@ -9,11 +9,12 @@ use rome_rowan::{AstNode, SyntaxNode, SyntaxNodeCast};

declare_rule! {
///
/// Disallow void type outside of generic or return types.
/// Disallow `void` type outside of generic or return types.
///
/// void in TypeScript refers to a function return that is meant to be ignored. Attempting to use a void type outside of a return type or generic type argument is often a sign of programmer error. void can also be misleading for other developers even if used correctly.
/// `void` in TypeScript refers to a function return that is meant to be ignored. Attempting to use a void type outside of a return type or generic type argument is often a sign of programmer error. void can also be misleading for other developers even if used correctly.
///
/// > The void type means cannot be mixed with any other types, other than never, which accepts all types. If you think you need this then you probably want the undefined type instead.
/// > The `void` type means cannot be mixed with any other types, other than `never`, which accepts all types.
/// > If you think you need this then you probably want the undefined type instead.
///
/// ## Examples
/// ### Invalid
Expand Down Expand Up @@ -43,6 +44,11 @@ declare_rule! {
///
/// ```ts
/// function foo(): void {};
/// function doSomething(this: void) {}
/// function printArg<T = void>(arg: T) {}
/// logAndReturn<void>(undefined);
/// let voidPromise: Promise<void> = new Promise<void>(() => { });
/// let voidMap: Map<string, void> = new Map<string, void>();
/// ```
///
pub(crate) NoConfusingVoidType {
Expand All @@ -62,14 +68,11 @@ pub enum VoidTypeIn {

impl Rule for NoConfusingVoidType {
type Query = Ast<AnyTsType>;

type State = VoidTypeIn;

type Signals = Option<Self::State>;

type Options = ();

fn run(ctx: &rome_analyze::context::RuleContext<Self>) -> Self::Signals {
fn run(ctx: &RuleContext<Self>) -> Self::Signals {
let node = ctx.query();

if let AnyTsType::TsVoidType(node) = node {
Expand All @@ -96,29 +99,29 @@ fn node_in(node: &SyntaxNode<Language>) -> Option<VoidTypeIn> {
let parent = node.parent()?;

// (string | void)
if let Some(n) = parent.cast_ref::<TsParenthesizedType>() {
return node_in(n.syntax());
if TsParenthesizedType::can_cast(parent.kind()) {
return node_in(&parent);
}

// string | void
if let Some(n) = parent.cast_ref::<TsUnionTypeVariantList>() {
return node_in(n.syntax());
if TsUnionTypeVariantList::can_cast(parent.kind()) {
return node_in(&parent);
}

// string & void
if let Some(n) = parent.cast_ref::<TsIntersectionTypeElementList>() {
return node_in(n.syntax());
if TsIntersectionTypeElementList::can_cast(parent.kind()) {
return node_in(&parent);
}

// arg: void
if let Some(n) = parent.cast_ref::<TsTypeAnnotation>() {
return node_in(n.syntax());
if TsTypeAnnotation::can_cast(parent.kind()) {
return node_in(&parent);
}

// fn<T = void>() {}
// T = void
if let Some(n) = parent.cast_ref::<TsDefaultTypeClause>() {
return node_in(n.syntax());
if TsDefaultTypeClause::can_cast(parent.kind()) {
return node_in(&parent);
}

// string | void or string & void
Expand All @@ -131,19 +134,17 @@ fn node_in(node: &SyntaxNode<Language>) -> Option<VoidTypeIn> {
}

// function fn(this: void) {}
if parent.cast_ref::<TsThisParameter>().is_some() {
if TsThisParameter::can_cast(parent.kind()) {
return None;
}

// fn(): void;
if parent.cast_ref::<TsReturnTypeAnnotation>().is_some() {
if TsReturnTypeAnnotation::can_cast(parent.kind()) {
return None;
}

// fn<T = void>() {} or Promise<void>
if parent.cast_ref::<TsTypeParameter>().is_some()
|| parent.cast_ref::<TsTypeArgumentList>().is_some()
{
if TsTypeParameter::can_cast(parent.kind()) || TsTypeArgumentList::can_cast(parent.kind()) {
return None;
}

Expand Down
2 changes: 1 addition & 1 deletion website/src/content/docs/linter/rules/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ Disallow primitive type aliases and misleading types.
### [noConfusingArrow](/linter/rules/no-confusing-arrow)
Disallow arrow functions where they could be confused with comparisons.
### [noConfusingVoidType](/linter/rules/no-confusing-void-type)
Disallow void type outside of generic or return types.
Disallow <code>void</code> type outside of generic or return types.
### [noConstantCondition](/linter/rules/no-constant-condition)
Disallow constant expressions in conditions
### [noControlCharactersInRegex](/linter/rules/no-control-characters-in-regex)
Expand Down
12 changes: 9 additions & 3 deletions website/src/content/docs/linter/rules/no-confusing-void-type.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ title: noConfusingVoidType (since v1.0.0)
---


Disallow void type outside of generic or return types.
Disallow `void` type outside of generic or return types.

void in TypeScript refers to a function return that is meant to be ignored. Attempting to use a void type outside of a return type or generic type argument is often a sign of programmer error. void can also be misleading for other developers even if used correctly.
`void` in TypeScript refers to a function return that is meant to be ignored. Attempting to use a void type outside of a return type or generic type argument is often a sign of programmer error. void can also be misleading for other developers even if used correctly.

>The void type means cannot be mixed with any other types, other than never, which accepts all types. If you think you need this then you probably want the undefined type instead.
>The `void` type means cannot be mixed with any other types, other than `never`, which accepts all types.
If you think you need this then you probably want the undefined type instead.


## Examples
Expand Down Expand Up @@ -102,6 +103,11 @@ nursery/noConfusingVoidType.js:2:27 <a href="https://biomejs.dev/linter/rules/no

```ts
function foo(): void {};
function doSomething(this: void) {}
function printArg<T = void>(arg: T) {}
logAndReturn<void>(undefined);
let voidPromise: Promise<void> = new Promise<void>(() => { });
let voidMap: Map<string, void> = new Map<string, void>();
```

## Related links
Expand Down

0 comments on commit f7db11e

Please sign in to comment.