-impl Format for Buzz {
- fn fmt(&self, f: &mut JsFormatter) -> FormatResult<()> {
- // implementation goes here
- write!(f, [token("Hello"), dynamic_token(&self.blast)])
- }
-}
-
-```
-
-## Rules when formatting AST nodes
-
-1. if a token is mandatory and the AST has that information, please use that token instead, for example:
-
- ```rust
- fn fmt_fields(node: Node, f: &mut JsFormatter) -> FormatResult<()> {
- write!(f, [node.l_paren_token().format()])?; // yes
- write!(f, [token("(")])?; // no
- }
- ```
-
-2. for tokens that are not mandatory, use our helpers
-3. do not attempt to "fix" the code. If you know a token/node is mandatory, return `None` instead
-
-## Debugging formatter output
-
-You can use the `dbg_write!` macro to output the written IR elements to the console (similar to how the `dbg!` macro works).
-
-```rust
-dbg_write!(f, [
- token("hello"),
- space_token(),
- token("world")
-])?;
+# `rome_js_formatter`
-// Writes
-// [src/main.rs:1][0] = StaticToken("hello")
-// [src/main.rs:1][1] = Space
-// [src/main.rs:1][0] = StaticToken("world")
-```
+Rome's JavaScript formatter implementation. Follow the [documentation](https://rustdocs.rome.tools/rome_js_formatter/index.html).
diff --git a/crates/rome_js_formatter/src/lib.rs b/crates/rome_js_formatter/src/lib.rs
index 7dc0bee5165..a68efd2d771 100644
--- a/crates/rome_js_formatter/src/lib.rs
+++ b/crates/rome_js_formatter/src/lib.rs
@@ -196,7 +196,143 @@ use crate::context::{JsFormatContext, JsFormatOptions};
use crate::cst::FormatJsSyntaxNode;
use crate::syntax_rewriter::transform;
-include!("../../rome_formatter/shared_traits.rs");
+/// Used to get an object that knows how to format this object.
+pub(crate) trait AsFormat {
+ type Format<'a>: rome_formatter::Format
+ where
+ Self: 'a;
+
+ /// Returns an object that is able to format this object.
+ fn format(&self) -> Self::Format<'_>;
+}
+
+/// Implement [AsFormat] for references to types that implement [AsFormat].
+impl AsFormat for &T
+where
+ T: AsFormat,
+{
+ type Format<'a> = T::Format<'a> where Self: 'a;
+
+ fn format(&self) -> Self::Format<'_> {
+ AsFormat::format(&**self)
+ }
+}
+
+/// Implement [AsFormat] for [SyntaxResult] where `T` implements [AsFormat].
+///
+/// Useful to format mandatory AST fields without having to unwrap the value first.
+impl AsFormat for rome_rowan::SyntaxResult
+where
+ T: AsFormat,
+{
+ type Format<'a> = rome_rowan::SyntaxResult> where Self: 'a;
+
+ fn format(&self) -> Self::Format<'_> {
+ match self {
+ Ok(value) => Ok(value.format()),
+ Err(err) => Err(*err),
+ }
+ }
+}
+
+/// Implement [AsFormat] for [Option] when `T` implements [AsFormat]
+///
+/// Allows to call format on optional AST fields without having to unwrap the field first.
+impl AsFormat for Option
+where
+ T: AsFormat,
+{
+ type Format<'a> = Option> where Self: 'a;
+
+ fn format(&self) -> Self::Format<'_> {
+ self.as_ref().map(|value| value.format())
+ }
+}
+
+/// Used to convert this object into an object that can be formatted.
+///
+/// The difference to [AsFormat] is that this trait takes ownership of `self`.
+pub(crate) trait IntoFormat {
+ type Format: rome_formatter::Format;
+
+ fn into_format(self) -> Self::Format;
+}
+
+impl IntoFormat for rome_rowan::SyntaxResult
+where
+ T: IntoFormat,
+{
+ type Format = rome_rowan::SyntaxResult;
+
+ fn into_format(self) -> Self::Format {
+ self.map(IntoFormat::into_format)
+ }
+}
+
+/// Implement [IntoFormat] for [Option] when `T` implements [IntoFormat]
+///
+/// Allows to call format on optional AST fields without having to unwrap the field first.
+impl IntoFormat for Option
+where
+ T: IntoFormat,
+{
+ type Format = Option;
+
+ fn into_format(self) -> Self::Format {
+ self.map(IntoFormat::into_format)
+ }
+}
+
+/// Formatting specific [Iterator] extensions
+pub(crate) trait FormattedIterExt {
+ /// Converts every item to an object that knows how to format it.
+ fn formatted(self) -> FormattedIter
+ where
+ Self: Iterator + Sized,
+ Self::Item: IntoFormat,
+ {
+ FormattedIter {
+ inner: self,
+ options: std::marker::PhantomData,
+ }
+ }
+}
+
+impl FormattedIterExt for I where I: std::iter::Iterator {}
+
+pub(crate) struct FormattedIter
+where
+ Iter: Iterator,
+{
+ inner: Iter,
+ options: std::marker::PhantomData,
+}
+
+impl std::iter::Iterator for FormattedIter
+where
+ Iter: Iterator,
+ Item: IntoFormat,
+{
+ type Item = Item::Format;
+
+ fn next(&mut self) -> Option {
+ Some(self.inner.next()?.into_format())
+ }
+}
+
+impl std::iter::FusedIterator for FormattedIter
+where
+ Iter: std::iter::FusedIterator,
+ Item: IntoFormat,
+{
+}
+
+impl std::iter::ExactSizeIterator for FormattedIter
+where
+ Iter: Iterator + std::iter::ExactSizeIterator,
+ Item: IntoFormat,
+{
+}
pub(crate) type JsFormatter<'buf> = Formatter<'buf, JsFormatContext>;
diff --git a/crates/rome_js_parser/Cargo.toml b/crates/rome_js_parser/Cargo.toml
index 42703c6c099..5dc838eed3a 100644
--- a/crates/rome_js_parser/Cargo.toml
+++ b/crates/rome_js_parser/Cargo.toml
@@ -1,22 +1,22 @@
[package]
-edition = "2021"
+edition = { workspace = true }
name = "rome_js_parser"
-version = "0.0.1"
-authors = ["Rome Tools Developers and Contributors"]
-license = "MIT"
-description = "An extremely fast ECMAScript parser made for the rslint project"
-repository = "https://github.com/rome/tools"
+version = "0.0.2"
+authors = { workspace = true }
+license = { workspace = true }
+description = "An extremely fast ECMAScript parser for Rome, forked from the RSlint project"
+repository = { workspace = true }
documentation = "https://rustdocs.rome.tools/rome_js_parser/index.html"
-
+categories = ["parser-implementations", "development-tools"]
[dependencies]
-rome_console = { version = "0.0.1",path = "../rome_console" }
-rome_diagnostics = { version = "0.0.1",path = "../rome_diagnostics" }
-rome_js_syntax = { version = "0.0.1",path = "../rome_js_syntax" }
-rome_js_factory = { version = "0.0.1",path = "../rome_js_factory" }
-rome_js_unicode_table = { version = "0.0.1",path = "../rome_js_unicode_table" }
-rome_rowan = { version = "0.0.1",path = "../rome_rowan" }
-rome_parser = { version = "0.0.1",path = "../rome_parser" }
+rome_console = { version = "0.0.1", path = "../rome_console" }
+rome_diagnostics = { version = "0.0.1", path = "../rome_diagnostics" }
+rome_js_syntax = { version = "0.0.2", path = "../rome_js_syntax" }
+rome_js_factory = { version = "0.0.2", path = "../rome_js_factory" }
+rome_js_unicode_table = { version = "0.0.1", path = "../rome_js_unicode_table" }
+rome_rowan = { version = "0.0.1", path = "../rome_rowan" }
+rome_parser = { version = "0.0.1", path = "../rome_parser" }
drop_bomb = "0.1.5"
bitflags = "1.3.2"
indexmap = { workspace = true }
@@ -33,3 +33,7 @@ quickcheck_macros = "1.0.0"
[features]
serde = ["rome_js_syntax/serde"]
tests = []
+
+# cargo-workspaces metadata
+[package.metadata.workspaces]
+independent = true
diff --git a/crates/rome_js_parser/LICENSE b/crates/rome_js_parser/LICENSE
index d5f1c1d407f..0c74aa6a873 100644
--- a/crates/rome_js_parser/LICENSE
+++ b/crates/rome_js_parser/LICENSE
@@ -1,4 +1,6 @@
-Copyright (c) 2020 Riccardo D'Ambrosio
+MIT License
+
+Copyright (c) Rome Tools, Inc. and its affiliates.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -10,10 +12,10 @@ furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
-OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/crates/rome_js_parser/README.md b/crates/rome_js_parser/README.md
new file mode 100644
index 00000000000..817ee91420b
--- /dev/null
+++ b/crates/rome_js_parser/README.md
@@ -0,0 +1,36 @@
+
+
+# `rome_js_parser`
+
+Rome's JavaScript parser implementation. Follow the [documentation](https://rustdocs.rome.tools/rome_js_parser/index.html).
+
diff --git a/crates/rome_js_parser/RSLINT_LICENSE b/crates/rome_js_parser/RSLINT_LICENSE
new file mode 100644
index 00000000000..d5f1c1d407f
--- /dev/null
+++ b/crates/rome_js_parser/RSLINT_LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2020 Riccardo D'Ambrosio
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/crates/rome_js_parser/src/lib.rs b/crates/rome_js_parser/src/lib.rs
index 4d13a3a96c1..5ad9b0cc839 100644
--- a/crates/rome_js_parser/src/lib.rs
+++ b/crates/rome_js_parser/src/lib.rs
@@ -10,7 +10,9 @@
//! is completely represented in the final syntax nodes.
//!
//! You probably do not want to use the parser struct, unless you want to parse fragments of Js source code or make your own productions.
-//! Instead use functions such as [parse_script], [parse_module], and [] which offer abstracted versions for parsing.
+//! Instead use functions such as [parse_script], and [parse_module] which offer abstracted versions for parsing.
+//!
+//! For more finer control, use [parse](crate::parse::parse) or [parse_js_with_cache],
//!
//! Notable features of the parser are:
//! - Extremely fast parsing and lexing through the extremely fast lexer.
diff --git a/crates/rome_js_parser/src/parse.rs b/crates/rome_js_parser/src/parse.rs
index 937387f6436..2faf2ee0f92 100644
--- a/crates/rome_js_parser/src/parse.rs
+++ b/crates/rome_js_parser/src/parse.rs
@@ -2,8 +2,7 @@
use crate::*;
use rome_js_syntax::{
- AnyJsRoot, JsExpressionSnipped, JsLanguage, JsModule, JsScript, JsSyntaxNode, ModuleKind,
- SourceType,
+ AnyJsRoot, JsLanguage, JsModule, JsScript, JsSyntaxNode, ModuleKind, SourceType,
};
use rome_parser::event::Event;
use rome_parser::token_source::Trivia;
@@ -184,7 +183,42 @@ pub fn parse_script(text: &str) -> Parse {
.unwrap()
}
-/// Same as `parse_text` but configures the parser to parse an ECMAScript module instead of a script
+/// Same as [parse_script] but configures the parser to parse an ECMAScript module instead of a script
+///
+/// ### Examples
+///
+/// Check the diagnostics emitted by the code
+/// ```
+/// use rome_js_parser::parse_module;
+/// let source = r#"
+/// import { someModule } from "./someModule.js";
+///
+/// someModule();
+/// "#;
+///
+/// let parse = parse_module(source);
+///
+/// // Retrieve the diagnostics emitted
+/// assert_eq!(parse.diagnostics().len(), 0);
+/// ```
+///
+/// Retrieve the emitted AST and check its kind:
+/// ```
+/// use rome_js_parser::parse_module;
+/// use rome_js_syntax::JsSyntaxKind;
+/// use rome_rowan::AstNode;
+/// let source = r#"
+/// import { someModule } from "./someModule.js";
+///
+/// someModule();
+/// "#;
+/// let parse = parse_module(source);
+///
+/// let tree = parse.tree();
+///
+/// assert_eq!(tree.syntax().kind(), JsSyntaxKind::JS_MODULE);
+/// ```
+///
pub fn parse_module(text: &str) -> Parse {
parse(text, SourceType::js_module())
.cast::()
@@ -192,12 +226,53 @@ pub fn parse_module(text: &str) -> Parse {
}
/// Parses the provided string as a EcmaScript program using the provided syntax features.
+///
+/// ### Examples
+///
+/// ```
+/// use rome_js_parser::parse;
+/// use rome_js_syntax::{LanguageVariant, LanguageVersion, ModuleKind, SourceType};
+/// // parse source text as TypeScript
+/// let mut module = SourceType::ts();
+/// let mut parsed = parse("type F = {}", module);
+/// assert_eq!(parsed.diagnostics().len(), 0);
+/// // parse source text as JSX
+/// module = SourceType::jsx();
+/// parsed = parse("", module);
+/// assert_eq!(parsed.diagnostics().len(), 0);
+/// // parse source text with granular control
+/// module = SourceType::default()
+/// .with_version(LanguageVersion::ESNext)
+/// .with_module_kind(ModuleKind::Module)
+/// .with_variant(LanguageVariant::Jsx);
+/// parsed = parse("foo[bar]", module);
+/// assert_eq!(parsed.diagnostics().len(), 0);
+/// ```
pub fn parse(text: &str, source_type: SourceType) -> Parse {
let mut cache = NodeCache::default();
parse_js_with_cache(text, source_type, &mut cache)
}
/// Parses the provided string as a EcmaScript program using the provided syntax features and node cache.
+///
+/// ### Examples
+///
+/// ```
+/// use rome_js_parser::parse_js_with_cache;
+/// use rome_js_syntax::SourceType;
+/// use rome_rowan::NodeCache;
+///
+/// let source_type = SourceType::js_module();
+/// let mut cache = NodeCache::default();
+/// let mut source = "function f() { return 2 }";
+///
+/// let parsed = parse_js_with_cache(source, source_type, &mut cache);
+/// assert_eq!(parsed.diagnostics().len(), 0);
+///
+/// source = "function bar() { return 3 }";
+/// let parsed = parse_js_with_cache(source, source_type, &mut cache);
+/// assert_eq!(parsed.diagnostics().len(), 0);
+/// ```
pub fn parse_js_with_cache(
text: &str,
source_type: SourceType,
@@ -211,15 +286,3 @@ pub fn parse_js_with_cache(
Parse::new(green, parse_errors)
})
}
-/// Losslessly Parse text into an expression [`Parse`](Parse) which can then be turned into an untyped root [`JsSyntaxNode`](JsSyntaxNode).
-/// Or turned into a typed [`JsExpressionSnipped`](JsExpressionSnipped) with [`tree`](Parse::tree).
-pub fn parse_expression(text: &str) -> Parse {
- let mut parser = JsParser::new(text, SourceType::js_module());
- syntax::expr::parse_expression_snipped(&mut parser).unwrap();
- let (events, tokens, errors) = parser.finish();
-
- let mut tree_sink = JsLosslessTreeSink::new(text, &tokens);
- rome_parser::event::process(&mut tree_sink, events, errors);
- let (green, parse_errors) = tree_sink.finish();
- Parse::new_script(green, parse_errors)
-}
diff --git a/crates/rome_js_parser/src/parser.rs b/crates/rome_js_parser/src/parser.rs
index c58c38a4c7f..4104c749703 100644
--- a/crates/rome_js_parser/src/parser.rs
+++ b/crates/rome_js_parser/src/parser.rs
@@ -212,59 +212,7 @@ pub struct JsParserCheckpoint {
#[cfg(test)]
mod tests {
use crate::prelude::*;
- use crate::JsLosslessTreeSink;
use rome_js_syntax::{JsSyntaxKind, SourceType};
- use rome_rowan::AstNode;
-
- #[test]
- fn example() {
- use crate::syntax::expr::parse_expression_snipped;
- use crate::JsParser;
- use rome_js_syntax::{AnyJsExpression, JsExpressionSnipped};
-
- let source = "(void b)";
-
- // File id is used for the labels inside parser errors to report them, the file id
- // is used to look up a file's source code and path inside of a codespan `Files` implementation.
- let mut parser = JsParser::new(source, SourceType::default());
-
- // Use one of the syntax parsing functions to parse an expression.
- // This adds node and token events to the parser which are then used to make a node.
- // A completed marker marks the start and end indices in the events vec which signify
- // the Start event, and the Finish event.
- // Completed markers can be turned into an ast node with parse_marker on the parser
- parse_expression_snipped(&mut parser).unwrap();
-
- // Consume the parser and get its events, then apply them to a tree sink with `process`.
- let (events, tokens, errors) = parser.finish();
-
- // Make a new text tree sink, its job is assembling events into a rowan GreenNode.
- // At each point (Start, Token, Finish, Error) it also consumes whitespace.
- // Other abstractions can also yield lossy syntax nodes if whitespace is not wanted.
- // Swap this for a LossyTreeSink for a lossy AST result.
- let mut sink = JsLosslessTreeSink::new(source, &tokens);
-
- rome_parser::event::process(&mut sink, events, errors);
-
- let (untyped_node, errors) = sink.finish();
-
- assert!(errors.is_empty());
- assert!(JsExpressionSnipped::can_cast(untyped_node.kind()));
-
- // Convert the untyped SyntaxNode into a typed AST node
- let expression_snipped = JsExpressionSnipped::cast(untyped_node).unwrap();
- let expression = expression_snipped.expression().unwrap();
-
- match expression {
- AnyJsExpression::JsParenthesizedExpression(parenthesized) => {
- assert_eq!(
- parenthesized.expression().unwrap().syntax().text(),
- "void b"
- );
- }
- _ => panic!("Expected parenthesized expression"),
- }
- }
#[test]
#[should_panic(
diff --git a/crates/rome_js_parser/src/syntax/expr.rs b/crates/rome_js_parser/src/syntax/expr.rs
index 254cc86e918..c9e864b5900 100644
--- a/crates/rome_js_parser/src/syntax/expr.rs
+++ b/crates/rome_js_parser/src/syntax/expr.rs
@@ -1177,12 +1177,6 @@ fn parse_parenthesized_expression(p: &mut JsParser) -> ParsedSyntax {
Present(m.complete(p, JS_PARENTHESIZED_EXPRESSION))
}
-pub(crate) fn parse_expression_snipped(p: &mut JsParser) -> ParsedSyntax {
- let m = p.start();
- parse_expression(p, ExpressionContext::default()).or_add_diagnostic(p, expected_expression);
- m.complete(p, JS_EXPRESSION_SNIPPED).into()
-}
-
/// A general expression.
pub(crate) fn parse_expression(p: &mut JsParser, context: ExpressionContext) -> ParsedSyntax {
let first = parse_assignment_expression_or_higher(p, context);
diff --git a/crates/rome_js_semantic/Cargo.toml b/crates/rome_js_semantic/Cargo.toml
index a181b2d2d87..f93ad60c423 100644
--- a/crates/rome_js_semantic/Cargo.toml
+++ b/crates/rome_js_semantic/Cargo.toml
@@ -1,11 +1,11 @@
[package]
-edition = "2021"
+edition = { workspace = true }
name = "rome_js_semantic"
version = "0.0.0"
-authors = ["Rome Tools Developers and Contributors"]
-license = "MIT"
+authors = { workspace = true }
+license = { workspace = true }
description = "Semantic model for the JavaScript language"
-repository = "https://github.com/rome/tools"
+repository = { workspace = true }
[dependencies]
rome_rowan = { path = "../rome_rowan" }
diff --git a/crates/rome_js_syntax/Cargo.toml b/crates/rome_js_syntax/Cargo.toml
index f91bb583bde..5ff1b1b5ca7 100644
--- a/crates/rome_js_syntax/Cargo.toml
+++ b/crates/rome_js_syntax/Cargo.toml
@@ -1,11 +1,11 @@
[package]
-edition = "2021"
+edition = { workspace = true }
name = "rome_js_syntax"
-version = "0.0.1"
-authors = ["Rome Tools Developers and Contributors"]
+version = "0.0.2"
+authors = { workspace = true }
description = "SyntaxKind and common rowan definitions for rome_js_parser"
-license = "MIT"
-repository = "https://github.com/rome/tools"
+license = { workspace = true }
+repository = { workspace = true }
documentation = "https://rustdocs.rome.tools/rome_js_syntax/index.html"
[dependencies]
diff --git a/crates/rome_js_syntax/README.md b/crates/rome_js_syntax/README.md
new file mode 100644
index 00000000000..d09804ef9ac
--- /dev/null
+++ b/crates/rome_js_syntax/README.md
@@ -0,0 +1,36 @@
+
+
+# `rome_json_formatter`
+
+Rome's JSON formatter implementation. Follow the [documentation](https://rustdocs.rome.tools/rome_json_formatter/index.html).
+
diff --git a/crates/rome_json_formatter/src/lib.rs b/crates/rome_json_formatter/src/lib.rs
index c5a2d3347c7..89070a1cc15 100644
--- a/crates/rome_json_formatter/src/lib.rs
+++ b/crates/rome_json_formatter/src/lib.rs
@@ -19,7 +19,143 @@ use rome_formatter::{Formatted, Printed};
use rome_json_syntax::{AnyJsonValue, JsonLanguage, JsonSyntaxNode, JsonSyntaxToken};
use rome_rowan::{AstNode, SyntaxNode, SyntaxTriviaPieceComments, TextRange};
-include!("../../rome_formatter/shared_traits.rs");
+/// Used to get an object that knows how to format this object.
+pub(crate) trait AsFormat {
+ type Format<'a>: rome_formatter::Format
+ where
+ Self: 'a;
+
+ /// Returns an object that is able to format this object.
+ fn format(&self) -> Self::Format<'_>;
+}
+
+/// Implement [AsFormat] for references to types that implement [AsFormat].
+impl AsFormat for &T
+where
+ T: AsFormat,
+{
+ type Format<'a> = T::Format<'a> where Self: 'a;
+
+ fn format(&self) -> Self::Format<'_> {
+ AsFormat::format(&**self)
+ }
+}
+
+/// Implement [AsFormat] for [SyntaxResult] where `T` implements [AsFormat].
+///
+/// Useful to format mandatory AST fields without having to unwrap the value first.
+impl AsFormat for rome_rowan::SyntaxResult
+where
+ T: AsFormat,
+{
+ type Format<'a> = rome_rowan::SyntaxResult> where Self: 'a;
+
+ fn format(&self) -> Self::Format<'_> {
+ match self {
+ Ok(value) => Ok(value.format()),
+ Err(err) => Err(*err),
+ }
+ }
+}
+
+/// Implement [AsFormat] for [Option] when `T` implements [AsFormat]
+///
+/// Allows to call format on optional AST fields without having to unwrap the field first.
+impl AsFormat for Option
+where
+ T: AsFormat,
+{
+ type Format<'a> = Option> where Self: 'a;
+
+ fn format(&self) -> Self::Format<'_> {
+ self.as_ref().map(|value| value.format())
+ }
+}
+
+/// Used to convert this object into an object that can be formatted.
+///
+/// The difference to [AsFormat] is that this trait takes ownership of `self`.
+pub(crate) trait IntoFormat {
+ type Format: rome_formatter::Format;
+
+ fn into_format(self) -> Self::Format;
+}
+
+impl IntoFormat for rome_rowan::SyntaxResult
+where
+ T: IntoFormat,
+{
+ type Format = rome_rowan::SyntaxResult;
+
+ fn into_format(self) -> Self::Format {
+ self.map(IntoFormat::into_format)
+ }
+}
+
+/// Implement [IntoFormat] for [Option] when `T` implements [IntoFormat]
+///
+/// Allows to call format on optional AST fields without having to unwrap the field first.
+impl IntoFormat for Option
+where
+ T: IntoFormat,
+{
+ type Format = Option;
+
+ fn into_format(self) -> Self::Format {
+ self.map(IntoFormat::into_format)
+ }
+}
+
+/// Formatting specific [Iterator] extensions
+pub(crate) trait FormattedIterExt {
+ /// Converts every item to an object that knows how to format it.
+ fn formatted(self) -> FormattedIter
+ where
+ Self: Iterator + Sized,
+ Self::Item: IntoFormat,
+ {
+ FormattedIter {
+ inner: self,
+ options: std::marker::PhantomData,
+ }
+ }
+}
+
+impl FormattedIterExt for I where I: std::iter::Iterator {}
+
+pub(crate) struct FormattedIter
+where
+ Iter: Iterator,
+{
+ inner: Iter,
+ options: std::marker::PhantomData,
+}
+
+impl std::iter::Iterator for FormattedIter
+where
+ Iter: Iterator,
+ Item: IntoFormat,
+{
+ type Item = Item::Format;
+
+ fn next(&mut self) -> Option {
+ Some(self.inner.next()?.into_format())
+ }
+}
+
+impl std::iter::FusedIterator for FormattedIter
+where
+ Iter: std::iter::FusedIterator,
+ Item: IntoFormat,
+{
+}
+
+impl std::iter::ExactSizeIterator for FormattedIter
+where
+ Iter: Iterator + std::iter::ExactSizeIterator,
+ Item: IntoFormat,
+{
+}
pub(crate) type JsonFormatter<'buf> = Formatter<'buf, JsonFormatContext>;
diff --git a/crates/rome_json_parser/Cargo.toml b/crates/rome_json_parser/Cargo.toml
index 491559094c8..8e16ae940d8 100644
--- a/crates/rome_json_parser/Cargo.toml
+++ b/crates/rome_json_parser/Cargo.toml
@@ -1,20 +1,22 @@
[package]
-edition = "2021"
name = "rome_json_parser"
-version = "0.0.0"
-authors = ["Rome Tools and Contributors"]
-license = "MIT"
+version = "0.0.1"
+edition = { workspace = true }
+authors = { workspace = true }
+repository = { workspace = true }
+license = { workspace = true }
description = "An extremely fast JSON parser"
-repository = "https://github.com/rome/tools"
+documentation = "https://rustdocs.rome.tools/rome_json_parser/index.html"
+categories = ["parser-implementations", "development-tools"]
[dependencies]
-rome_rowan = { path = "../rome_rowan" }
-rome_console = { path = "../rome_console" }
-rome_diagnostics = { path = "../rome_diagnostics" }
-rome_json_syntax = { path = "../rome_json_syntax" }
-rome_json_factory = { path = "../rome_json_factory" }
-rome_js_unicode_table = { path = "../rome_js_unicode_table" }
-rome_parser = { path = "../rome_parser" }
+rome_rowan = {version = "0.0.1", path = "../rome_rowan" }
+rome_console = {version = "0.0.1", path = "../rome_console" }
+rome_diagnostics = {version = "0.0.1", path = "../rome_diagnostics" }
+rome_json_syntax = {version = "0.0.1", path = "../rome_json_syntax" }
+rome_json_factory = { version = "0.0.1", path = "../rome_json_factory" }
+rome_js_unicode_table = {version = "0.0.1", path = "../rome_js_unicode_table" }
+rome_parser = { version = "0.0.1", path = "../rome_parser" }
tracing = { workspace = true }
[dev-dependencies]
@@ -23,3 +25,6 @@ quickcheck = "1.0.3"
quickcheck_macros = "1.0.0"
insta = { workspace = true }
+# cargo-workspaces metadata
+[package.metadata.workspaces]
+independent = true
diff --git a/crates/rome_json_parser/LICENSE b/crates/rome_json_parser/LICENSE
new file mode 100644
index 00000000000..0c74aa6a873
--- /dev/null
+++ b/crates/rome_json_parser/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) Rome Tools, Inc. and its affiliates.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/crates/rome_json_parser/README.md b/crates/rome_json_parser/README.md
new file mode 100644
index 00000000000..9b660600abb
--- /dev/null
+++ b/crates/rome_json_parser/README.md
@@ -0,0 +1,36 @@
+