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
20 changes: 19 additions & 1 deletion crates/oxc_semantic/src/jsdoc/parser/jsdoc_tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ mod test {
Some(("t2", "{t2}")),
),
("/** @k3 { t3 } */", Some(("t3", "{ t3 }"))),
("/** @k4 x{t4}y */", Some(("t4", "{t4}"))),
("/** @k4 x{t4}y */", None),
("/** @k5 {t5}} */", Some(("t5", "{t5}"))),
("/** @k6 */", None),
("/** @k7 x */", None),
Expand Down Expand Up @@ -467,6 +467,24 @@ c7 */",
),
("/** @param {t15}ƒa */", Some(("t15", "{t15}")), Some(("ƒa", "ƒa")), ("", " ")),
("/** @type{t16}n16*/", Some(("t16", "{t16}")), Some(("n16", "n16")), ("", "")),
(
"/** @param entries Entries in the {@link SearchableMap} */",
None,
Some(("entries", "entries")),
("Entries in the {@link SearchableMap}", " Entries in the {@link SearchableMap} "),
),
(
"/** @param bar - With braces {} */",
None,
Some(("bar", "bar")),
("- With braces {}", " - With braces {} "),
),
(
"/** @param {string} name See {@link Foo} */",
Some(("string", "{string}")),
Some(("name", "name")),
("See {@link Foo}", " See {@link Foo} "),
),
] {
let allocator = Allocator::default();
let semantic = build_semantic(&allocator, source_text);
Expand Down
30 changes: 17 additions & 13 deletions crates/oxc_semantic/src/jsdoc/parser/utils.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
// For now, just returns the most outer braces
// Find the type annotation range `{...}` at the start of the string (after whitespace).
// According to JSDoc spec, type annotations must appear at the beginning of the tag body.
// Curly braces appearing later (e.g. `{@link Foo}` in descriptions) are not type annotations.
pub fn find_type_range(s: &str) -> Option<(usize, usize)> {
let mut start = None;
let trimmed = s.trim_start();
if !trimmed.starts_with('{') {
return None;
}

let offset = s.len() - trimmed.len();
let mut brace_count = 0;
for (idx, ch) in s.char_indices() {

for (idx, ch) in trimmed.char_indices() {
match ch {
'{' => {
brace_count += 1;

if start.is_none() {
start = Some(idx);
}
}
'}' => {
brace_count -= 1;

if brace_count == 0
&& let Some(start) = start
{
return Some((start, idx + 1));
if brace_count == 0 {
return Some((offset, offset + idx + 1));
}
}
_ => {}
Expand Down Expand Up @@ -101,13 +102,16 @@ mod test {
for (actual, expect) in [
("{t1}", Some("{t1}")),
(" { t2 } ", Some("{ t2 }")),
("x{{ t3: string }}x", Some("{{ t3: string }}")),
("x{{ t3: string }}x", None),
("{t4} name", Some("{t4}")),
(" {t5} ", Some("{t5}")),
("{t6 x", None),
("t7", None),
("{{t8}", None),
("", None),
("entries Description {@link Type}", None),
("name See {@link Foo} and {@link Bar}", None),
("bar - With braces {}", None),
("{[ true, false ]}", Some("{[ true, false ]}")),
(
"{{
Expand Down
Loading