From 6c612d141c3160dd335a2497bd1cb74701d51dea Mon Sep 17 00:00:00 2001 From: leaysgur <6259812+leaysgur@users.noreply.github.com> Date: Mon, 5 Aug 2024 02:25:13 +0000 Subject: [PATCH] fix(semantic/jsdoc): Handle whitespace absence (#4642) Follow up for #4632 --- .../src/jsdoc/parser/jsdoc_tag.rs | 24 +++++++++---------- crates/oxc_semantic/src/jsdoc/parser/utils.rs | 5 +++- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/crates/oxc_semantic/src/jsdoc/parser/jsdoc_tag.rs b/crates/oxc_semantic/src/jsdoc/parser/jsdoc_tag.rs index 2fde414755287..c8a36ba4ce241 100644 --- a/crates/oxc_semantic/src/jsdoc/parser/jsdoc_tag.rs +++ b/crates/oxc_semantic/src/jsdoc/parser/jsdoc_tag.rs @@ -130,15 +130,9 @@ impl<'a> JSDocTag<'a> { let (type_part, name_comment_content, span_start) = match utils::find_type_range(self.body_raw) { Some((t_start, t_end)) => { - let c_start = { - let mut c_start = t_end; - // +1 if whitespace - if self.body_raw.as_bytes()[c_start] == b' ' { - c_start += 1; - } - c_start - }; - + // There may be, or may not be whitespace + // e.g. `@kind {type}name_comment` + let c_start = t_end; ( Some(JSDocTagTypePart::new( &self.body_raw[t_start..t_end], @@ -439,7 +433,7 @@ c7 */", Some(("n7", "n7")), ("c7", "\n\nc7 "), ), - ("/** @k8 {t8} */", Some(("t8", "{t8}")), None, ("", "")), + ("/** @k8 {t8} */", Some(("t8", "{t8}")), None, ("", " ")), ("/** @k9 n9 */", None, Some(("n9", "n9")), ("", " ")), ("/** @property n[].n10 */", None, Some(("n[].n10", "n[].n10")), ("", " ")), ("/** @property n.n11 */", None, Some(("n.n11", "n.n11")), ("", " ")), @@ -462,6 +456,7 @@ c7 */", ("- opt", " - opt "), ), ("/** @param {t15}ƒa */", Some(("t15", "{t15}")), Some(("ƒa", "ƒa")), ("", " ")), + ("/** @type{t16}n16*/", Some(("t16", "{t16}")), Some(("n16", "n16")), ("", "")), ] { let allocator = Allocator::default(); let semantic = build_semantic(&allocator, source_text); @@ -471,15 +466,18 @@ c7 */", jsdocs.next().unwrap().tags().first().unwrap().type_name_comment(); assert_eq!( type_part.map(|t| (t.parsed(), t.span.source_text(source_text))), - parsed_type_part + parsed_type_part, + "type_part failed to assert in {source_text}" ); assert_eq!( type_name_part.map(|n| (n.parsed(), n.span.source_text(source_text))), - parsed_type_name_part + parsed_type_name_part, + "type_name_part failed to assert in {source_text}" ); assert_eq!( (comment_part.parsed().as_str(), comment_part.span.source_text(source_text)), - parsed_comment_part + parsed_comment_part, + "comment_part failed to assert in {source_text}" ); } } diff --git a/crates/oxc_semantic/src/jsdoc/parser/utils.rs b/crates/oxc_semantic/src/jsdoc/parser/utils.rs index ab4195be16436..baa4943c71cac 100644 --- a/crates/oxc_semantic/src/jsdoc/parser/utils.rs +++ b/crates/oxc_semantic/src/jsdoc/parser/utils.rs @@ -71,7 +71,9 @@ pub fn find_type_name_range(s: &str) -> Option<(usize, usize)> { pub fn find_token_range(s: &str) -> Option<(usize, usize)> { let mut start = None; for (idx, ch) in s.char_indices() { - if ch.is_whitespace() { + // `{` may appear just after `@kind{type}` + // Other syntax characters also can be splitter...? + if ch.is_whitespace() || ch == '{' { if let Some(start) = start { return Some((start, idx)); } @@ -150,6 +152,7 @@ t9b: number; ("", None), (" トークン5\n", Some("トークン5")), ("\nk6\nx", Some("k6")), + ("k7{", Some("k7")), ] { assert_eq!(find_token_range(actual).map(|(s, e)| &actual[s..e]), expect); }