@@ -104,13 +104,16 @@ fn has_one_super_type(decl: &TSInterfaceDeclaration) -> bool {
104104}
105105
106106fn check_member ( member : & TSSignature , node : & AstNode < ' _ > , ctx : & LintContext < ' _ > ) {
107- let TSSignature :: TSCallSignatureDeclaration ( decl) = member else {
108- return ;
107+ let ( span, return_type) = match member {
108+ TSSignature :: TSConstructSignatureDeclaration ( decl) => ( decl. span , & decl. return_type ) ,
109+ TSSignature :: TSCallSignatureDeclaration ( decl) => ( decl. span , & decl. return_type ) ,
110+ _ => return ,
109111 } ;
110- let Some ( type_annotation) = & decl. return_type else {
112+
113+ let Some ( type_annotation) = & return_type else {
111114 return ;
112115 } ;
113- let Span { start, end, .. } = decl . span ;
116+ let Span { start, end, .. } = span;
114117 let colon_pos = type_annotation. span . start - start;
115118 let source_code = & ctx. source_text ( ) ;
116119 let text: & str = & source_code[ start as usize ..end as usize ] ;
@@ -128,7 +131,7 @@ fn check_member(member: &TSSignature, node: &AstNode<'_>, ctx: &LintContext<'_>)
128131 AstKind :: TSInterfaceDeclaration ( interface_decl) => {
129132 if let Some ( type_parameters) = & interface_decl. type_parameters {
130133 ctx. diagnostic_with_fix (
131- prefer_function_type_diagnostic ( & suggestion, decl . span ) ,
134+ prefer_function_type_diagnostic ( & suggestion, span) ,
132135 |fixer| {
133136 let mut span = interface_decl. id . span ;
134137 span. end = type_parameters. span . end ;
@@ -142,76 +145,71 @@ fn check_member(member: &TSSignature, node: &AstNode<'_>, ctx: &LintContext<'_>)
142145 } ,
143146 ) ;
144147 } else {
145- ctx. diagnostic_with_fix (
146- prefer_function_type_diagnostic ( & suggestion, decl. span ) ,
147- |_| {
148- let mut is_parent_exported = false ;
149- let mut node_start = interface_decl. span . start ;
150- let mut node_end = interface_decl. span . end ;
151- if let Some ( parent_node) = ctx. nodes ( ) . parent_node ( node. id ( ) ) {
152- if let AstKind :: ExportNamedDeclaration ( export_name_decl) =
153- parent_node. kind ( )
154- {
155- is_parent_exported = true ;
156- node_start = export_name_decl. span . start ;
157- node_end = export_name_decl. span . end ;
158- }
148+ ctx. diagnostic_with_fix ( prefer_function_type_diagnostic ( & suggestion, span) , |_| {
149+ let mut is_parent_exported = false ;
150+ let mut node_start = interface_decl. span . start ;
151+ let mut node_end = interface_decl. span . end ;
152+ if let Some ( parent_node) = ctx. nodes ( ) . parent_node ( node. id ( ) ) {
153+ if let AstKind :: ExportNamedDeclaration ( export_name_decl) =
154+ parent_node. kind ( )
155+ {
156+ is_parent_exported = true ;
157+ node_start = export_name_decl. span . start ;
158+ node_end = export_name_decl. span . end ;
159159 }
160+ }
160161
161- let has_comments = ctx. has_comments_between ( interface_decl. span ) ;
162-
163- if has_comments {
164- let comments = ctx
165- . comments_range ( node_start..node_end)
166- . map ( |comment| ( * comment, comment. content_span ( ) ) ) ;
167-
168- let comments_text = {
169- let mut comments_vec: Vec < String > = vec ! [ ] ;
170- comments. for_each ( |( comment_interface, span) | {
171- let comment = span. source_text ( source_code) ;
172-
173- match comment_interface. kind {
174- CommentKind :: Line => {
175- let single_line_comment: String =
176- format ! ( "//{comment}\n " ) ;
177- comments_vec. push ( single_line_comment) ;
178- }
179- CommentKind :: Block => {
180- let multi_line_comment: String =
181- format ! ( "/*{comment}*/\n " ) ;
182- comments_vec. push ( multi_line_comment) ;
183- }
162+ let has_comments = ctx. has_comments_between ( interface_decl. span ) ;
163+
164+ if has_comments {
165+ let comments = ctx
166+ . comments_range ( node_start..node_end)
167+ . map ( |comment| ( * comment, comment. content_span ( ) ) ) ;
168+
169+ let comments_text = {
170+ let mut comments_vec: Vec < String > = vec ! [ ] ;
171+ comments. for_each ( |( comment_interface, span) | {
172+ let comment = span. source_text ( source_code) ;
173+
174+ match comment_interface. kind {
175+ CommentKind :: Line => {
176+ let single_line_comment: String = format ! ( "//{comment}\n " ) ;
177+ comments_vec. push ( single_line_comment) ;
184178 }
185- } ) ;
186-
187- comments_vec. join ( "" )
188- } ;
189-
190- return Fix :: new (
191- format ! (
192- "{}{}{} = {};" ,
193- comments_text,
194- if is_parent_exported { "export type " } else { "type " } ,
195- & interface_decl. id. name,
196- & suggestion
197- ) ,
198- Span :: new ( node_start, node_end) ,
199- )
200- . with_message ( CONVERT_TO_FUNCTION_TYPE ) ;
201- }
179+ CommentKind :: Block => {
180+ let multi_line_comment: String = format ! ( "/*{comment}*/\n " ) ;
181+ comments_vec. push ( multi_line_comment) ;
182+ }
183+ }
184+ } ) ;
185+
186+ comments_vec. join ( "" )
187+ } ;
202188
203- Fix :: new (
189+ return Fix :: new (
204190 format ! (
205- "{} {} = {};" ,
206- if is_parent_exported { "export type" } else { "type" } ,
191+ "{}{}{} = {};" ,
192+ comments_text,
193+ if is_parent_exported { "export type " } else { "type " } ,
207194 & interface_decl. id. name,
208195 & suggestion
209196 ) ,
210197 Span :: new ( node_start, node_end) ,
211198 )
212- . with_message ( CONVERT_TO_FUNCTION_TYPE )
213- } ,
214- ) ;
199+ . with_message ( CONVERT_TO_FUNCTION_TYPE ) ;
200+ }
201+
202+ Fix :: new (
203+ format ! (
204+ "{} {} = {};" ,
205+ if is_parent_exported { "export type" } else { "type" } ,
206+ & interface_decl. id. name,
207+ & suggestion
208+ ) ,
209+ Span :: new ( node_start, node_end) ,
210+ )
211+ . with_message ( CONVERT_TO_FUNCTION_TYPE )
212+ } ) ;
215213 }
216214 }
217215
@@ -221,7 +219,7 @@ fn check_member(member: &TSSignature, node: &AstNode<'_>, ctx: &LintContext<'_>)
221219 union_type. types . iter ( ) . for_each ( |ts_type| {
222220 if let TSType :: TSTypeLiteral ( literal) = ts_type {
223221 ctx. diagnostic_with_fix (
224- prefer_function_type_diagnostic ( & suggestion, decl . span ) ,
222+ prefer_function_type_diagnostic ( & suggestion, span) ,
225223 |fixer| {
226224 fixer
227225 . replace ( literal. span , format ! ( "({suggestion})" ) )
@@ -233,7 +231,7 @@ fn check_member(member: &TSSignature, node: &AstNode<'_>, ctx: &LintContext<'_>)
233231 }
234232
235233 TSType :: TSTypeLiteral ( literal) => ctx. diagnostic_with_fix (
236- prefer_function_type_diagnostic ( & suggestion, decl . span ) ,
234+ prefer_function_type_diagnostic ( & suggestion, span) ,
237235 |fixer| {
238236 fixer
239237 . replace ( literal. span , suggestion)
@@ -242,7 +240,7 @@ fn check_member(member: &TSSignature, node: &AstNode<'_>, ctx: &LintContext<'_>)
242240 ) ,
243241
244242 _ => {
245- ctx. diagnostic ( prefer_function_type_diagnostic ( & suggestion, decl . span ) ) ;
243+ ctx. diagnostic ( prefer_function_type_diagnostic ( & suggestion, span) ) ;
246244 }
247245 }
248246 }
@@ -259,7 +257,7 @@ fn check_member(member: &TSSignature, node: &AstNode<'_>, ctx: &LintContext<'_>)
259257 return ;
260258 }
261259 ctx. diagnostic_with_fix (
262- prefer_function_type_diagnostic ( & suggestion, decl . span ) ,
260+ prefer_function_type_diagnostic ( & suggestion, span) ,
263261 |fixer| {
264262 fixer
265263 . replace ( literal. span , format ! ( "({suggestion})" ) )
@@ -279,7 +277,7 @@ fn check_member(member: &TSSignature, node: &AstNode<'_>, ctx: &LintContext<'_>)
279277 return ;
280278 }
281279 ctx. diagnostic_with_fix (
282- prefer_function_type_diagnostic ( & suggestion, decl . span ) ,
280+ prefer_function_type_diagnostic ( & suggestion, span) ,
283281 |fixer| {
284282 fixer
285283 . replace ( literal. span , format ! ( "({suggestion})" ) )
@@ -290,7 +288,7 @@ fn check_member(member: &TSSignature, node: &AstNode<'_>, ctx: &LintContext<'_>)
290288 }
291289
292290 TSType :: TSTypeLiteral ( literal) => ctx. diagnostic_with_fix (
293- prefer_function_type_diagnostic ( & suggestion, decl . span ) ,
291+ prefer_function_type_diagnostic ( & suggestion, span) ,
294292 |fixer| {
295293 fixer
296294 . replace ( literal. span , suggestion)
@@ -302,7 +300,7 @@ fn check_member(member: &TSSignature, node: &AstNode<'_>, ctx: &LintContext<'_>)
302300 }
303301 }
304302
305- _ => ctx. diagnostic ( prefer_function_type_diagnostic ( & suggestion, decl . span ) ) ,
303+ _ => ctx. diagnostic ( prefer_function_type_diagnostic ( & suggestion, span) ) ,
306304 }
307305}
308306
@@ -502,6 +500,7 @@ fn test() {
502500 " ,
503501 "type X = {} | { (): void; }" ,
504502 "type X = {} & { (): void; };" ,
503+ "type K = { new(): T };" ,
505504 ] ;
506505
507506 let fix = vec ! [
@@ -720,6 +719,7 @@ type X = {} & (() => void);
720719 "export type AnyFn = (...args: any[]) => any;" ,
721720 None ,
722721 ) ,
722+ ( "type K = { new(): T };" , "type K = new() => T;" , None ) ,
723723 ] ;
724724
725725 Tester :: new ( PreferFunctionType :: NAME , PreferFunctionType :: PLUGIN , pass, fail)
0 commit comments