@@ -37,35 +37,71 @@ impl<'a> ModuleRecordBuilder<'a> {
3737 pub fn errors ( & self ) -> std:: vec:: Vec < OxcDiagnostic > {
3838 let mut errors = vec ! [ ] ;
3939
40+ let module_record = & self . module_record ;
41+
4042 // Skip checking for exports in TypeScript
4143 if self . source_type . is_typescript ( ) {
42- return errors;
43- }
44-
45- let module_record = & self . module_record ;
44+ // TS1363: A type-only import can specify a default import or named bindings, but not both.
45+ // Group import entries by statement and check only those statements that are type-only imports.
46+ if !module_record. import_entries . is_empty ( ) {
47+ // Build map of type-only import statement spans -> (has_default, has_named).
48+ // `requested_modules` contains entries for both imports and exports, so filter is_import && is_type.
49+ let mut seen: rustc_hash:: FxHashMap < Span , ( bool , bool ) > =
50+ rustc_hash:: FxHashMap :: default ( ) ;
51+ for requests in module_record. requested_modules . values ( ) {
52+ for req in requests {
53+ if req. is_import && req. is_type {
54+ seen. entry ( req. statement_span ) . or_insert ( ( false , false ) ) ;
55+ }
56+ }
57+ }
58+ if !seen. is_empty ( ) {
59+ for entry in & module_record. import_entries {
60+ if let Some ( lookup) = seen. get_mut ( & entry. statement_span ) {
61+ match & entry. import_name {
62+ ImportImportName :: Default ( _) => lookup. 0 = true ,
63+ ImportImportName :: Name ( _) | ImportImportName :: NamespaceObject => {
64+ lookup. 1 = true ;
65+ }
66+ }
67+ }
68+ }
69+ for ( stmt_span, ( has_default, has_named) ) in seen {
70+ if has_default && has_named {
71+ errors. push ( diagnostics:: type_only_import_default_and_named ( stmt_span) ) ;
72+ }
73+ }
74+ }
75+ }
76+ } else {
77+ // It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries.
78+ for name_span in & self . exported_bindings_duplicated {
79+ let old_span = module_record. exported_bindings [ & name_span. name ] ;
80+ errors. push ( diagnostics:: duplicate_export (
81+ & name_span. name ,
82+ name_span. span ,
83+ old_span,
84+ ) ) ;
85+ }
4686
47- // It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries.
48- for name_span in & self . exported_bindings_duplicated {
49- let old_span = module_record. exported_bindings [ & name_span. name ] ;
50- errors. push ( diagnostics:: duplicate_export ( & name_span. name , name_span. span , old_span) ) ;
87+ // Multiple default exports
88+ // `export default foo`
89+ // `export { default }`
90+ let default_exports = module_record
91+ . local_export_entries
92+ . iter ( )
93+ . filter_map ( |export_entry| export_entry. export_name . default_export_span ( ) )
94+ . chain (
95+ module_record
96+ . indirect_export_entries
97+ . iter ( )
98+ . filter_map ( |export_entry| export_entry. export_name . default_export_span ( ) ) ,
99+ ) ;
100+ if default_exports. clone ( ) . count ( ) > 1 {
101+ errors. push ( diagnostics:: duplicate_default_export ( default_exports) ) ;
102+ }
51103 }
52104
53- // Multiple default exports
54- // `export default foo`
55- // `export { default }`
56- let default_exports = module_record
57- . local_export_entries
58- . iter ( )
59- . filter_map ( |export_entry| export_entry. export_name . default_export_span ( ) )
60- . chain (
61- module_record
62- . indirect_export_entries
63- . iter ( )
64- . filter_map ( |export_entry| export_entry. export_name . default_export_span ( ) ) ,
65- ) ;
66- if default_exports. clone ( ) . count ( ) > 1 {
67- errors. push ( diagnostics:: duplicate_default_export ( default_exports) ) ;
68- }
69105 errors
70106 }
71107
0 commit comments