use rustc_hash::FxHashMap;
use oxc_ast::{AstKind, ast::Comment};
use oxc_span::{GetSpan, Span};
use super::parser::JSDoc;
pub struct JSDocBuilderResult<'a> {
pub attached: FxHashMap<u32, Vec<JSDoc<'a>>>,
pub not_attached: Vec<JSDoc<'a>>,
}
#[derive(Default)]
pub struct JSDocBuilder<'a> {
not_attached_docs: FxHashMap<u32, Vec<JSDoc<'a>>>,
attached_docs: FxHashMap<u32, Vec<JSDoc<'a>>>,
}
impl<'a> JSDocBuilder<'a> {
pub fn new(source_text: &'a str, comments: &[Comment]) -> Self {
let mut not_attached_docs: FxHashMap<u32, Vec<_>> = FxHashMap::default();
for comment in comments.iter().filter(|comment| comment.is_jsdoc()) {
not_attached_docs
.entry(comment.attached_to)
.or_default()
.push(Self::parse_jsdoc_comment(comment, source_text));
}
Self { not_attached_docs, attached_docs: FxHashMap::default() }
}
pub fn build(self) -> JSDocBuilderResult<'a> {
JSDocBuilderResult {
attached: self.attached_docs,
not_attached: self.not_attached_docs.into_iter().flat_map(|(_, v)| v).collect(),
}
}
pub fn retrieve_attached_jsdoc(&mut self, kind: &AstKind<'a>) -> bool {
if should_attach_jsdoc(kind) {
let start = kind.span().start;
if let Some(docs) = self.not_attached_docs.remove(&start) {
self.attached_docs.insert(start, docs);
return true;
}
}
false
}
fn parse_jsdoc_comment(comment: &Comment, source_text: &'a str) -> JSDoc<'a> {
let span = comment.content_span();
let jsdoc_span = Span::new(span.start + 1, span.end);
let comment_content = jsdoc_span.source_text(source_text);
JSDoc::new(comment_content, jsdoc_span)
}
}
#[rustfmt::skip]
fn should_attach_jsdoc(kind: &AstKind) -> bool {
matches!(kind,
AstKind::BlockStatement(_)
| AstKind::BreakStatement(_)
| AstKind::ContinueStatement(_)
| AstKind::DebuggerStatement(_)
| AstKind::DoWhileStatement(_)
| AstKind::EmptyStatement(_)
| AstKind::ExpressionStatement(_)
| AstKind::ForInStatement(_)
| AstKind::ForOfStatement(_)
| AstKind::ForStatement(_)
| AstKind::IfStatement(_)
| AstKind::LabeledStatement(_)
| AstKind::ReturnStatement(_)
| AstKind::SwitchStatement(_)
| AstKind::ThrowStatement(_)
| AstKind::TryStatement(_)
| AstKind::WhileStatement(_)
| AstKind::WithStatement(_)
| AstKind::SwitchCase(_)
| AstKind::CatchClause(_)
| AstKind::VariableDeclaration(_)
| AstKind::VariableDeclarator(_)
| AstKind::ArrowFunctionExpression(_)
| AstKind::ObjectExpression(_)
| AstKind::ParenthesizedExpression(_)
| AstKind::ObjectProperty(_)
| AstKind::Function(_)
| AstKind::FormalParameter(_)
| AstKind::Class(_)
| AstKind::MethodDefinition(_)
| AstKind::PropertyDefinition(_)
| AstKind::StaticBlock(_)
| AstKind::Decorator(_)
| AstKind::ExportAllDeclaration(_)
| AstKind::ExportDefaultDeclaration(_)
| AstKind::ExportNamedDeclaration(_)
| AstKind::ImportDeclaration(_)
)
}