fix(rome_js_semantic): include binding for type parameters
ADD
crates/rome_js_analyze/tests/specs/correctness/noUndeclaredVariables.ts
+// valid
+export type EventHandler<T extends string> = `on${T}`
+export type EventHandlerDefault<T extends string = 'click'> = `on${T}`
+
+export type NestedContext<S extends NestedContext<''>> = '' | `(${S})`
+export type NestedContextDefault<S extends NestedContextDefault = ''> = '' | `(${S})`
+
+export type Whatever<S extends number> = `Hello ${S}`
+export type WhateverDefault<S extends number = 2> = `Hello ${S}`
+
+// Invalid
+export type Invalid<S extends number> = `Hello ${T}`
\ No newline at end of file

MODIFY
crates/rome_js_semantic/src/events.rs
crates/rome_js_semantic/src/events.rs
@@ -8,7 +8,7 @@ use rome_js_syntax::{
JsCallExpression, JsForVariableDeclaration, JsIdentifierAssignment, JsIdentifierBinding,
JsLanguage, JsParenthesizedExpression, JsReferenceIdentifier, JsSyntaxKind, JsSyntaxNode,
JsSyntaxToken, JsVariableDeclaration, JsVariableDeclarator, JsVariableDeclaratorList,
- JsxReferenceIdentifier, TextRange, TextSize, TsIdentifierBinding,
+ JsxReferenceIdentifier, TextRange, TextSize, TsIdentifierBinding, TsTypeParameter,
};
use rome_rowan::{syntax::Preorder, AstNode, SyntaxNodeCast, SyntaxNodeOptionExt, SyntaxTokenText};
@@ -245,7 +245,7 @@ impl SemanticEventExtractor {
use rome_js_syntax::JsSyntaxKind::*;
match node.kind() {
- JS_IDENTIFIER_BINDING | TS_IDENTIFIER_BINDING => {
+ JS_IDENTIFIER_BINDING | TS_IDENTIFIER_BINDING | TS_TYPE_PARAMETER => {
self.enter_identifier_binding(node);
}
JS_REFERENCE_IDENTIFIER | JSX_REFERENCE_IDENTIFIER => {
@@ -322,8 +322,8 @@ impl SemanticEventExtractor {
use JsSyntaxKind::*;
debug_assert!(matches!(
node.kind(),
- JS_IDENTIFIER_BINDING | TS_IDENTIFIER_BINDING
- ), "specified node is not a identifier binding (JS_IDENTIFIER_BINDING, TS_IDENTIFIER_BINDING)");
+ JS_IDENTIFIER_BINDING | TS_IDENTIFIER_BINDING | TS_TYPE_PARAMETER
+ ), "specified node is not a identifier binding (JS_IDENTIFIER_BINDING, TS_IDENTIFIER_BINDING, TS_TYPE_PARAMETER)");
let (name_token, is_var) = match node.kind() {
JS_IDENTIFIER_BINDING => {
@@ -338,6 +338,12 @@ impl SemanticEventExtractor {
let is_var = Self::is_var(&binding);
(name_token, is_var)
}
+ TS_TYPE_PARAMETER => {
+ let binding = node.clone().cast::<TsTypeParameter>()?;
+ let name_token = binding.name().ok()?.ident_token().ok()?;
+ let is_var = Self::is_var(&binding);
+ (name_token, is_var)
+ }
_ => return None,
};

MODIFY
crates/rome_js_semantic/src/tests/assertions.rs
crates/rome_js_semantic/src/tests/assertions.rs
@@ -669,10 +669,6 @@ impl SemanticAssertions {
// where we expect
let e = events.iter().find(|event| match event {
SemanticEvent::ScopeEnded { started_at, .. } => {
- println!(
- "started_at: {:?} scope_start_assertions_range: {:?}",
- started_at, scope_start_assertions_range
- );
*started_at == scope_start_assertions_range.start()
}
_ => false,

MODIFY
crates/rome_js_semantic/src/tests/scopes.rs
crates/rome_js_semantic/src/tests/scopes.rs
@@ -32,6 +32,21 @@ assert_semantics! {
ok_scope_class_setter, ";class A { set/*START A*/ name(v) {}/*END A*/ }",
}
+// Type parameters
+assert_semantics! {
+ ok_type_parameter, "export type /*START A*/ EventHandler<Event /*# Event */ /*@ A */ extends string> = `on${ Event /*READ Event */ }` /*END A*/",
+ ok_type_parameter_with_default, "export type /*START A */ EventHandler<Event /*# Event */ /*@ A */ extends string = 'click'> = `on${ Event /*READ Event */ }` /*END A*/",
+ ok_type_parameter_multiple_declaration, "
+ export type /*START ScopeA */ EventHandler<Event /*# EventA */ /*@ ScopeA */ extends string> = `on${ Event /*READ EventA */ }`; /*END ScopeA */
+ export type /*START ScopeB */ EventHandlerDefault<Event /*# EventB */ /*@ ScopeB */ extends string = 'click'> = `on${ Event /*READ EventB */ }`; /*END ScopeB */
+ ",
+ ok_type_parameter_interface, "
+ export interface /*START A*/ EventHandler<Event /*# Event */ /*@ A */ extends string> {
+ [`on${ Event /*READ Event */ }`]: (event: Event /*READ Event */, data: unknown) => void;
+ } /*END A*/
+ ",
+}
+
// Others
assert_semantics! {
ok_scope_global, "/*START GLOBAL*//*END GLOBAL*/",

fix(rome_js_semantic): include binding for type parameters (#3803)