Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/oxc_linter/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ mod jsdoc {
pub mod require_property_type;
pub mod require_returns;
pub mod require_returns_description;
pub mod require_returns_type;
pub mod require_yields;
}

Expand Down Expand Up @@ -762,6 +763,7 @@ oxc_macros::declare_all_lint_rules! {
jsdoc::require_property_description,
jsdoc::require_returns,
jsdoc::require_returns_description,
jsdoc::require_returns_type,
jsdoc::require_yields,
tree_shaking::no_side_effects_in_initialization,
}
160 changes: 160 additions & 0 deletions crates/oxc_linter/src/rules/jsdoc/require_returns_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

use crate::{
ast_util::is_function_node,
context::LintContext,
rule::Rule,
utils::{get_function_nearest_jsdoc_node, should_ignore_as_internal, should_ignore_as_private},
AstNode,
};

fn missing_type_diagnostic(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint-plugin-jsdoc(require-returns-type): Missing JSDoc `@returns` type.")
.with_help("Add {type} to `@returns` tag.")
.with_labels([span0.into()])
}

#[derive(Debug, Default, Clone)]
pub struct RequireReturnsType;

declare_oxc_lint!(
/// ### What it does
/// Requires that `@returns` tag has a type value (in curly brackets).
///
/// ### Why is this bad?
/// A `@returns` tag should have a type value.
///
/// ### Example
/// ```javascript
/// // Passing
/// /** @returns {string} */
/// function quux (foo) {}
///
/// // Failing
/// /** @returns */
/// function quux (foo) {}
/// ```
RequireReturnsType,
pedantic,
);

impl Rule for RequireReturnsType {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
if !is_function_node(node) {
return;
}

// If no JSDoc is found, skip
let Some(jsdocs) = get_function_nearest_jsdoc_node(node, ctx)
.and_then(|node| ctx.jsdoc().get_all_by_node(node))
else {
return;
};

let settings = &ctx.settings().jsdoc;
let resolved_returns_tag_name = settings.resolve_tag_name("returns");
for jsdoc in jsdocs
.iter()
.filter(|jsdoc| !should_ignore_as_internal(jsdoc, settings))
.filter(|jsdoc| !should_ignore_as_private(jsdoc, settings))
{
for tag in jsdoc.tags() {
if tag.kind.parsed() != resolved_returns_tag_name {
continue;
}

// If type exists, skip
if let (Some(_), _) = tag.type_comment() {
continue;
};

ctx.diagnostic(missing_type_diagnostic(tag.kind.span));
}
}
}
}

#[test]
fn test() {
use crate::tester::Tester;

let pass = vec![
(
"
/**
* @returns {number}
*/
function quux () {

}
",
None,
None,
),
(
"
/**
* @function
* @returns Foo.
*/
",
None,
None,
),
(
"
/**
* @callback
* @returns Foo.
*/
",
None,
None,
),
];

let fail = vec![
(
"
/**
* @returns
*/
function quux () {

}
",
None,
None,
),
(
"
/**
* @returns Foo.
*/
function quux () {

}
",
None,
None,
),
(
"
/**
* @return Foo.
*/
function quux () {

}
",
None,
Some(serde_json::json!({ "settings": { "jsdoc": {
"tagNamePreference": { "returns": "return", },
}, } })),
),
];

Tester::new(RequireReturnsType::NAME, pass, fail).test_and_snapshot();
}
30 changes: 30 additions & 0 deletions crates/oxc_linter/src/snapshots/require_returns_type.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
source: crates/oxc_linter/src/tester.rs
expression: require_returns_type
---
⚠ eslint-plugin-jsdoc(require-returns-type): Missing JSDoc `@returns` type.
╭─[require_returns_type.tsx:3:17]
2 │ /**
3 │ * @returns
· ────────
4 │ */
╰────
help: Add {type} to `@returns` tag.

⚠ eslint-plugin-jsdoc(require-returns-type): Missing JSDoc `@returns` type.
╭─[require_returns_type.tsx:3:17]
2 │ /**
3 │ * @returns Foo.
· ────────
4 │ */
╰────
help: Add {type} to `@returns` tag.

⚠ eslint-plugin-jsdoc(require-returns-type): Missing JSDoc `@returns` type.
╭─[require_returns_type.tsx:3:17]
2 │ /**
3 │ * @return Foo.
· ───────
4 │ */
╰────
help: Add {type} to `@returns` tag.