Skip to content

Commit b21b766

Browse files
authored
feat(verbatim-module-syntax): error for empty export declaration (#1455)
1 parent 31effff commit b21b766

File tree

1 file changed

+103
-33
lines changed

1 file changed

+103
-33
lines changed

src/rules/verbatim_module_syntax.rs

Lines changed: 103 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ use deno_ast::{
1919
use derive_more::Display;
2020

2121
const 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 {}\nexport { Test };": [
@@ -573,7 +643,7 @@ mod tests {
573643
col: 0,
574644
message: Message::AllExportIdentsUsedInTypes,
575645
hint: Hint::ChangeExportToExportType,
576-
fix: (FIX_DESC, "interface Test {}\nexport type { Test };"),
646+
fix: (FIX_ADD_TYPE_KEYWORD_DESC, "interface Test {}\nexport type { Test };"),
577647
}
578648
],
579649
"type Test = 'test';\nexport { 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';\nexport type { Test };"),
655+
fix: (FIX_ADD_TYPE_KEYWORD_DESC, "type Test = 'test';\nexport type { Test };"),
586656
}
587657
],
588658
};

0 commit comments

Comments
 (0)