Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
370 changes: 370 additions & 0 deletions .claude/commands/update-fcs.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

## [Unreleased]

### Added

- Support for the record spread syntax introduced in F# preview, [RFC FS-1151](https://github.com/fsharp/fslang-design/pull/805). A spread can appear in a record expression, `{ ...source; Field = value }`, in an anonymous record expression, `{| ...source; Field = value |}`, and in the record representation of a type definition, `type Target = { ...Source; Field: int }`, in both implementation and signature files. [#3400](https://github.com/fsprojects/fantomas/pull/3400)
- Interpolated strings with a negative alignment, `$"{value,-10}"`, now format instead of failing with a parse error. Alignment and format specifiers keep their existing layout, so `$"{value,10:N2}"` is unaffected. [#3400](https://github.com/fsprojects/fantomas/pull/3400)

### Changed

- Breaking: warnings and errors are written to standard error instead of standard out. Informational output stays on standard out, including `--version` and the files `--check` reports as needing formatting, so a caller can tell the tool's output apart from its diagnostics by stream. Scripts that capture standard out to detect failures need to capture standard error as well. [#3399](https://github.com/fsprojects/fantomas/pull/3399)
- Update FCS to 'Parser: recover on missing when conditions', commit d05075e098278aedcea3379159504d664628a495 [#3400](https://github.com/fsprojects/fantomas/pull/3400)

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Some common use cases include:

<!-- Versions -->
<PropertyGroup>
<FCSCommitHash>ab1f6ceaaec997d2854ac1c07a6c0f107675d95c</FCSCommitHash>
<FCSCommitHash>d05075e098278aedcea3379159504d664628a495</FCSCommitHash>
</PropertyGroup>

<PropertyGroup>
Expand Down
4 changes: 4 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
<PackageVersion Include="System.Runtime" Version="4.3.1" />
<PackageVersion Include="FsLexYacc" Version="11.3.0" />

<!-- Hosts the vendored FSharpEmbedResourceText MSBuild task, see Fantomas.FCS.BuildTasks. -->
<PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" />
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.11.4" />

<PackageVersion Include="Ionide.KeepAChangelog.Tasks" Version="0.3.3"/>
<PackageVersion Include="DotNet.ReproducibleBuilds" Version="2.0.2"/>

Expand Down
15 changes: 13 additions & 2 deletions build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,9 @@ let updateFileRaw (file: FileInfo) =
let updatedLines =
lines
|> Array.map (fun line ->
if line.Contains("FSharp.Compiler") then
if line.StartsWith("namespace FSharp.Build") then
line.Replace("namespace FSharp.Build", "namespace Fantomas.FCS.Build")
elif line.Contains("FSharp.Compiler") then
line.Replace("FSharp.Compiler", "Fantomas.FCS")
elif line.Contains("[<TailCall>]") then
line.Replace("[<TailCall>]", "[<Microsoft.FSharp.Core.TailCall>]")
Expand Down Expand Up @@ -292,7 +294,12 @@ pipeline "Init" {
workingDir __SOURCE_DIRECTORY__
stage "Download FCS files" {
run (fun _ ->
[| "src/Compiler/FSComp.txt"
[|
// Not a compiler source. This is the MSBuild task that turns FSComp.txt into the SR
// module. Since dotnet/fsharp#20097 the generated diagnostic accessors return RichText
// instead of string, and the task shipped in the .NET SDK cannot generate those yet.
"src/FSharp.Build/FSharpEmbedResourceText.fs"
"src/Compiler/FSComp.txt"
"src/Compiler/FSStrings.resx"
"src/Compiler/Utilities/NullHelpers.fs"
"src/Compiler/Utilities/Activity.fsi"
Expand All @@ -303,6 +310,8 @@ pipeline "Init" {
"src/Compiler/Utilities/sformat.fs"
"src/Compiler/Utilities/sr.fsi"
"src/Compiler/Utilities/sr.fs"
"src/Compiler/Facilities/RichText.fsi"
"src/Compiler/Facilities/RichText.fs"
"src/Compiler/Utilities/ResizeArray.fsi"
"src/Compiler/Utilities/ResizeArray.fs"
"src/Compiler/Utilities/HashMultiMap.fsi"
Expand Down Expand Up @@ -359,6 +368,8 @@ pipeline "Init" {
"src/Compiler/pars.fsy"
"src/Compiler/SyntaxTree/UnicodeLexing.fsi"
"src/Compiler/SyntaxTree/UnicodeLexing.fs"
"src/Compiler/SyntaxTree/XmlDocIncludeExpander.fsi"
"src/Compiler/SyntaxTree/XmlDocIncludeExpander.fs"
"src/Compiler/SyntaxTree/XmlDoc.fsi"
"src/Compiler/SyntaxTree/XmlDoc.fs"
"src/Compiler/SyntaxTree/SyntaxTrivia.fsi"
Expand Down
50 changes: 50 additions & 0 deletions src/Fantomas.Core.Tests/AttributeTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,56 @@ open System.Runtime.InteropServices
do ()
"""

[<Test>]
let ``should preserve return attribute in front of a binding`` () =
formatSourceString
"""
[<return: Struct>]
let (|Foo|_|) x = ValueNone
"""
config
|> prepend newline
|> should
equal
"""
[<return: Struct>]
let (|Foo|_|) x = ValueNone
"""

[<Test>]
let ``should preserve return attribute next to another attribute in front of a binding`` () =
formatSourceString
"""
[<return: Struct; SomeOther>]
let (|Foo|_|) x = ValueNone
"""
config
|> prepend newline
|> should
equal
"""
[<return: Struct; SomeOther>]
let (|Foo|_|) x = ValueNone
"""

[<Test>]
let ``should preserve return attribute in its own attribute list in front of a binding`` () =
formatSourceString
"""
[<Obsolete("x")>]
[<return: Struct>]
let (|Foo|_|) x = ValueNone
"""
config
|> prepend newline
|> should
equal
"""
[<Obsolete("x")>]
[<return: Struct>]
let (|Foo|_|) x = ValueNone
"""

[<Test>]
let ``should preserve single return type attribute`` () =
formatSourceString """let f x : [<return: Attribute>] int = x""" config
Expand Down
22 changes: 22 additions & 0 deletions src/Fantomas.Core.Tests/ControlStructureTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,28 @@ if age < 10 then
printfn "You are only %d years old and already learning F#? Wow!" age
"""

[<Test>]
let ``wildcard identifier in for loop`` () =
formatSourceString
"""
for _ = 1 to 10 do
printfn "hi"

for _ = 10 downto 1 do
()
"""
config
|> prepend newline
|> should
equal
"""
for _ = 1 to 10 do
printfn "hi"

for _ = 10 downto 1 do
()
"""

[<Test>]
let ``for loops`` () =
formatSourceString
Expand Down
1 change: 1 addition & 0 deletions src/Fantomas.Core.Tests/Fantomas.Core.Tests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<Compile Include="HashDirectiveTests.fs" />
<Compile Include="NumberOfItemsListOrArrayTests.fs" />
<Compile Include="NumberOfItemsRecordTests.fs" />
<Compile Include="RecordSpreadTests.fs" />
<Compile Include="SynExprNewTests.fs" />
<Compile Include="CastTests.fs" />
<Compile Include="MultiLineLambdaClosingNewlineTests.fs" />
Expand Down
60 changes: 60 additions & 0 deletions src/Fantomas.Core.Tests/InterpolatedStringTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,66 @@ $\"\"\"one: {1}<
>two: {2}\"\"\"
"

// The parser reports the alignment of `{x,10}` separately from the expression since
// dotnet/fsharp#19971. Fantomas has always printed a space after the comma, because the alignment
// used to arrive as part of a tuple expression. These pin that existing output.
[<Test>]
let ``alignment in string interpolation`` () =
formatSourceString
"""
let s = $"value {x,10}"
"""
config
|> prepend newline
|> should
equal
"""
let s = $"value {x, 10}"
"""

[<Test>]
let ``negative alignment in string interpolation`` () =
formatSourceString
"""
let s = $"value {x,-10}"
"""
config
|> prepend newline
|> should
equal
"""
let s = $"value {x, -10}"
"""

[<Test>]
let ``alignment and format in string interpolation`` () =
formatSourceString
"""
let s = $"{x,10:N2} then {y}"
"""
config
|> prepend newline
|> should
equal
"""
let s = $"{x, 10:N2} then {y}"
"""

[<Test>]
let ``alignment in string interpolation from AST`` () =
formatAST
false
"""
$"{x,10:N2} then {y}"
"""
config
|> prepend newline
|> should
equal
"""
$"{x, 10:N2} then {y}"
"""

[<Test>]
let ``format in FillExpr, 1549`` () =
formatSourceString
Expand Down
Loading
Loading