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

This commit is contained in:
Emanuele Stoppa 2021-11-08 18:11:29 +00:00 committed by GitHub
parent c0104e59b2
commit aab688d98f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 321 additions and 26 deletions

View file

@ -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!(),
}
}
}

View file

@ -33,6 +33,7 @@ impl ToFormatElement for Expr {
Expr::TsNonNull(_) => todo!(),
Expr::TsAssertion(_) => todo!(),
Expr::TsConstAssertion(_) => todo!(),
Expr::JsUnknownExpression(_) => todo!(),
}
}
}

View file

@ -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!(),
}
}
}

View file

@ -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!(),
}
}
}

View file

@ -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!(),
}
}
}

View file

@ -30,6 +30,7 @@ impl ToFormatElement for Stmt {
Stmt::ForOfStmt(_) => todo!(),
Stmt::Decl(decl) => decl.to_format_element(formatter),
Stmt::JsUnknownStatement(_) => todo!(),
}
}
}

View file

@ -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)
}

View file

@ -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!(),
})
}

View file

@ -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)

View file

@ -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!(),
}
}

View file

@ -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,
}

View file

@ -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.

View file

@ -20,6 +20,29 @@
//
// - "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

View file

@ -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())

View file

@ -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",
],
};