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

Commit

Permalink
refactor(rslint_parser): Update Literals AST Facade
Browse files Browse the repository at this point in the history
Refines the AST Facade for literals to match the grammar proposed in #1719. This change is part of #1725.

* Introduce new `JsAnyLiteral`
* Split `Literal` into `JsStringLiteral`, `JsBooleanLiteral`, `JsNullLiteral`, `JsRegexLiteral`, and `JsBigIntLiteral`. This allows to implement custom methods on the corresponding literal nodes.
* Renames the `number` and kinds to `JS_NUMBER_LITERAL_TOKEN` `JS_STRING_LITERAL_TOKEN` to avoid conflicts with the TS `number` keyword (and keep symmetry).
* Removed some unused keywords and special handling inside of the code gen.
  • Loading branch information
MichaReiser committed Nov 12, 2021
1 parent 124d5a5 commit b5e5af8
Show file tree
Hide file tree
Showing 66 changed files with 765 additions and 623 deletions.
37 changes: 18 additions & 19 deletions crates/rome_formatter/src/cst.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use crate::{token, FormatElement, FormatResult, Formatter, ToFormatElement};
use crate::{FormatElement, FormatResult, Formatter, ToFormatElement};
use rslint_parser::ast::{
ArgList, ArrayExpr, ArrayPattern, ArrowExpr, AssignPattern, CallExpr, ClassBody, ClassDecl,
ClassProp, Condition, ConstructorParameters, FnDecl, ForInStmt, ForStmt, ForStmtInit,
ForStmtTest, ForStmtUpdate, Getter, IdentProp, JsBlockStatement, JsCaseClause, JsCatchClause,
JsContinueStatement, JsDebuggerStatement, JsDefaultClause, JsDoWhileStatement,
JsEmptyStatement, JsExpressionStatement, JsFinallyClause, JsIfStatement, JsLabeledStatement,
JsReturnStatement, JsScript, JsSwitchStatement, JsTryStatement, JsVariableDeclarationStatement,
JsVariableDeclarator, JsWhileStatement, JsWithStatement, Literal, LiteralProp, Name, NameRef,
ForStmtTest, ForStmtUpdate, Getter, IdentProp, JsBlockStatement, JsBooleanLiteral,
JsCaseClause, JsCatchClause, JsContinueStatement, JsDebuggerStatement, JsDefaultClause,
JsDoWhileStatement, JsEmptyStatement, JsExpressionStatement, JsFinallyClause, JsIfStatement,
JsLabeledStatement, JsNullLiteral, JsNumberLiteral, JsReturnStatement, JsScript,
JsStringLiteral, JsSwitchStatement, JsTryStatement, JsVariableDeclarationStatement,
JsVariableDeclarator, JsWhileStatement, JsWithStatement, LiteralProp, Name, NameRef,
ObjectExpr, ParameterList, SequenceExpr, Setter, SinglePattern,
};
use rslint_parser::{AstNode, AstToken, SyntaxKind, SyntaxNode, SyntaxToken};
use rslint_parser::{AstNode, SyntaxKind, SyntaxNode};

impl ToFormatElement for SyntaxNode {
fn to_format_element(&self, formatter: &Formatter) -> FormatResult<FormatElement> {
Expand All @@ -23,7 +24,16 @@ impl ToFormatElement for SyntaxNode {
SyntaxKind::ASSIGN_PATTERN => AssignPattern::cast(self.clone())
.unwrap()
.to_format_element(formatter),
SyntaxKind::LITERAL => Literal::cast(self.clone())
SyntaxKind::JS_BOOLEAN_LITERAL => JsBooleanLiteral::cast(self.clone())
.unwrap()
.to_format_element(formatter),
SyntaxKind::JS_STRING_LITERAL => JsStringLiteral::cast(self.clone())
.unwrap()
.to_format_element(formatter),
SyntaxKind::JS_NULL_LITERAL => JsNullLiteral::cast(self.clone())
.unwrap()
.to_format_element(formatter),
SyntaxKind::JS_NUMBER_LITERAL => JsNumberLiteral::cast(self.clone())
.unwrap()
.to_format_element(formatter),
SyntaxKind::NAME => Name::cast(self.clone())
Expand Down Expand Up @@ -171,14 +181,3 @@ impl ToFormatElement for SyntaxNode {
}
}
}

impl ToFormatElement for SyntaxToken {
fn to_format_element(&self, formatter: &Formatter) -> FormatResult<FormatElement> {
match self.kind() {
SyntaxKind::STRING => rslint_parser::ast::String::cast(self.clone())
.unwrap()
.to_format_element(formatter),
_ => Ok(token(self.text())),
}
}
}
23 changes: 16 additions & 7 deletions crates/rome_formatter/src/format_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,36 @@ use crate::{
space_token, token,
};
use rslint_parser::ast::{
ArrayExpr, GroupingExpr, Literal, LiteralProp, ObjectExpr, ObjectProp, UnaryExpr,
ArrayExpr, GroupingExpr, JsBooleanLiteral, JsNullLiteral, JsNumberLiteral, JsStringLiteral,
LiteralProp, ObjectExpr, ObjectProp, UnaryExpr,
};
use rslint_parser::{parse_text, AstNode, SyntaxKind, SyntaxNode, SyntaxToken};
use rslint_parser::{parse_text, AstNode, SyntaxKind, SyntaxNode, SyntaxNodeExt, SyntaxToken};

fn tokenize_token(syntax_token: SyntaxToken) -> FormatElement {
match syntax_token.kind() {
SyntaxKind::NULL_KW => token("null"),
SyntaxKind::TRUE_KW => token("true"),
SyntaxKind::FALSE_KW => token("false"),
SyntaxKind::STRING => token(syntax_token.text()),
SyntaxKind::NUMBER => token(syntax_token.text()),
SyntaxKind::JS_STRING_LITERAL_TOKEN => token(syntax_token.text()),
SyntaxKind::JS_NUMBER_LITERAL_TOKEN => token(syntax_token.text()),
SyntaxKind::MINUS => token("-"),
_ => panic!("Unsupported JSON token {:?}", syntax_token),
}
}

fn tokenize_node(node: SyntaxNode) -> FormatElement {
match node.kind() {
SyntaxKind::LITERAL => {
let literal = Literal::cast(node).unwrap();
tokenize_token(literal.token())
SyntaxKind::JS_STRING_LITERAL => {
tokenize_token(node.to::<JsStringLiteral>().value_token().unwrap())
}
SyntaxKind::JS_BOOLEAN_LITERAL => {
tokenize_token(node.to::<JsBooleanLiteral>().value_token().unwrap())
}
SyntaxKind::JS_NULL_LITERAL => {
tokenize_token(node.to::<JsNullLiteral>().value_token().unwrap())
}
SyntaxKind::JS_NUMBER_LITERAL => {
tokenize_token(node.to::<JsNumberLiteral>().value_token().unwrap())
}
SyntaxKind::UNARY_EXPR => {
let expr = UnaryExpr::cast(node).unwrap();
Expand Down
8 changes: 4 additions & 4 deletions crates/rome_formatter/src/formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ impl Formatter {
/// use rome_rowan::{NodeOrToken, TreeBuilder};
///
/// let mut builder = TreeBuilder::<'_, JsLanguage>::new();
/// builder.start_node(SyntaxKind::LITERAL);
/// builder.token(SyntaxKind::STRING, "'abc'");
/// builder.start_node(SyntaxKind::JS_STRING_LITERAL);
/// builder.token(SyntaxKind::JS_STRING_LITERAL_TOKEN, "'abc'");
/// builder.finish_node();
/// let node = builder.finish();
///
Expand All @@ -97,10 +97,10 @@ impl Formatter {
/// let formatter = Formatter::default();
/// let result = formatter.format_token(&syntax_token);
///
/// assert_eq!(Ok(token("\"abc\"")), result)
/// assert_eq!(Ok(token("'abc'")), result)
/// ```
pub fn format_token(&self, syntax_token: &SyntaxToken) -> FormatResult<FormatElement> {
syntax_token.to_format_element(self)
Ok(token(syntax_token.text()))
}

/// Formats each child and returns the result as a list.
Expand Down
2 changes: 1 addition & 1 deletion crates/rome_formatter/src/ts/expressions/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ impl ToFormatElement for JsAnyExpression {
fn to_format_element(&self, formatter: &Formatter) -> FormatResult<FormatElement> {
match self {
JsAnyExpression::ArrowExpr(arrow) => arrow.to_format_element(formatter),
JsAnyExpression::Literal(literal) => literal.to_format_element(formatter),
JsAnyExpression::JsAnyLiteral(literal) => literal.to_format_element(formatter),
JsAnyExpression::Template(_) => todo!(),
JsAnyExpression::NameRef(name_ref) => name_ref.to_format_element(formatter),
JsAnyExpression::ThisExpr(_) => todo!(),
Expand Down
60 changes: 56 additions & 4 deletions crates/rome_formatter/src/ts/expressions/literal.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,61 @@
use rslint_parser::ast::Literal;
use crate::{token, FormatElement, FormatResult, Formatter, ToFormatElement};
use rslint_parser::ast::{
JsAnyLiteral, JsBigIntLiteral, JsBooleanLiteral, JsNullLiteral, JsNumberLiteral,
JsStringLiteral,
};

use crate::{FormatElement, FormatResult, Formatter, ToFormatElement};
impl ToFormatElement for JsStringLiteral {
fn to_format_element(&self, _: &Formatter) -> FormatResult<FormatElement> {
let value_token = self.value_token()?;
let quoted = value_token.text();

impl ToFormatElement for Literal {
// uses single quotes
if quoted.starts_with('\'') {
let mut double_quoted = String::from(quoted);
double_quoted.replace_range(0..1, "\"");
double_quoted.replace_range(double_quoted.len() - 1..double_quoted.len(), "\"");
Ok(token(double_quoted.as_str()))
} else {
Ok(token(quoted))
}
}
}

impl ToFormatElement for JsBooleanLiteral {
fn to_format_element(&self, formatter: &Formatter) -> FormatResult<FormatElement> {
formatter.format_token(&self.value_token()?)
}
}

impl ToFormatElement for JsNullLiteral {
fn to_format_element(&self, formatter: &Formatter) -> FormatResult<FormatElement> {
formatter.format_token(&self.value_token()?)
}
}

impl ToFormatElement for JsNumberLiteral {
fn to_format_element(&self, formatter: &Formatter) -> FormatResult<FormatElement> {
formatter.format_token(&self.value_token()?)
}
}

impl ToFormatElement for JsBigIntLiteral {
fn to_format_element(&self, formatter: &Formatter) -> FormatResult<FormatElement> {
formatter.format_token(&self.value_token()?)
}
}

impl ToFormatElement for JsAnyLiteral {
fn to_format_element(&self, formatter: &Formatter) -> FormatResult<FormatElement> {
formatter.format_token(&self.token())
match self {
JsAnyLiteral::JsBooleanLiteral(boolean) => boolean.to_format_element(formatter),
JsAnyLiteral::JsStringLiteral(string_literal) => {
string_literal.to_format_element(formatter)
}
JsAnyLiteral::JsNumberLiteral(number) => number.to_format_element(formatter),
JsAnyLiteral::JsBigIntLiteral(big_int) => big_int.to_format_element(formatter),
JsAnyLiteral::JsNullLiteral(null_literal) => null_literal.to_format_element(formatter),
JsAnyLiteral::JsRegexLiteral(_) => todo!(),
}
}
}
1 change: 0 additions & 1 deletion crates/rome_formatter/src/ts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ mod script;
mod setter;
mod spread;
mod statements;
mod tokens;

#[cfg(test)]
mod test {
Expand Down
3 changes: 2 additions & 1 deletion crates/rome_formatter/src/ts/props/prop_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ impl ToFormatElement for PropName {
fn to_format_element(&self, formatter: &Formatter) -> FormatResult<FormatElement> {
match self {
PropName::ComputedPropertyName(_) => todo!(),
PropName::Literal(literal) => literal.to_format_element(formatter),
PropName::JsStringLiteral(literal) => literal.to_format_element(formatter),
PropName::JsNumberLiteral(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!(),
Expand Down
1 change: 0 additions & 1 deletion crates/rome_formatter/src/ts/tokens/mod.rs

This file was deleted.

16 changes: 0 additions & 16 deletions crates/rome_formatter/src/ts/tokens/string_token.rs

This file was deleted.

8 changes: 5 additions & 3 deletions crates/rslint_lexer/src/highlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,12 @@ impl<'s> Iterator for Highlighter<'s> {
}
t if t.is_punct() => rgb![86, 182, 194],
t if t.is_keyword() => rgb![198, 120, 221],
SyntaxKind::STRING | SyntaxKind::BACKTICK | SyntaxKind::TEMPLATE_CHUNK => {
SyntaxKind::JS_STRING_LITERAL_TOKEN
| SyntaxKind::BACKTICK
| SyntaxKind::TEMPLATE_CHUNK => {
rgb![152, 195, 121]
}
SyntaxKind::NUMBER => rgb![209, 154, 102],
SyntaxKind::JS_NUMBER_LITERAL_TOKEN => rgb![209, 154, 102],
SyntaxKind::DOLLARCURLY => rgb![198, 120, 221],
SyntaxKind::ERROR_TOKEN => rgb![244, 71, 71],
SyntaxKind::COMMENT => rgb![127, 132, 142],
Expand All @@ -137,7 +139,7 @@ impl<'s> Iterator for Highlighter<'s> {
}
}

/// Colors a piece of source code using ANSI.
/// Colors a piece of source code using ANSI.
/// The string returned will be unaltered if stdout and stderr are not terminals.
pub fn color(source: &str) -> String {
Highlighter::new(source).color()
Expand Down
10 changes: 5 additions & 5 deletions crates/rslint_lexer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ impl<'src> Lexer<'src> {
Some(err),
)
} else {
tok!(NUMBER, self.cur - start)
tok!(JS_NUMBER_LITERAL_TOKEN, self.cur - start)
}
}

Expand Down Expand Up @@ -1009,7 +1009,7 @@ impl<'src> Lexer<'src> {
}
},
_ => {
return (Token::new(SyntaxKind::REGEX, self.cur - start), diagnostic)
return (Token::new(SyntaxKind::JS_REGEX_LITERAL_TOKEN, self.cur - start), diagnostic)
}
}
}
Expand All @@ -1020,15 +1020,15 @@ impl<'src> Lexer<'src> {
let err = Diagnostic::error(self.file_id, "", "expected a character after a regex escape, but found none")
.primary(self.cur..self.cur + 1, "expected a character following this");

return (Token::new(SyntaxKind::REGEX, self.cur - start), Some(err));
return (Token::new(SyntaxKind::JS_REGEX_LITERAL_TOKEN, self.cur - start), Some(err));
}
},
None => {
let err = Diagnostic::error(self.file_id, "", "unterminated regex literal")
.primary(self.cur..self.cur, "...but the file ends here")
.secondary(start..start + 1, "a regex literal starts there...");

return (Token::new(SyntaxKind::REGEX, self.cur - start), Some(err));
return (Token::new(SyntaxKind::JS_REGEX_LITERAL_TOKEN, self.cur - start), Some(err));
},
_ => {},
}
Expand Down Expand Up @@ -1333,7 +1333,7 @@ impl<'src> Lexer<'src> {
Some(err),
)
} else {
tok!(STRING, self.cur - start)
tok!(JS_STRING_LITERAL_TOKEN, self.cur - start)
}
}
IDT => self.resolve_identifier((byte as char, start)),
Expand Down
Loading

0 comments on commit b5e5af8

Please sign in to comment.