mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(linter): bind CatchVariable
This commit is contained in:
parent
34c0599db8
commit
995e7c1767
6 changed files with 164 additions and 16 deletions
|
|
@ -93,3 +93,30 @@ impl<'a> Binder for FormalParameters<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Binder for CatchClause<'a> {
|
||||
fn bind(&self, builder: &mut SemanticBuilder) {
|
||||
let current_scope_id = builder.scope.current_scope_id;
|
||||
if let Some(param) = &self.param {
|
||||
// https://tc39.es/ecma262/#sec-variablestatements-in-catch-blocks
|
||||
// It is a Syntax Error if any element of the BoundNames of CatchParameter also occurs in the VarDeclaredNames of Block
|
||||
// unless CatchParameter is CatchParameter : BindingIdentifier
|
||||
if let BindingPatternKind::BindingIdentifier(ident) = ¶m.kind {
|
||||
let includes = SymbolFlags::FunctionScopedVariable | SymbolFlags::CatchVariable;
|
||||
// Overshadows declarations so redeclarator error is not reported here
|
||||
let symbol_id = builder.symbols.create(ident.name.clone(), ident.span, includes);
|
||||
builder.scope.current_scope_mut().variables.insert(ident.name.clone(), symbol_id);
|
||||
} else {
|
||||
for ident in param.bound_names() {
|
||||
builder.declare_symbol(
|
||||
&ident.name,
|
||||
ident.span,
|
||||
current_scope_id,
|
||||
SymbolFlags::BlockScopedVariable | SymbolFlags::CatchVariable,
|
||||
SymbolFlags::BlockScopedVariableExcludes,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,6 +181,9 @@ impl<'a> SemanticBuilder<'a> {
|
|||
AstKind::FormalParameters(params) => {
|
||||
params.bind(self);
|
||||
}
|
||||
AstKind::CatchClause(clause) => {
|
||||
clause.bind(self);
|
||||
}
|
||||
AstKind::IdentifierReference(ident) => {
|
||||
self.reference_identifier(ident);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ bitflags! {
|
|||
/// A block-scoped variable (let or const)
|
||||
const BlockScopedVariable = 1 << 1;
|
||||
const Class = 1 << 5;
|
||||
const CatchVariable = 1 << 6; // try {} catch(catch_variable) {}
|
||||
|
||||
const Variable = Self::FunctionScopedVariable.bits | Self::BlockScopedVariable.bits;
|
||||
const Value = Self::Variable.bits | Self::Class.bits;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
Babel Summary:
|
||||
AST Parsed : 2056/2069 (99.37%)
|
||||
Positive Passed: 2056/2069 (99.37%)
|
||||
Negative Passed: 965/1502 (64.25%)
|
||||
Negative Passed: 972/1502 (64.71%)
|
||||
Expect Syntax Error: "annex-b/disabled/1.1-html-comments-close/input.js"
|
||||
Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-if-body/input.js"
|
||||
Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-multiple-labels/input.js"
|
||||
|
|
@ -9,10 +9,8 @@ Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions/input.js"
|
|||
Expect Syntax Error: "annex-b/disabled/3.2.4-duplicate-function-in-block/input.js"
|
||||
Expect Syntax Error: "annex-b/disabled/3.2.5-duplicate-function-in-switch/input.js"
|
||||
Expect Syntax Error: "annex-b/disabled/3.3-function-in-if-body/input.js"
|
||||
Expect Syntax Error: "annex-b/disabled/3.4-var-redeclaration-catch-binding/input.js"
|
||||
Expect Syntax Error: "annex-b/disabled/3.5-for-in-initializer/input.js"
|
||||
Expect Syntax Error: "annex-b/enabled/3.1-sloppy-labeled-functions-if-body/input.js"
|
||||
Expect Syntax Error: "annex-b/enabled/3.4-var-redeclaration-catch-binding/input.js"
|
||||
Expect Syntax Error: "core/categorized/invalid-fn-decl-inside-loop/input.js"
|
||||
Expect Syntax Error: "core/categorized/invalid-fn-decl-labeled-inside-if/input.js"
|
||||
Expect Syntax Error: "core/categorized/invalid-fn-decl-labeled-inside-loop/input.js"
|
||||
|
|
@ -26,12 +24,7 @@ Expect Syntax Error: "core/legacy-octal/legacy-octal-after-use-strict-function/i
|
|||
Expect Syntax Error: "core/legacy-octal/legacy-octal-after-use-strict/input.js"
|
||||
Expect Syntax Error: "core/opts/allowNewTargetOutsideFunction-false-2/input.js"
|
||||
Expect Syntax Error: "core/opts/allowNewTargetOutsideFunction-false/input.js"
|
||||
Expect Syntax Error: "core/scope/dupl-bind-catch-arr-destr/input.js"
|
||||
Expect Syntax Error: "core/scope/dupl-bind-catch-func/input.js"
|
||||
Expect Syntax Error: "core/scope/dupl-bind-catch-let/input.js"
|
||||
Expect Syntax Error: "core/scope/dupl-bind-catch-obj-destr/input.js"
|
||||
Expect Syntax Error: "core/scope/dupl-bind-catch-var-arr-destr/input.js"
|
||||
Expect Syntax Error: "core/scope/dupl-bind-catch-var-obj-destr/input.js"
|
||||
Expect Syntax Error: "core/scope/dupl-bind-class-func/input.js"
|
||||
Expect Syntax Error: "core/scope/dupl-bind-func-gen/input.js"
|
||||
Expect Syntax Error: "core/scope/dupl-bind-func-module-sloppy/input.js"
|
||||
|
|
@ -649,6 +642,24 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
|
|||
2 │ function b<const T extends U>() {}
|
||||
╰────
|
||||
|
||||
× Identifier `"f"` has already been declared
|
||||
╭─[annex-b/disabled/3.4-var-redeclaration-catch-binding/input.js:1:1]
|
||||
1 │ try {} catch (e) { var e; }
|
||||
2 │ try {} catch ({ f }) { var f; }
|
||||
· ┬ ┬
|
||||
· │ ╰── It can not be redeclared here
|
||||
· ╰── `f` has already been declared here
|
||||
╰────
|
||||
|
||||
× Identifier `"f"` has already been declared
|
||||
╭─[annex-b/enabled/3.4-var-redeclaration-catch-binding/input.js:1:1]
|
||||
1 │ try {} catch (e) { var e; }
|
||||
2 │ try {} catch ({ f }) { var f; }
|
||||
· ┬ ┬
|
||||
· │ ╰── It can not be redeclared here
|
||||
· ╰── `f` has already been declared here
|
||||
╰────
|
||||
|
||||
× Expect token
|
||||
╭─[core/categorized/for-missing-semicolons/input.js:2:1]
|
||||
2 │ var a = 1
|
||||
|
|
@ -915,6 +926,16 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
|
|||
· ╰── It can not be redeclared here
|
||||
╰────
|
||||
|
||||
× Identifier `"foo"` has already been declared
|
||||
╭─[core/scope/dupl-bind-catch-arr-destr/input.js:1:1]
|
||||
1 │ try {
|
||||
2 │ } catch ([foo, foo]) {
|
||||
· ─┬─ ─┬─
|
||||
· │ ╰── It can not be redeclared here
|
||||
· ╰── `foo` has already been declared here
|
||||
3 │ }
|
||||
╰────
|
||||
|
||||
× Identifier `"foo"` has already been declared
|
||||
╭─[core/scope/dupl-bind-catch-dbl-let/input.js:1:1]
|
||||
1 │ let foo; try {} catch (foo) {} let foo;
|
||||
|
|
@ -923,6 +944,52 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
|
|||
· ╰── `foo` has already been declared here
|
||||
╰────
|
||||
|
||||
× Identifier `"foo"` has already been declared
|
||||
╭─[core/scope/dupl-bind-catch-let/input.js:1:1]
|
||||
1 │ try {
|
||||
2 │ } catch (foo) {
|
||||
· ─┬─
|
||||
· ╰── `foo` has already been declared here
|
||||
3 │ let foo;
|
||||
· ─┬─
|
||||
· ╰── It can not be redeclared here
|
||||
4 │ }
|
||||
╰────
|
||||
|
||||
× Identifier `"foo"` has already been declared
|
||||
╭─[core/scope/dupl-bind-catch-obj-destr/input.js:1:1]
|
||||
1 │ try {
|
||||
2 │ } catch ({ a: foo, b: { c: [foo] } }) {
|
||||
· ─┬─ ─┬─
|
||||
· │ ╰── It can not be redeclared here
|
||||
· ╰── `foo` has already been declared here
|
||||
3 │ }
|
||||
╰────
|
||||
|
||||
× Identifier `"foo"` has already been declared
|
||||
╭─[core/scope/dupl-bind-catch-var-arr-destr/input.js:1:1]
|
||||
1 │ try {
|
||||
2 │ } catch ([foo]) {
|
||||
· ─┬─
|
||||
· ╰── `foo` has already been declared here
|
||||
3 │ var foo;
|
||||
· ─┬─
|
||||
· ╰── It can not be redeclared here
|
||||
4 │ }
|
||||
╰────
|
||||
|
||||
× Identifier `"foo"` has already been declared
|
||||
╭─[core/scope/dupl-bind-catch-var-obj-destr/input.js:1:1]
|
||||
1 │ try {
|
||||
2 │ } catch ({ foo }) {
|
||||
· ─┬─
|
||||
· ╰── `foo` has already been declared here
|
||||
3 │ var foo;
|
||||
· ─┬─
|
||||
· ╰── It can not be redeclared here
|
||||
4 │ }
|
||||
╰────
|
||||
|
||||
× Identifier `"foo"` has already been declared
|
||||
╭─[core/scope/dupl-bind-class-class/input.js:1:1]
|
||||
1 │ class foo {};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
Test262 Summary:
|
||||
AST Parsed : 44022/44034 (99.97%)
|
||||
Positive Passed: 44022/44034 (99.97%)
|
||||
Negative Passed: 2694/3917 (68.78%)
|
||||
Negative Passed: 2696/3917 (68.83%)
|
||||
Expect Syntax Error: "annexB/language/statements/for-in/const-initializer.js"
|
||||
Expect Syntax Error: "annexB/language/statements/for-in/let-initializer.js"
|
||||
Expect Syntax Error: "annexB/language/statements/for-in/strict-initializer.js"
|
||||
|
|
@ -1178,9 +1178,7 @@ Expect Syntax Error: "language/statements/try/catch-parameter-boundnames-restric
|
|||
Expect Syntax Error: "language/statements/try/dstr/ary-ptrn-rest-init-ary.js"
|
||||
Expect Syntax Error: "language/statements/try/dstr/ary-ptrn-rest-init-id.js"
|
||||
Expect Syntax Error: "language/statements/try/dstr/ary-ptrn-rest-init-obj.js"
|
||||
Expect Syntax Error: "language/statements/try/early-catch-duplicates.js"
|
||||
Expect Syntax Error: "language/statements/try/early-catch-function.js"
|
||||
Expect Syntax Error: "language/statements/try/early-catch-lex.js"
|
||||
Expect Syntax Error: "language/statements/try/static-init-await-binding-invalid.js"
|
||||
Expect Syntax Error: "language/statements/variable/12.2.1-1gs.js"
|
||||
Expect Syntax Error: "language/statements/variable/12.2.1-4gs.js"
|
||||
|
|
@ -24397,6 +24395,24 @@ Expect to Parse: "language/statements/class/decorator/syntax/valid/decorator-par
|
|||
33 │
|
||||
╰────
|
||||
|
||||
× Identifier `"x"` has already been declared
|
||||
╭─[language/statements/try/early-catch-duplicates.js:15:1]
|
||||
15 │
|
||||
16 │ try { } catch ([x, x]) {}
|
||||
· ┬ ┬
|
||||
· │ ╰── It can not be redeclared here
|
||||
· ╰── `x` has already been declared here
|
||||
╰────
|
||||
|
||||
× Identifier `"x"` has already been declared
|
||||
╭─[language/statements/try/early-catch-lex.js:16:1]
|
||||
16 │
|
||||
17 │ try { } catch (x) { let x; }
|
||||
· ┬ ┬
|
||||
· │ ╰── It can not be redeclared here
|
||||
· ╰── `x` has already been declared here
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[language/statements/try/optional-catch-binding-parens.js:19:1]
|
||||
19 │
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
TypeScript Summary:
|
||||
AST Parsed : 2306/2338 (98.63%)
|
||||
Positive Passed: 2306/2338 (98.63%)
|
||||
Negative Passed: 587/2532 (23.18%)
|
||||
AST Parsed : 2305/2338 (98.59%)
|
||||
Positive Passed: 2305/2338 (98.59%)
|
||||
Negative Passed: 589/2532 (23.26%)
|
||||
Expect Syntax Error: "Symbols/ES5SymbolProperty2.ts"
|
||||
Expect Syntax Error: "Symbols/ES5SymbolProperty6.ts"
|
||||
Expect Syntax Error: "additionalChecks/noPropertyAccessFromIndexSignature1.ts"
|
||||
|
|
@ -998,7 +998,6 @@ Expect Syntax Error: "jsdoc/jsdocAugments_errorInExtendsExpression.ts"
|
|||
Expect Syntax Error: "jsdoc/jsdocAugments_nameMismatch.ts"
|
||||
Expect Syntax Error: "jsdoc/jsdocAugments_noExtends.ts"
|
||||
Expect Syntax Error: "jsdoc/jsdocAugments_notAClass.ts"
|
||||
Expect Syntax Error: "jsdoc/jsdocCatchClauseWithTypeAnnotation.ts"
|
||||
Expect Syntax Error: "jsdoc/jsdocFunctionType.ts"
|
||||
Expect Syntax Error: "jsdoc/jsdocFunction_missingReturn.ts"
|
||||
Expect Syntax Error: "jsdoc/jsdocImplements_class.ts"
|
||||
|
|
@ -1561,7 +1560,6 @@ Expect Syntax Error: "statements/for-ofStatements/ES5For-ofTypeCheck9.ts"
|
|||
Expect Syntax Error: "statements/forStatements/forStatementsMultipleInvalidDecl.ts"
|
||||
Expect Syntax Error: "statements/returnStatements/invalidReturnStatements.ts"
|
||||
Expect Syntax Error: "statements/switchStatements/switchStatements.ts"
|
||||
Expect Syntax Error: "statements/tryStatements/catchClauseWithTypeAnnotation.ts"
|
||||
Expect Syntax Error: "types/any/anyAsConstructor.ts"
|
||||
Expect Syntax Error: "types/any/anyAsGenericFunctionCall.ts"
|
||||
Expect Syntax Error: "types/any/assignAnyToEveryType.ts"
|
||||
|
|
@ -1947,6 +1945,19 @@ Expect Syntax Error: "types/unknown/unknownControlFlow.ts"
|
|||
Expect Syntax Error: "types/unknown/unknownType1.ts"
|
||||
Expect Syntax Error: "types/unknown/unknownType2.ts"
|
||||
Expect Syntax Error: "types/witness/witness.ts"
|
||||
Expect to Parse: "async/es6/asyncWithVarShadowing_es6.ts"
|
||||
|
||||
× Identifier `"x"` has already been declared
|
||||
╭─[async/es6/asyncWithVarShadowing_es6.ts:131:1]
|
||||
131 │ }
|
||||
132 │ catch ({ x }) {
|
||||
· ┬
|
||||
· ╰── `x` has already been declared here
|
||||
133 │ var x;
|
||||
· ┬
|
||||
· ╰── It can not be redeclared here
|
||||
134 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/propertyMemberDeclarations/autoAccessor4.ts"
|
||||
|
||||
× Automatic Semicolon Insertion
|
||||
|
|
@ -6104,6 +6115,19 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
|
|||
4 │ }
|
||||
╰────
|
||||
|
||||
× Identifier `"err"` has already been declared
|
||||
╭─[jsdoc/jsdocCatchClauseWithTypeAnnotation.ts:39:1]
|
||||
39 │ try { }
|
||||
40 │ catch (err) {
|
||||
· ─┬─
|
||||
· ╰── `err` has already been declared here
|
||||
41 │ /** @type {string} */
|
||||
42 │ let err;
|
||||
· ─┬─
|
||||
· ╰── It can not be redeclared here
|
||||
43 │ }
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[jsdoc/jsdocDisallowedInTypescript.ts:3:1]
|
||||
3 │ // grammar error from checker
|
||||
|
|
@ -8873,6 +8897,16 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
|
|||
4 │
|
||||
╰────
|
||||
|
||||
× Identifier `"x"` has already been declared
|
||||
╭─[statements/tryStatements/catchClauseWithTypeAnnotation.ts:28:1]
|
||||
28 │ // minor bug: shows that the `catch` argument is skipped when checking scope
|
||||
29 │ try { } catch (x) { let x: string; }
|
||||
· ┬ ┬
|
||||
· │ ╰── It can not be redeclared here
|
||||
· ╰── `x` has already been declared here
|
||||
30 │ try { } catch (x) { var x: string; }
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[statements/tryStatements/invalidTryStatements.ts:1:1]
|
||||
1 │ function fn() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue