feat: unknown nodes to track incorrect code
MODIFY
crates/rome_formatter/src/ts/class/class_declarator.rs
crates/rome_formatter/src/ts/class/class_declarator.rs
@@ -60,6 +60,7 @@ impl ToFormatElement for ClassElement {
ClassElement::TsIndexSignature(_) => todo!(),
ClassElement::Getter(getter) => getter.to_format_element(formatter),
ClassElement::Setter(setter) => setter.to_format_element(formatter),
+ ClassElement::JsUnknownMember(_) => todo!(),
}
}
}

MODIFY
crates/rome_formatter/src/ts/expressions/expression.rs
crates/rome_formatter/src/ts/expressions/expression.rs
@@ -33,6 +33,7 @@ impl ToFormatElement for Expr {
Expr::TsNonNull(_) => todo!(),
Expr::TsAssertion(_) => todo!(),
Expr::TsConstAssertion(_) => todo!(),
+ Expr::JsUnknownExpression(_) => todo!(),
}
}
}

MODIFY
crates/rome_formatter/src/ts/patterns/pattern.rs
crates/rome_formatter/src/ts/patterns/pattern.rs
@@ -10,6 +10,7 @@ impl ToFormatElement for Pattern {
Pattern::ArrayPattern(array_pattern) => array_pattern.to_format_element(formatter),
Pattern::ExprPattern(_) => todo!(),
Pattern::SinglePattern(single) => single.to_format_element(formatter),
+ Pattern::JsUnknownPattern(_) => todo!(),
}
}
}

MODIFY
crates/rome_formatter/src/ts/props/object_prop.rs
crates/rome_formatter/src/ts/props/object_prop.rs
@@ -11,6 +11,7 @@ impl ToFormatElement for ObjectProp {
ObjectProp::InitializedProp(_) => todo!(),
ObjectProp::IdentProp(ident) => ident.to_format_element(formatter),
ObjectProp::Method(_) => todo!(),
+ ObjectProp::JsUnknownMember(_) => todo!(),
}
}
}

MODIFY
crates/rome_formatter/src/ts/props/prop_name.rs
crates/rome_formatter/src/ts/props/prop_name.rs
@@ -9,6 +9,7 @@ impl ToFormatElement for PropName {
PropName::Literal(literal) => literal.to_format_element(formatter),
PropName::Ident(ident) => ident.to_format_element(formatter),
PropName::Name(name) => name.to_format_element(formatter),
+ PropName::JsUnknownBinding(_) => todo!(),
}
}
}

MODIFY
crates/rome_formatter/src/ts/statements/statement.rs
crates/rome_formatter/src/ts/statements/statement.rs
@@ -30,6 +30,7 @@ impl ToFormatElement for Stmt {
Stmt::ForOfStmt(_) => todo!(),
Stmt::Decl(decl) => decl.to_format_element(formatter),
+ Stmt::JsUnknownStatement(_) => todo!(),
}
}
}

MODIFY
crates/rslint_parser/src/ast.rs
crates/rslint_parser/src/ast.rs
@@ -186,7 +186,7 @@ impl<N: AstNode> IntoIterator for AstNodeList<N> {
}
mod support {
- use super::{AstNode, AstNodeList, SyntaxKind, SyntaxNode, SyntaxToken};
+ use super::{AstNode, AstNodeList, SyntaxElementChildren, SyntaxKind, SyntaxNode, SyntaxToken};
use crate::ast::AstChildren;
use crate::SyntaxList;
use crate::{SyntaxError, SyntaxResult};
@@ -201,6 +201,10 @@ mod support {
parent.children().find_map(N::cast)
}
+ pub(super) fn elements(parent: &SyntaxNode) -> SyntaxElementChildren {
+ parent.children_with_tokens()
+ }
+
pub(super) fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {
AstChildren::new(parent)
}

MODIFY
crates/rslint_parser/src/ast/expr_ext.rs
crates/rslint_parser/src/ast/expr_ext.rs
@@ -35,9 +35,8 @@ impl LiteralProp {
pub fn value(&self) -> SyntaxResult<Expr> {
let child = self.syntax().children().nth(1);
match child {
- Some(child) => {
- Expr::cast(child).ok_or_else(|| SyntaxError::MissingRequiredChild(self.syntax().clone()))
- }
+ Some(child) => Expr::cast(child)
+ .ok_or_else(|| SyntaxError::MissingRequiredChild(self.syntax().clone())),
None => Err(SyntaxError::MissingRequiredChild(self.syntax().clone())),
}
}
@@ -569,6 +568,7 @@ impl ObjectProp {
.key()
.map_or_else(|_| None, |key| Some(key.syntax().clone()))?,
ObjectProp::SpreadProp(_) => return None,
+ ObjectProp::JsUnknownMember(_) => todo!(),
}
.into(),
)
@@ -581,6 +581,7 @@ fn prop_name_syntax(name: PropName) -> Option<SyntaxNode> {
PropName::Literal(lit) => lit.syntax().clone(),
PropName::Name(name) => name.syntax().clone(),
PropName::ComputedPropertyName(_) => return None,
+ PropName::JsUnknownBinding(_) => todo!(),
})
}

MODIFY
crates/rslint_parser/src/ast/generated/nodes.rs
crates/rslint_parser/src/ast/generated/nodes.rs
@@ -9,6 +9,48 @@ use crate::{
SyntaxNode, SyntaxResult, SyntaxToken, T,
};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct JsUnknownStatement {
+ pub(crate) syntax: SyntaxNode,
+}
+impl JsUnknownStatement {
+ pub fn syntax_element(&self) -> SyntaxElementChildren { support::elements(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct JsUnknownExpression {
+ pub(crate) syntax: SyntaxNode,
+}
+impl JsUnknownExpression {
+ pub fn syntax_element(&self) -> SyntaxElementChildren { support::elements(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct JsUnknownPattern {
+ pub(crate) syntax: SyntaxNode,
+}
+impl JsUnknownPattern {
+ pub fn syntax_element(&self) -> SyntaxElementChildren { support::elements(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct JsUnknownMember {
+ pub(crate) syntax: SyntaxNode,
+}
+impl JsUnknownMember {
+ pub fn syntax_element(&self) -> SyntaxElementChildren { support::elements(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct JsUnknownBinding {
+ pub(crate) syntax: SyntaxNode,
+}
+impl JsUnknownBinding {
+ pub fn syntax_element(&self) -> SyntaxElementChildren { support::elements(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct JsUnknownAssignmentTarget {
+ pub(crate) syntax: SyntaxNode,
+}
+impl JsUnknownAssignmentTarget {
+ pub fn syntax_element(&self) -> SyntaxElementChildren { support::elements(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Ident {
pub(crate) syntax: SyntaxNode,
}
@@ -2214,6 +2256,7 @@ pub enum Stmt {
TryStmt(TryStmt),
DebuggerStmt(DebuggerStmt),
Decl(Decl),
+ JsUnknownStatement(JsUnknownStatement),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ModuleItem {
@@ -2270,6 +2313,7 @@ pub enum Expr {
TsNonNull(TsNonNull),
TsAssertion(TsAssertion),
TsConstAssertion(TsConstAssertion),
+ JsUnknownExpression(JsUnknownExpression),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ForHead {
@@ -2289,6 +2333,7 @@ pub enum Pattern {
ObjectPattern(ObjectPattern),
ArrayPattern(ArrayPattern),
ExprPattern(ExprPattern),
+ JsUnknownPattern(JsUnknownPattern),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum TsType {
@@ -2343,6 +2388,7 @@ pub enum ObjectProp {
InitializedProp(InitializedProp),
IdentProp(IdentProp),
Method(Method),
+ JsUnknownMember(JsUnknownMember),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ClassElement {
@@ -2354,6 +2400,7 @@ pub enum ClassElement {
TsIndexSignature(TsIndexSignature),
Getter(Getter),
Setter(Setter),
+ JsUnknownMember(JsUnknownMember),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum PropName {
@@ -2361,6 +2408,7 @@ pub enum PropName {
Literal(Literal),
Ident(Ident),
Name(Name),
+ JsUnknownBinding(JsUnknownBinding),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ConstructorParamOrPat {
@@ -2384,6 +2432,7 @@ pub enum ObjectPatternProp {
KeyValuePattern(KeyValuePattern),
RestPattern(RestPattern),
SinglePattern(SinglePattern),
+ JsUnknownPattern(JsUnknownPattern),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ImportClause {
@@ -2425,6 +2474,72 @@ pub enum TsNamespaceBody {
TsModuleBlock(TsModuleBlock),
TsNamespaceDecl(TsNamespaceDecl),
}
+impl AstNode for JsUnknownStatement {
+ fn can_cast(kind: SyntaxKind) -> bool { kind == JS_UNKNOWN_STATEMENT }
+ fn cast(syntax: SyntaxNode) -> Option<Self> {
+ if Self::can_cast(syntax.kind()) {
+ Some(Self { syntax })
+ } else {
+ None
+ }
+ }
+ fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for JsUnknownExpression {
+ fn can_cast(kind: SyntaxKind) -> bool { kind == JS_UNKNOWN_EXPRESSION }
+ fn cast(syntax: SyntaxNode) -> Option<Self> {
+ if Self::can_cast(syntax.kind()) {
+ Some(Self { syntax })
+ } else {
+ None
+ }
+ }
+ fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for JsUnknownPattern {
+ fn can_cast(kind: SyntaxKind) -> bool { kind == JS_UNKNOWN_PATTERN }
+ fn cast(syntax: SyntaxNode) -> Option<Self> {
+ if Self::can_cast(syntax.kind()) {
+ Some(Self { syntax })
+ } else {
+ None
+ }
+ }
+ fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for JsUnknownMember {
+ fn can_cast(kind: SyntaxKind) -> bool { kind == JS_UNKNOWN_MEMBER }
+ fn cast(syntax: SyntaxNode) -> Option<Self> {
+ if Self::can_cast(syntax.kind()) {
+ Some(Self { syntax })
+ } else {
+ None
+ }
+ }
+ fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for JsUnknownBinding {
+ fn can_cast(kind: SyntaxKind) -> bool { kind == JS_UNKNOWN_BINDING }
+ fn cast(syntax: SyntaxNode) -> Option<Self> {
+ if Self::can_cast(syntax.kind()) {
+ Some(Self { syntax })
+ } else {
+ None
+ }
+ }
+ fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for JsUnknownAssignmentTarget {
+ fn can_cast(kind: SyntaxKind) -> bool { kind == JS_UNKNOWN_ASSIGNMENT_TARGET }
+ fn cast(syntax: SyntaxNode) -> Option<Self> {
+ if Self::can_cast(syntax.kind()) {
+ Some(Self { syntax })
+ } else {
+ None
+ }
+ }
+ fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
impl AstNode for Ident {
fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT }
fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4250,12 +4365,16 @@ impl From<TryStmt> for Stmt {
impl From<DebuggerStmt> for Stmt {
fn from(node: DebuggerStmt) -> Stmt { Stmt::DebuggerStmt(node) }
}
+impl From<JsUnknownStatement> for Stmt {
+ fn from(node: JsUnknownStatement) -> Stmt { Stmt::JsUnknownStatement(node) }
+}
impl AstNode for Stmt {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
BLOCK_STMT | EMPTY_STMT | EXPR_STMT | IF_STMT | DO_WHILE_STMT | WHILE_STMT
| FOR_STMT | FOR_IN_STMT | FOR_OF_STMT | CONTINUE_STMT | BREAK_STMT | RETURN_STMT
- | WITH_STMT | LABELLED_STMT | SWITCH_STMT | THROW_STMT | TRY_STMT | DEBUGGER_STMT => true,
+ | WITH_STMT | LABELLED_STMT | SWITCH_STMT | THROW_STMT | TRY_STMT | DEBUGGER_STMT
+ | JS_UNKNOWN_STATEMENT => true,
k if Decl::can_cast(k) => true,
_ => false,
}
@@ -4280,6 +4399,7 @@ impl AstNode for Stmt {
THROW_STMT => Stmt::ThrowStmt(ThrowStmt { syntax }),
TRY_STMT => Stmt::TryStmt(TryStmt { syntax }),
DEBUGGER_STMT => Stmt::DebuggerStmt(DebuggerStmt { syntax }),
+ JS_UNKNOWN_STATEMENT => Stmt::JsUnknownStatement(JsUnknownStatement { syntax }),
_ => {
if let Some(decl) = Decl::cast(syntax.clone()) {
return Some(Stmt::Decl(decl));
@@ -4309,6 +4429,7 @@ impl AstNode for Stmt {
Stmt::ThrowStmt(it) => &it.syntax,
Stmt::TryStmt(it) => &it.syntax,
Stmt::DebuggerStmt(it) => &it.syntax,
+ Stmt::JsUnknownStatement(it) => &it.syntax,
Stmt::Decl(it) => it.syntax(),
}
}
@@ -4539,14 +4660,42 @@ impl From<TsAssertion> for Expr {
impl From<TsConstAssertion> for Expr {
fn from(node: TsConstAssertion) -> Expr { Expr::TsConstAssertion(node) }
}
+impl From<JsUnknownExpression> for Expr {
+ fn from(node: JsUnknownExpression) -> Expr { Expr::JsUnknownExpression(node) }
+}
impl AstNode for Expr {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
- ARROW_EXPR | LITERAL | TEMPLATE | NAME_REF | THIS_EXPR | ARRAY_EXPR | OBJECT_EXPR
- | GROUPING_EXPR | BRACKET_EXPR | DOT_EXPR | NEW_EXPR | CALL_EXPR | UNARY_EXPR
- | BIN_EXPR | COND_EXPR | ASSIGN_EXPR | SEQUENCE_EXPR | FN_EXPR | CLASS_EXPR
- | NEW_TARGET | IMPORT_META | SUPER_CALL | IMPORT_CALL | YIELD_EXPR | AWAIT_EXPR
- | PRIVATE_PROP_ACCESS | TS_NON_NULL | TS_ASSERTION | TS_CONST_ASSERTION => true,
+ ARROW_EXPR
+ | LITERAL
+ | TEMPLATE
+ | NAME_REF
+ | THIS_EXPR
+ | ARRAY_EXPR
+ | OBJECT_EXPR
+ | GROUPING_EXPR
+ | BRACKET_EXPR
+ | DOT_EXPR
+ | NEW_EXPR
+ | CALL_EXPR
+ | UNARY_EXPR
+ | BIN_EXPR
+ | COND_EXPR
+ | ASSIGN_EXPR
+ | SEQUENCE_EXPR
+ | FN_EXPR
+ | CLASS_EXPR
+ | NEW_TARGET
+ | IMPORT_META
+ | SUPER_CALL
+ | IMPORT_CALL
+ | YIELD_EXPR
+ | AWAIT_EXPR
+ | PRIVATE_PROP_ACCESS
+ | TS_NON_NULL
+ | TS_ASSERTION
+ | TS_CONST_ASSERTION
+ | JS_UNKNOWN_EXPRESSION => true,
_ => false,
}
}
@@ -4581,6 +4730,7 @@ impl AstNode for Expr {
TS_NON_NULL => Expr::TsNonNull(TsNonNull { syntax }),
TS_ASSERTION => Expr::TsAssertion(TsAssertion { syntax }),
TS_CONST_ASSERTION => Expr::TsConstAssertion(TsConstAssertion { syntax }),
+ JS_UNKNOWN_EXPRESSION => Expr::JsUnknownExpression(JsUnknownExpression { syntax }),
_ => return None,
};
Some(res)
@@ -4616,6 +4766,7 @@ impl AstNode for Expr {
Expr::TsNonNull(it) => &it.syntax,
Expr::TsAssertion(it) => &it.syntax,
Expr::TsConstAssertion(it) => &it.syntax,
+ Expr::JsUnknownExpression(it) => &it.syntax,
}
}
}
@@ -4695,11 +4846,14 @@ impl From<ArrayPattern> for Pattern {
impl From<ExprPattern> for Pattern {
fn from(node: ExprPattern) -> Pattern { Pattern::ExprPattern(node) }
}
+impl From<JsUnknownPattern> for Pattern {
+ fn from(node: JsUnknownPattern) -> Pattern { Pattern::JsUnknownPattern(node) }
+}
impl AstNode for Pattern {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
SINGLE_PATTERN | REST_PATTERN | ASSIGN_PATTERN | OBJECT_PATTERN | ARRAY_PATTERN
- | EXPR_PATTERN => true,
+ | EXPR_PATTERN | JS_UNKNOWN_PATTERN => true,
_ => false,
}
}
@@ -4711,6 +4865,7 @@ impl AstNode for Pattern {
OBJECT_PATTERN => Pattern::ObjectPattern(ObjectPattern { syntax }),
ARRAY_PATTERN => Pattern::ArrayPattern(ArrayPattern { syntax }),
EXPR_PATTERN => Pattern::ExprPattern(ExprPattern { syntax }),
+ JS_UNKNOWN_PATTERN => Pattern::JsUnknownPattern(JsUnknownPattern { syntax }),
_ => return None,
};
Some(res)
@@ -4723,6 +4878,7 @@ impl AstNode for Pattern {
Pattern::ObjectPattern(it) => &it.syntax,
Pattern::ArrayPattern(it) => &it.syntax,
Pattern::ExprPattern(it) => &it.syntax,
+ Pattern::JsUnknownPattern(it) => &it.syntax,
}
}
}
@@ -4983,11 +5139,14 @@ impl From<IdentProp> for ObjectProp {
impl From<Method> for ObjectProp {
fn from(node: Method) -> ObjectProp { ObjectProp::Method(node) }
}
+impl From<JsUnknownMember> for ObjectProp {
+ fn from(node: JsUnknownMember) -> ObjectProp { ObjectProp::JsUnknownMember(node) }
+}
impl AstNode for ObjectProp {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
LITERAL_PROP | GETTER | SETTER | SPREAD_PROP | INITIALIZED_PROP | IDENT_PROP
- | METHOD => true,
+ | METHOD | JS_UNKNOWN_MEMBER => true,
_ => false,
}
}
@@ -5000,6 +5159,7 @@ impl AstNode for ObjectProp {
INITIALIZED_PROP => ObjectProp::InitializedProp(InitializedProp { syntax }),
IDENT_PROP => ObjectProp::IdentProp(IdentProp { syntax }),
METHOD => ObjectProp::Method(Method { syntax }),
+ JS_UNKNOWN_MEMBER => ObjectProp::JsUnknownMember(JsUnknownMember { syntax }),
_ => return None,
};
Some(res)
@@ -5013,6 +5173,7 @@ impl AstNode for ObjectProp {
ObjectProp::InitializedProp(it) => &it.syntax,
ObjectProp::IdentProp(it) => &it.syntax,
ObjectProp::Method(it) => &it.syntax,
+ ObjectProp::JsUnknownMember(it) => &it.syntax,
}
}
}
@@ -5040,11 +5201,14 @@ impl From<Getter> for ClassElement {
impl From<Setter> for ClassElement {
fn from(node: Setter) -> ClassElement { ClassElement::Setter(node) }
}
+impl From<JsUnknownMember> for ClassElement {
+ fn from(node: JsUnknownMember) -> ClassElement { ClassElement::JsUnknownMember(node) }
+}
impl AstNode for ClassElement {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
EMPTY_STMT | METHOD | PRIVATE_PROP | CLASS_PROP | CONSTRUCTOR | TS_INDEX_SIGNATURE
- | GETTER | SETTER => true,
+ | GETTER | SETTER | JS_UNKNOWN_MEMBER => true,
_ => false,
}
}
@@ -5058,6 +5222,7 @@ impl AstNode for ClassElement {
TS_INDEX_SIGNATURE => ClassElement::TsIndexSignature(TsIndexSignature { syntax }),
GETTER => ClassElement::Getter(Getter { syntax }),
SETTER => ClassElement::Setter(Setter { syntax }),
+ JS_UNKNOWN_MEMBER => ClassElement::JsUnknownMember(JsUnknownMember { syntax }),
_ => return None,
};
Some(res)
@@ -5072,6 +5237,7 @@ impl AstNode for ClassElement {
ClassElement::TsIndexSignature(it) => &it.syntax,
ClassElement::Getter(it) => &it.syntax,
ClassElement::Setter(it) => &it.syntax,
+ ClassElement::JsUnknownMember(it) => &it.syntax,
}
}
}
@@ -5087,10 +5253,13 @@ impl From<Ident> for PropName {
impl From<Name> for PropName {
fn from(node: Name) -> PropName { PropName::Name(node) }
}
+impl From<JsUnknownBinding> for PropName {
+ fn from(node: JsUnknownBinding) -> PropName { PropName::JsUnknownBinding(node) }
+}
impl AstNode for PropName {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
- COMPUTED_PROPERTY_NAME | LITERAL | IDENT | NAME => true,
+ COMPUTED_PROPERTY_NAME | LITERAL | IDENT | NAME | JS_UNKNOWN_BINDING => true,
_ => false,
}
}
@@ -5102,6 +5271,7 @@ impl AstNode for PropName {
LITERAL => PropName::Literal(Literal { syntax }),
IDENT => PropName::Ident(Ident { syntax }),
NAME => PropName::Name(Name { syntax }),
+ JS_UNKNOWN_BINDING => PropName::JsUnknownBinding(JsUnknownBinding { syntax }),
_ => return None,
};
Some(res)
@@ -5112,6 +5282,7 @@ impl AstNode for PropName {
PropName::Literal(it) => &it.syntax,
PropName::Ident(it) => &it.syntax,
PropName::Name(it) => &it.syntax,
+ PropName::JsUnknownBinding(it) => &it.syntax,
}
}
}
@@ -5220,10 +5391,16 @@ impl From<RestPattern> for ObjectPatternProp {
impl From<SinglePattern> for ObjectPatternProp {
fn from(node: SinglePattern) -> ObjectPatternProp { ObjectPatternProp::SinglePattern(node) }
}
+impl From<JsUnknownPattern> for ObjectPatternProp {
+ fn from(node: JsUnknownPattern) -> ObjectPatternProp {
+ ObjectPatternProp::JsUnknownPattern(node)
+ }
+}
impl AstNode for ObjectPatternProp {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
- ASSIGN_PATTERN | KEY_VALUE_PATTERN | REST_PATTERN | SINGLE_PATTERN => true,
+ ASSIGN_PATTERN | KEY_VALUE_PATTERN | REST_PATTERN | SINGLE_PATTERN
+ | JS_UNKNOWN_PATTERN => true,
_ => false,
}
}
@@ -5233,6 +5410,7 @@ impl AstNode for ObjectPatternProp {
KEY_VALUE_PATTERN => ObjectPatternProp::KeyValuePattern(KeyValuePattern { syntax }),
REST_PATTERN => ObjectPatternProp::RestPattern(RestPattern { syntax }),
SINGLE_PATTERN => ObjectPatternProp::SinglePattern(SinglePattern { syntax }),
+ JS_UNKNOWN_PATTERN => ObjectPatternProp::JsUnknownPattern(JsUnknownPattern { syntax }),
_ => return None,
};
Some(res)
@@ -5243,6 +5421,7 @@ impl AstNode for ObjectPatternProp {
ObjectPatternProp::KeyValuePattern(it) => &it.syntax,
ObjectPatternProp::RestPattern(it) => &it.syntax,
ObjectPatternProp::SinglePattern(it) => &it.syntax,
+ ObjectPatternProp::JsUnknownPattern(it) => &it.syntax,
}
}
}
@@ -5607,6 +5786,36 @@ impl std::fmt::Display for TsNamespaceBody {
std::fmt::Display::fmt(self.syntax(), f)
}
}
+impl std::fmt::Display for JsUnknownStatement {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
+impl std::fmt::Display for JsUnknownExpression {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
+impl std::fmt::Display for JsUnknownPattern {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
+impl std::fmt::Display for JsUnknownMember {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
+impl std::fmt::Display for JsUnknownBinding {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
+impl std::fmt::Display for JsUnknownAssignmentTarget {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
impl std::fmt::Display for Ident {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)

MODIFY
crates/rslint_parser/src/syntax/util.rs
crates/rslint_parser/src/syntax/util.rs
@@ -178,6 +178,7 @@ fn check_pat(
}
ast::ObjectPatternProp::RestPattern(pat) => pat.into(),
ast::ObjectPatternProp::SinglePattern(pat) => pat.into(),
+ ast::ObjectPatternProp::JsUnknownPattern(_) => todo!(),
};
check_pat(p, pat, map, marker);
}
@@ -193,6 +194,7 @@ fn check_pat(
}
}
ast::Pattern::ExprPattern(_) => unreachable!(),
+ ast::Pattern::JsUnknownPattern(_) => todo!(),
}
}

MODIFY
crates/rslint_syntax/src/generated.rs
crates/rslint_syntax/src/generated.rs
@@ -332,6 +332,12 @@ pub enum SyntaxKind {
TS_ENTITY_NAME,
BOOLEAN,
BIG_INT_VALUE,
+ JS_UNKNOWN_EXPRESSION,
+ JS_UNKNOWN_STATEMENT,
+ JS_UNKNOWN_PATTERN,
+ JS_UNKNOWN_MEMBER,
+ JS_UNKNOWN_BINDING,
+ JS_UNKNOWN_ASSIGNMENT_TARGET,
#[doc(hidden)]
__LAST,
}

MODIFY
xtask/README.md
xtask/README.md
@@ -28,7 +28,7 @@ Here's a list of internal conventions that we follow to write grammar:
}
```
-2. unions of tokens have to have a label. In this way, the code generation can handle it properly and generate a better AST.
+1. unions of tokens have to have a label. In this way, the code generation can handle it properly and generate a better AST.
```text
BinExpr = left: Expr op: ('+' | '-' | '*') right: Expr
@@ -51,3 +51,6 @@ Here's a list of internal conventions that we follow to write grammar:
}
}
```
+
+1. Nodes used to track broken code should contain the **Unknown** word in its name (it's case sensitive).
+This is needed because it will generate a different type of code, useful in case of errors inside the source code Rome will parse.

MODIFY
xtask/js.ungram
xtask/js.ungram
//
// - "manual__" prefix is used to _exclude_ those method from being autogenerated
// and they will be manually implemented
+// - SyntaxNode, SyntaxToken and SyntaxElement will be stripped from the codegen
+// - Unknown nodes are special nodes used to keep track of broken code; they are
+// not part of the grammar but they will appear inside the green tree
+//
+
+
+///////////////
+// UNKNOWN NODES
+///////////////
+// SyntaxElement is a generic data structure that is meant to track nodes and tokens
+// in cases where we care about both types
+//
+// As Unknown* node will need to yield both tokens and nodes without discrimition,
+// and their children will need to yield nodes and tokens as well.
+// For this reason, SyntaxElement = SyntaxElement
+SyntaxElement = SyntaxElement
+
+JsUnknownStatement = SyntaxElement*
+JsUnknownExpression = SyntaxElement*
+JsUnknownPattern = SyntaxElement*
+JsUnknownMember = SyntaxElement*
+JsUnknownBinding = SyntaxElement*
+JsUnknownAssignmentTarget = SyntaxElement*
Ident = 'ident'
Script = 'shebang'? items:Stmt*
@@ -49,6 +72,7 @@ Stmt =
| TryStmt
| DebuggerStmt
| Decl
+ | JsUnknownStatement
// Block statement
@@ -181,6 +205,7 @@ Expr =
| TsNonNull
| TsAssertion
| TsConstAssertion
+ | JsUnknownExpression
// the backtick is just a placeholder, there's
@@ -273,6 +298,7 @@ ClassElement =
| TsIndexSignature
| Getter
| Setter
+ | JsUnknownMember
Constructor =
accessibility:TsAccessibility?
@@ -399,6 +425,7 @@ Pattern =
| ObjectPattern
| ArrayPattern
| ExprPattern
+ | JsUnknownPattern
// single pattern
SinglePattern
@@ -419,6 +446,7 @@ ObjectPatternProp =
| KeyValuePattern
| RestPattern
| SinglePattern
+ | JsUnknownPattern
// assign pattern
AssignPattern = key:Pattern ':'? ty:TsType '=' value:Expr
@@ -444,6 +472,7 @@ ObjectProp =
| InitializedProp
| IdentProp
| Method
+ | JsUnknownMember
// literal prop
@@ -454,6 +483,7 @@ PropName =
| Literal
| Ident
| Name
+ | JsUnknownBinding
// computed property

MODIFY
xtask/src/codegen/generate_nodes.rs
xtask/src/codegen/generate_nodes.rs
@@ -7,11 +7,29 @@ use crate::{
};
use quote::{format_ident, quote};
+// these node won't generate any code
+const BUILT_IN_TYPE: &str = "SyntaxElement";
+
pub fn generate_nodes(ast: &AstSrc) -> Result<String> {
- let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = ast
+ let filtered_enums: Vec<_> = ast
+ .enums
+ .iter()
+ .filter(|e| e.name.as_str() != BUILT_IN_TYPE)
+ .collect();
+
+ let filtered_nodes: Vec<_> = ast
.nodes
.iter()
- .map(|node| {
+ .filter(|e| e.name.as_str() != BUILT_IN_TYPE)
+ .collect();
+
+ let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = filtered_nodes
+ .iter()
+ .filter_map(|node| {
+ if node.name.as_str() == BUILT_IN_TYPE {
+ return None;
+ }
+
let name = format_ident!("{}", node.name);
let kind = format_ident!("{}", to_upper_snake_case(node.name.as_str()));
let mut slot = 0usize;
@@ -55,10 +73,20 @@ pub fn generate_nodes(ast: &AstSrc) -> Result<String> {
optional,
has_many,
} => {
+ let is_built_in_tpe = &ty.eq(BUILT_IN_TYPE);
let ty = format_ident!("{}", &ty);
let method_name = field.method_name();
- if *optional {
+ // this is when we encounter a node that has "Unknown" in its name
+ // it will return tokens a and nodes regardless because there's an error
+ // inside the code
+ if *is_built_in_tpe {
+ quote! {
+ pub fn #method_name(&self) -> SyntaxElementChildren {
+ support::elements(&self.syntax)
+ }
+ }
+ } else if *optional {
quote! {
pub fn #method_name(&self) -> Option<#ty> {
support::as_optional_node(&self.syntax)
@@ -81,7 +109,7 @@ pub fn generate_nodes(ast: &AstSrc) -> Result<String> {
}
}
});
- (
+ Some((
quote! {
// TODO: review documentation
// #[doc = #documentation]
@@ -105,7 +133,7 @@ pub fn generate_nodes(ast: &AstSrc) -> Result<String> {
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
},
- )
+ ))
})
.unzip();
@@ -116,8 +144,7 @@ pub fn generate_nodes(ast: &AstSrc) -> Result<String> {
.map(|current_enum| (current_enum.name.clone(), current_enum.variants.clone()))
.collect();
- let (enum_defs, enum_boilerplate_impls): (Vec<_>, Vec<_>) = ast
- .enums
+ let (enum_defs, enum_boilerplate_impls): (Vec<_>, Vec<_>) = filtered_enums
.iter()
.map(|en| {
// here we collect all the variants because this will generate the enums
@@ -161,7 +188,7 @@ pub fn generate_nodes(ast: &AstSrc) -> Result<String> {
let variant_cast: Vec<_> = simple_variants
.iter()
.map(|current_enum| {
- let variant_is_enum = ast.enums.iter().find(|e| &e.name == *current_enum);
+ let variant_is_enum = filtered_enums.iter().find(|e| &e.name == *current_enum);
let variant_name = format_ident!("{}", current_enum);
if variant_is_enum.is_some() {
@@ -292,8 +319,8 @@ pub fn generate_nodes(ast: &AstSrc) -> Result<String> {
})
.unzip();
- let enum_names = ast.enums.iter().map(|it| &it.name);
- let node_names = ast.nodes.iter().map(|it| &it.name);
+ let enum_names = filtered_enums.iter().map(|it| &it.name);
+ let node_names = filtered_nodes.iter().map(|it| &it.name);
let display_impls = enum_names
.chain(node_names.clone())

MODIFY
xtask/src/codegen/kinds_src.rs
xtask/src/codegen/kinds_src.rs
@@ -342,6 +342,13 @@ pub const KINDS_SRC: KindsSrc = KindsSrc {
"TS_ENTITY_NAME",
"BOOLEAN",
"BIG_INT_VALUE",
+ // unknown tokens
+ "JS_UNKNOWN_EXPRESSION",
+ "JS_UNKNOWN_STATEMENT",
+ "JS_UNKNOWN_PATTERN",
+ "JS_UNKNOWN_MEMBER",
+ "JS_UNKNOWN_BINDING",
+ "JS_UNKNOWN_ASSIGNMENT_TARGET",
],
};

feat: unknown nodes to track incorrect code (#1752)