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 @@ -394,6 +394,7 @@ mod jsdoc {
pub mod no_defaults;
pub mod require_param;
pub mod require_param_description;
pub mod require_param_name;
pub mod require_param_type;
pub mod require_property;
pub mod require_property_description;
Expand Down Expand Up @@ -766,6 +767,7 @@ oxc_macros::declare_all_lint_rules! {
jsdoc::no_defaults,
jsdoc::require_param,
jsdoc::require_param_description,
jsdoc::require_param_name,
jsdoc::require_param_type,
jsdoc::require_property,
jsdoc::require_property_type,
Expand Down
188 changes: 188 additions & 0 deletions crates/oxc_linter/src/rules/jsdoc/require_param_name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
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_name_diagnostic(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint-plugin-jsdoc(require-param-name): Missing JSDoc `@param` name.")
.with_help("Add name to `@param` tag.")
.with_labels([span0.into()])
}

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

declare_oxc_lint!(
/// ### What it does
/// Requires that all `@param` tags have names.
///
/// ### Why is this bad?
/// The name of a param should be documented.
///
/// ### Example
/// ```javascript
/// // Passing
/// /** @param {SomeType} foo */
/// function quux (foo) {}
///
/// // Failing
/// /** @param {SomeType} */
/// function quux (foo) {}
/// ```
RequireParamName,
pedantic,
);

impl Rule for RequireParamName {
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_param_tag_name = settings.resolve_tag_name("param");

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_param_tag_name {
continue;
}

let (_, name_part, _) = tag.type_name_comment();

// If name exists, skip
if name_part.is_some() {
continue;
}

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

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

let pass = vec![
(
"
/**
* @param foo
*/
function quux (foo) {

}
",
None,
None,
),
(
"
/**
* @param {string} foo
*/
function quux (foo) {

}
",
None,
None,
),
(
"
/**
* @function
* @param
*/
",
None,
None,
),
(
"
/**
* @callback
* @param
*/
",
None,
None,
),
(
"
/**
* @param {Function} [processor=data => data] A function to run
*/
function processData(processor) {
return processor(data)
}
",
None,
None,
),
(
"
/** Example with multi-line param type.
*
* @param {function(
* number
* )} cb Callback.
*/
function example(cb) {
cb(42);
}
",
None,
None,
),
];

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

}
",
None,
None,
),
(
"
/**
* @param {string}
*/
function quux (foo) {

}
",
None,
None,
),
];

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

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