mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
feat(linter/jsdoc): Support settings.ignore(Private|Internal) (#3147)
> https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/settings.md#user-content-settings-allow-tags-private-or-internal-to-disable-rules-for-that-comment-block ...and fixed the issue that intended initial settings values are not used in some cases.
This commit is contained in:
parent
8cdd5b0fd8
commit
d7a8345e4c
14 changed files with 173 additions and 26 deletions
|
|
@ -17,7 +17,8 @@ use self::errors::{
|
|||
FailedToParseJsonc,
|
||||
};
|
||||
pub use self::{
|
||||
env::ESLintEnv, globals::ESLintGlobals, rules::ESLintRules, settings::ESLintSettings,
|
||||
env::ESLintEnv, globals::ESLintGlobals, rules::ESLintRules,
|
||||
settings::jsdoc::JSDocPluginSettings, settings::ESLintSettings,
|
||||
};
|
||||
|
||||
/// ESLint Config
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use rustc_hash::FxHashMap;
|
|||
use serde::Deserialize;
|
||||
|
||||
/// <https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/settings.md>
|
||||
#[derive(Debug, Deserialize, Default)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct JSDocPluginSettings {
|
||||
/// For all rules but NOT apply to `check-access` and `empty-tags` rule
|
||||
#[serde(default, rename = "ignorePrivate")]
|
||||
|
|
@ -70,6 +70,23 @@ pub struct JSDocPluginSettings {
|
|||
// }[]
|
||||
}
|
||||
|
||||
// `Default` attribute does not call custom `default = "path"` function!
|
||||
impl Default for JSDocPluginSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
ignore_private: false,
|
||||
ignore_internal: false,
|
||||
// Exists only for these defaults
|
||||
ignore_replaces_docs: true,
|
||||
override_replaces_docs: true,
|
||||
arguments_extends_replaces_docs: false,
|
||||
implements_replaces_docs: false,
|
||||
exempt_destructured_roots_from_checks: false,
|
||||
tag_name_preference: FxHashMap::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl JSDocPluginSettings {
|
||||
/// Only for `check-tag-names` rule
|
||||
/// Return `Some(reason)` if blocked
|
||||
|
|
@ -187,6 +204,16 @@ mod test {
|
|||
assert!(settings.override_replaces_docs);
|
||||
assert!(!settings.arguments_extends_replaces_docs);
|
||||
assert!(!settings.implements_replaces_docs);
|
||||
|
||||
let settings = JSDocPluginSettings::default();
|
||||
|
||||
assert!(!settings.ignore_private);
|
||||
assert!(!settings.ignore_internal);
|
||||
assert_eq!(settings.tag_name_preference.len(), 0);
|
||||
assert!(settings.ignore_replaces_docs);
|
||||
assert!(settings.override_replaces_docs);
|
||||
assert!(!settings.arguments_extends_replaces_docs);
|
||||
assert!(!settings.implements_replaces_docs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use self::{
|
|||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
mod jsdoc;
|
||||
pub mod jsdoc;
|
||||
mod jsx_a11y;
|
||||
mod next;
|
||||
mod react;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use oxc_span::Span;
|
|||
use phf::phf_set;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
use crate::{context::LintContext, rule::Rule};
|
||||
use crate::{context::LintContext, rule::Rule, utils::should_ignore_as_internal};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
enum CheckAccessDiagnostic {
|
||||
|
|
@ -75,7 +75,12 @@ impl Rule for CheckAccess {
|
|||
access_related_tag_names.insert(settings.resolve_tag_name(level));
|
||||
}
|
||||
|
||||
for jsdoc in ctx.semantic().jsdoc().iter_all() {
|
||||
for jsdoc in ctx
|
||||
.semantic()
|
||||
.jsdoc()
|
||||
.iter_all()
|
||||
.filter(|jsdoc| !should_ignore_as_internal(jsdoc, settings))
|
||||
{
|
||||
let mut access_related_tags_count = 0;
|
||||
for tag in jsdoc.tags() {
|
||||
let tag_name = tag.kind.parsed();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@ use oxc_macros::declare_oxc_lint;
|
|||
use oxc_span::Span;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
use crate::{context::LintContext, rule::Rule};
|
||||
use crate::{
|
||||
context::LintContext,
|
||||
rule::Rule,
|
||||
utils::{should_ignore_as_internal, should_ignore_as_private},
|
||||
};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
enum CheckPropertyNamesDiagnostic {
|
||||
|
|
@ -63,7 +67,13 @@ impl Rule for CheckPropertyNames {
|
|||
let settings = &ctx.settings().jsdoc;
|
||||
let resolved_property_tag_name = settings.resolve_tag_name("property");
|
||||
|
||||
for jsdoc in ctx.semantic().jsdoc().iter_all() {
|
||||
for jsdoc in ctx
|
||||
.semantic()
|
||||
.jsdoc()
|
||||
.iter_all()
|
||||
.filter(|jsdoc| !should_ignore_as_internal(jsdoc, settings))
|
||||
.filter(|jsdoc| !should_ignore_as_private(jsdoc, settings))
|
||||
{
|
||||
let mut seen: FxHashMap<&str, FxHashSet<Span>> = FxHashMap::default();
|
||||
for tag in jsdoc.tags() {
|
||||
if tag.kind.parsed() != resolved_property_tag_name {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@ use oxc_span::Span;
|
|||
use phf::phf_set;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{context::LintContext, rule::Rule};
|
||||
use crate::{
|
||||
context::LintContext,
|
||||
rule::Rule,
|
||||
utils::{should_ignore_as_internal, should_ignore_as_private},
|
||||
};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("eslint-plugin-jsdoc(check-tag-names): Invalid tag name found.")]
|
||||
|
|
@ -212,7 +216,13 @@ impl Rule for CheckTagNames {
|
|||
let is_declare = false;
|
||||
let is_ambient = is_dts || is_declare;
|
||||
|
||||
for jsdoc in ctx.semantic().jsdoc().iter_all() {
|
||||
for jsdoc in ctx
|
||||
.semantic()
|
||||
.jsdoc()
|
||||
.iter_all()
|
||||
.filter(|jsdoc| !should_ignore_as_internal(jsdoc, settings))
|
||||
.filter(|jsdoc| !should_ignore_as_private(jsdoc, settings))
|
||||
{
|
||||
for tag in jsdoc.tags() {
|
||||
let tag_name = tag.kind.parsed();
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use oxc_span::Span;
|
|||
use phf::phf_set;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{context::LintContext, rule::Rule};
|
||||
use crate::{context::LintContext, rule::Rule, utils::should_ignore_as_private};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("eslint-plugin-jsdoc(empty-tags): Expects the void tags to be empty of any content.")]
|
||||
|
|
@ -95,6 +95,8 @@ impl Rule for EmptyTags {
|
|||
}
|
||||
|
||||
fn run_once(&self, ctx: &LintContext) {
|
||||
let settings = &ctx.settings().jsdoc;
|
||||
|
||||
let is_empty_tag_kind = |tag_name: &str| {
|
||||
if EMPTY_TAGS.contains(tag_name) {
|
||||
return true;
|
||||
|
|
@ -105,7 +107,12 @@ impl Rule for EmptyTags {
|
|||
false
|
||||
};
|
||||
|
||||
for jsdoc in ctx.semantic().jsdoc().iter_all() {
|
||||
for jsdoc in ctx
|
||||
.semantic()
|
||||
.jsdoc()
|
||||
.iter_all()
|
||||
.filter(|jsdoc| !should_ignore_as_private(jsdoc, settings))
|
||||
{
|
||||
for tag in jsdoc.tags() {
|
||||
let tag_name = tag.kind.parsed();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
use crate::{
|
||||
ast_util::is_function_node, context::LintContext, rule::Rule,
|
||||
utils::get_function_nearest_jsdoc_node, AstNode,
|
||||
ast_util::is_function_node,
|
||||
context::LintContext,
|
||||
rule::Rule,
|
||||
utils::{get_function_nearest_jsdoc_node, should_ignore_as_internal, should_ignore_as_private},
|
||||
AstNode,
|
||||
};
|
||||
use oxc_ast::AstKind;
|
||||
use oxc_diagnostics::{
|
||||
|
|
@ -93,7 +96,11 @@ impl Rule for ImplementsOnClasses {
|
|||
let resolved_constructor_tag_name = settings.resolve_tag_name("constructor");
|
||||
|
||||
let (mut implements_found, mut class_or_ctor_found) = (None, false);
|
||||
for jsdoc in &jsdocs {
|
||||
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() {
|
||||
let tag_name = tag.kind.parsed();
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,11 @@ use oxc_span::Span;
|
|||
use serde::Deserialize;
|
||||
|
||||
use crate::{
|
||||
ast_util::is_function_node, context::LintContext, rule::Rule,
|
||||
utils::get_function_nearest_jsdoc_node, AstNode,
|
||||
ast_util::is_function_node,
|
||||
context::LintContext,
|
||||
rule::Rule,
|
||||
utils::{get_function_nearest_jsdoc_node, should_ignore_as_internal, should_ignore_as_private},
|
||||
AstNode,
|
||||
};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
|
|
@ -74,7 +77,11 @@ impl Rule for NoDefaults {
|
|||
let resolved_param_tag_name = settings.resolve_tag_name("param");
|
||||
let config = &self.0;
|
||||
|
||||
for jsdoc in jsdocs {
|
||||
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() {
|
||||
let tag_name = tag.kind.parsed();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ use oxc_diagnostics::{
|
|||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_span::Span;
|
||||
|
||||
use crate::{context::LintContext, rule::Rule};
|
||||
use crate::{
|
||||
context::LintContext,
|
||||
rule::Rule,
|
||||
utils::{should_ignore_as_internal, should_ignore_as_private},
|
||||
};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("eslint-plugin-jsdoc(require-property): The `@typedef` and `@namespace` tags must include a `@property` tag with the type Object.")]
|
||||
|
|
@ -58,7 +62,13 @@ impl Rule for RequireProperty {
|
|||
let resolved_typedef_tag_name = settings.resolve_tag_name("typedef");
|
||||
let resolved_namespace_tag_name = settings.resolve_tag_name("namespace");
|
||||
|
||||
for jsdoc in ctx.semantic().jsdoc().iter_all() {
|
||||
for jsdoc in ctx
|
||||
.semantic()
|
||||
.jsdoc()
|
||||
.iter_all()
|
||||
.filter(|jsdoc| !should_ignore_as_internal(jsdoc, settings))
|
||||
.filter(|jsdoc| !should_ignore_as_private(jsdoc, settings))
|
||||
{
|
||||
let mut should_report = None;
|
||||
for tag in jsdoc.tags() {
|
||||
let tag_name = tag.kind.parsed();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ use oxc_diagnostics::{
|
|||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_span::Span;
|
||||
|
||||
use crate::{context::LintContext, rule::Rule};
|
||||
use crate::{
|
||||
context::LintContext,
|
||||
rule::Rule,
|
||||
utils::{should_ignore_as_internal, should_ignore_as_private},
|
||||
};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("eslint-plugin-jsdoc(require-property-description): Missing description in @property tag.")]
|
||||
|
|
@ -45,7 +49,13 @@ impl Rule for RequirePropertyDescription {
|
|||
let settings = &ctx.settings().jsdoc;
|
||||
let resolved_property_tag_name = settings.resolve_tag_name("property");
|
||||
|
||||
for jsdoc in ctx.semantic().jsdoc().iter_all() {
|
||||
for jsdoc in ctx
|
||||
.semantic()
|
||||
.jsdoc()
|
||||
.iter_all()
|
||||
.filter(|jsdoc| !should_ignore_as_internal(jsdoc, settings))
|
||||
.filter(|jsdoc| !should_ignore_as_private(jsdoc, settings))
|
||||
{
|
||||
for tag in jsdoc.tags() {
|
||||
let tag_name = tag.kind;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ use oxc_diagnostics::{
|
|||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_span::Span;
|
||||
|
||||
use crate::{context::LintContext, rule::Rule};
|
||||
use crate::{
|
||||
context::LintContext,
|
||||
rule::Rule,
|
||||
utils::{should_ignore_as_internal, should_ignore_as_private},
|
||||
};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("eslint-plugin-jsdoc(require-property-name): Missing name in @property tag.")]
|
||||
|
|
@ -45,7 +49,13 @@ impl Rule for RequirePropertyName {
|
|||
let settings = &ctx.settings().jsdoc;
|
||||
let resolved_property_tag_name = settings.resolve_tag_name("property");
|
||||
|
||||
for jsdoc in ctx.semantic().jsdoc().iter_all() {
|
||||
for jsdoc in ctx
|
||||
.semantic()
|
||||
.jsdoc()
|
||||
.iter_all()
|
||||
.filter(|jsdoc| !should_ignore_as_internal(jsdoc, settings))
|
||||
.filter(|jsdoc| !should_ignore_as_private(jsdoc, settings))
|
||||
{
|
||||
for tag in jsdoc.tags() {
|
||||
let tag_name = tag.kind;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ use oxc_diagnostics::{
|
|||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_span::Span;
|
||||
|
||||
use crate::{context::LintContext, rule::Rule};
|
||||
use crate::{
|
||||
context::LintContext,
|
||||
rule::Rule,
|
||||
utils::{should_ignore_as_internal, should_ignore_as_private},
|
||||
};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("eslint-plugin-jsdoc(require-property-type): Missing type in @property tag.")]
|
||||
|
|
@ -45,7 +49,13 @@ impl Rule for RequirePropertyType {
|
|||
let settings = &ctx.settings().jsdoc;
|
||||
let resolved_property_tag_name = settings.resolve_tag_name("property");
|
||||
|
||||
for jsdoc in ctx.semantic().jsdoc().iter_all() {
|
||||
for jsdoc in ctx
|
||||
.semantic()
|
||||
.jsdoc()
|
||||
.iter_all()
|
||||
.filter(|jsdoc| !should_ignore_as_internal(jsdoc, settings))
|
||||
.filter(|jsdoc| !should_ignore_as_private(jsdoc, settings))
|
||||
{
|
||||
for tag in jsdoc.tags() {
|
||||
let tag_name = tag.kind;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::{context::LintContext, AstNode};
|
||||
use crate::{config::JSDocPluginSettings, context::LintContext, AstNode};
|
||||
use oxc_ast::AstKind;
|
||||
use oxc_semantic::JSDoc;
|
||||
|
||||
/// JSDoc is often attached on the parent node of a function.
|
||||
///
|
||||
|
|
@ -36,3 +37,35 @@ pub fn get_function_nearest_jsdoc_node<'a, 'b>(
|
|||
|
||||
Some(current_node)
|
||||
}
|
||||
|
||||
pub fn should_ignore_as_internal(jsdoc: &JSDoc, settings: &JSDocPluginSettings) -> bool {
|
||||
if settings.ignore_internal {
|
||||
let resolved_internal_tag_name = settings.resolve_tag_name("internal");
|
||||
|
||||
for tag in jsdoc.tags() {
|
||||
if tag.kind.parsed() == resolved_internal_tag_name {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn should_ignore_as_private(jsdoc: &JSDoc, settings: &JSDocPluginSettings) -> bool {
|
||||
if settings.ignore_private {
|
||||
let resolved_private_tag_name = settings.resolve_tag_name("private");
|
||||
let resolved_access_tag_name = settings.resolve_tag_name("access");
|
||||
|
||||
for tag in jsdoc.tags() {
|
||||
let tag_name = tag.kind.parsed();
|
||||
if tag_name == resolved_private_tag_name
|
||||
|| tag_name == resolved_access_tag_name && tag.comment().parsed() == "private"
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue