@@ -16,49 +16,42 @@ use crate::{
1616 } ,
1717} ;
1818
19- /// Formats a node with TypeScript type cast comments if present.
20- ///
21- /// This function handles the formatting of JSDoc type cast comments that appear
22- /// immediately before parenthesized expressions, creating patterns like:
23- /// `(/** @type {string} */ value)` or `(/** @type {number} */ (expression))`
19+ /// Checks if a node is a type cast node and returns the comments to be printed.
2420///
25- /// The function:
26- /// 1. Checks if there's a closing parenthesis after the node (indicating a type cast)
27- /// 2. Looks for associated type cast comments that precede the node
28- /// 3. Wraps the node in parentheses with proper formatting and indentation
29- /// 4. Handles both object/array expressions and other expression types differently
21+ /// This function detects if a node is part of a TypeScript type cast pattern
22+ /// by checking for JSDoc type cast comments and proper parenthesis structure.
3023///
31- /// Returns `Ok(true)` if the node was formatted as a type cast, `Ok(false)` otherwise.
32- /// This allows callers to know whether they need to apply their own formatting.
33- pub fn format_type_cast_comment_node < ' a , T > (
34- node : & ( impl Format < ' a , T > + GetSpan ) ,
35- is_object_or_array_expression : bool ,
36- f : & mut Formatter < ' _ , ' a > ,
37- ) -> FormatResult < bool > {
24+ /// Returns:
25+ /// - `Some(&[])` if the node is a type cast node but no comments need to be printed
26+ /// - `Some(&[Comment, ...])` if the node is a type cast node with comments to print
27+ /// - `None` if the node is not a type cast node
28+ pub fn is_type_cast_node < ' a > ( node : & impl GetSpan , f : & Formatter < ' _ , ' a > ) -> Option < & ' a [ Comment ] > {
3829 let comments = f. context ( ) . comments ( ) ;
3930 let span = node. span ( ) ;
4031 let source = f. source_text ( ) ;
4132
33+ // Check if there's a closing parenthesis after the node (possibly after comments)
4234 if !source. next_non_whitespace_byte_is ( span. end , b')' ) {
4335 let comments_after_node = comments. comments_after ( span. end ) ;
4436 let mut start = span. end ;
4537 // Skip comments after the node to find the next non-whitespace byte whether it's a `)`
4638 for comment in comments_after_node {
47- if !source. all_bytes_match ( start, comment. span . start , |b| b . is_ascii_whitespace ( ) ) {
39+ if !source. bytes_range ( start, comment. span . start ) . trim_ascii_start ( ) . is_empty ( ) {
4840 break ;
4941 }
5042 start = comment. span . end ;
5143 }
5244 // Still not a `)`, return early because it's not a type cast
5345 if !source. next_non_whitespace_byte_is ( start, b')' ) {
54- return Ok ( false ) ;
46+ return None ;
5547 }
5648 }
5749
50+ // Check for type cast comment in printed or unprinted comments
5851 if !comments. is_handled_type_cast_comment ( )
5952 && let Some ( last_printed_comment) = comments. printed_comments ( ) . last ( )
6053 && last_printed_comment. span . end <= span. start
61- && f . source_text ( ) . next_non_whitespace_byte_is ( last_printed_comment. span . end , b'(' )
54+ && source . next_non_whitespace_byte_is ( last_printed_comment. span . end , b'(' )
6255 && f. comments ( ) . is_type_cast_comment ( last_printed_comment)
6356 {
6457 // Get the source text from the end of type cast comment to the node span
@@ -68,10 +61,11 @@ pub fn format_type_cast_comment_node<'a, T>(
6861 // ^^^^
6962 // Should wrap for `baz` rather than `baz.zoo`
7063 if has_closed_parentheses ( node_source_text) {
71- return Ok ( false ) ;
64+ None
65+ } else {
66+ // Type cast node, but comment was already printed
67+ Some ( & [ ] )
7268 }
73-
74- f. context_mut ( ) . comments_mut ( ) . mark_as_type_cast_node ( node) ;
7569 } else if let Some ( type_cast_comment_index) = comments. get_type_cast_comment_index ( span) {
7670 let comments = f. context ( ) . comments ( ) . unprinted_comments ( ) ;
7771 let type_cast_comment = & comments[ type_cast_comment_index] ;
@@ -83,19 +77,49 @@ pub fn format_type_cast_comment_node<'a, T>(
8377 // ^^^^
8478 // Should wrap for `baz` rather than `baz.zoo`
8579 if has_closed_parentheses ( node_source_text) {
86- return Ok ( false ) ;
80+ None
81+ } else {
82+ // Type cast node with comments to print
83+ Some ( & comments[ ..=type_cast_comment_index] )
8784 }
88-
89- let type_cast_comments = & comments[ ..=type_cast_comment_index] ;
90-
91- write ! ( f, [ FormatLeadingComments :: Comments ( type_cast_comments) ] ) ?;
92- f. context_mut ( ) . comments_mut ( ) . mark_as_type_cast_node ( node) ;
93- // If the printed cast comment is already handled, return early to avoid infinite recursion.
9485 } else {
9586 // No typecast comment
87+ None
88+ }
89+ }
90+
91+ /// Formats a node with TypeScript type cast comments if present.
92+ ///
93+ /// This function handles the formatting of JSDoc type cast comments that appear
94+ /// immediately before parenthesized expressions, creating patterns like:
95+ /// `(/** @type {string} */ value)` or `(/** @type {number} */ (expression))`
96+ ///
97+ /// The function:
98+ /// 1. Checks if there's a closing parenthesis after the node (indicating a type cast)
99+ /// 2. Looks for associated type cast comments that precede the node
100+ /// 3. Wraps the node in parentheses with proper formatting and indentation
101+ /// 4. Handles both object/array expressions and other expression types differently
102+ ///
103+ /// Returns `Ok(true)` if the node was formatted as a type cast, `Ok(false)` otherwise.
104+ /// This allows callers to know whether they need to apply their own formatting.
105+ pub fn format_type_cast_comment_node < ' a , T > (
106+ node : & ( impl Format < ' a , T > + GetSpan ) ,
107+ is_object_or_array_expression : bool ,
108+ f : & mut Formatter < ' _ , ' a > ,
109+ ) -> FormatResult < bool > {
110+ // Check if this is a type cast node and get the comments to print
111+ let Some ( type_cast_comments) = is_type_cast_node ( node, f) else {
96112 return Ok ( false ) ;
113+ } ;
114+
115+ // Print the type cast comments if any
116+ if !type_cast_comments. is_empty ( ) {
117+ write ! ( f, [ FormatLeadingComments :: Comments ( type_cast_comments) ] ) ?;
97118 }
98119
120+ let span = node. span ( ) ;
121+ f. context_mut ( ) . comments_mut ( ) . mark_as_type_cast_node ( node) ;
122+
99123 // https://github.com/prettier/prettier/blob/7584432401a47a26943dd7a9ca9a8e032ead7285/src/language-js/print/estree.js#L117-L120
100124 if is_object_or_array_expression && !f. comments ( ) . has_comment_before ( span. start ) {
101125 write ! ( f, group( & format_args!( "(" , & format_once( |f| node. fmt( f) ) , ")" ) ) ) ?;
0 commit comments