Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions crates/oxc_linter/src/rules/eslint/no_unused_vars/tests/oxc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1292,6 +1292,19 @@ fn test_report_vars_only_used_as_types() {
.test();
}

#[test]
fn test_js() {
let pass = vec![
// https://github.com/oxc-project/oxc/issues/11215
"export function promisify() { var fn; function fn() {}; return fn; }",
];

Tester::new(NoUnusedVars::NAME, NoUnusedVars::PLUGIN, pass, vec![])
.change_rule_path_extension("js")
.intentionally_allow_no_fix_tests()
.test();
}

// #[test]
// fn test_template() {
// let pass = vec![];
Expand Down
31 changes: 31 additions & 0 deletions crates/oxc_semantic/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,37 @@ impl<'a> SemanticBuilder<'a> {
excludes: SymbolFlags,
) -> SymbolId {
if let Some(symbol_id) = self.check_redeclaration(scope_id, span, name, excludes, true) {
// While cases such as:
// ```javascript
// var x;
// function x() {}
// ```
// are illegal in TypeScript, they are legal in JavaScript.
// Since, in JavaScript, the `function` declaration is hoisted first, we need to make sure that
// if we find a `function` declaration after a `var` declaration, we need to update the
// `symbol_declarations` to point to the `function` declaration.
// ```javascript
// var x;
// function x() {}
// ```
if !self.source_type.is_typescript()
&& includes.contains(SymbolFlags::Function)
&& self.scoping.symbol_flags(symbol_id) == SymbolFlags::FunctionScopedVariable
&& !self.scoping.symbol_flags(symbol_id).contains(SymbolFlags::Function)
{
let old_span = self.scoping.symbol_spans[symbol_id];
let old_flags = self.scoping.symbol_flags(symbol_id);
let old_node_id = self.scoping.symbol_declaration(symbol_id);
self.scoping.symbol_spans[symbol_id] = span;
self.scoping.symbol_flags[symbol_id] = includes;
self.scoping.symbol_scope_ids[symbol_id] = scope_id;
self.scoping.symbol_declarations[symbol_id] = self.current_node_id;

self.scoping.add_symbol_redeclaration(symbol_id, old_flags, old_node_id, old_span);
self.scoping.union_symbol_flag(symbol_id, includes);
return symbol_id;
}

self.add_redeclare_variable(symbol_id, includes, span);
self.scoping.union_symbol_flag(symbol_id, includes);
return symbol_id;
Expand Down
3 changes: 0 additions & 3 deletions tasks/transform_conformance/snapshots/babel.snap.md
Original file line number Diff line number Diff line change
Expand Up @@ -1012,9 +1012,6 @@ rebuilt : ScopeId(7): []
Symbol flags mismatch for "a":
after transform: SymbolId(0): SymbolFlags(BlockScopedVariable)
rebuilt : SymbolId(8): SymbolFlags(Function)
Symbol span mismatch for "a":
after transform: SymbolId(0): Span { start: 27, end: 28 }
rebuilt : SymbolId(8): Span { start: 86, end: 87 }
Symbol scope ID mismatch for "a":
after transform: SymbolId(0): ScopeId(2)
rebuilt : SymbolId(8): ScopeId(0)
Expand Down
Loading