Skip to content

Commit

Permalink
feat(format/grit): grit formatter initial configuration (#3885)
Browse files Browse the repository at this point in the history
  • Loading branch information
branberry authored Sep 16, 2024
1 parent d6be3f2 commit 300d6c6
Show file tree
Hide file tree
Showing 9 changed files with 635 additions and 40 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 16 additions & 15 deletions crates/biome_formatter/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ where
</details>


Then, you'll have to create three types:
Then, you'll have to create four types:
1. `HtmlCommentStyle`
1. `HtmlFormatContext`
1. `FormatHtmlSyntaxNode`
Expand Down Expand Up @@ -195,12 +195,12 @@ Usually, the type context must contain `comments` and `source_map` fields:
```rust
pub struct HtmlFormatContext {
/// The comments of the nodes and tokens in the program.
comments: Rc<CssComments>,
source_map: Option<TransformSourceMap>,
comments: Rc<HtmlComments>,
source_map: Option<TransformSourceMap>,
}

impl HtmlFormatContext {
pub fn new(comments: CssComments) -> Self {
pub fn new(comments: HtmlComments) -> Self {
Self {
comments: Rc::new(comments),
source_map: None,
Expand Down Expand Up @@ -244,15 +244,15 @@ impl FormatRule<HtmlSyntaxNode> for FormatHtmlSyntaxNode {
}
}

impl AsFormat<HtmlFormatContext> for FormatHtmlSyntaxNode {
impl AsFormat<HtmlFormatContext> for HtmlSyntaxNode {
type Format<'a> = FormatRefWithRule<'a, HtmlSyntaxNode, FormatHtmlSyntaxNode>;

fn format(&self) -> Self::Format<'_> {
FormatRefWithRule::new(self, FormatHtmlSyntaxNode)
}
}

impl IntoFormat<HtmlFormatContext> for FormatHtmlSyntaxNode {
impl IntoFormat<HtmlFormatContext> for HtmlSyntaxNode {
type Format = FormatOwnedWithRule<HtmlSyntaxNode, FormatHtmlSyntaxNode>;

fn into_format(self) -> Self::Format {
Expand All @@ -268,7 +268,7 @@ impl IntoFormat<HtmlFormatContext> for FormatHtmlSyntaxNode {
This is small type that you need to instruct the formatter infra about a certain language. This type needs to implement the trait `biome_formatter::FormatLanguage`

```rust
impl FormatLanguage for HtmlLanguage {
impl FormatLanguage for HtmlFormatLanguage {
type SyntaxLanguage = HtmlLanguage;
type Context = HtmlFormatContext;
type FormatRule = FormatHtmlSyntaxNode;
Expand All @@ -294,7 +294,7 @@ where
N: AstNode<Language = HtmlLanguage>,
{
// this is the method that actually start the formatting
fn fmt(&self, node: &N, f: &mut HtmlForamtter) -> FormatResult<()> {
fn fmt(&self, node: &N, f: &mut HtmlFormatter) -> FormatResult<()> {
if self.is_suppressed(node, f) {
return write!(f, [format_suppressed_node(node.syntax())]);
}
Expand All @@ -305,18 +305,18 @@ where
self.fmt_trailing_comments(node, f)
}

fn fmt_fields(&self, node: &N, f: &mut HtmlForamtter) -> FormatResult<()>;
fn fmt_fields(&self, node: &N, f: &mut HtmlFormatter) -> FormatResult<()>;

/// Returns `true` if the node has a suppression comment and should use the same formatting as in the source document.
fn is_suppressed(&self, node: &N, f: &JsonFormatter) -> bool {
fn is_suppressed(&self, node: &N, f: &HtmlFormatter) -> bool {
f.context().comments().is_suppressed(node.syntax())
}

/// Formats the [leading comments](biome_formatter::comments#leading-comments) of the node.
///
/// You may want to override this method if you want to manually handle the formatting of comments
/// inside of the `fmt_fields` method or customize the formatting of the leading comments.
fn fmt_leading_comments(&self, node: &N, f: &mut HtmlForamtter) -> FormatResult<()> {
fn fmt_leading_comments(&self, node: &N, f: &mut HtmlFormatter) -> FormatResult<()> {
format_leading_comments(node.syntax()).fmt(f)
}

Expand All @@ -327,7 +327,7 @@ where
/// no comments are dropped.
///
/// A node can have dangling comments if all its children are tokens or if all node childrens are optional.
fn fmt_dangling_comments(&self, node: &N, f: &mut HtmlForamtter) -> FormatResult<()> {
fn fmt_dangling_comments(&self, node: &N, f: &mut HtmlFormatter) -> FormatResult<()> {
format_dangling_comments(node.syntax())
.with_soft_block_indent()
.fmt(f)
Expand All @@ -337,7 +337,7 @@ where
///
/// You may want to override this method if you want to manually handle the formatting of comments
/// inside of the `fmt_fields` method or customize the formatting of the trailing comments.
fn fmt_trailing_comments(&self, node: &N, f: &mut HtmlForamtter) -> FormatResult<()> {
fn fmt_trailing_comments(&self, node: &N, f: &mut HtmlFormatter) -> FormatResult<()> {
format_trailing_comments(node.syntax()).fmt(f)
}
}
Expand All @@ -349,9 +349,10 @@ Now that everything is wired, you just needs to expose a public method that does

```rust
pub fn format_node(
options: HtmlFormatOptions,
root: &HtmlSyntaxNode,
) -> FormatResult<Formatted<HtmlFormatContext>> {
biome_formatter::format_node(root, HtmlFormatLanguage {})
biome_formatter::format_node(root, HtmlFormatLanguage::new(options))
}
```

Expand Down Expand Up @@ -379,7 +380,7 @@ Updated the `Cargo.toml` file to import some testing utility:
```toml
[dev-dependencies]
biome_formatter_test = { path = "../biome_formatter_test" }
biome_html_factory = { path = "../biome_html_parser" }
biome_html_factory = { path = "../biome_html_factory" }
biome_html_parser = { path = "../biome_html_parser" }
biome_parser = { path = "../biome_parser" }
biome_service = { path = "../biome_service" }
Expand Down
10 changes: 5 additions & 5 deletions crates/biome_grit_formatter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ version = "0.0.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
#biome_formatter = { workspace = true }
#biome_grit_syntax = { workspace = true }
#biome_rowan = { workspace = true }
biome_formatter = { workspace = true }
biome_grit_syntax = { workspace = true }
biome_rowan = { workspace = true }

[dev-dependencies]
#serde = { workspace = true, features = ["derive"] }
#serde_json = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }

# cargo-workspaces metadata
[package.metadata.workspaces]
Expand Down
83 changes: 83 additions & 0 deletions crates/biome_grit_formatter/src/comments.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use crate::GritFormatContext;

use biome_formatter::{
comments::{is_doc_comment, CommentStyle, Comments, SourceComment},
prelude::*,
prelude::{align, dynamic_text, format_once, hard_line_break, Formatter},
write, FormatResult, FormatRule,
};
use biome_grit_syntax::GritLanguage;
use biome_rowan::TextLen;

pub type GritComments = Comments<GritLanguage>;

#[derive(Eq, PartialEq, Copy, Clone, Debug, Default)]
pub struct GritCommentStyle;

impl CommentStyle for GritCommentStyle {
type Language = GritLanguage;

fn is_suppression(_text: &str) -> bool {
false
}

fn get_comment_kind(
_comment: &biome_rowan::SyntaxTriviaPieceComments<Self::Language>,
) -> biome_formatter::comments::CommentKind {
todo!()
}

fn place_comment(
&self,
comment: biome_formatter::comments::DecoratedComment<Self::Language>,
) -> biome_formatter::comments::CommentPlacement<Self::Language> {
biome_formatter::comments::CommentPlacement::Default(comment)
}
}

#[derive(Default)]
pub struct FormatGritLeadingComment;

impl FormatRule<SourceComment<GritLanguage>> for FormatGritLeadingComment {
type Context = GritFormatContext;
// Copied and pasted this from the css formatter, not sure how much this needs to change.
fn fmt(
&self,
comment: &SourceComment<GritLanguage>,
f: &mut Formatter<Self::Context>,
) -> FormatResult<()> {
if is_doc_comment(comment.piece()) {
let mut source_offset = comment.piece().text_range().start();

let mut lines = comment.piece().text().lines();

// SAFETY: Safe, `is_doc_comment` only returns `true` for multiline comments
let first_line = lines.next().unwrap();
write!(f, [dynamic_text(first_line.trim_end(), source_offset)])?;

source_offset += first_line.text_len();

// Indent the remaining lines by one space so that all `*` are aligned.
write!(
f,
[align(
1,
&format_once(|f| {
for line in lines {
write!(
f,
[hard_line_break(), dynamic_text(line.trim(), source_offset)]
)?;

source_offset += line.text_len();
}

Ok(())
})
)]
)
} else {
write!(f, [comment.piece().as_piece()])
}
}
}
151 changes: 151 additions & 0 deletions crates/biome_grit_formatter/src/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
use crate::comments::{FormatGritLeadingComment, GritCommentStyle, GritComments};
use biome_formatter::{
CstFormatContext, FormatContext, FormatOptions, IndentStyle, IndentWidth, LineEnding,
LineWidth, QuoteStyle, TransformSourceMap,
};
use biome_grit_syntax::GritLanguage;
use std::rc::Rc;

#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct GritFormatContext {
comments: Rc<GritComments>,
source_map: Option<TransformSourceMap>,
}

impl GritFormatContext {
pub fn new(comments: GritComments) -> Self {
Self {
comments: Rc::new(comments),
source_map: None,
}
}

pub fn with_source_map(mut self, source_map: Option<TransformSourceMap>) -> Self {
self.source_map = source_map;
self
}
}

impl FormatContext for GritFormatContext {
type Options = GritFormatOptions;

fn options(&self) -> &Self::Options {
todo!()
}

fn source_map(&self) -> Option<&TransformSourceMap> {
todo!()
}
}
impl CstFormatContext for GritFormatContext {
type Language = GritLanguage;

type Style = GritCommentStyle;

type CommentRule = FormatGritLeadingComment;

fn comments(&self) -> &biome_formatter::comments::Comments<Self::Language> {
todo!()
}
}

#[derive(Debug, Default, Clone, PartialEq)]

pub struct GritFormatOptions {
indent_style: IndentStyle,
indent_width: IndentWidth,
line_ending: LineEnding,
line_width: LineWidth,
quote_style: QuoteStyle,
}

impl GritFormatOptions {
pub fn new() -> Self {
Self {
indent_style: IndentStyle::default(),
indent_width: IndentWidth::default(),
line_ending: LineEnding::default(),
line_width: LineWidth::default(),
quote_style: QuoteStyle::default(),
}
}
pub fn with_indent_style(mut self, indent_style: IndentStyle) -> Self {
self.indent_style = indent_style;
self
}

pub fn with_indent_width(mut self, indent_width: IndentWidth) -> Self {
self.indent_width = indent_width;
self
}

pub fn with_line_ending(mut self, line_ending: LineEnding) -> Self {
self.line_ending = line_ending;
self
}

pub fn with_line_width(mut self, line_width: LineWidth) -> Self {
self.line_width = line_width;
self
}

pub fn with_quote_style(mut self, quote_style: QuoteStyle) -> Self {
self.quote_style = quote_style;
self
}

pub fn set_indent_style(&mut self, indent_style: IndentStyle) {
self.indent_style = indent_style;
}

pub fn set_indent_width(&mut self, indent_width: IndentWidth) {
self.indent_width = indent_width;
}

pub fn set_line_ending(&mut self, line_ending: LineEnding) {
self.line_ending = line_ending;
}

pub fn set_line_width(&mut self, line_width: LineWidth) {
self.line_width = line_width;
}

pub fn set_quote_style(&mut self, quote_style: QuoteStyle) {
self.quote_style = quote_style;
}

pub fn quote_style(&self) -> QuoteStyle {
self.quote_style
}
}

impl FormatOptions for GritFormatOptions {
fn indent_style(&self) -> IndentStyle {
todo!()
}

fn indent_width(&self) -> IndentWidth {
todo!()
}

fn line_width(&self) -> LineWidth {
todo!()
}

fn line_ending(&self) -> LineEnding {
todo!()
}

fn attribute_position(&self) -> biome_formatter::AttributePosition {
todo!()
}

fn bracket_spacing(&self) -> biome_formatter::BracketSpacing {
todo!()
}

fn as_print_options(&self) -> biome_formatter::prelude::PrinterOptions {
todo!()
}
}
Loading

0 comments on commit 300d6c6

Please sign in to comment.