@@ -21,7 +21,7 @@ impl LetElseDetector {
2121 let Stmt :: Local ( local) = first_stmt else { return None } ;
2222 // Must have an initializer that is a `node.kind()` call
2323 let Some ( init) = & local. init else { return None } ;
24- if !is_node_kind_call ( & init. expr ) {
24+ if !( is_node_kind_call ( & init. expr ) || is_node_kind_as_call ( & init . expr ) ) {
2525 return None ;
2626 }
2727 // Must have a diverging `else` block
@@ -38,8 +38,23 @@ impl LetElseDetector {
3838 }
3939
4040 let mut detector = Self { node_types : NodeTypeSet :: new ( ) } ;
41- let result = detector. extract_variants_from_pat ( & local. pat ) ;
42- if detector. node_types . is_empty ( ) || result == CollectionResult :: Incomplete {
41+
42+ if is_node_kind_as_call ( & init. expr ) {
43+ // If the initializer is `node.kind().as_<variant>()`, extract that variant.
44+ if let Expr :: MethodCall ( mc) = & * init. expr
45+ && let Some ( variant) = extract_variant_from_as_call ( mc)
46+ {
47+ detector. node_types . insert ( variant) ;
48+ }
49+ } else {
50+ // Otherwise, the initializer is `node.kind()`, so extract from the pattern.
51+ // Expecting `AstKind::Variant` pattern
52+ let result = detector. extract_variants_from_pat ( & local. pat ) ;
53+ if result == CollectionResult :: Incomplete {
54+ return None ;
55+ }
56+ }
57+ if detector. node_types . is_empty ( ) {
4358 return None ;
4459 }
4560
@@ -60,3 +75,45 @@ impl LetElseDetector {
6075 }
6176 }
6277}
78+
79+ /// Checks if is `node.kind().as_some_ast_kind()`
80+ pub fn is_node_kind_as_call ( expr : & Expr ) -> bool {
81+ if let Expr :: MethodCall ( mc) = expr
82+ && mc. method . to_string ( ) . starts_with ( "as_" )
83+ && mc. args . is_empty ( )
84+ && is_node_kind_call ( & mc. receiver )
85+ {
86+ return true ;
87+ }
88+ false
89+ }
90+
91+ fn extract_variant_from_as_call ( mc : & syn:: ExprMethodCall ) -> Option < String > {
92+ // Looking for `node.kind().as_<snake_case_variant>()`
93+ let method_ident = mc. method . to_string ( ) ;
94+ if !method_ident. starts_with ( "as_" ) || !mc. args . is_empty ( ) {
95+ return None ;
96+ }
97+ // Receiver must be `node.kind()`
98+ if !is_node_kind_call ( & mc. receiver ) {
99+ return None ;
100+ }
101+ let snake_variant = & method_ident[ 3 ..] ; // strip `as_`
102+ if snake_variant == "member_expression_kind" {
103+ return None ;
104+ }
105+ Some ( snake_to_pascal_case ( snake_variant) )
106+ }
107+
108+ fn snake_to_pascal_case ( s : & str ) -> String {
109+ s. split ( '_' )
110+ . filter ( |seg| !seg. is_empty ( ) )
111+ . map ( |seg| {
112+ let mut chars = seg. chars ( ) ;
113+ match chars. next ( ) {
114+ Some ( first) => first. to_ascii_uppercase ( ) . to_string ( ) + chars. as_str ( ) ,
115+ None => String :: new ( ) ,
116+ }
117+ } )
118+ . collect ( )
119+ }
0 commit comments