feat(rome_service): configuration file shape
MODIFY
Cargo.lock
Cargo.lock
@@ -1624,6 +1624,8 @@ dependencies = [
"rome_js_parser",
"rome_js_syntax",
"rome_rowan",
+ "serde",
+ "serde_json",
]
[[package]]
@@ -1714,9 +1716,9 @@ checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
[[package]]
name = "serde"
-version = "1.0.136"
+version = "1.0.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
+checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47"
dependencies = [
"serde_derive",
]
@@ -1733,9 +1735,9 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.136"
+version = "1.0.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
+checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c"
dependencies = [
"proc-macro2",
"quote",
@@ -1853,9 +1855,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.86"
+version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
+checksum = "a07e33e919ebcd69113d5be0e4d70c5707004ff45188910106854f38b960df4a"
dependencies = [
"proc-macro2",
"quote",

MODIFY
crates/rome_formatter/src/lib.rs
crates/rome_formatter/src/lib.rs
@@ -66,6 +66,7 @@ use rome_rowan::{
};
use std::error::Error;
use std::fmt;
+use std::fmt::Display;
use std::num::ParseIntError;
use std::str::FromStr;
@@ -172,6 +173,16 @@ impl TryFrom<u16> for LineWidth {
}
}
+impl Display for LineWidthFromIntError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ writeln!(
+ f,
+ "The line width exceeds the maximum value ({})",
+ LineWidth::MAX
+ )
+ }
+}
+
impl From<LineWidth> for u16 {
fn from(value: LineWidth) -> Self {
value.0

MODIFY
crates/rome_service/Cargo.toml
crates/rome_service/Cargo.toml
@@ -7,7 +7,8 @@ edition = "2021"
[dependencies]
dashmap = "5.2.0"
-
+serde = { version = "1.0.133", features = ["derive"] }
+serde_json = "1.0.74"
rome_analyze = { path = "../rome_analyze" }
rome_console = { path = "../rome_console" }
rome_diagnostics = { path = "../rome_diagnostics" }

ADD
crates/rome_service/src/configuration/formatter.rs
+use rome_formatter::{IndentStyle, LineWidth};
+use serde::Deserialize;
+#[derive(Deserialize, Debug, Eq, PartialEq)]
+#[serde(rename_all = "camelCase", default)]
+pub struct FormatterConfiguration {
+ // if `false`, it disables the feature. `true` by default
+ pub enabled: bool,
+
+ /// Stores whether formatting should be allowed to proceed if a given file
+ /// has syntax errors
+ pub format_with_errors: bool,
+
+ /// The indent style.
+ pub indent_style: PlainIndentStyle,
+
+ /// The size of the indentation, 2 by default
+ indent_size: u8,
+
+ /// What's the max width of a line. Defaults to 80.
+ #[serde(deserialize_with = "deserialize_line_width")]
+ pub line_width: LineWidth,
+}
+
+impl From<&FormatterConfiguration> for IndentStyle {
+ fn from(c: &FormatterConfiguration) -> Self {
+ match c.indent_style {
+ PlainIndentStyle::Tab => IndentStyle::Tab,
+ PlainIndentStyle::Space => IndentStyle::Space(c.indent_size),
+ }
+ }
+}
+
+fn deserialize_line_width<'de, D>(deserializer: D) -> Result<LineWidth, D::Error>
+where
+ D: serde::de::Deserializer<'de>,
+{
+ let value: u16 = Deserialize::deserialize(deserializer)?;
+ LineWidth::try_from(value).map_err(serde::de::Error::custom)
+}
+
+impl Default for FormatterConfiguration {
+ fn default() -> Self {
+ Self {
+ enabled: true,
+ format_with_errors: false,
+ indent_size: 2,
+ indent_style: PlainIndentStyle::default(),
+ line_width: LineWidth::default(),
+ }
+ }
+}
+
+#[derive(Deserialize, Debug, Eq, PartialEq)]
+#[serde(rename_all = "camelCase")]
+pub enum PlainIndentStyle {
+ /// Tab
+ Tab,
+ /// Space
+ Space,
+}
+
+impl Default for PlainIndentStyle {
+ fn default() -> Self {
+ Self::Tab
+ }
+}

ADD
crates/rome_service/src/configuration/javascript.rs
+use rome_js_formatter::context::QuoteStyle;
+use serde::Deserialize;
+
+#[derive(Default, Debug, Deserialize, Eq, PartialEq)]
+pub struct JavascriptConfiguration {
+ pub formatter: JavascriptFormatter,
+}
+
+#[derive(Default, Debug, Deserialize, Eq, PartialEq)]
+#[serde(rename_all = "camelCase", default)]
+pub struct JavascriptFormatter {
+ /// The style for quotes. Defaults to double.
+ pub quote_style: PlainQuoteStyle,
+}
+
+#[derive(Deserialize, Debug, Eq, PartialEq)]
+#[serde(rename_all = "camelCase")]
+pub enum PlainQuoteStyle {
+ Double,
+ Single,
+}
+
+impl Default for PlainQuoteStyle {
+ fn default() -> Self {
+ Self::Double
+ }
+}
+
+impl From<JavascriptConfiguration> for QuoteStyle {
+ fn from(j: JavascriptConfiguration) -> Self {
+ match j.formatter.quote_style {
+ PlainQuoteStyle::Double => QuoteStyle::Double,
+ PlainQuoteStyle::Single => QuoteStyle::Single,
+ }
+ }
+}

ADD
crates/rome_service/src/configuration/mod.rs
+//! This module contains the configuration of `rome.json`
+//!
+//! The configuration is divided by "tool", and then it's possible to further customise it
+//! by language. The language might further options divided by tool.
+
+use crate::configuration::formatter::FormatterConfiguration;
+use crate::configuration::javascript::JavascriptConfiguration;
+use serde::Deserialize;
+
+mod formatter;
+mod javascript;
+
+/// The configuration that is contained inside the file `rome.json`
+#[derive(Default, Debug, Eq, PartialEq, Deserialize)]
+#[serde(default)]
+pub struct Configuration {
+ /// One root file should exist. Useful when `extends` comes into play.
+ ///
+ /// If `true`, this file should be the master configuration.
+ pub root: bool,
+
+ /// The configuration of the formatter
+ pub formatter: FormatterConfiguration,
+
+ /// Specific configuration for the JavaScript language
+ pub javascript: JavascriptConfiguration,
+}

MODIFY
crates/rome_service/src/lib.rs
crates/rome_service/src/lib.rs
@@ -5,6 +5,7 @@ use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::ops::{Deref, DerefMut};
+pub mod configuration;
mod file_handlers;
pub mod settings;
pub mod workspace;

ADD
crates/rome_service/tests/all_fields.json
+{
+ "root": true,
+ "formatter": {
+ "enabled": true,
+ "formatWithErrors": true,
+ "indentStyle": "tab",
+ "indentSize": 2,
+ "lineWidth": 80
+ },
+ "javascript": {
+ "formatter": {
+ "quoteStyle": "double"
+ }
+ }
+}
\ No newline at end of file

ADD
crates/rome_service/tests/empty.json
+{}
\ No newline at end of file

ADD
crates/rome_service/tests/line_width.json
+{
+ "root": true,
+ "formatter": {
+ "lineWidth": 450
+ }
+}
\ No newline at end of file

ADD
crates/rome_service/tests/mod.rs
+mod configuration {
+ use rome_service::configuration::Configuration;
+ use std::env::current_dir;
+ use std::fs::read_to_string;
+
+ #[test]
+ fn parse_all_fields() {
+ let mut working_dir = current_dir().unwrap();
+ working_dir.push("tests");
+ working_dir.push("all_fields.json");
+ let content = read_to_string(working_dir).unwrap();
+
+ let configuration = serde_json::from_str::<Configuration>(&content);
+
+ assert!(configuration.is_ok())
+ }
+
+ #[test]
+ fn parse_default_values() {
+ let mut working_dir = current_dir().unwrap();
+ working_dir.push("tests");
+ working_dir.push("empty.json");
+ let content = read_to_string(working_dir).unwrap();
+
+ let configuration = serde_json::from_str::<Configuration>(&content);
+
+ match configuration {
+ Ok(configuration) => {
+ assert_eq!(configuration, Configuration::default());
+ }
+ Err(err) => {
+ panic!("{err}");
+ }
+ }
+ }
+
+ #[test]
+ fn line_width_error() {
+ let mut working_dir = current_dir().unwrap();
+ working_dir.push("tests");
+ working_dir.push("line_width.json");
+ let content = read_to_string(working_dir).unwrap();
+
+ let configuration = serde_json::from_str::<Configuration>(&content);
+
+ assert!(configuration.is_err());
+
+ if let Err(err) = configuration {
+ assert!(err
+ .to_string()
+ .as_str()
+ .contains("The line width exceeds the maximum value (320)"),)
+ }
+ }
+}

feat(rome_service): configuration file shape (#2825)