mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
fix(semantic): correctly resolve binding for return type of functions (#6388)
Fixes #6387.
This commit is contained in:
parent
b0e1c03284
commit
f3850eb53b
3 changed files with 137 additions and 9 deletions
|
|
@ -1655,6 +1655,18 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
|
|||
if let Some(return_type) = &func.return_type {
|
||||
self.visit_ts_type_annotation(return_type);
|
||||
}
|
||||
|
||||
if func.params.has_parameter() || func.return_type.is_some() {
|
||||
// `function foo({bar: identifier_reference}) {}`
|
||||
// ^^^^^^^^^^^^^^^^^^^^
|
||||
// `function foo<SomeType>(v: SomeType): SomeType { return v; }`
|
||||
// ^^^^^^^^ ^^^^^^^^
|
||||
// Parameter initializers must be resolved after all parameters have been declared.
|
||||
// Param types and return type must be resolved after type parameters have been declared.
|
||||
// In both cases, need to avoid binding to variables/types declared inside the function body.
|
||||
self.resolve_references_for_current_scope();
|
||||
}
|
||||
|
||||
if let Some(body) = &func.body {
|
||||
self.visit_function_body(body);
|
||||
}
|
||||
|
|
@ -1719,6 +1731,17 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
|
|||
self.visit_ts_type_annotation(return_type);
|
||||
}
|
||||
|
||||
if expr.params.has_parameter() || expr.return_type.is_some() {
|
||||
// `let foo = ({bar: identifier_reference}) => {};`
|
||||
// ^^^^^^^^^^^^^^^^^^^^
|
||||
// `let foo = <SomeType>(v: SomeType): SomeType => v;`
|
||||
// ^^^^^^^^ ^^^^^^^^
|
||||
// Parameter initializers must be resolved after all parameters have been declared.
|
||||
// Param types and return type must be resolved after type parameters have been declared.
|
||||
// In both cases, need to avoid binding to variables/types declared inside the function body.
|
||||
self.resolve_references_for_current_scope();
|
||||
}
|
||||
|
||||
self.visit_function_body(&expr.body);
|
||||
|
||||
/* cfg */
|
||||
|
|
@ -2021,15 +2044,6 @@ impl<'a> SemanticBuilder<'a> {
|
|||
AstKind::Function(_) | AstKind::ArrowFunctionExpression(_) => {
|
||||
self.function_stack.pop();
|
||||
}
|
||||
AstKind::FormalParameters(parameters) => {
|
||||
if parameters.kind != FormalParameterKind::Signature && parameters.has_parameter() {
|
||||
// `function foo({bar: identifier_reference}) {}`
|
||||
// ^^^^^^^^^^^^^^^^^^^^ Parameter initializer must be resolved
|
||||
// after all parameters have been declared
|
||||
// to avoid binding to variables inside the scope
|
||||
self.resolve_references_for_current_scope();
|
||||
}
|
||||
}
|
||||
AstKind::CatchParameter(_) => {
|
||||
self.resolve_references_for_current_scope();
|
||||
}
|
||||
|
|
|
|||
102
crates/oxc_semantic/tests/fixtures/oxc/ts/functions/return-type.snap
vendored
Normal file
102
crates/oxc_semantic/tests/fixtures/oxc/ts/functions/return-type.snap
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
---
|
||||
source: crates/oxc_semantic/tests/main.rs
|
||||
input_file: crates/oxc_semantic/tests/fixtures/oxc/ts/functions/return-type.ts
|
||||
---
|
||||
[
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
"flags": "ScopeFlags(StrictMode)",
|
||||
"id": 1,
|
||||
"node": "TSTypeAliasDeclaration",
|
||||
"symbols": []
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
"flags": "ScopeFlags(StrictMode)",
|
||||
"id": 3,
|
||||
"node": "TSTypeAliasDeclaration",
|
||||
"symbols": []
|
||||
}
|
||||
],
|
||||
"flags": "ScopeFlags(StrictMode | Function)",
|
||||
"id": 2,
|
||||
"node": "Function(Foo)",
|
||||
"symbols": [
|
||||
{
|
||||
"flags": "SymbolFlags(TypeAlias)",
|
||||
"id": 2,
|
||||
"name": "T",
|
||||
"node": "TSTypeAliasDeclaration",
|
||||
"references": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [],
|
||||
"flags": "ScopeFlags(StrictMode)",
|
||||
"id": 5,
|
||||
"node": "TSTypeAliasDeclaration",
|
||||
"symbols": []
|
||||
}
|
||||
],
|
||||
"flags": "ScopeFlags(StrictMode | Function | Arrow)",
|
||||
"id": 4,
|
||||
"node": "ArrowFunctionExpression",
|
||||
"symbols": [
|
||||
{
|
||||
"flags": "SymbolFlags(TypeAlias)",
|
||||
"id": 4,
|
||||
"name": "T",
|
||||
"node": "TSTypeAliasDeclaration",
|
||||
"references": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"flags": "ScopeFlags(StrictMode | Top)",
|
||||
"id": 0,
|
||||
"node": "Program",
|
||||
"symbols": [
|
||||
{
|
||||
"flags": "SymbolFlags(TypeAlias)",
|
||||
"id": 0,
|
||||
"name": "T",
|
||||
"node": "TSTypeAliasDeclaration",
|
||||
"references": [
|
||||
{
|
||||
"flags": "ReferenceFlags(Type)",
|
||||
"id": 0,
|
||||
"name": "T",
|
||||
"node_id": 12
|
||||
},
|
||||
{
|
||||
"flags": "ReferenceFlags(Type)",
|
||||
"id": 1,
|
||||
"name": "T",
|
||||
"node_id": 27
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"flags": "SymbolFlags(BlockScopedVariable | Function)",
|
||||
"id": 1,
|
||||
"name": "Foo",
|
||||
"node": "Function(Foo)",
|
||||
"references": []
|
||||
},
|
||||
{
|
||||
"flags": "SymbolFlags(BlockScopedVariable | ConstVariable)",
|
||||
"id": 3,
|
||||
"name": "Bar",
|
||||
"node": "VariableDeclarator(Bar)",
|
||||
"references": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
12
crates/oxc_semantic/tests/fixtures/oxc/ts/functions/return-type.ts
vendored
Normal file
12
crates/oxc_semantic/tests/fixtures/oxc/ts/functions/return-type.ts
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
export type T = number;
|
||||
|
||||
function Foo(): T {
|
||||
type T = string;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Bar = (): T => {
|
||||
type T = string;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in a new issue