Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

fix(js_semantic):handle exported modules and their members #4205

Merged
merged 1 commit into from
Feb 14, 2023
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ fn is_property_parameter_ok_not_be_used(parameter: TsPropertyParameter) -> Optio
Some(false)
}

fn is_is_ambient_context(node: &JsSyntaxNode) -> bool {
fn is_ambient_context(node: &JsSyntaxNode) -> bool {
node.ancestors()
.any(|x| x.kind() == JsSyntaxKind::TS_DECLARE_STATEMENT)
}
Expand Down Expand Up @@ -205,7 +205,7 @@ fn suggested_fix_if_unused(binding: &AnyJsIdentifierBinding) -> Option<Suggested

// declarations need to be check if they are under `declare`
node @ AnyJsBindingDeclaration::JsVariableDeclarator(_) => {
let is_binding_ok = is_is_ambient_context(&node.syntax().clone());
let is_binding_ok = is_ambient_context(node.syntax());
if !is_binding_ok {
suggestion_for_binding(binding)
} else {
Expand All @@ -219,7 +219,7 @@ fn suggested_fix_if_unused(binding: &AnyJsIdentifierBinding) -> Option<Suggested
| node @ AnyJsBindingDeclaration::TsEnumDeclaration(_)
| node @ AnyJsBindingDeclaration::TsModuleDeclaration(_)
| node @ AnyJsBindingDeclaration::TsImportEqualsDeclaration(_) => {
if is_is_ambient_context(&node.syntax().clone()) {
if is_ambient_context(node.syntax()) {
None
} else {
Some(SuggestedFix::NoSuggestion)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export module MyModule {
export function id() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
source: crates/rome_js_analyze/tests/spec_tests.rs
assertion_line: 351
expression: ambient-module.ts
---
# Input
```js
export module MyModule {
export function id() {}
}

```


44 changes: 7 additions & 37 deletions crates/rome_js_semantic/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,11 @@ impl SemanticEventExtractor {
self.push_binding_into_scope(hoisted_scope_id, &name_token);
self.export_declaration(node, &parent);
}
TS_MODULE_DECLARATION => {
let hoisted_scope_id = self.scope_index_to_hoist_declarations(1);
self.push_binding_into_scope(hoisted_scope_id, &name_token);
self.export_declaration(node, &parent);
}
_ => {
self.push_binding_into_scope(None, &name_token);
}
Expand Down Expand Up @@ -791,12 +796,6 @@ impl SemanticEventExtractor {
function_declaration.kind(),
JS_FUNCTION_DECLARATION | JS_FUNCTION_EXPORT_DEFAULT_DECLARATION
));

// scope[0] = global, scope[1] = the function itself
if self.scopes.len() != 2 {
return;
}

let is_exported = matches!(
function_declaration.parent().kind(),
Some(JS_EXPORT | JS_EXPORT_DEFAULT_DECLARATION_CLAUSE)
Expand All @@ -816,12 +815,6 @@ impl SemanticEventExtractor {
) {
use JsSyntaxKind::*;
debug_assert!(matches!(function_expression.kind(), JS_FUNCTION_EXPRESSION));

// scope[0] = global, scope[1] = the function itself
if self.scopes.len() != 2 {
return;
}

let is_module_exports = function_expression
.parent()
.map(|x| self.is_assignment_left_side_module_exports(&x))
Expand All @@ -837,12 +830,6 @@ impl SemanticEventExtractor {
fn export_class_expression(&mut self, binding: &JsSyntaxNode, class_expression: &JsSyntaxNode) {
use JsSyntaxKind::*;
debug_assert!(matches!(class_expression.kind(), JS_CLASS_EXPRESSION));

// scope[0] = global, scope[1] = the class expression itself
if self.scopes.len() != 2 {
return;
}

let is_module_exports = class_expression
.parent()
.map(|x| self.is_assignment_left_side_module_exports(&x))
Expand All @@ -854,7 +841,7 @@ impl SemanticEventExtractor {
}
}

// Check if a class, type alias is exported and raise the [Exported] event.
// Check if a class, type alias, enum, interface, module is exported and raise the [Exported] event.
fn export_declaration(&mut self, binding: &JsSyntaxNode, declaration: &JsSyntaxNode) {
use JsSyntaxKind::*;
debug_assert!(matches!(
Expand All @@ -864,13 +851,8 @@ impl SemanticEventExtractor {
| TS_TYPE_ALIAS_DECLARATION
| TS_ENUM_DECLARATION
| TS_INTERFACE_DECLARATION
| TS_MODULE_DECLARATION
));

// scope[0] = global, scope[1] = what is being exported
if self.scopes.len() != 2 {
return;
}

let is_exported = matches!(
declaration.parent().kind(),
Some(JS_EXPORT | JS_EXPORT_DEFAULT_DECLARATION_CLAUSE)
Expand All @@ -891,12 +873,6 @@ impl SemanticEventExtractor {
) {
use JsSyntaxKind::*;
debug_assert!(matches!(variable_declarator.kind(), JS_VARIABLE_DECLARATOR));

// export can only exist in the global scope
if self.scopes.len() > 1 {
return;
}

let is_exported = matches!(
variable_declarator
.parent()
Expand All @@ -918,12 +894,6 @@ impl SemanticEventExtractor {
fn is_js_reference_identifier_exported(&mut self, reference: &JsSyntaxNode) -> bool {
use JsSyntaxKind::*;
debug_assert!(matches!(reference.kind(), JS_REFERENCE_IDENTIFIER));

// export can only exist in the global scope
if self.scopes.len() > 1 {
return false;
}

let reference_parent = reference.parent();
let reference_greatparent = reference_parent.as_ref().and_then(|p| p.parent());

Expand Down
2 changes: 1 addition & 1 deletion crates/rome_js_semantic/src/tests/scopes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ assert_semantics! {
",
}

// modules
// Modules
assert_semantics! {
ok_scope_module, "module/*START M*/ M {}/*END M*/;",
}
Expand Down