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

fix(rome_js_analyze): fix ts const assertion on noUndeclaredVariables #3981

Merged
merged 3 commits into from
Dec 8, 2022
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 @@ -6,10 +6,8 @@ use crate::semantic_services::SemanticServices;
use rome_analyze::context::RuleContext;
use rome_analyze::{declare_rule, Rule, RuleDiagnostic};
use rome_console::markup;
use rome_js_syntax::{
JsIdentifierAssignment, JsReferenceIdentifier, JsxReferenceIdentifier, TextRange,
};
use rome_rowan::{declare_node_union, AstNode};
use rome_js_syntax::{TextRange, TsAsExpression, TsReferenceType};
use rome_rowan::AstNode;

declare_rule! {
/// Prevents the usage of variables that haven't been declared inside the document
Expand All @@ -28,10 +26,6 @@ declare_rule! {
}
}

declare_node_union! {
pub(crate) AnyIdentifier = JsReferenceIdentifier | JsIdentifierAssignment | JsxReferenceIdentifier
}

impl Rule for NoUndeclaredVariables {
type Query = SemanticServices;
type State = (TextRange, String);
Expand All @@ -42,16 +36,20 @@ impl Rule for NoUndeclaredVariables {
ctx.query()
.all_unresolved_references()
.filter_map(|reference| {
let node = reference.syntax().clone();
let node = AnyIdentifier::unwrap_cast(node);
let token = match node {
AnyIdentifier::JsReferenceIdentifier(node) => node.value_token(),
AnyIdentifier::JsIdentifierAssignment(node) => node.name_token(),
AnyIdentifier::JsxReferenceIdentifier(node) => node.value_token(),
};
let identifier = reference.tree();
let under_as_expression = identifier
.parent::<TsReferenceType>()
.and_then(|ty| ty.parent::<TsAsExpression>())
.is_some();

let token = token.ok()?;
let token = identifier.value_token().ok()?;
let text = token.text_trimmed();

// Typescript Const Assertion
if text == "const" && under_as_expression {
return None;
}

if is_global(text) {
return None;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ export type NestedContextDefault<S extends NestedContextDefault = ''> = '' | `($
export type Whatever<S extends number> = `Hello ${S}`
export type WhateverDefault<S extends number = 2> = `Hello ${S}`

// Const assertions are valid
const fruits = ["banana"] as const;

// Invalid
export type Invalid<S extends number> = `Hello ${T}`
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,21 @@ export type NestedContextDefault<S extends NestedContextDefault = ''> = '' | `($
export type Whatever<S extends number> = `Hello ${S}`
export type WhateverDefault<S extends number = 2> = `Hello ${S}`

// Const assertions are valid
const fruits = ["banana"] as const;

// Invalid
export type Invalid<S extends number> = `Hello ${T}`
```

# Diagnostics
```
noUndeclaredVariables.ts:12:50 lint/correctness/noUndeclaredVariables ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
noUndeclaredVariables.ts:15:50 lint/correctness/noUndeclaredVariables ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

! The T variable is undeclared

11 │ // Invalid
> 12 │ export type Invalid<S extends number> = `Hello ${T}`
14 │ // Invalid
> 15 │ export type Invalid<S extends number> = `Hello ${T}`
│ ^


Expand Down
6 changes: 6 additions & 0 deletions crates/rome_js_semantic/src/semantic_model/reference.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use rome_js_syntax::AnyJsIdentifierUsage;

use super::*;
use std::sync::Arc;

Expand Down Expand Up @@ -117,6 +119,10 @@ impl UnresolvedReference {
&self.data.node_by_range[&reference.range]
}

pub fn tree(&self) -> AnyJsIdentifierUsage {
AnyJsIdentifierUsage::unwrap_cast(self.syntax().clone())
}

pub fn range(&self) -> &TextRange {
let reference = &self.data.unresolved_references[self.id];
&reference.range
Expand Down
16 changes: 16 additions & 0 deletions crates/rome_js_syntax/src/identifier_ext.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use crate::{JsIdentifierAssignment, JsReferenceIdentifier, JsSyntaxToken, JsxReferenceIdentifier};
use rome_rowan::{declare_node_union, SyntaxResult};

declare_node_union! {
pub AnyJsIdentifierUsage = JsReferenceIdentifier | JsIdentifierAssignment | JsxReferenceIdentifier
}

impl AnyJsIdentifierUsage {
pub fn value_token(&self) -> SyntaxResult<JsSyntaxToken> {
match self {
AnyJsIdentifierUsage::JsReferenceIdentifier(node) => node.value_token(),
AnyJsIdentifierUsage::JsIdentifierAssignment(node) => node.name_token(),
AnyJsIdentifierUsage::JsxReferenceIdentifier(node) => node.value_token(),
}
}
}
2 changes: 2 additions & 0 deletions crates/rome_js_syntax/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
mod generated;
pub mod binding_ext;
pub mod expr_ext;
pub mod identifier_ext;
pub mod import_ext;
pub mod jsx_ext;
pub mod modifier_ext;
Expand All @@ -18,6 +19,7 @@ mod union_ext;

pub use self::generated::*;
pub use expr_ext::*;
pub use identifier_ext::*;
pub use modifier_ext::*;
pub use rome_rowan::{
SyntaxNodeText, TextLen, TextRange, TextSize, TokenAtOffset, TriviaPieceKind, WalkEvent,
Expand Down
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载