Skip to content

Commit

Permalink
fix(isolated_declarations): Support expando functions
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelMitchell-at committed Aug 15, 2024
1 parent 9c700ed commit 2dba19a
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 5 deletions.
72 changes: 70 additions & 2 deletions crates/oxc_isolated_declarations/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use oxc_allocator::Allocator;
use oxc_ast::{ast::*, AstBuilder, Visit};
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{Atom, SourceType, SPAN};
use rustc_hash::FxHashSet;
use rustc_hash::{FxHashMap, FxHashSet};

use crate::scope::ScopeTree;

Expand Down Expand Up @@ -405,6 +405,67 @@ impl<'a> IsolatedDeclarations<'a> {
}

pub fn report_error_for_expando_function(&self, stmts: &oxc_allocator::Vec<'a, Statement<'a>>) {
let mut assignable_properties_for_namespace = FxHashMap::<&str, FxHashSet<Atom>>::default();
for stmt in stmts {
let Statement::ExportNamedDeclaration(decl) = stmt else { continue };
let Some(Declaration::TSModuleDeclaration(decl)) = &decl.declaration else { continue };
if decl.kind != TSModuleDeclarationKind::Namespace {
continue;
}
let TSModuleDeclarationName::Identifier(ident) = &decl.id else { continue };
let Some(TSModuleDeclarationBody::TSModuleBlock(block)) = &decl.body else {
continue;
};
for stmt in block.body.iter() {
let Statement::ExportNamedDeclaration(decl) = stmt else { continue };
match &decl.declaration {
Some(Declaration::VariableDeclaration(var)) => {
for declarator in &var.declarations {
if let Some(name) = declarator.id.get_identifier() {
assignable_properties_for_namespace
.entry(&ident.name)
.or_default()
.insert(name);
}
}
}
Some(Declaration::FunctionDeclaration(func)) => {
if let Some(id) = func.id.as_ref() {
assignable_properties_for_namespace
.entry(&ident.name)
.or_default()
.insert(id.name.clone());
}
}
Some(Declaration::ClassDeclaration(cls)) => {
if let Some(id) = cls.id.as_ref() {
assignable_properties_for_namespace
.entry(&ident.name)
.or_default()
.insert(id.name.clone());
}
}
Some(Declaration::TSEnumDeclaration(decl)) => {
assignable_properties_for_namespace
.entry(&ident.name)
.or_default()
.insert(decl.id.name.clone());
}
Some(Declaration::UsingDeclaration(decl)) => {
for declarator in &decl.declarations {
if let Some(name) = declarator.id.get_identifier() {
assignable_properties_for_namespace
.entry(&ident.name)
.or_default()
.insert(name);
}
}
}
_ => {}
}
}
}

let mut can_expando_function_names = FxHashSet::default();
for stmt in stmts {
match stmt {
Expand Down Expand Up @@ -468,7 +529,14 @@ impl<'a> IsolatedDeclarations<'a> {
&assignment.left
{
if let Expression::Identifier(ident) = &static_member_expr.object {
if can_expando_function_names.contains(&ident.name) {
if can_expando_function_names.contains(&ident.name)
&& !assignable_properties_for_namespace
.get(&ident.name.as_str())
.map_or(false, |properties| {
properties.contains(&static_member_expr.property.name)
})
{
println!("{:?}", assignable_properties_for_namespace);
self.error(function_with_assigning_properties(
static_member_expr.span,
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@ export function foo(): void {}
foo.apply = () => {}

export const bar = (): void => {}
bar.call = ()=> {}
bar.call = () => {}


export namespace NS {
export const goo = (): void => {}
goo.length = 10
}

export namespace foo {
let bar = 42;
export let baz = 100;
}

foo.bar = 42;
foo.baz = 100;

// unexported
const zoo = (): void => {}
zoo.toString = ()=> {}
zoo.toString = () => {}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ export declare const bar: () => void;
export declare namespace NS {
export const goo: () => void;
}
export declare namespace foo {
export let baz: number;
}


==================== Errors ====================
Expand Down Expand Up @@ -38,7 +41,17 @@ export declare namespace NS {
| properties assigned to this function.
,-[5:1]
4 | export const bar = (): void => {}
5 | bar.call = ()=> {}
5 | bar.call = () => {}
: ^^^^^^^^
6 |
`----
x TS9023: Assigning properties to functions without declaring them is not
| supported with --isolatedDeclarations. Add an explicit declaration for the
| properties assigned to this function.
,-[18:1]
17 |
18 | foo.bar = 42;
: ^^^^^^^
19 | foo.baz = 100;
`----

0 comments on commit 2dba19a

Please sign in to comment.