@@ -68,40 +68,16 @@ impl Rule for NoNonNullAssertedOptionalChain {
6868 return ;
6969 } ;
7070
71- let chain_span = match non_null_expr. expression . get_inner_expression ( ) {
72- Expression :: ChainExpression ( chain) => match & chain. expression {
73- ChainElement :: ComputedMemberExpression ( member) if member. optional => {
74- Some ( member. object . span ( ) )
75- }
76- ChainElement :: StaticMemberExpression ( member) if member. optional => {
77- Some ( member. object . span ( ) )
78- }
79- ChainElement :: PrivateFieldExpression ( member) if member. optional => {
80- Some ( member. object . span ( ) )
81- }
82- ChainElement :: CallExpression ( call) if call. optional => Some ( call. callee . span ( ) ) ,
83- _ => None ,
84- } ,
85- Expression :: CallExpression ( call) => {
86- if call. optional && !is_parent_member_or_call ( node, ctx) {
87- Some ( call. callee . span ( ) )
88- } else if let Some ( member) = call. callee . as_member_expression ( ) {
89- if member. optional ( ) && !is_parent_member_or_call ( node, ctx) {
90- Some ( member. object ( ) . span ( ) )
91- } else {
92- None
93- }
94- } else {
95- None
96- }
97- }
98- expr @ match_member_expression ! ( Expression ) => {
99- let member_expr = expr. to_member_expression ( ) ;
100- if member_expr. optional ( ) && !is_parent_member_or_call ( node, ctx) {
101- Some ( member_expr. object ( ) . span ( ) )
102- } else {
103- None
104- }
71+ let expression = non_null_expr. expression . get_inner_expression ( ) ;
72+ let chain_span = match expression {
73+ Expression :: ChainExpression ( chain) => find_optional_chain_span ( & chain. expression ) ,
74+ Expression :: CallExpression ( _)
75+ | Expression :: ComputedMemberExpression ( _)
76+ | Expression :: StaticMemberExpression ( _)
77+ | Expression :: PrivateFieldExpression ( _)
78+ if !is_parent_member_or_call ( node, ctx) =>
79+ {
80+ find_optional_chain_span_in_expression ( expression)
10581 }
10682 _ => None ,
10783 } ;
@@ -124,6 +100,66 @@ impl Rule for NoNonNullAssertedOptionalChain {
124100 }
125101}
126102
103+ fn find_optional_chain_span ( chain : & ChainElement < ' _ > ) -> Option < Span > {
104+ let expression = match chain {
105+ ChainElement :: CallExpression ( call) => {
106+ if call. optional {
107+ return Some ( call. callee . span ( ) ) ;
108+ }
109+ & call. callee
110+ }
111+ ChainElement :: TSNonNullExpression ( non_null) => & non_null. expression ,
112+ ChainElement :: ComputedMemberExpression ( member) => {
113+ if member. optional {
114+ return Some ( member. object . span ( ) ) ;
115+ }
116+ & member. object
117+ }
118+ ChainElement :: StaticMemberExpression ( member) => {
119+ if member. optional {
120+ return Some ( member. object . span ( ) ) ;
121+ }
122+ & member. object
123+ }
124+ ChainElement :: PrivateFieldExpression ( member) => {
125+ if member. optional {
126+ return Some ( member. object . span ( ) ) ;
127+ }
128+ & member. object
129+ }
130+ } ;
131+
132+ find_optional_chain_span_in_expression ( expression)
133+ }
134+
135+ fn find_optional_chain_span_in_expression ( mut expression : & Expression < ' _ > ) -> Option < Span > {
136+ loop {
137+ if matches ! ( expression, Expression :: ParenthesizedExpression ( _) ) {
138+ return None ;
139+ }
140+
141+ match expression. get_inner_expression ( ) {
142+ Expression :: ChainExpression ( chain) => {
143+ return find_optional_chain_span ( & chain. expression ) ;
144+ }
145+ Expression :: CallExpression ( call) => {
146+ if call. optional {
147+ return Some ( call. callee . span ( ) ) ;
148+ }
149+ expression = & call. callee ;
150+ }
151+ expr @ match_member_expression ! ( Expression ) => {
152+ let member = expr. to_member_expression ( ) ;
153+ if member. optional ( ) {
154+ return Some ( member. object ( ) . span ( ) ) ;
155+ }
156+ expression = member. object ( ) ;
157+ }
158+ _ => return None ,
159+ }
160+ }
161+ }
162+
127163fn is_parent_member_or_call ( node : & AstNode < ' _ > , ctx : & LintContext < ' _ > ) -> bool {
128164 let parent_kind = ctx. nodes ( ) . parent_kind ( node. id ( ) ) ;
129165 matches ! ( parent_kind, AstKind :: CallExpression ( _) ) || parent_kind. is_member_expression_kind ( )
@@ -154,7 +190,10 @@ fn test() {
154190 "foo?.bar!;" ,
155191 "foo?.['bar']!;" ,
156192 "foo?.bar()!;" ,
193+ "foo?.bar().baz()!;" ,
194+ "foo?.bar.baz!;" ,
157195 "foo.bar?.()!;" ,
196+ "foo.bar?.().baz!;" ,
158197 "(foo?.bar)!.baz" ,
159198 "(foo?.bar)!().baz" ,
160199 "(foo?.bar)!" ,
@@ -167,6 +206,9 @@ fn test() {
167206 ( "foo?.bar!" , "foo?.bar" ) ,
168207 ( "foo?.['bar']!" , "foo?.['bar']" ) ,
169208 ( "foo?.bar()!" , "foo?.bar()" ) ,
209+ ( "foo?.bar().baz()!" , "foo?.bar().baz()" ) ,
210+ ( "foo?.bar.baz!" , "foo?.bar.baz" ) ,
211+ ( "foo.bar?.().baz!" , "foo.bar?.().baz" ) ,
170212 ( "(foo?.bar)!.baz" , "(foo?.bar).baz" ) ,
171213 ( "(foo?.bar)!().baz" , "(foo?.bar)().baz" ) ,
172214 ( "(foo?.bar)!" , "(foo?.bar)" ) ,
0 commit comments