@@ -19,7 +19,8 @@ use deno_ast::{
1919use derive_more:: Display ;
2020
2121const CODE : & str = "verbatim-module-syntax" ;
22- const FIX_DESC : & str = "Add a type keyword" ;
22+ const FIX_ADD_TYPE_KEYWORD_DESC : & str = "Add a type keyword" ;
23+ const FIX_USE_IMPORT_DECL_DESC : & str = "Use an import declaration" ;
2324
2425#[ allow( clippy:: enum_variant_names) ]
2526#[ derive( Display ) ]
@@ -32,6 +33,10 @@ enum Message {
3233 AllExportIdentsUsedInTypes ,
3334 #[ display( fmt = "Export identifier only used in types" ) ]
3435 ExportIdentUsedInTypes ,
36+ #[ display(
37+ fmt = "Empty export declaration elided without verbatim-module-syntax"
38+ ) ]
39+ ExportDeclarationElided ,
3540}
3641
3742#[ derive( Display ) ]
@@ -44,6 +49,8 @@ enum Hint {
4449 ChangeExportToExportType ,
4550 #[ display( fmt = "Add a `type` keyword before the identifier" ) ]
4651 AddTypeKeyword ,
52+ #[ display( fmt = "Change to side effect import for consistent behavior" ) ]
53+ ChangeSideEffectImport ,
4754}
4855
4956#[ derive( Debug ) ]
@@ -108,7 +115,7 @@ impl VerbatimModuleSyntax {
108115 Message :: AllImportIdentsUsedInTypes ,
109116 Some ( Hint :: ChangeImportToImportType . to_string ( ) ) ,
110117 vec ! [ LintFix {
111- description: FIX_DESC . into( ) ,
118+ description: FIX_ADD_TYPE_KEYWORD_DESC . into( ) ,
112119 changes,
113120 } ] ,
114121 ) ;
@@ -120,7 +127,7 @@ impl VerbatimModuleSyntax {
120127 Message :: ImportIdentUsedInTypes ,
121128 Some ( Hint :: AddTypeKeyword . to_string ( ) ) ,
122129 vec ! [ LintFix {
123- description: FIX_DESC . into( ) ,
130+ description: FIX_ADD_TYPE_KEYWORD_DESC . into( ) ,
124131 changes: vec![ LintFixChange {
125132 new_text: "type " . into( ) ,
126133 range: specifier. start( ) . range( ) ,
@@ -138,10 +145,48 @@ impl VerbatimModuleSyntax {
138145 context : & mut Context ,
139146 program : Program ,
140147 ) {
141- if named_export. type_only ( )
142- || named_export. specifiers . is_empty ( )
143- || named_export. src . is_some ( )
144- {
148+ if named_export. type_only ( ) {
149+ return ;
150+ }
151+
152+ if named_export. specifiers . is_empty ( ) {
153+ if let Some ( src) = & named_export. src {
154+ let quote_kind = if src. text_fast ( program) . starts_with ( "'" ) {
155+ '\''
156+ } else {
157+ '\"'
158+ } ;
159+ let semicolon = if named_export. text_fast ( program) . ends_with ( ';' ) {
160+ ";"
161+ } else {
162+ ""
163+ } ;
164+ let changes = Vec :: from ( [ LintFixChange {
165+ new_text : format ! (
166+ "import {0}{1}{0}{2}" ,
167+ quote_kind,
168+ src. value( ) ,
169+ semicolon
170+ )
171+ . into ( ) ,
172+ range : named_export. range ( ) ,
173+ } ] ) ;
174+ context. add_diagnostic_with_fixes (
175+ named_export. range ( ) ,
176+ CODE ,
177+ Message :: ExportDeclarationElided ,
178+ Some ( Hint :: ChangeSideEffectImport . to_string ( ) ) ,
179+ vec ! [ LintFix {
180+ description: FIX_USE_IMPORT_DECL_DESC . into( ) ,
181+ changes,
182+ } ] ,
183+ ) ;
184+
185+ return ;
186+ }
187+ }
188+
189+ if named_export. specifiers . is_empty ( ) || named_export. src . is_some ( ) {
145190 return ;
146191 }
147192
@@ -189,7 +234,7 @@ impl VerbatimModuleSyntax {
189234 Message :: AllExportIdentsUsedInTypes ,
190235 Some ( Hint :: ChangeExportToExportType . to_string ( ) ) ,
191236 vec ! [ LintFix {
192- description: FIX_DESC . into( ) ,
237+ description: FIX_ADD_TYPE_KEYWORD_DESC . into( ) ,
193238 changes,
194239 } ] ,
195240 ) ;
@@ -201,7 +246,7 @@ impl VerbatimModuleSyntax {
201246 Message :: ExportIdentUsedInTypes ,
202247 Some ( Hint :: AddTypeKeyword . to_string ( ) ) ,
203248 vec ! [ LintFix {
204- description: FIX_DESC . into( ) ,
249+ description: FIX_ADD_TYPE_KEYWORD_DESC . into( ) ,
205250 changes: vec![ LintFixChange {
206251 new_text: "type " . into( ) ,
207252 range: specifier. start( ) . range( ) ,
@@ -390,6 +435,7 @@ mod tests {
390435 "import { value, type Type } from 'module'; console.log(value); export type { Type };" ,
391436 "import { value, type Type } from 'module'; export { value, type Type };" ,
392437 "export { value } from './value.ts';" ,
438+ "export {};" ,
393439 "const logger = { setItems }; export { logger };" ,
394440 "class Test {} export { Test };" ,
395441 } ;
@@ -404,167 +450,191 @@ mod tests {
404450 col: 0 ,
405451 message: Message :: AllImportIdentsUsedInTypes ,
406452 hint: Hint :: ChangeImportToImportType ,
407- fix: ( FIX_DESC , "import type { Type } from 'module'; type Test = Type;" ) ,
453+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import type { Type } from 'module'; type Test = Type;" ) ,
408454 }
409455 ] ,
410456 "import { Type, Other } from 'module'; type Test = Type | Other;" : [
411457 {
412458 col: 0 ,
413459 message: Message :: AllImportIdentsUsedInTypes ,
414460 hint: Hint :: ChangeImportToImportType ,
415- fix: ( FIX_DESC , "import type { Type, Other } from 'module'; type Test = Type | Other;" ) ,
461+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import type { Type, Other } from 'module'; type Test = Type | Other;" ) ,
416462 }
417463 ] ,
418464 "import { type Type, Other } from 'module'; type Test = Type | Other;" : [
419465 {
420466 col: 0 ,
421467 message: Message :: AllImportIdentsUsedInTypes ,
422468 hint: Hint :: ChangeImportToImportType ,
423- fix: ( FIX_DESC , "import type { Type, Other } from 'module'; type Test = Type | Other;" ) ,
469+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import type { Type, Other } from 'module'; type Test = Type | Other;" ) ,
424470 }
425471 ] ,
426472 "import { Type, value } from 'module'; type Test = Type; value();" : [
427473 {
428474 col: 9 ,
429475 message: Message :: ImportIdentUsedInTypes ,
430476 hint: Hint :: AddTypeKeyword ,
431- fix: ( FIX_DESC , "import { type Type, value } from 'module'; type Test = Type; value();" ) ,
477+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import { type Type, value } from 'module'; type Test = Type; value();" ) ,
432478 }
433479 ] ,
434480 "import { Type, Other, value } from 'module'; type Test = Type | Other; value();" : [
435481 {
436482 col: 9 ,
437483 message: Message :: ImportIdentUsedInTypes ,
438484 hint: Hint :: AddTypeKeyword ,
439- fix: ( FIX_DESC , "import { type Type, Other, value } from 'module'; type Test = Type | Other; value();" ) ,
485+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import { type Type, Other, value } from 'module'; type Test = Type | Other; value();" ) ,
440486 } ,
441487 {
442488 col: 15 ,
443489 message: Message :: ImportIdentUsedInTypes ,
444490 hint: Hint :: AddTypeKeyword ,
445- fix: ( FIX_DESC , "import { Type, type Other, value } from 'module'; type Test = Type | Other; value();" ) ,
491+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import { Type, type Other, value } from 'module'; type Test = Type | Other; value();" ) ,
446492 }
447493 ] ,
448494 "import * as value from 'module'; type Test = typeof value;" : [
449495 {
450496 col: 0 ,
451497 message: Message :: AllImportIdentsUsedInTypes ,
452498 hint: Hint :: ChangeImportToImportType ,
453- fix: ( FIX_DESC , "import type * as value from 'module'; type Test = typeof value;" ) ,
499+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import type * as value from 'module'; type Test = typeof value;" ) ,
454500 }
455501 ] ,
456502 "import value from 'module'; type Test = typeof value;" : [
457503 {
458504 col: 0 ,
459505 message: Message :: AllImportIdentsUsedInTypes ,
460506 hint: Hint :: ChangeImportToImportType ,
461- fix: ( FIX_DESC , "import type value from 'module'; type Test = typeof value;" ) ,
507+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import type value from 'module'; type Test = typeof value;" ) ,
462508 }
463509 ] ,
464510 "type Test = string; export { Test };" : [
465511 {
466512 col: 20 ,
467513 message: Message :: AllExportIdentsUsedInTypes ,
468514 hint: Hint :: ChangeExportToExportType ,
469- fix: ( FIX_DESC , "type Test = string; export type { Test };" ) ,
515+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "type Test = string; export type { Test };" ) ,
470516 }
471517 ] ,
472518 "type Test = string; type Test2 = string; export { Test, Test2 };" : [
473519 {
474520 col: 41 ,
475521 message: Message :: AllExportIdentsUsedInTypes ,
476522 hint: Hint :: ChangeExportToExportType ,
477- fix: ( FIX_DESC , "type Test = string; type Test2 = string; export type { Test, Test2 };" ) ,
523+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "type Test = string; type Test2 = string; export type { Test, Test2 };" ) ,
478524 }
479525 ] ,
480526 "import { type value } from 'module'; export { value };" : [
481527 {
482528 col: 0 ,
483529 message: Message :: AllImportIdentsUsedInTypes ,
484530 hint: Hint :: ChangeImportToImportType ,
485- fix: ( FIX_DESC , "import type { value } from 'module'; export { value };" ) ,
531+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import type { value } from 'module'; export { value };" ) ,
486532 } ,
487533 {
488534 col: 37 ,
489535 message: Message :: AllExportIdentsUsedInTypes ,
490536 hint: Hint :: ChangeExportToExportType ,
491- fix: ( FIX_DESC , "import { type value } from 'module'; export type { value };" ) ,
537+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import { type value } from 'module'; export type { value };" ) ,
492538 }
493539 ] ,
494540 "import { value } from 'module'; export { type value };" : [
495541 {
496542 col: 0 ,
497543 message: Message :: AllImportIdentsUsedInTypes ,
498544 hint: Hint :: ChangeImportToImportType ,
499- fix: ( FIX_DESC , "import type { value } from 'module'; export { type value };" ) ,
545+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import type { value } from 'module'; export { type value };" ) ,
500546 } ,
501547 {
502548 col: 32 ,
503549 message: Message :: AllExportIdentsUsedInTypes ,
504550 hint: Hint :: ChangeExportToExportType ,
505- fix: ( FIX_DESC , "import { value } from 'module'; export type { value };" ) ,
551+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import { value } from 'module'; export type { value };" ) ,
506552 }
507553 ] ,
508554 "import type { value } from 'module'; export { value };" : [
509555 {
510556 col: 37 ,
511557 message: Message :: AllExportIdentsUsedInTypes ,
512558 hint: Hint :: ChangeExportToExportType ,
513- fix: ( FIX_DESC , "import type { value } from 'module'; export type { value };" ) ,
559+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import type { value } from 'module'; export type { value };" ) ,
514560 }
515561 ] ,
516562 "import { value } from 'module'; export type { value };" : [
517563 {
518564 col: 0 ,
519565 message: Message :: AllImportIdentsUsedInTypes ,
520566 hint: Hint :: ChangeImportToImportType ,
521- fix: ( FIX_DESC , "import type { value } from 'module'; export type { value };" ) ,
567+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import type { value } from 'module'; export type { value };" ) ,
522568 }
523569 ] ,
524570 "import { value, type Type } from 'module'; console.log(value); export { Type };" : [
525571 {
526572 col: 63 ,
527573 message: Message :: AllExportIdentsUsedInTypes ,
528574 hint: Hint :: ChangeExportToExportType ,
529- fix: ( FIX_DESC , "import { value, type Type } from 'module'; console.log(value); export type { Type };" ) ,
575+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import { value, type Type } from 'module'; console.log(value); export type { Type };" ) ,
530576 }
531577 ] ,
532578 "import { value, Type } from 'module'; console.log(value); export { type Type };" : [
533579 {
534580 col: 16 ,
535581 message: Message :: ImportIdentUsedInTypes ,
536582 hint: Hint :: AddTypeKeyword ,
537- fix: ( FIX_DESC , "import { value, type Type } from 'module'; console.log(value); export { type Type };" ) ,
583+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import { value, type Type } from 'module'; console.log(value); export { type Type };" ) ,
538584 } ,
539585 {
540586 col: 58 ,
541587 message: Message :: AllExportIdentsUsedInTypes ,
542588 hint: Hint :: ChangeExportToExportType ,
543- fix: ( FIX_DESC , "import { value, Type } from 'module'; console.log(value); export type { Type };" ) ,
589+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import { value, Type } from 'module'; console.log(value); export type { Type };" ) ,
544590 }
545591 ] ,
546592 "import { value, Type } from 'module'; console.log(value); export type { Type };" : [
547593 {
548594 col: 16 ,
549595 message: Message :: ImportIdentUsedInTypes ,
550596 hint: Hint :: AddTypeKeyword ,
551- fix: ( FIX_DESC , "import { value, type Type } from 'module'; console.log(value); export type { Type };" ) ,
597+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import { value, type Type } from 'module'; console.log(value); export type { Type };" ) ,
552598 }
553599 ] ,
554600 "import { value, type Type } from 'module'; export { value, Type };" : [
555601 {
556602 col: 59 ,
557603 message: Message :: ExportIdentUsedInTypes ,
558604 hint: Hint :: AddTypeKeyword ,
559- fix: ( FIX_DESC , "import { value, type Type } from 'module'; export { value, type Type };" ) ,
605+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import { value, type Type } from 'module'; export { value, type Type };" ) ,
560606 }
561607 ] ,
562608 "import { value, Type } from 'module'; export { value, type Type };" : [
563609 {
564610 col: 16 ,
565611 message: Message :: ImportIdentUsedInTypes ,
566612 hint: Hint :: AddTypeKeyword ,
567- fix: ( FIX_DESC , "import { value, type Type } from 'module'; export { value, type Type };" ) ,
613+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "import { value, type Type } from 'module'; export { value, type Type };" ) ,
614+ }
615+ ] ,
616+ "export { } from 'module';" : [
617+ {
618+ col: 0 ,
619+ message: Message :: ExportDeclarationElided ,
620+ hint: Hint :: ChangeSideEffectImport ,
621+ fix: ( FIX_USE_IMPORT_DECL_DESC , "import 'module';" ) ,
622+ }
623+ ] ,
624+ "export { } from \" module\" ;" : [
625+ {
626+ col: 0 ,
627+ message: Message :: ExportDeclarationElided ,
628+ hint: Hint :: ChangeSideEffectImport ,
629+ fix: ( FIX_USE_IMPORT_DECL_DESC , "import \" module\" ;" ) ,
630+ }
631+ ] ,
632+ "export { } from \" module\" " : [
633+ {
634+ col: 0 ,
635+ message: Message :: ExportDeclarationElided ,
636+ hint: Hint :: ChangeSideEffectImport ,
637+ fix: ( FIX_USE_IMPORT_DECL_DESC , "import \" module\" " ) ,
568638 }
569639 ] ,
570640 "interface Test {}\n export { Test };" : [
@@ -573,7 +643,7 @@ mod tests {
573643 col: 0 ,
574644 message: Message :: AllExportIdentsUsedInTypes ,
575645 hint: Hint :: ChangeExportToExportType ,
576- fix: ( FIX_DESC , "interface Test {}\n export type { Test };" ) ,
646+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "interface Test {}\n export type { Test };" ) ,
577647 }
578648 ] ,
579649 "type Test = 'test';\n export { Test };" : [
@@ -582,7 +652,7 @@ mod tests {
582652 col: 0 ,
583653 message: Message :: AllExportIdentsUsedInTypes ,
584654 hint: Hint :: ChangeExportToExportType ,
585- fix: ( FIX_DESC , "type Test = 'test';\n export type { Test };" ) ,
655+ fix: ( FIX_ADD_TYPE_KEYWORD_DESC , "type Test = 'test';\n export type { Test };" ) ,
586656 }
587657 ] ,
588658 } ;
0 commit comments