# Formatter

This document defines the currently implemented Masterbelt formatting behavior.

The formatter is intentionally minimal at this stage. Future syntax additions must extend this document before or together with formatter changes.

## Options

The formatter accepts an indentation string option.

The indentation string is used for one indentation level inside grouped declarations. Callers should derive this value from the user's editor configuration when available.

If no indentation string is provided, the formatter uses two spaces.

## Source Files

The formatter parses source text and emits top-level declarations, statements, and comments in source order.

Top-level items are separated by one blank line.

The formatted output ends with one trailing line feed.

## Comments

Line comments and block comments are preserved.

Line comments and block comments that appear as top-level items are emitted on their own lines in source order.

Consecutive top-level line comments and block comments are kept together without blank lines between them.

A top-level line comment or block comment immediately followed by a declaration or statement is kept adjacent to that declaration or statement, with no blank line inserted between the comment and the following item.

Line comments that appear after a declaration item or expression statement on the same source line are preserved as trailing line comments on the formatted line.

Inside grouped const declarations, line comments and block comments are indented by one indentation level.

## Documentation Comments

Documentation comments are emitted immediately before the declaration, statement, or grouped const item they document.

The formatter preserves the documentation comment text after the leading `///`.

Top-level documentation comments are not indented.

Grouped const item documentation comments are indented by one indentation level.

## Const Declarations

A single-item const declaration is formatted on one line:

```mst
const A = 1
const A: int = 1
pub const A: bool = true
```

A const declaration with more than one item is formatted as a group:

```mst
pub const (
  A = 1
  B: string = "x"
)
```

Grouped const items are indented by one indentation level.

The outer visibility modifier applies to the group and is emitted before `const`.

## Expression Statements

Expression statements are formatted as their expression.

## Master Validation Section

The `validation` section of a master ([validation.md](../masterdata/validation.md)) is formatted as a brace-delimited section. When a master documents a canonical section order, the `validation` section follows `filter` and precedes `static`, matching the grammar order.

- The `each` and `all` scope groups each indent one level deeper than the `validation` section. Consecutive groups are separated by exactly one blank line.
- Within a group, each `validate <id> { ... }` block indents one level deeper than the group. Consecutive `validate` blocks are separated by exactly one blank line.
- An `assert <expr>` statement is formatted like any other statement. Rule bodies reuse the existing statement and expression formatting.

```mst
master Records {
  record { primary ID: int, Name: string, Value: int }

  validation {
    each {
      validate nameRequired {
        assert row.Name != ""
      }

      validate valuePositive {
        assert row.Value > 0
      }
    }

    all {
      validate checkValueSum {
        let total = 0
        for row in table {
          total = total + row.Value
        }
        assert total < 1000
      }
    }
  }
}
```

## Master Scope Section

A master [scope](../masterdata/schema.md#scope-section) declaration is formatted as `[pub ][indexed ]scope name(params) body` with canonical spacing. The two modifiers always render in `pub indexed scope` order regardless of their surface spelling.

- A block-body scope renders its body one level deeper than the declaration, reusing the function-block statement and expression formatting; the `return` and any chained method calls follow the existing expression style.
- An arrow-body scope renders `=> expression` on the declaration line.
- Each scope declaration sits at the master-body indent and is separated from neighbouring sections by exactly one blank line, the same as the other sections.

```mst
master Records {
  record { primary id: int, age: int, gender: int }

  scope adult() {
    return self.where(fn(row) => row.age.ge(20))
  }

  pub scope genderedAdult(gender: int) {
    return self.adult().gendered(gender)
  }

  indexed scope youngest() => self.orderBy(fn(row) => row.age.asc())
}
```

## Literals

Null and boolean literals are emitted as `null`, `true`, and `false`.

Integer literals preserve their parsed source spelling.

String literals are emitted from their decoded value using the supported escape sequences.
