mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-14 22:29:17 +00:00
fix(parser): reject invalid modifiers on import aliases (#26622)
Oxc currently accepts and discards invalid modifiers on TypeScript import aliases. Validate them before constructing the declaration: `declare import X = A.B;` now reports TS1079, and `abstract import X = A.B;` reports TS1242. Adds regression coverage for modifier combinations and exported, ambient, external, and type-only aliases. Valid aliases retain their existing behavior.
This commit is contained in:
1 parent
957241c3cf
commit
827fdbdf52
17 files changed
+179
-18
No files matched your search
@@ -889,6 +889,11 @@ parser_diagnostics! {
|
||||
OxcDiagnostic::error("import() requires a specifier.").with_label(span)
|
||||
};
|
||||
|
||||
declare_modifier_on_import(span: Span) => {
|
||||
ts_error("1079", "A 'declare' modifier cannot be used with an import declaration.")
|
||||
.with_label(span)
|
||||
};
|
||||
|
||||
modifier_cannot_be_used_here(modifier: Modifier, allowed: Option<ModifierKinds>) => {
|
||||
OxcDiagnostic::error(format!("'{}' modifier cannot be used here.", modifier.kind))
|
||||
.with_label(modifier.span())
|
||||
|
||||
@@ -689,6 +689,20 @@ impl<'a, C: Config> ParserImpl<'a, C> {
|
||||
Declaration::ClassDeclaration(decl)
|
||||
}
|
||||
Kind::Import => {
|
||||
self.verify_modifiers(
|
||||
modifiers,
|
||||
ModifierKinds::new([ModifierKind::Export]),
|
||||
true,
|
||||
|modifier, allowed| match modifier.kind {
|
||||
ModifierKind::Declare => {
|
||||
diagnostics::declare_modifier_on_import(modifier.span())
|
||||
}
|
||||
ModifierKind::Abstract => {
|
||||
diagnostics::illegal_abstract_modifier(modifier.span())
|
||||
}
|
||||
_ => diagnostics::modifier_cannot_be_used_here(modifier, allowed),
|
||||
},
|
||||
);
|
||||
self.bump_any();
|
||||
let token = self.cur_token();
|
||||
let mut import_kind = ImportOrExportKind::Value;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
namespace A { export class B {} }
|
||||
abstract import type X = require("external");
|
||||
@@ -0,0 +1,2 @@
|
||||
namespace A { export class B {} }
|
||||
abstract import X = A.B;
|
||||
@@ -0,0 +1,2 @@
|
||||
namespace A { export class B {} }
|
||||
declare abstract import X = A.B;
|
||||
@@ -0,0 +1,2 @@
|
||||
namespace A { export class B {} }
|
||||
declare import X = require("external");
|
||||
@@ -0,0 +1,2 @@
|
||||
namespace A { export class B {} }
|
||||
export abstract import X = A.B;
|
||||
@@ -0,0 +1,2 @@
|
||||
namespace A { export class B {} }
|
||||
export declare import type X = require("external");
|
||||
@@ -0,0 +1,2 @@
|
||||
namespace A { export class B {} }
|
||||
export declare import X = A.B;
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace A { export class B {} }
|
||||
import Local = A.B;
|
||||
export import Exported = A.B;
|
||||
import External = require("external");
|
||||
export import ExportedExternal = require("external");
|
||||
export import type ExportedType = require("external");
|
||||
declare namespace Ambient {
|
||||
import Local = A.B;
|
||||
export import Exported = A.B;
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
codegen_misc Summary:
|
||||
AST Parsed : 110/110 (100.00%)
|
||||
Positive Passed: 110/110 (100.00%)
|
||||
AST Parsed : 111/111 (100.00%)
|
||||
Positive Passed: 111/111 (100.00%)
|
||||
@@ -1,3 +1,3 @@
|
||||
formatter_misc Summary:
|
||||
AST Parsed : 110/110 (100.00%)
|
||||
Positive Passed: 110/110 (100.00%)
|
||||
AST Parsed : 111/111 (100.00%)
|
||||
Positive Passed: 111/111 (100.00%)
|
||||
@@ -1,3 +1,3 @@
|
||||
lexer_misc Summary:
|
||||
AST Parsed : 337/337 (100.00%)
|
||||
Positive Passed: 337/337 (100.00%)
|
||||
AST Parsed : 345/345 (100.00%)
|
||||
Positive Passed: 345/345 (100.00%)
|
||||
@@ -1,7 +1,7 @@
|
||||
parser_misc Summary:
|
||||
AST Parsed : 110/110 (100.00%)
|
||||
Positive Passed: 110/110 (100.00%)
|
||||
Negative Passed: 227/227 (100.00%)
|
||||
AST Parsed : 111/111 (100.00%)
|
||||
Positive Passed: 111/111 (100.00%)
|
||||
Negative Passed: 234/234 (100.00%)
|
||||
|
||||
× TS(1275): 'accessor' modifier can only appear on a property declaration.
|
||||
╭─[misc/fail/accessor-modifier-abstract-method.ts:1:29]
|
||||
@@ -936,6 +936,62 @@ Negative Passed: 227/227 (100.00%)
|
||||
· ╰── `from` expected
|
||||
╰────
|
||||
|
||||
× TS(1242): 'abstract' modifier can only appear on a class, method, or property declaration.
|
||||
╭─[misc/fail/import-equals-modifier-abstract-type-require.ts:2:1]
|
||||
1 │ namespace A { export class B {} }
|
||||
2 │ abstract import type X = require("external");
|
||||
· ────────
|
||||
╰────
|
||||
|
||||
× TS(1242): 'abstract' modifier can only appear on a class, method, or property declaration.
|
||||
╭─[misc/fail/import-equals-modifier-abstract.ts:2:1]
|
||||
1 │ namespace A { export class B {} }
|
||||
2 │ abstract import X = A.B;
|
||||
· ────────
|
||||
╰────
|
||||
|
||||
× TS(1079): A 'declare' modifier cannot be used with an import declaration.
|
||||
╭─[misc/fail/import-equals-modifier-declare-abstract.ts:2:1]
|
||||
1 │ namespace A { export class B {} }
|
||||
2 │ declare abstract import X = A.B;
|
||||
· ───────
|
||||
╰────
|
||||
|
||||
× TS(1242): 'abstract' modifier can only appear on a class, method, or property declaration.
|
||||
╭─[misc/fail/import-equals-modifier-declare-abstract.ts:2:9]
|
||||
1 │ namespace A { export class B {} }
|
||||
2 │ declare abstract import X = A.B;
|
||||
· ────────
|
||||
╰────
|
||||
|
||||
× TS(1079): A 'declare' modifier cannot be used with an import declaration.
|
||||
╭─[misc/fail/import-equals-modifier-declare-require.ts:2:1]
|
||||
1 │ namespace A { export class B {} }
|
||||
2 │ declare import X = require("external");
|
||||
· ───────
|
||||
╰────
|
||||
|
||||
× TS(1242): 'abstract' modifier can only appear on a class, method, or property declaration.
|
||||
╭─[misc/fail/import-equals-modifier-export-abstract.ts:2:8]
|
||||
1 │ namespace A { export class B {} }
|
||||
2 │ export abstract import X = A.B;
|
||||
· ────────
|
||||
╰────
|
||||
|
||||
× TS(1079): A 'declare' modifier cannot be used with an import declaration.
|
||||
╭─[misc/fail/import-equals-modifier-export-declare-type-require.ts:2:8]
|
||||
1 │ namespace A { export class B {} }
|
||||
2 │ export declare import type X = require("external");
|
||||
· ───────
|
||||
╰────
|
||||
|
||||
× TS(1079): A 'declare' modifier cannot be used with an import declaration.
|
||||
╭─[misc/fail/import-equals-modifier-export-declare.ts:2:8]
|
||||
1 │ namespace A { export class B {} }
|
||||
2 │ export declare import X = A.B;
|
||||
· ───────
|
||||
╰────
|
||||
|
||||
× Identifier expected. 'this' is a reserved word that cannot be used here.
|
||||
╭─[misc/fail/import-equals-this.ts:2:12]
|
||||
1 │ // `this` is not valid in import equals declaration
|
||||
|
||||
@@ -3,7 +3,7 @@ commit: b465fdbf
|
||||
parser_typescript Summary:
|
||||
AST Parsed : 9783/9783 (100.00%)
|
||||
Positive Passed: 9783/9783 (100.00%)
|
||||
Negative Passed: 1649/2636 (62.56%)
|
||||
Negative Passed: 1651/2636 (62.63%)
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration3.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration4.ts
|
||||
@@ -202,8 +202,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/declarationE
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/declarationEmitUsingTypeAlias1.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/declareModifierOnImport1.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/decoratorsOnComputedProperties.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/defaultArgsInOverloads.ts
|
||||
@@ -450,8 +448,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/importAndVar
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/importAssertionsDeprecated.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/importDeclWithClassModifiers.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/importTypeAssertionDeprecation.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/importWithTrailingSlash.ts
|
||||
@@ -5863,6 +5859,12 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
╰────
|
||||
help: Remove the duplicate modifier.
|
||||
|
||||
× TS(1079): A 'declare' modifier cannot be used with an import declaration.
|
||||
╭─[typescript/tests/cases/compiler/declareModifierOnImport1.ts:1:1]
|
||||
1 │ declare import a = b;
|
||||
· ───────
|
||||
╰────
|
||||
|
||||
× Expected `,` or `)` but found `:`
|
||||
╭─[typescript/tests/cases/compiler/decoratorInJsFile.ts:3:10]
|
||||
2 │ class SomeClass {
|
||||
@@ -7774,6 +7776,33 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
╰────
|
||||
help: Wrap this with quotes
|
||||
|
||||
× 'public' modifier cannot be used here.
|
||||
╭─[typescript/tests/cases/compiler/importDeclWithClassModifiers.ts:5:8]
|
||||
4 │ }
|
||||
5 │ export public import a = x.c;
|
||||
· ──────
|
||||
6 │ export private import b = x.c;
|
||||
╰────
|
||||
help: Only 'export' modifier is allowed here.
|
||||
|
||||
× 'private' modifier cannot be used here.
|
||||
╭─[typescript/tests/cases/compiler/importDeclWithClassModifiers.ts:6:8]
|
||||
5 │ export public import a = x.c;
|
||||
6 │ export private import b = x.c;
|
||||
· ───────
|
||||
7 │ export static import c = x.c;
|
||||
╰────
|
||||
help: Only 'export' modifier is allowed here.
|
||||
|
||||
× 'static' modifier cannot be used here.
|
||||
╭─[typescript/tests/cases/compiler/importDeclWithClassModifiers.ts:7:8]
|
||||
6 │ export private import b = x.c;
|
||||
7 │ export static import c = x.c;
|
||||
· ──────
|
||||
8 │ var b: a;
|
||||
╰────
|
||||
help: Only 'export' modifier is allowed here.
|
||||
|
||||
× TS(1029): 'export' modifier must precede 'declare' modifier.
|
||||
╭─[typescript/tests/cases/compiler/importDeclWithDeclareModifier.ts:5:9]
|
||||
4 │ }
|
||||
@@ -7782,6 +7811,14 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
6 │ var b: a;
|
||||
╰────
|
||||
|
||||
× TS(1079): A 'declare' modifier cannot be used with an import declaration.
|
||||
╭─[typescript/tests/cases/compiler/importDeclWithDeclareModifier.ts:5:1]
|
||||
4 │ }
|
||||
5 │ declare export import a = x.c;
|
||||
· ───────
|
||||
6 │ var b: a;
|
||||
╰────
|
||||
|
||||
× TS(1029): 'export' modifier must precede 'declare' modifier.
|
||||
╭─[typescript/tests/cases/compiler/importDeclWithDeclareModifierInAmbientContext.ts:6:13]
|
||||
5 │ }
|
||||
@@ -7793,6 +7830,14 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
× TS(1038): A 'declare' modifier cannot be used in an already ambient context.
|
||||
╭─[typescript/tests/cases/compiler/importDeclWithDeclareModifierInAmbientContext.ts:6:5]
|
||||
5 │ }
|
||||
6 │ declare export import a = x.c;
|
||||
· ───────
|
||||
7 │ var b: a;
|
||||
╰────
|
||||
|
||||
× TS(1079): A 'declare' modifier cannot be used with an import declaration.
|
||||
╭─[typescript/tests/cases/compiler/importDeclWithDeclareModifierInAmbientContext.ts:6:5]
|
||||
5 │ }
|
||||
6 │ declare export import a = x.c;
|
||||
· ───────
|
||||
7 │ var b: a;
|
||||
@@ -17752,6 +17797,15 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
╰────
|
||||
help: Allowed modifiers are: declare, async
|
||||
|
||||
× 'accessor' modifier cannot be used here.
|
||||
╭─[typescript/tests/cases/conformance/classes/propertyMemberDeclarations/autoAccessorDisallowedModifiers.ts:34:1]
|
||||
33 │ accessor function F1() {}
|
||||
34 │ accessor import "x";
|
||||
· ────────
|
||||
35 │ accessor import {} from "x";
|
||||
╰────
|
||||
help: Only 'export' modifier is allowed here.
|
||||
|
||||
× Unexpected token
|
||||
╭─[typescript/tests/cases/conformance/classes/propertyMemberDeclarations/autoAccessorDisallowedModifiers.ts:34:17]
|
||||
33 │ accessor function F1() {}
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
semantic_misc Summary:
|
||||
AST Parsed : 110/110 (100.00%)
|
||||
Positive Passed: 105/110 (95.45%)
|
||||
AST Parsed : 111/111 (100.00%)
|
||||
Positive Passed: 105/111 (94.59%)
|
||||
semantic Error: tasks/coverage/misc/pass/declare-let-private.ts
|
||||
Bindings mismatch:
|
||||
after transform: ScopeId(0): ["private"]
|
||||
rebuilt : ScopeId(0): []
|
||||
|
||||
semantic Error: tasks/coverage/misc/pass/import-equals-modifiers.ts
|
||||
Bindings mismatch:
|
||||
after transform: ScopeId(0): ["A", "Ambient", "Exported", "ExportedExternal", "ExportedType"]
|
||||
rebuilt : ScopeId(0): ["A", "Exported", "ExportedExternal"]
|
||||
Symbol reference IDs mismatch for "A":
|
||||
after transform: SymbolId(0): [ReferenceId(1), ReferenceId(2), ReferenceId(3), ReferenceId(6), ReferenceId(7)]
|
||||
rebuilt : SymbolId(0): [ReferenceId(2), ReferenceId(3), ReferenceId(4)]
|
||||
|
||||
semantic Error: tasks/coverage/misc/pass/oxc-11593.ts
|
||||
Scope parent mismatch:
|
||||
after transform: ScopeId(2): Some(ScopeId(1))
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
transformer_misc Summary:
|
||||
AST Parsed : 110/110 (100.00%)
|
||||
Positive Passed: 110/110 (100.00%)
|
||||
AST Parsed : 111/111 (100.00%)
|
||||
Positive Passed: 111/111 (100.00%)
|
||||
Reference in new issue
Block a user