Skip to content

feat(lint): handle jsdoc and tsdoc syntax in nounusedimports #5698

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Danielku15
Copy link

Summary

#4677

Adds the initial foundation for detecting type usage in JSDoc and TSDoc comments to avoid imports being flagged as unused.

  • The general contextual model approach is adapted from use_hook_at_top_level.rs 1
  • The parser for the doc content is currently built via regex and not very sophisticated. Creating a proper parser like its done for other syntax formats (Markdown, CSS, JS, TS,..) is likely beneifical.
  • Following JSDocs are not detected:
    • JS Doc class fields (this.field = initializers in constructor) - Performance impact might be quite high if we handle all assignment expression statements.
    • JS Typedefs - They are standalone JSDocs which are hard to catch unless we parse everything. Maybe people should anyhow use /** @typedef {import('module').Type} Alias */ in such cases instead of adding an import?

Test Plan

I added a variety of spec-tests which should show that things are mostly working as expected. Especially for TypeScript things should be well covered for most use-cases. For JSDoc I am a bit more reserved.

Footnotes

  1. https://github.com/biomejs/biome/issues/4677#issuecomment-2813648388

@github-actions github-actions bot added A-Project Area: project A-Linter Area: linter L-JavaScript Language: JavaScript and super languages labels Apr 17, 2025
@Danielku15 Danielku15 changed the title feat(noUnusedImports): Handle JSDoc and TSDoc syntax feat(nounusedimports): Handle JSDoc and TSDoc syntax Apr 17, 2025
@Danielku15 Danielku15 changed the title feat(nounusedimports): Handle JSDoc and TSDoc syntax feat(lint): handle jsdoc and tsdoc syntax in nounusedimports Apr 17, 2025
Copy link
Contributor

@arendjr arendjr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! You mentioned this is your first venture into Rust? Even more impressive!

Great test cases, clear implementation, and limitations well documented 👍

Do you want to add a changeset still?

LazyLock::new(|| Regex::new(r"\{@(link|see)\s*([^}| #\.]+)(?:[^}]+)?\}").unwrap());

static JSDOC_TYPE_TAG_REGEX: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"@(param|returns|type|typedef)\s*\{([^}]+)}").unwrap());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose the last } doesn't really need escaping, but let's stay on the safe side :)

Suggested change
LazyLock::new(|| Regex::new(r"@(param|returns|type|typedef)\s*\{([^}]+)}").unwrap());
LazyLock::new(|| Regex::new(r"@(param|returns|type|typedef)\s*\{([^}]+)\}").unwrap());

}

fn load_jsdoc_types_from_node(model: &mut JsDocTypeModel, node: &SyntaxNode<JsLanguage>) {
if let Ok(comment) = JsdocComment::try_from(node) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do the regular expressions need to be able to work across newlines? If not, maybe you can even use JsdocComment::text_is_jsdoc_comment() only and avoid instantiating the JsdocComment itself. The regular expressions may just work fine on the raw string, so you would avoid some allocation and unnecesssary work in that case.

Copy link

codspeed-hq bot commented Apr 18, 2025

CodSpeed Performance Report

Merging #5698 will not alter performance

Comparing Danielku15:feat/jsdocs-types (cf0bf0b) with main (f3c34de)

Summary

✅ 95 untouched benchmarks

match event {
WalkEvent::Enter(node) => {
if AnyJsWithTypeReferencingJsDoc::can_cast(node.kind()) {
load_jsdoc_types_from_node(&mut self.jsdoc_types, &node);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
load_jsdoc_types_from_node(&mut self.jsdoc_types, &node);
load_jsdoc_types_from_node(&mut self.jsdoc_types, node);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Linter Area: linter A-Project Area: project L-JavaScript Language: JavaScript and super languages
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants