Skip to content

Commit 5122df1

Browse files
committed
More agent context
1 parent 71bf670 commit 5122df1

File tree

1 file changed

+73
-6
lines changed

1 file changed

+73
-6
lines changed

AGENTS.md

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ Fantomas is an F# code formatter that transforms F# source code into a standardi
3535

3636
```bash
3737
# Most common commands for LLMs
38-
dotnet fsi build.fsx # Build and test
39-
dotnet fsi build.fsx -p FormatChanged # Format changes
38+
dotnet build # Quick build check (use during development)
4039
dotnet test --filter "test-name" # Run specific test
40+
dotnet fsi build.fsx -p FormatChanged # Format changes
41+
dotnet fsi build.fsx # Full build and test (use for final verification)
4142
dotnet fsi build.fsx -p FormatAll # Format all files
4243
```
4344

@@ -118,14 +119,17 @@ dotnet fsi build.fsx
118119
### 3. Testing
119120

120121
```bash
121-
# Run all tests
122-
dotnet fsi build.fsx
122+
# Quick build check during development
123+
dotnet build
123124

124125
# Run specific test
125126
dotnet test src/Fantomas.Core.Tests/ --filter "test-name"
126127

127128
# Format changed files
128129
dotnet fsi build.fsx -p FormatChanged
130+
131+
# Full build and test (use for final verification)
132+
dotnet fsi build.fsx
129133
```
130134

131135
### 4. Build Commands
@@ -171,6 +175,13 @@ dotnet fsi build.fsx -p EnsureRepoConfig
171175
- **WriterModel**: Track current state (column, indentation level)
172176
- **Config**: Formatting configuration options
173177

178+
#### Indentation System
179+
- **Indentation Events**: `IndentBy`, `UnIndentBy`, `SetIndent`, `RestoreIndent`
180+
- **Column Tracking**: `AtColumn` helps maintain alignment at specific positions
181+
- **Critical Rule**: Indentation only takes effect after `WriteLine`/`WriteLineBecauseOfTrivia` events
182+
- **Common Pattern**: `indent``sepNln` → content → `unindent`
183+
- **Helper Functions**: `indentSepNlnUnindent`, `atCurrentColumn`, `atCurrentColumnIndent`
184+
174185
#### Trivia System
175186
- **ContentBefore/ContentAfter**: Attach comments and directives to nodes
176187
- **Directive**: Conditional compilation directives (#if, #endif)
@@ -267,6 +278,62 @@ let ``descriptive test name, issue-number`` () =
267278
- Check WriterEvents to understand formatting decisions
268279
- Use MCP tools to test formatting in real-time
269280

281+
### Understanding Indentation
282+
283+
Indentation in Fantomas is **deferred** - it only takes effect after newline events:
284+
285+
```fsharp
286+
// This pattern is very common in CodePrinter:
287+
indent +> sepNln +> content +> unindent
288+
289+
// Or using the helper:
290+
indentSepNlnUnindent content
291+
```
292+
293+
**Key Points:**
294+
- `indent` adds an `IndentBy` event to the context
295+
- The actual indentation only applies when `WriteLine`/`WriteLineBecauseOfTrivia` events are processed
296+
- `WriterModel.update` in `Context.fs` handles this by setting `Indent = max m.Indent m.AtColumn` on newlines
297+
- Always pair `indent` with `unindent` to avoid indentation drift
298+
- Use `atCurrentColumn` and `atCurrentColumnIndent` for fixed column positioning
299+
300+
**Example from CodePrinterHelperFunctionsTests.fs:**
301+
```fsharp
302+
let g = !-"first line" +> indent +> sepNln +> !-"second line" +> unindent
303+
// Result: "first line\n second line"
304+
```
305+
306+
### Understanding genNode and Trivia Processing
307+
308+
The `genNode` function is crucial for understanding how indentation interacts with trivia:
309+
310+
```fsharp
311+
let genNode<'n when 'n :> Node> (n: 'n) (f: Context -> Context) =
312+
enterNode n +> recordCursorNode f n +> leaveNode n
313+
314+
let enterNode<'n when 'n :> Node> (n: 'n) =
315+
col sepNone n.ContentBefore (genTrivia n)
316+
```
317+
318+
**Critical Understanding:**
319+
- `genNode` processes `ContentBefore` trivia first, then runs the function, then `ContentAfter` trivia
320+
- `genTrivia` handles directives and comments, often emitting `sepNlnForTrivia` events
321+
- **Trivia processing can override indentation**: When `genTrivia` processes directives, it may emit newline events that apply indentation before your intended content
322+
- This is why `indentSepNlnUnindent` patterns can fail when nodes have trivia - the trivia emits newlines that consume the indentation
323+
324+
**Common Issue Pattern:**
325+
```fsharp
326+
// This fails when node has ContentBefore trivia:
327+
indentSepNlnUnindent (genIdentListNode node)
328+
// Because genIdentListNode calls genNode, which processes trivia first
329+
// The trivia emits newlines that apply indentation before the module name
330+
```
331+
332+
**Solution Approaches:**
333+
1. **Bypass genNode**: Write content directly without trivia processing
334+
2. **Handle trivia separately**: Process trivia before applying indentation
335+
3. **Use different indentation strategy**: Apply indentation at a different level in the tree
336+
270337
## MCP Tools
271338

272339
### Fantomas Format Code Tool
@@ -474,7 +541,7 @@ if not errors.IsEmpty then
474541
```bash
475542
# 1. Setup
476543
git checkout -b fix-3188
477-
dotnet fsi build.fsx
544+
dotnet build
478545

479546
# 2. Write test
480547
# Add test to ModuleTests.fs
@@ -484,7 +551,7 @@ dotnet fsi build.fsx
484551

485552
# 4. Test and verify
486553
dotnet test src/Fantomas.Core.Tests/ --filter "3188"
487-
dotnet fsi build.fsx
554+
dotnet build
488555

489556
# 5. Format changes
490557
dotnet fsi build.fsx -p FormatChanged

0 commit comments

Comments
 (0)