From 0caefea8bbb187586387a9e544c89de83f62a468 Mon Sep 17 00:00:00 2001
From: Martin521 <29605222+Martin521@users.noreply.github.com>
Date: Tue, 3 Jun 2025 16:18:53 +0000
Subject: [PATCH 01/11] adaptations for sdk 9.0 and 10.0
---
Directory.Build.props | 2 +-
Directory.Packages.props | 2 +-
build.fsx | 4 +
global.json | 2 +-
src/Fantomas.Benchmarks/packages.lock.json | 10 +-
src/Fantomas.Client.Tests/packages.lock.json | 8 +-
src/Fantomas.Client/packages.lock.json | 6 +-
.../ASTTransformerTests.fs | 4 +-
.../AutoPropertiesTests.fs | 2 +-
src/Fantomas.Core.Tests/CommentTests.fs | 5 +
src/Fantomas.Core.Tests/HashDirectiveTests.fs | 3 +-
src/Fantomas.Core.Tests/SynLongIdentTests.fs | 4 +-
src/Fantomas.Core.Tests/packages.lock.json | 10 +-
src/Fantomas.Core/ASTTransformer.fs | 47 +++---
src/Fantomas.Core/Trivia.fs | 43 +++---
src/Fantomas.Core/packages.lock.json | 8 +-
src/Fantomas.FCS/Fantomas.FCS.fsproj | 16 +-
src/Fantomas.FCS/Parse.fs | 137 +++++-------------
src/Fantomas.FCS/packages.lock.json | 6 +-
src/Fantomas.Tests/packages.lock.json | 14 +-
src/Fantomas/packages.lock.json | 12 +-
21 files changed, 154 insertions(+), 191 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 26e34508ab..1d03c11ff1 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -45,7 +45,7 @@ Some common use cases include:
- e668b90e3c087e5fba8a855e502af60bf35be45e
+ 20ff6a94300b5f2f5498d3d8ad1a44abaabc5c22
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 084fea47dc..878be9ff50 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -4,7 +4,7 @@
true
-
+
diff --git a/build.fsx b/build.fsx
index 63c8458d3a..6c4a2f0e08 100644
--- a/build.fsx
+++ b/build.fsx
@@ -301,6 +301,10 @@ pipeline "Init" {
"src/Compiler/SyntaxTree/SyntaxTree.fs"
"src/Compiler/SyntaxTree/SyntaxTreeOps.fsi"
"src/Compiler/SyntaxTree/SyntaxTreeOps.fs"
+ "src/Compiler/SyntaxTree/WarnScopes.fsi"
+ "src/Compiler/SyntaxTree/WarnScopes.fs"
+ "src/Compiler/SyntaxTree/LexerStore.fsi"
+ "src/Compiler/SyntaxTree/LexerStore.fs"
"src/Compiler/SyntaxTree/ParseHelpers.fsi"
"src/Compiler/SyntaxTree/ParseHelpers.fs"
"src/Compiler/SyntaxTree/LexHelpers.fsi"
diff --git a/global.json b/global.json
index 6f6aff9de6..d3dbe09378 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "8.0.400",
+ "version": "9.0.300",
"rollForward": "latestPatch"
}
}
\ No newline at end of file
diff --git a/src/Fantomas.Benchmarks/packages.lock.json b/src/Fantomas.Benchmarks/packages.lock.json
index cc618a9806..664a872c78 100644
--- a/src/Fantomas.Benchmarks/packages.lock.json
+++ b/src/Fantomas.Benchmarks/packages.lock.json
@@ -28,9 +28,9 @@
},
"FSharp.Core": {
"type": "Direct",
- "requested": "[8.0.100, )",
- "resolved": "8.0.100",
- "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg=="
+ "requested": "[9.0.300, )",
+ "resolved": "9.0.300",
+ "contentHash": "TVt2J7RCE1KCS2IaONF+p8/KIZ1eHNbW+7qmKF6hGoD4tXl+o07ja1mPtFjMqRa5uHMFaTrGTPn/m945WnDLiQ=="
},
"G-Research.FSharp.Analyzers": {
"type": "Direct",
@@ -272,14 +272,14 @@
"fantomas.core": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[8.0.100, )",
+ "FSharp.Core": "[9.0.300, )",
"Fantomas.FCS": "[1.0.0, )"
}
},
"fantomas.fcs": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[8.0.100, )",
+ "FSharp.Core": "[9.0.300, )",
"System.Collections.Immutable": "[8.0.0, )",
"System.Diagnostics.DiagnosticSource": "[8.0.1, )",
"System.Memory": "[4.6.0, )",
diff --git a/src/Fantomas.Client.Tests/packages.lock.json b/src/Fantomas.Client.Tests/packages.lock.json
index 6bbec117ff..54e3169b0b 100644
--- a/src/Fantomas.Client.Tests/packages.lock.json
+++ b/src/Fantomas.Client.Tests/packages.lock.json
@@ -16,9 +16,9 @@
},
"FSharp.Core": {
"type": "Direct",
- "requested": "[8.0.100, )",
- "resolved": "8.0.100",
- "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg=="
+ "requested": "[9.0.300, )",
+ "resolved": "9.0.300",
+ "contentHash": "TVt2J7RCE1KCS2IaONF+p8/KIZ1eHNbW+7qmKF6hGoD4tXl+o07ja1mPtFjMqRa5uHMFaTrGTPn/m945WnDLiQ=="
},
"G-Research.FSharp.Analyzers": {
"type": "Direct",
@@ -137,7 +137,7 @@
"fantomas.client": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[8.0.100, )",
+ "FSharp.Core": "[9.0.300, )",
"SemanticVersioning": "[2.0.2, )",
"StreamJsonRpc": "[2.20.20, )"
}
diff --git a/src/Fantomas.Client/packages.lock.json b/src/Fantomas.Client/packages.lock.json
index 65f0ab5696..c1c97d0b32 100644
--- a/src/Fantomas.Client/packages.lock.json
+++ b/src/Fantomas.Client/packages.lock.json
@@ -22,9 +22,9 @@
},
"FSharp.Core": {
"type": "Direct",
- "requested": "[8.0.100, )",
- "resolved": "8.0.100",
- "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg=="
+ "requested": "[9.0.300, )",
+ "resolved": "9.0.300",
+ "contentHash": "TVt2J7RCE1KCS2IaONF+p8/KIZ1eHNbW+7qmKF6hGoD4tXl+o07ja1mPtFjMqRa5uHMFaTrGTPn/m945WnDLiQ=="
},
"G-Research.FSharp.Analyzers": {
"type": "Direct",
diff --git a/src/Fantomas.Core.Tests/ASTTransformerTests.fs b/src/Fantomas.Core.Tests/ASTTransformerTests.fs
index 498f9c86c5..41a5b7c9e0 100644
--- a/src/Fantomas.Core.Tests/ASTTransformerTests.fs
+++ b/src/Fantomas.Core.Tests/ASTTransformerTests.fs
@@ -40,7 +40,6 @@ let ``avoid stack-overflow in long array/list, 2485`` () =
true,
QualifiedNameOfFile(Ident("", Range.Zero)),
[],
- [],
[ SynModuleOrNamespace(
[],
false,
@@ -53,8 +52,7 @@ let ``avoid stack-overflow in long array/list, 2485`` () =
{ LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.None }
) ],
(false, false),
- { ConditionalDirectives = []
- CodeComments = [] },
+ ParsedInputTrivia.Empty,
Set.empty
)
)
diff --git a/src/Fantomas.Core.Tests/AutoPropertiesTests.fs b/src/Fantomas.Core.Tests/AutoPropertiesTests.fs
index ab6a962df9..8600920912 100644
--- a/src/Fantomas.Core.Tests/AutoPropertiesTests.fs
+++ b/src/Fantomas.Core.Tests/AutoPropertiesTests.fs
@@ -74,7 +74,7 @@ type X =
member internal Y: int with public get, private set
"""
-[]
+[]
let ``abstract member with public get, private set`` () =
formatSignatureString
"""
diff --git a/src/Fantomas.Core.Tests/CommentTests.fs b/src/Fantomas.Core.Tests/CommentTests.fs
index e3285e3e3c..228d01bb09 100644
--- a/src/Fantomas.Core.Tests/CommentTests.fs
+++ b/src/Fantomas.Core.Tests/CommentTests.fs
@@ -5,6 +5,11 @@ open FsUnit
open Fantomas.Core.Tests.TestHelpers
open Fantomas.Core
+[]
+let ``should keep sticky-to-the-left comments after #if directivesXXX`` () =
+ formatSourceString "#if DEBUG // debug only\n#endif\n" config
+ |> should equal "#if DEBUG // debug only\n#endif\n"
+
[]
let ``should keep sticky-to-the-left comments after nowarn directives`` () =
formatSourceString """#nowarn "51" // address-of operator can occur in the code""" config
diff --git a/src/Fantomas.Core.Tests/HashDirectiveTests.fs b/src/Fantomas.Core.Tests/HashDirectiveTests.fs
index 233b10aee6..0edfeb5d08 100644
--- a/src/Fantomas.Core.Tests/HashDirectiveTests.fs
+++ b/src/Fantomas.Core.Tests/HashDirectiveTests.fs
@@ -248,6 +248,7 @@ let ``#help without string`` () =
#help List.map
"""
+// As of F# 10.0, warn directives are treated as trivia like #if, so argruments are not formatted
[]
let ``#nowarn with integer`` () =
formatSourceString
@@ -259,5 +260,5 @@ let ``#nowarn with integer`` () =
|> should
equal
"""
-#nowarn 1182
+#nowarn 1182
"""
diff --git a/src/Fantomas.Core.Tests/SynLongIdentTests.fs b/src/Fantomas.Core.Tests/SynLongIdentTests.fs
index eed7c2d0e5..c10079c6c1 100644
--- a/src/Fantomas.Core.Tests/SynLongIdentTests.fs
+++ b/src/Fantomas.Core.Tests/SynLongIdentTests.fs
@@ -352,7 +352,6 @@ let ``backticks can be added from AST only scenarios`` () =
true,
QualifiedNameOfFile testIdent,
[],
- [],
[ SynModuleOrNamespace(
[ testIdent ],
false,
@@ -377,8 +376,7 @@ let ``backticks can be added from AST only scenarios`` () =
{ LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.None }
) ],
(true, false),
- { ConditionalDirectives = []
- CodeComments = [] },
+ ParsedInputTrivia.Empty,
Set.empty
)
)
diff --git a/src/Fantomas.Core.Tests/packages.lock.json b/src/Fantomas.Core.Tests/packages.lock.json
index 50a2903a96..87f141e46c 100644
--- a/src/Fantomas.Core.Tests/packages.lock.json
+++ b/src/Fantomas.Core.Tests/packages.lock.json
@@ -19,9 +19,9 @@
},
"FSharp.Core": {
"type": "Direct",
- "requested": "[8.0.100, )",
- "resolved": "8.0.100",
- "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg=="
+ "requested": "[9.0.300, )",
+ "resolved": "9.0.300",
+ "contentHash": "TVt2J7RCE1KCS2IaONF+p8/KIZ1eHNbW+7qmKF6hGoD4tXl+o07ja1mPtFjMqRa5uHMFaTrGTPn/m945WnDLiQ=="
},
"FsUnit": {
"type": "Direct",
@@ -138,14 +138,14 @@
"fantomas.core": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[8.0.100, )",
+ "FSharp.Core": "[9.0.300, )",
"Fantomas.FCS": "[1.0.0, )"
}
},
"fantomas.fcs": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[8.0.100, )",
+ "FSharp.Core": "[9.0.300, )",
"System.Collections.Immutable": "[8.0.0, )",
"System.Diagnostics.DiagnosticSource": "[8.0.1, )",
"System.Memory": "[4.6.0, )",
diff --git a/src/Fantomas.Core/ASTTransformer.fs b/src/Fantomas.Core/ASTTransformer.fs
index 58450725c3..292d3b7984 100644
--- a/src/Fantomas.Core/ASTTransformer.fs
+++ b/src/Fantomas.Core/ASTTransformer.fs
@@ -966,22 +966,22 @@ let mkExpr (creationAide: CreationAide) (e: SynExpr) : Expr =
| SynExpr.AddressOf(false, e, _, StartRange 2 (ampersandToken, _range)) ->
ExprSingleNode(stn "&&" ampersandToken, false, false, mkExpr creationAide e, exprRange)
|> Expr.Single
- | SynExpr.YieldOrReturn((true, _), e, StartRange 5 (yieldKeyword, _range)) ->
+ | SynExpr.YieldOrReturn((true, _), e, StartRange 5 (yieldKeyword, _range), _) ->
ExprSingleNode(stn "yield" yieldKeyword, true, true, mkExpr creationAide e, exprRange)
|> Expr.Single
- | SynExpr.YieldOrReturn((false, _), e, StartRange 6 (returnKeyword, _range)) ->
+ | SynExpr.YieldOrReturn((false, _), e, StartRange 6 (returnKeyword, _range), _) ->
ExprSingleNode(stn "return" returnKeyword, true, true, mkExpr creationAide e, exprRange)
|> Expr.Single
- | SynExpr.YieldOrReturnFrom((true, _), e, StartRange 6 (yieldBangKeyword, _range)) ->
+ | SynExpr.YieldOrReturnFrom((true, _), e, StartRange 6 (yieldBangKeyword, _range), _) ->
ExprSingleNode(stn "yield!" yieldBangKeyword, true, true, mkExpr creationAide e, exprRange)
|> Expr.Single
- | SynExpr.YieldOrReturnFrom((false, _), e, StartRange 7 (returnBangKeyword, _range)) ->
+ | SynExpr.YieldOrReturnFrom((false, _), e, StartRange 7 (returnBangKeyword, _range), _) ->
ExprSingleNode(stn "return!" returnBangKeyword, true, true, mkExpr creationAide e, exprRange)
|> Expr.Single
| SynExpr.Do(e, StartRange 2 (doKeyword, _range)) ->
ExprSingleNode(stn "do" doKeyword, true, true, mkExpr creationAide e, exprRange)
|> Expr.Single
- | SynExpr.DoBang(e, StartRange 3 (doBangKeyword, _range)) ->
+ | SynExpr.DoBang(e, StartRange 3 (doBangKeyword, _range), _) ->
ExprSingleNode(stn "do!" doBangKeyword, true, true, mkExpr creationAide e, exprRange)
|> Expr.Single
| SynExpr.Fixed(e, StartRange 5 (fixedKeyword, _range)) ->
@@ -1029,9 +1029,7 @@ let mkExpr (creationAide: CreationAide) (e: SynExpr) : Expr =
let fieldNodes =
recordFields
|> List.choose (function
- | SynExprRecordField((fieldName, _), Some mEq, Some expr, _) ->
- let m = unionRanges fieldName.Range expr.Range
-
+ | SynExprRecordField((fieldName, _), Some mEq, Some expr, m, _) ->
Some(
RecordFieldNode(mkSynLongIdent creationAide fieldName, stn "=" mEq, mkExpr creationAide expr, m)
)
@@ -1144,7 +1142,7 @@ let mkExpr (creationAide: CreationAide) (e: SynExpr) : Expr =
_,
pat,
e1,
- SynExpr.YieldOrReturn((true, _), e2, _),
+ SynExpr.YieldOrReturn((true, _), e2, _, _),
StartRange 3 (mFor, _)) ->
ExprForEachNode(
stn "for" mFor,
@@ -2809,7 +2807,7 @@ let mkMemberDefn (creationAide: CreationAide) (md: SynMemberDefn) =
let memberDefinitionRange = md.Range
match md with
- | SynMemberDefn.ImplicitInherit(t, e, _, StartRange 7 (mInherit, _)) ->
+ | SynMemberDefn.ImplicitInherit(t, e, _, StartRange 7 (mInherit, _), _) ->
mkInheritConstructor creationAide t e mInherit memberDefinitionRange
|> MemberDefn.ImplicitInherit
@@ -2870,9 +2868,12 @@ let mkMemberDefn (creationAide: CreationAide) (md: SynMemberDefn) =
)
|> MemberDefn.ExplicitCtor
| SynMemberDefn.Member(memberDefn, _) -> mkBinding creationAide memberDefn |> MemberDefn.Member
- | SynMemberDefn.Inherit(baseType, _, StartRange 7 (mInherit, _)) ->
- MemberDefnInheritNode(stn "inherit" mInherit, mkType creationAide baseType, memberDefinitionRange)
- |> MemberDefn.Inherit
+ | SynMemberDefn.Inherit(baseTypeOpt, _, StartRange 7 (mInherit, _), _) ->
+ match baseTypeOpt with
+ | Some baseType ->
+ MemberDefnInheritNode(stn "inherit" mInherit, mkType creationAide baseType, memberDefinitionRange)
+ |> MemberDefn.Inherit
+ | None -> failwith "successful parse shouldn't have any unfinished inherit"
| SynMemberDefn.ValField(f, _) -> mkSynField creationAide f |> MemberDefn.ValField
| SynMemberDefn.LetBindings(
bindings = [ SynBinding(trivia = { LeadingKeyword = SynLeadingKeyword.Extern _ }) as binding ]) ->
@@ -3598,25 +3599,27 @@ let mkSigFile
let mds = List.map (mkModuleOrNamespaceSig creationAide) contents
Oak(phds, mds, m)
-let includeTrivia
- (baseRange: range)
- (comments: CommentTrivia list)
- (conditionDirectives: ConditionalDirectiveTrivia list)
- : range =
+let includeTrivia (baseRange: range) (trivia: ParsedInputTrivia) : range =
let ranges =
[ yield!
List.map
(function
| CommentTrivia.LineComment m
| CommentTrivia.BlockComment m -> m)
- comments
+ trivia.CodeComments
yield!
List.map
(function
| ConditionalDirectiveTrivia.If(range = range)
| ConditionalDirectiveTrivia.Else(range = range)
| ConditionalDirectiveTrivia.EndIf(range = range) -> range)
- conditionDirectives ]
+ trivia.ConditionalDirectives
+ yield!
+ List.map
+ (function
+ | WarnDirectiveTrivia.Nowarn range
+ | WarnDirectiveTrivia.Warnon range -> range)
+ trivia.WarnDirectives ]
(baseRange, ranges)
||> List.fold (fun acc triviaRange ->
@@ -3668,7 +3671,7 @@ let mkFullTreeRange ast =
| Some lastModule -> mkSynModuleOrNamespaceFullRange lastModule
let astRange = unionRanges startPos endPos
- includeTrivia astRange trivia.CodeComments trivia.ConditionalDirectives
+ includeTrivia astRange trivia
| ParsedInput.SigFile(ParsedSigFileInput(hashDirectives = directives; contents = modules; trivia = trivia)) ->
let startPos =
@@ -3688,7 +3691,7 @@ let mkFullTreeRange ast =
| Some lastModule -> mkSynModuleOrNamespaceSigFullRange lastModule
let astRange = unionRanges startPos endPos
- includeTrivia astRange trivia.CodeComments trivia.ConditionalDirectives
+ includeTrivia astRange trivia
let mkOak (sourceText: ISourceText option) (ast: ParsedInput) =
let creationAide = { SourceText = sourceText }
diff --git a/src/Fantomas.Core/Trivia.fs b/src/Fantomas.Core/Trivia.fs
index 2c963cb350..4d243ee753 100644
--- a/src/Fantomas.Core/Trivia.fs
+++ b/src/Fantomas.Core/Trivia.fs
@@ -136,15 +136,21 @@ type ConditionalDirectiveTrivia with
| ConditionalDirectiveTrivia.Else m
| ConditionalDirectiveTrivia.EndIf m -> m
-let internal collectTriviaFromDirectives
+type WarnDirectiveTrivia with
+
+ member x.Range =
+ match x with
+ | WarnDirectiveTrivia.Nowarn m
+ | WarnDirectiveTrivia.Warnon m -> m
+
+let internal collectTriviaFromDirectiveRanges
(source: ISourceText)
- (directives: ConditionalDirectiveTrivia list)
+ (directiveRanges: range list)
(codeRange: range)
: TriviaNode list =
- directives
- |> List.filter (fun cdt -> RangeHelpers.rangeContainsRange codeRange cdt.Range)
- |> List.map (fun cdt ->
- let m = cdt.Range
+ directiveRanges
+ |> List.filter (RangeHelpers.rangeContainsRange codeRange)
+ |> List.map (fun m ->
let text = (source.GetSubTextFromRange m).TrimEnd()
let content = Directive text
TriviaNode(content, m))
@@ -315,27 +321,24 @@ let addToTree (tree: Oak) (trivia: TriviaNode seq) =
let enrichTree (config: FormatConfig) (sourceText: ISourceText) (ast: ParsedInput) (tree: Oak) : Oak =
let fullTreeRange = tree.Range
- let directives, codeComments =
+ let parsedTrivia =
match ast with
- | ParsedInput.ImplFile(ParsedImplFileInput(
- trivia = { ConditionalDirectives = directives
- CodeComments = codeComments })) -> directives, codeComments
- | ParsedInput.SigFile(ParsedSigFileInput(
- trivia = { ConditionalDirectives = directives
- CodeComments = codeComments })) -> directives, codeComments
+ | ParsedInput.ImplFile(ParsedImplFileInput(trivia = t))
+ | ParsedInput.SigFile(ParsedSigFileInput(trivia = t)) -> t
let trivia =
let newlines =
- collectTriviaFromBlankLines config sourceText tree codeComments fullTreeRange
+ collectTriviaFromBlankLines config sourceText tree parsedTrivia.CodeComments fullTreeRange
let comments =
- match ast with
- | ParsedInput.ImplFile(ParsedImplFileInput(trivia = trivia)) ->
- collectTriviaFromCodeComments sourceText trivia.CodeComments fullTreeRange
- | ParsedInput.SigFile(ParsedSigFileInput(trivia = trivia)) ->
- collectTriviaFromCodeComments sourceText trivia.CodeComments fullTreeRange
+ collectTriviaFromCodeComments sourceText parsedTrivia.CodeComments fullTreeRange
+
+ let directiveRanges =
+ (parsedTrivia.ConditionalDirectives |> List.map _.Range)
+ @ (parsedTrivia.WarnDirectives |> List.map _.Range)
- let directives = collectTriviaFromDirectives sourceText directives fullTreeRange
+ let directives =
+ collectTriviaFromDirectiveRanges sourceText directiveRanges fullTreeRange
[| yield! comments; yield! newlines; yield! directives |]
|> Array.sortBy (fun n -> n.Range.Start.Line, n.Range.Start.Column)
diff --git a/src/Fantomas.Core/packages.lock.json b/src/Fantomas.Core/packages.lock.json
index 423ac63843..b816c9716a 100644
--- a/src/Fantomas.Core/packages.lock.json
+++ b/src/Fantomas.Core/packages.lock.json
@@ -22,9 +22,9 @@
},
"FSharp.Core": {
"type": "Direct",
- "requested": "[8.0.100, )",
- "resolved": "8.0.100",
- "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg=="
+ "requested": "[9.0.300, )",
+ "resolved": "9.0.300",
+ "contentHash": "TVt2J7RCE1KCS2IaONF+p8/KIZ1eHNbW+7qmKF6hGoD4tXl+o07ja1mPtFjMqRa5uHMFaTrGTPn/m945WnDLiQ=="
},
"G-Research.FSharp.Analyzers": {
"type": "Direct",
@@ -127,7 +127,7 @@
"fantomas.fcs": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[8.0.100, )",
+ "FSharp.Core": "[9.0.300, )",
"System.Collections.Immutable": "[8.0.0, )",
"System.Diagnostics.DiagnosticSource": "[8.0.1, )",
"System.Memory": "[4.6.0, )",
diff --git a/src/Fantomas.FCS/Fantomas.FCS.fsproj b/src/Fantomas.FCS/Fantomas.FCS.fsproj
index dc2b8f3d4a..26de30e34b 100644
--- a/src/Fantomas.FCS/Fantomas.FCS.fsproj
+++ b/src/Fantomas.FCS/Fantomas.FCS.fsproj
@@ -220,11 +220,11 @@
SyntaxTree\pplex.fsl
- --module Fantomas.FCS.PPParser --open Fantomas.FCS --open Fantomas.FCS.Syntax --open Fantomas.FCS.ParseHelpers --internal --lexlib Internal.Utilities.Text.Lexing --parslib Internal.Utilities.Text.Parsing --buffer-type-argument char
+ --module Fantomas.FCS.PPParser --open Fantomas.FCS --open Fantomas.FCS.Syntax --open Fantomas.FCS.ParseHelpers --open Fantomas.FCS.LexerStore --internal --lexlib Internal.Utilities.Text.Lexing --parslib Internal.Utilities.Text.Parsing --buffer-type-argument char
SyntaxTree\pppars.fsy
- --module Fantomas.FCS.Lexer --open Fantomas.FCS.Lexhelp --open Internal.Utilities.Text.Lexing --open Fantomas.FCS.Parser --open Fantomas.FCS.Text --open Fantomas.FCS.ParseHelpers --internal --unicode --lexlib Internal.Utilities.Text.Lexing
+ --module Fantomas.FCS.Lexer --open Fantomas.FCS.Lexhelp --open Internal.Utilities.Text.Lexing --open Fantomas.FCS.Parser --open Fantomas.FCS.Text --open Fantomas.FCS.ParseHelpers --open Fantomas.FCS.LexerStore --internal --unicode --lexlib Internal.Utilities.Text.Lexing
SyntaxTree\lex.fsl
@@ -273,6 +273,18 @@
SyntaxTree\SyntaxTreeOps.fs
+
+ SyntaxTree\WarnScopes.fsi
+
+
+ SyntaxTree\WarnScopes.fs
+
+
+ SyntaxTree\LexerStore.fsi
+
+
+ SyntaxTree\LexerStore.fs
+
SyntaxTree\ParseHelpers.fsi
diff --git a/src/Fantomas.FCS/Parse.fs b/src/Fantomas.FCS/Parse.fs
index e95dcea013..f12385f1ae 100644
--- a/src/Fantomas.FCS/Parse.fs
+++ b/src/Fantomas.FCS/Parse.fs
@@ -11,6 +11,7 @@ open Fantomas.FCS
open Fantomas.FCS.AbstractIL.IL
open Fantomas.FCS.DiagnosticsLogger
open Fantomas.FCS.Features
+open Fantomas.FCS.LexerStore
open Fantomas.FCS.Lexhelp
open Fantomas.FCS.Text
open Fantomas.FCS.Text.Position
@@ -153,27 +154,16 @@ let QualFileNameOfImpls filename specs =
| [ SynModuleOrNamespace(kind = kind; range = m) ] when not kind.IsModule -> QualFileNameOfFilename m filename
| _ -> QualFileNameOfFilename (mkRange filename pos0 pos0) filename
-let GetScopedPragmasForInput input =
- match input with
- | ParsedInput.SigFile(ParsedSigFileInput(scopedPragmas = pragmas)) -> pragmas
- | ParsedInput.ImplFile(ParsedImplFileInput(scopedPragmas = pragmas)) -> pragmas
+let collectCodeComments (lexbuf: UnicodeLexing.Lexbuf) =
+ let tripleSlashComments = XmlDocStore.ReportInvalidXmlDocPositions lexbuf
-let collectCodeComments (lexbuf: UnicodeLexing.Lexbuf) (tripleSlashComments: range list) =
- [ yield! LexbufCommentStore.GetComments(lexbuf)
- yield! (List.map CommentTrivia.LineComment tripleSlashComments) ]
+ [ yield! CommentStore.GetComments(lexbuf)
+ yield! List.map CommentTrivia.LineComment tripleSlashComments ]
|> List.sortBy (function
| CommentTrivia.LineComment r
| CommentTrivia.BlockComment r -> r.StartLine, r.StartColumn)
-let PostParseModuleImpls
- (
- defaultNamespace,
- filename,
- isLastCompiland,
- ParsedImplFile(hashDirectives, impls),
- lexbuf: UnicodeLexing.Lexbuf,
- tripleSlashComments: range list
- ) =
+let PostParseModuleImpls (defaultNamespace, filename, isLastCompiland, ParsedImplFile(hashDirectives, impls), lexbuf) =
match
impls
|> List.rev
@@ -191,23 +181,13 @@ let PostParseModuleImpls
let qualName = QualFileNameOfImpls filename impls
let isScript = IsScript filename
- let scopedPragmas = []
- let conditionalDirectives = LexbufIfdefStore.GetTrivia(lexbuf)
- let codeComments = collectCodeComments lexbuf tripleSlashComments
+ let trivia =
+ { ConditionalDirectives = IfdefStore.GetTrivia(lexbuf)
+ WarnDirectives = WarnScopes.getDirectiveTrivia (lexbuf)
+ CodeComments = collectCodeComments lexbuf }
ParsedInput.ImplFile(
- ParsedImplFileInput(
- filename,
- isScript,
- qualName,
- scopedPragmas,
- hashDirectives,
- impls,
- isLastCompiland,
- { ConditionalDirectives = conditionalDirectives
- CodeComments = codeComments },
- Set.empty
- )
+ ParsedImplFileInput(filename, isScript, qualName, hashDirectives, impls, isLastCompiland, trivia, Set.empty)
)
let PostParseModuleSpec (_i, defaultNamespace, _isLastCompiland, filename, intf) =
@@ -273,14 +253,8 @@ let PostParseModuleSpec (_i, defaultNamespace, _isLastCompiland, filename, intf)
SynModuleOrNamespaceSig(lid, isRecursive, kind, decls, xmlDoc, attributes, None, range, trivia)
let PostParseModuleSpecs
- (
- defaultNamespace,
- filename,
- isLastCompiland,
- ParsedSigFile(hashDirectives, specs),
- lexbuf: UnicodeLexing.Lexbuf,
- tripleSlashComments: range list
- ) =
+ (defaultNamespace, filename, isLastCompiland, ParsedSigFile(hashDirectives, specs), lexbuf: UnicodeLexing.Lexbuf)
+ =
match
specs
|> List.rev
@@ -296,23 +270,13 @@ let PostParseModuleSpecs
|> List.mapi (fun i x -> PostParseModuleSpec(i, defaultNamespace, isLastCompiland, filename, x))
let qualName = QualFileNameOfSpecs filename specs
- let scopedPragmas = []
-
- let conditionalDirectives = LexbufIfdefStore.GetTrivia(lexbuf)
- let codeComments = collectCodeComments lexbuf tripleSlashComments
-
- ParsedInput.SigFile(
- ParsedSigFileInput(
- filename,
- qualName,
- scopedPragmas,
- hashDirectives,
- specs,
- { ConditionalDirectives = conditionalDirectives
- CodeComments = codeComments },
- Set.empty
- )
- )
+
+ let trivia =
+ { ConditionalDirectives = IfdefStore.GetTrivia(lexbuf)
+ WarnDirectives = WarnScopes.getDirectiveTrivia (lexbuf)
+ CodeComments = collectCodeComments lexbuf }
+
+ ParsedInput.SigFile(ParsedSigFileInput(filename, qualName, hashDirectives, specs, trivia, Set.empty))
let ParseInput
(
@@ -337,38 +301,24 @@ let ParseInput
use _ = UseDiagnosticsLogger delayLogger
use _ = UseBuildPhase BuildPhase.Parse
- let mutable scopedPragmas = []
-
try
- let input =
- if mlCompatSuffixes |> List.exists (FileSystemUtils.checkSuffix lower) then
- if lexbuf.SupportsFeature LanguageFeature.MLCompatRevisions then
- errorR (Error(FSComp.SR.buildInvalidSourceFileExtensionML filename, rangeStartup))
- else
- mlCompatWarning (FSComp.SR.buildCompilingExtensionIsForML ()) rangeStartup
-
- // Call the appropriate parser - for signature files or implementation files
- if FSharpImplFileSuffixes |> List.exists (FileSystemUtils.checkSuffix lower) then
- let impl = Parser.implementationFile lexer lexbuf
-
- let tripleSlashComments =
- LexbufLocalXmlDocStore.ReportInvalidXmlDocPositions(lexbuf)
-
- PostParseModuleImpls(defaultNamespace, filename, isLastCompiland, impl, lexbuf, tripleSlashComments)
- elif FSharpSigFileSuffixes |> List.exists (FileSystemUtils.checkSuffix lower) then
- let intfs = Parser.signatureFile lexer lexbuf
-
- let tripleSlashComments =
- LexbufLocalXmlDocStore.ReportInvalidXmlDocPositions(lexbuf)
-
- PostParseModuleSpecs(defaultNamespace, filename, isLastCompiland, intfs, lexbuf, tripleSlashComments)
- else if lexbuf.SupportsFeature LanguageFeature.MLCompatRevisions then
- error (Error(FSComp.SR.buildInvalidSourceFileExtensionUpdated filename, rangeStartup))
+ if mlCompatSuffixes |> List.exists (FileSystemUtils.checkSuffix lower) then
+ if lexbuf.SupportsFeature LanguageFeature.MLCompatRevisions then
+ errorR (Error(FSComp.SR.buildInvalidSourceFileExtensionML filename, rangeStartup))
else
- error (Error(FSComp.SR.buildInvalidSourceFileExtension filename, rangeStartup))
-
- scopedPragmas <- GetScopedPragmasForInput input
- input
+ mlCompatWarning (FSComp.SR.buildCompilingExtensionIsForML ()) rangeStartup
+
+ // Call the appropriate parser - for signature files or implementation files
+ if FSharpImplFileSuffixes |> List.exists (FileSystemUtils.checkSuffix lower) then
+ let impl = Parser.implementationFile lexer lexbuf
+ PostParseModuleImpls(defaultNamespace, filename, isLastCompiland, impl, lexbuf)
+ elif FSharpSigFileSuffixes |> List.exists (FileSystemUtils.checkSuffix lower) then
+ let intfs = Parser.signatureFile lexer lexbuf
+ PostParseModuleSpecs(defaultNamespace, filename, isLastCompiland, intfs, lexbuf)
+ else if lexbuf.SupportsFeature LanguageFeature.MLCompatRevisions then
+ error (Error(FSComp.SR.buildInvalidSourceFileExtensionUpdated filename, rangeStartup))
+ else
+ error (Error(FSComp.SR.buildInvalidSourceFileExtension filename, rangeStartup))
finally
// OK, now commit the errors, since the ScopedPragmas will (hopefully) have been scraped
let filteringErrorLogger = errorLogger // TODO: does this matter? //GetErrorLoggerFilteringByScopedPragmas(false, scopedPragmas, diagnosticOptions, errorLogger)
@@ -379,16 +329,7 @@ let EmptyParsedInput (filename, isLastCompiland) =
if FSharpSigFileSuffixes |> List.exists (FileSystemUtils.checkSuffix lower) then
ParsedInput.SigFile(
- ParsedSigFileInput(
- filename,
- QualFileNameOfImpls filename [],
- [],
- [],
- [],
- { ConditionalDirectives = []
- CodeComments = [] },
- Set.empty
- )
+ ParsedSigFileInput(filename, QualFileNameOfImpls filename [], [], [], ParsedInputTrivia.Empty, Set.empty)
)
else
ParsedInput.ImplFile(
@@ -398,10 +339,8 @@ let EmptyParsedInput (filename, isLastCompiland) =
QualFileNameOfImpls filename [],
[],
[],
- [],
isLastCompiland,
- { ConditionalDirectives = []
- CodeComments = [] },
+ ParsedInputTrivia.Empty,
Set.empty
)
)
diff --git a/src/Fantomas.FCS/packages.lock.json b/src/Fantomas.FCS/packages.lock.json
index 9482e407e7..5aaf2aa316 100644
--- a/src/Fantomas.FCS/packages.lock.json
+++ b/src/Fantomas.FCS/packages.lock.json
@@ -22,9 +22,9 @@
},
"FSharp.Core": {
"type": "Direct",
- "requested": "[8.0.100, )",
- "resolved": "8.0.100",
- "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg=="
+ "requested": "[9.0.300, )",
+ "resolved": "9.0.300",
+ "contentHash": "TVt2J7RCE1KCS2IaONF+p8/KIZ1eHNbW+7qmKF6hGoD4tXl+o07ja1mPtFjMqRa5uHMFaTrGTPn/m945WnDLiQ=="
},
"FsLexYacc": {
"type": "Direct",
diff --git a/src/Fantomas.Tests/packages.lock.json b/src/Fantomas.Tests/packages.lock.json
index 7c8f686ebd..c69c2a15ac 100644
--- a/src/Fantomas.Tests/packages.lock.json
+++ b/src/Fantomas.Tests/packages.lock.json
@@ -19,9 +19,9 @@
},
"FSharp.Core": {
"type": "Direct",
- "requested": "[8.0.100, )",
- "resolved": "8.0.100",
- "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg=="
+ "requested": "[9.0.300, )",
+ "resolved": "9.0.300",
+ "contentHash": "TVt2J7RCE1KCS2IaONF+p8/KIZ1eHNbW+7qmKF6hGoD4tXl+o07ja1mPtFjMqRa5uHMFaTrGTPn/m945WnDLiQ=="
},
"FsUnit": {
"type": "Direct",
@@ -213,7 +213,7 @@
"type": "Project",
"dependencies": {
"Argu": "[6.2.4, )",
- "FSharp.Core": "[8.0.100, )",
+ "FSharp.Core": "[9.0.300, )",
"Fantomas.Client": "[1.0.0, )",
"Fantomas.Core": "[1.0.0, )",
"Ignore": "[0.2.1, )",
@@ -230,7 +230,7 @@
"fantomas.client": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[8.0.100, )",
+ "FSharp.Core": "[9.0.300, )",
"SemanticVersioning": "[2.0.2, )",
"StreamJsonRpc": "[2.20.20, )"
}
@@ -238,14 +238,14 @@
"fantomas.core": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[8.0.100, )",
+ "FSharp.Core": "[9.0.300, )",
"Fantomas.FCS": "[1.0.0, )"
}
},
"fantomas.fcs": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[8.0.100, )",
+ "FSharp.Core": "[9.0.300, )",
"System.Collections.Immutable": "[8.0.0, )",
"System.Diagnostics.DiagnosticSource": "[8.0.1, )",
"System.Memory": "[4.6.0, )",
diff --git a/src/Fantomas/packages.lock.json b/src/Fantomas/packages.lock.json
index a69893af5b..86e7420ce4 100644
--- a/src/Fantomas/packages.lock.json
+++ b/src/Fantomas/packages.lock.json
@@ -38,9 +38,9 @@
},
"FSharp.Core": {
"type": "Direct",
- "requested": "[8.0.100, )",
- "resolved": "8.0.100",
- "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg=="
+ "requested": "[9.0.300, )",
+ "resolved": "9.0.300",
+ "contentHash": "TVt2J7RCE1KCS2IaONF+p8/KIZ1eHNbW+7qmKF6hGoD4tXl+o07ja1mPtFjMqRa5uHMFaTrGTPn/m945WnDLiQ=="
},
"G-Research.FSharp.Analyzers": {
"type": "Direct",
@@ -278,7 +278,7 @@
"fantomas.client": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[8.0.100, )",
+ "FSharp.Core": "[9.0.300, )",
"SemanticVersioning": "[2.0.2, )",
"StreamJsonRpc": "[2.20.20, )"
}
@@ -286,14 +286,14 @@
"fantomas.core": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[8.0.100, )",
+ "FSharp.Core": "[9.0.300, )",
"Fantomas.FCS": "[1.0.0, )"
}
},
"fantomas.fcs": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[8.0.100, )",
+ "FSharp.Core": "[9.0.300, )",
"System.Collections.Immutable": "[8.0.0, )",
"System.Diagnostics.DiagnosticSource": "[8.0.1, )",
"System.Memory": "[4.6.0, )",
From 421673728687c7c113b29fb17cb3d9e3ae872697 Mon Sep 17 00:00:00 2001
From: Martin521 <29605222+Martin521@users.noreply.github.com>
Date: Wed, 4 Jun 2025 11:57:33 +0000
Subject: [PATCH 02/11] review follow-up
---
src/Fantomas.Core.Tests/CommentTests.fs | 2 +-
src/Fantomas.Core/ASTTransformer.fs | 32 ++++++++++++++-----------
2 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/src/Fantomas.Core.Tests/CommentTests.fs b/src/Fantomas.Core.Tests/CommentTests.fs
index 228d01bb09..55e064344f 100644
--- a/src/Fantomas.Core.Tests/CommentTests.fs
+++ b/src/Fantomas.Core.Tests/CommentTests.fs
@@ -6,7 +6,7 @@ open Fantomas.Core.Tests.TestHelpers
open Fantomas.Core
[]
-let ``should keep sticky-to-the-left comments after #if directivesXXX`` () =
+let ``should keep sticky-to-the-left comments after #if directives`` () =
formatSourceString "#if DEBUG // debug only\n#endif\n" config
|> should equal "#if DEBUG // debug only\n#endif\n"
diff --git a/src/Fantomas.Core/ASTTransformer.fs b/src/Fantomas.Core/ASTTransformer.fs
index 292d3b7984..8916c767d8 100644
--- a/src/Fantomas.Core/ASTTransformer.fs
+++ b/src/Fantomas.Core/ASTTransformer.fs
@@ -966,23 +966,23 @@ let mkExpr (creationAide: CreationAide) (e: SynExpr) : Expr =
| SynExpr.AddressOf(false, e, _, StartRange 2 (ampersandToken, _range)) ->
ExprSingleNode(stn "&&" ampersandToken, false, false, mkExpr creationAide e, exprRange)
|> Expr.Single
- | SynExpr.YieldOrReturn((true, _), e, StartRange 5 (yieldKeyword, _range), _) ->
- ExprSingleNode(stn "yield" yieldKeyword, true, true, mkExpr creationAide e, exprRange)
+ | SynExpr.YieldOrReturn((true, _), e, _range, trivia) ->
+ ExprSingleNode(stn "yield" trivia.YieldOrReturnKeyword, true, true, mkExpr creationAide e, exprRange)
|> Expr.Single
- | SynExpr.YieldOrReturn((false, _), e, StartRange 6 (returnKeyword, _range), _) ->
- ExprSingleNode(stn "return" returnKeyword, true, true, mkExpr creationAide e, exprRange)
+ | SynExpr.YieldOrReturn((false, _), e, _range, trivia) ->
+ ExprSingleNode(stn "return" trivia.YieldOrReturnKeyword, true, true, mkExpr creationAide e, exprRange)
|> Expr.Single
- | SynExpr.YieldOrReturnFrom((true, _), e, StartRange 6 (yieldBangKeyword, _range), _) ->
- ExprSingleNode(stn "yield!" yieldBangKeyword, true, true, mkExpr creationAide e, exprRange)
+ | SynExpr.YieldOrReturnFrom((true, _), e, _range, trivia) ->
+ ExprSingleNode(stn "yield!" trivia.YieldOrReturnFromKeyword, true, true, mkExpr creationAide e, exprRange)
|> Expr.Single
- | SynExpr.YieldOrReturnFrom((false, _), e, StartRange 7 (returnBangKeyword, _range), _) ->
- ExprSingleNode(stn "return!" returnBangKeyword, true, true, mkExpr creationAide e, exprRange)
+ | SynExpr.YieldOrReturnFrom((false, _), e, _range, trivia) ->
+ ExprSingleNode(stn "return!" trivia.YieldOrReturnFromKeyword, true, true, mkExpr creationAide e, exprRange)
|> Expr.Single
| SynExpr.Do(e, StartRange 2 (doKeyword, _range)) ->
ExprSingleNode(stn "do" doKeyword, true, true, mkExpr creationAide e, exprRange)
|> Expr.Single
- | SynExpr.DoBang(e, StartRange 3 (doBangKeyword, _range), _) ->
- ExprSingleNode(stn "do!" doBangKeyword, true, true, mkExpr creationAide e, exprRange)
+ | SynExpr.DoBang(e, _range, trivia) ->
+ ExprSingleNode(stn "do!" trivia.DoBangKeyword, true, true, mkExpr creationAide e, exprRange)
|> Expr.Single
| SynExpr.Fixed(e, StartRange 5 (fixedKeyword, _range)) ->
ExprSingleNode(stn "fixed" fixedKeyword, true, false, mkExpr creationAide e, exprRange)
@@ -2807,8 +2807,8 @@ let mkMemberDefn (creationAide: CreationAide) (md: SynMemberDefn) =
let memberDefinitionRange = md.Range
match md with
- | SynMemberDefn.ImplicitInherit(t, e, _, StartRange 7 (mInherit, _), _) ->
- mkInheritConstructor creationAide t e mInherit memberDefinitionRange
+ | SynMemberDefn.ImplicitInherit(t, e, _, _, trivia) ->
+ mkInheritConstructor creationAide t e trivia.InheritKeyword memberDefinitionRange
|> MemberDefn.ImplicitInherit
// Transforms: `member this.Y with get() = "meh"` into `member this.Y = "meh"`
@@ -2868,10 +2868,14 @@ let mkMemberDefn (creationAide: CreationAide) (md: SynMemberDefn) =
)
|> MemberDefn.ExplicitCtor
| SynMemberDefn.Member(memberDefn, _) -> mkBinding creationAide memberDefn |> MemberDefn.Member
- | SynMemberDefn.Inherit(baseTypeOpt, _, StartRange 7 (mInherit, _), _) ->
+ | SynMemberDefn.Inherit(baseTypeOpt, _, _isInline, trivia) ->
match baseTypeOpt with
| Some baseType ->
- MemberDefnInheritNode(stn "inherit" mInherit, mkType creationAide baseType, memberDefinitionRange)
+ MemberDefnInheritNode(
+ stn "inherit" trivia.InheritKeyword,
+ mkType creationAide baseType,
+ memberDefinitionRange
+ )
|> MemberDefn.Inherit
| None -> failwith "successful parse shouldn't have any unfinished inherit"
| SynMemberDefn.ValField(f, _) -> mkSynField creationAide f |> MemberDefn.ValField
From 10b59bb1f47d0dd7a07bb02326e27aac76aca928 Mon Sep 17 00:00:00 2001
From: Martin521 <29605222+Martin521@users.noreply.github.com>
Date: Wed, 4 Jun 2025 15:39:48 +0000
Subject: [PATCH 03/11] update dockerfile also to sdk 9
---
.devcontainer/Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index bda0692f15..63fd6d08db 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0.400
+FROM mcr.microsoft.com/dotnet/sdk:9.0.300
# Avoid warnings by switching to noninteractive
ENV DEBIAN_FRONTEND=noninteractive
From c68f23ce30fcbcf5d9dca6519c1415384fee2e28 Mon Sep 17 00:00:00 2001
From: nojaf
Date: Fri, 14 Nov 2025 06:24:51 +0100
Subject: [PATCH 04/11] Update to dotnet 10
---
.devcontainer/Dockerfile | 2 +-
global.json | 2 +-
.../Fantomas.Benchmarks.fsproj | 2 +-
src/Fantomas.Benchmarks/packages.lock.json | 113 +-----------------
.../Fantomas.Client.Tests.fsproj | 2 +-
src/Fantomas.Client.Tests/packages.lock.json | 23 +---
.../Fantomas.Core.Tests.fsproj | 2 +-
src/Fantomas.Core.Tests/packages.lock.json | 56 +--------
src/Fantomas.Tests/Fantomas.Tests.fsproj | 2 +-
src/Fantomas.Tests/packages.lock.json | 67 +----------
src/Fantomas/Fantomas.fsproj | 2 +-
src/Fantomas/packages.lock.json | 57 +--------
12 files changed, 29 insertions(+), 301 deletions(-)
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index 63fd6d08db..6e3cd0f5b4 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:9.0.300
+FROM mcr.microsoft.com/dotnet/sdk:10.0.100
# Avoid warnings by switching to noninteractive
ENV DEBIAN_FRONTEND=noninteractive
diff --git a/global.json b/global.json
index d3dbe09378..971b5004e2 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "9.0.300",
+ "version": "10.0.100",
"rollForward": "latestPatch"
}
}
\ No newline at end of file
diff --git a/src/Fantomas.Benchmarks/Fantomas.Benchmarks.fsproj b/src/Fantomas.Benchmarks/Fantomas.Benchmarks.fsproj
index 5152fe51d8..88a3ddcbda 100644
--- a/src/Fantomas.Benchmarks/Fantomas.Benchmarks.fsproj
+++ b/src/Fantomas.Benchmarks/Fantomas.Benchmarks.fsproj
@@ -2,7 +2,7 @@
Exe
- net8.0
+ net10.0
false
diff --git a/src/Fantomas.Benchmarks/packages.lock.json b/src/Fantomas.Benchmarks/packages.lock.json
index 664a872c78..fbe63b1d49 100644
--- a/src/Fantomas.Benchmarks/packages.lock.json
+++ b/src/Fantomas.Benchmarks/packages.lock.json
@@ -1,7 +1,7 @@
{
"version": 2,
"dependencies": {
- "net8.0": {
+ "net10.0": {
"BenchmarkDotNet": {
"type": "Direct",
"requested": "[0.14.0, )",
@@ -79,13 +79,7 @@
"resolved": "4.1.0",
"contentHash": "bNzTyxP3iD5FPFHfVDl15Y6/wSoI7e3MeV0lOaj9igbIKTjgrmuw6LoVJ06jUNFA7+KaDC/OIsStWl/FQJz6sQ==",
"dependencies": {
- "Microsoft.CodeAnalysis.Analyzers": "3.3.3",
- "System.Collections.Immutable": "5.0.0",
- "System.Memory": "4.5.4",
- "System.Reflection.Metadata": "5.0.0",
- "System.Runtime.CompilerServices.Unsafe": "5.0.0",
- "System.Text.Encoding.CodePages": "4.5.1",
- "System.Threading.Tasks.Extensions": "4.5.4"
+ "Microsoft.CodeAnalysis.Analyzers": "3.3.3"
}
},
"Microsoft.CodeAnalysis.CSharp": {
@@ -110,19 +104,13 @@
"resolved": "2.2.332302",
"contentHash": "Hp84ivxSKIMTBzYSATxmUsm3YSXHWivcwiRRbsydGmqujMUK8BAueLN0ssAVEOkOBmh0vjUBhrq7YcroT7VCug==",
"dependencies": {
- "Microsoft.Diagnostics.NETCore.Client": "0.2.251802",
- "System.Collections.Immutable": "5.0.0",
- "System.Runtime.CompilerServices.Unsafe": "5.0.0"
+ "Microsoft.Diagnostics.NETCore.Client": "0.2.251802"
}
},
"Microsoft.Diagnostics.Tracing.TraceEvent": {
"type": "Transitive",
"resolved": "3.1.8",
- "contentHash": "kl3UMrZKSeSEYZ8rt/GjLUQToREjgQABqfg6PzQBmSlYHTZOKE9ePEOS2xptROQ9SVvngg3QGX51TIT11iZ0wA==",
- "dependencies": {
- "Microsoft.Win32.Registry": "4.4.0",
- "System.Runtime.CompilerServices.Unsafe": "5.0.0"
- }
+ "contentHash": "kl3UMrZKSeSEYZ8rt/GjLUQToREjgQABqfg6PzQBmSlYHTZOKE9ePEOS2xptROQ9SVvngg3QGX51TIT11iZ0wA=="
},
"Microsoft.DotNet.PlatformAbstractions": {
"type": "Transitive",
@@ -186,31 +174,13 @@
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "2.1.1",
- "contentHash": "scJ1GZNIxMmjpENh0UZ8XCQ6vzr/LzeF9WvEA51Ix2OQGAs9WPgPu8ABVUdvpKPLuor/t05gm6menJK3PwqOXg==",
- "dependencies": {
- "System.Memory": "4.5.1",
- "System.Runtime.CompilerServices.Unsafe": "4.5.1"
- }
+ "contentHash": "scJ1GZNIxMmjpENh0UZ8XCQ6vzr/LzeF9WvEA51Ix2OQGAs9WPgPu8ABVUdvpKPLuor/t05gm6menJK3PwqOXg=="
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ=="
},
- "Microsoft.NETCore.Targets": {
- "type": "Transitive",
- "resolved": "1.1.3",
- "contentHash": "3Wrmi0kJDzClwAC+iBdUBpEKmEle8FQNsCs77fkiOIw/9oYA07bL1EZNX0kQ2OMN3xpwvl0vAtOCYY3ndDNlhQ=="
- },
- "Microsoft.Win32.Registry": {
- "type": "Transitive",
- "resolved": "5.0.0",
- "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
- "dependencies": {
- "System.Security.AccessControl": "5.0.0",
- "System.Security.Principal.Windows": "5.0.0"
- }
- },
"Perfolizer": {
"type": "Transitive",
"resolved": "0.3.17",
@@ -227,48 +197,9 @@
"contentHash": "MF1CHaRcC+MLFdnDthv4/bKWBZnlnSpkGqa87pKukQefgEdwtb9zFW6zs0GjPp73qtpYYg4q6PEKbzJbxCpKfw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "5.0.0",
- "Microsoft.Win32.Registry": "5.0.0",
"System.CodeDom": "5.0.0"
}
},
- "System.Reflection.Metadata": {
- "type": "Transitive",
- "resolved": "5.0.0",
- "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ=="
- },
- "System.Runtime.CompilerServices.Unsafe": {
- "type": "Transitive",
- "resolved": "5.0.0",
- "contentHash": "ZD9TMpsmYJLrxbbmdvhwt9YEgG5WntEnZ/d1eH8JBX9LBp+Ju8BSBhUGbZMNVHHomWo2KVImJhTDl2hIgw/6MA=="
- },
- "System.Security.AccessControl": {
- "type": "Transitive",
- "resolved": "5.0.0",
- "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
- "dependencies": {
- "Microsoft.NETCore.Platforms": "5.0.0",
- "System.Security.Principal.Windows": "5.0.0"
- }
- },
- "System.Security.Principal.Windows": {
- "type": "Transitive",
- "resolved": "5.0.0",
- "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA=="
- },
- "System.Text.Encoding.CodePages": {
- "type": "Transitive",
- "resolved": "4.5.1",
- "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==",
- "dependencies": {
- "Microsoft.NETCore.Platforms": "2.1.2",
- "System.Runtime.CompilerServices.Unsafe": "4.5.2"
- }
- },
- "System.Threading.Tasks.Extensions": {
- "type": "Transitive",
- "resolved": "4.5.4",
- "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg=="
- },
"fantomas.core": {
"type": "Project",
"dependencies": {
@@ -279,39 +210,7 @@
"fantomas.fcs": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[9.0.300, )",
- "System.Collections.Immutable": "[8.0.0, )",
- "System.Diagnostics.DiagnosticSource": "[8.0.1, )",
- "System.Memory": "[4.6.0, )",
- "System.Runtime": "[4.3.1, )"
- }
- },
- "System.Collections.Immutable": {
- "type": "CentralTransitive",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg=="
- },
- "System.Diagnostics.DiagnosticSource": {
- "type": "CentralTransitive",
- "requested": "[8.0.1, )",
- "resolved": "8.0.1",
- "contentHash": "vaoWjvkG1aenR2XdjaVivlCV9fADfgyhW5bZtXT23qaEea0lWiUljdQuze4E31vKM7ZWJaSUsbYIKE3rnzfZUg=="
- },
- "System.Memory": {
- "type": "CentralTransitive",
- "requested": "[4.6.0, )",
- "resolved": "4.6.0",
- "contentHash": "OEkbBQoklHngJ8UD8ez2AERSk2g+/qpAaSWWCBFbpH727HxDq5ydVkuncBaKcKfwRqXGWx64dS6G1SUScMsitg=="
- },
- "System.Runtime": {
- "type": "CentralTransitive",
- "requested": "[4.3.1, )",
- "resolved": "4.3.1",
- "contentHash": "abhfv1dTK6NXOmu4bgHIONxHyEqFjW8HwXPmpY9gmll+ix9UNo4XDcmzJn6oLooftxNssVHdJC1pGT9jkSynQg==",
- "dependencies": {
- "Microsoft.NETCore.Platforms": "1.1.1",
- "Microsoft.NETCore.Targets": "1.1.3"
+ "FSharp.Core": "[9.0.300, )"
}
}
}
diff --git a/src/Fantomas.Client.Tests/Fantomas.Client.Tests.fsproj b/src/Fantomas.Client.Tests/Fantomas.Client.Tests.fsproj
index 3fe6e272c0..b1ea8b9214 100644
--- a/src/Fantomas.Client.Tests/Fantomas.Client.Tests.fsproj
+++ b/src/Fantomas.Client.Tests/Fantomas.Client.Tests.fsproj
@@ -2,7 +2,7 @@
FS0988
- net8.0
+ net10.0
false
false
Major
diff --git a/src/Fantomas.Client.Tests/packages.lock.json b/src/Fantomas.Client.Tests/packages.lock.json
index 54e3169b0b..674a0fdb3a 100644
--- a/src/Fantomas.Client.Tests/packages.lock.json
+++ b/src/Fantomas.Client.Tests/packages.lock.json
@@ -1,7 +1,7 @@
{
"version": 2,
"dependencies": {
- "net8.0": {
+ "net10.0": {
"CliWrap": {
"type": "Direct",
"requested": "[3.6.7, )",
@@ -81,10 +81,7 @@
"Microsoft.TestPlatform.ObjectModel": {
"type": "Transitive",
"resolved": "17.12.0",
- "contentHash": "TDqkTKLfQuAaPcEb3pDDWnh7b3SyZF+/W9OZvWFp6eJCIiiYFdSB6taE2I6tWrFw5ywhzOb6sreoGJTI6m3rSQ==",
- "dependencies": {
- "System.Reflection.Metadata": "1.6.0"
- }
+ "contentHash": "TDqkTKLfQuAaPcEb3pDDWnh7b3SyZF+/W9OZvWFp6eJCIiiYFdSB6taE2I6tWrFw5ywhzOb6sreoGJTI6m3rSQ=="
},
"Microsoft.TestPlatform.TestHost": {
"type": "Transitive",
@@ -120,20 +117,9 @@
"contentHash": "r4G7uHHfoo8LCilPOdtf2C+Q5ymHOAXtciT4ZtB2xRlAvv4gPkWBYNAijFblStv3+uidp81j5DP11jMZl4BfJw==",
"dependencies": {
"Microsoft.VisualStudio.Threading": "17.10.48",
- "Microsoft.VisualStudio.Validation": "17.8.8",
- "System.IO.Pipelines": "8.0.0"
+ "Microsoft.VisualStudio.Validation": "17.8.8"
}
},
- "System.IO.Pipelines": {
- "type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA=="
- },
- "System.Reflection.Metadata": {
- "type": "Transitive",
- "resolved": "1.6.0",
- "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ=="
- },
"fantomas.client": {
"type": "Project",
"dependencies": {
@@ -165,8 +151,7 @@
"Microsoft.VisualStudio.Threading.Analyzers": "17.10.48",
"Microsoft.VisualStudio.Validation": "17.8.8",
"Nerdbank.Streams": "2.11.74",
- "Newtonsoft.Json": "13.0.1",
- "System.IO.Pipelines": "8.0.0"
+ "Newtonsoft.Json": "13.0.1"
}
}
}
diff --git a/src/Fantomas.Core.Tests/Fantomas.Core.Tests.fsproj b/src/Fantomas.Core.Tests/Fantomas.Core.Tests.fsproj
index 6f606dc0ce..433285415b 100644
--- a/src/Fantomas.Core.Tests/Fantomas.Core.Tests.fsproj
+++ b/src/Fantomas.Core.Tests/Fantomas.Core.Tests.fsproj
@@ -1,7 +1,7 @@
FS0988
- net8.0
+ net10.0
FS0025
false
Major
diff --git a/src/Fantomas.Core.Tests/packages.lock.json b/src/Fantomas.Core.Tests/packages.lock.json
index 87f141e46c..c4fa425dd9 100644
--- a/src/Fantomas.Core.Tests/packages.lock.json
+++ b/src/Fantomas.Core.Tests/packages.lock.json
@@ -1,7 +1,7 @@
{
"version": 2,
"dependencies": {
- "net8.0": {
+ "net10.0": {
"FsCheck": {
"type": "Direct",
"requested": "[2.16.5, )",
@@ -81,23 +81,10 @@
"resolved": "17.12.0",
"contentHash": "4svMznBd5JM21JIG2xZKGNanAHNXplxf/kQDFfLHXQ3OnpJkayRK/TjacFjA+EYmoyuNXHo/sOETEfcYtAzIrA=="
},
- "Microsoft.NETCore.Platforms": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "TMBuzAHpTenGbGgk0SMTwyEkyijY/Eae4ZGsFNYJvAr/LDn1ku3Etp3FPxChmDp5HHF3kzJuoaa08N0xjqAJfQ=="
- },
- "Microsoft.NETCore.Targets": {
- "type": "Transitive",
- "resolved": "1.1.3",
- "contentHash": "3Wrmi0kJDzClwAC+iBdUBpEKmEle8FQNsCs77fkiOIw/9oYA07bL1EZNX0kQ2OMN3xpwvl0vAtOCYY3ndDNlhQ=="
- },
"Microsoft.TestPlatform.ObjectModel": {
"type": "Transitive",
"resolved": "17.12.0",
- "contentHash": "TDqkTKLfQuAaPcEb3pDDWnh7b3SyZF+/W9OZvWFp6eJCIiiYFdSB6taE2I6tWrFw5ywhzOb6sreoGJTI6m3rSQ==",
- "dependencies": {
- "System.Reflection.Metadata": "1.6.0"
- }
+ "contentHash": "TDqkTKLfQuAaPcEb3pDDWnh7b3SyZF+/W9OZvWFp6eJCIiiYFdSB6taE2I6tWrFw5ywhzOb6sreoGJTI6m3rSQ=="
},
"Microsoft.TestPlatform.TestHost": {
"type": "Transitive",
@@ -108,11 +95,6 @@
"Newtonsoft.Json": "13.0.1"
}
},
- "System.Reflection.Metadata": {
- "type": "Transitive",
- "resolved": "1.6.0",
- "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ=="
- },
"TestableIO.System.IO.Abstractions": {
"type": "Transitive",
"resolved": "21.1.3",
@@ -145,11 +127,7 @@
"fantomas.fcs": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[9.0.300, )",
- "System.Collections.Immutable": "[8.0.0, )",
- "System.Diagnostics.DiagnosticSource": "[8.0.1, )",
- "System.Memory": "[4.6.0, )",
- "System.Runtime": "[4.3.1, )"
+ "FSharp.Core": "[9.0.300, )"
}
},
"Newtonsoft.Json": {
@@ -157,34 +135,6 @@
"requested": "[13.0.3, )",
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
- },
- "System.Collections.Immutable": {
- "type": "CentralTransitive",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg=="
- },
- "System.Diagnostics.DiagnosticSource": {
- "type": "CentralTransitive",
- "requested": "[8.0.1, )",
- "resolved": "8.0.1",
- "contentHash": "vaoWjvkG1aenR2XdjaVivlCV9fADfgyhW5bZtXT23qaEea0lWiUljdQuze4E31vKM7ZWJaSUsbYIKE3rnzfZUg=="
- },
- "System.Memory": {
- "type": "CentralTransitive",
- "requested": "[4.6.0, )",
- "resolved": "4.6.0",
- "contentHash": "OEkbBQoklHngJ8UD8ez2AERSk2g+/qpAaSWWCBFbpH727HxDq5ydVkuncBaKcKfwRqXGWx64dS6G1SUScMsitg=="
- },
- "System.Runtime": {
- "type": "CentralTransitive",
- "requested": "[4.3.1, )",
- "resolved": "4.3.1",
- "contentHash": "abhfv1dTK6NXOmu4bgHIONxHyEqFjW8HwXPmpY9gmll+ix9UNo4XDcmzJn6oLooftxNssVHdJC1pGT9jkSynQg==",
- "dependencies": {
- "Microsoft.NETCore.Platforms": "1.1.1",
- "Microsoft.NETCore.Targets": "1.1.3"
- }
}
}
}
diff --git a/src/Fantomas.Tests/Fantomas.Tests.fsproj b/src/Fantomas.Tests/Fantomas.Tests.fsproj
index 8243c389c8..502ee6f1a0 100644
--- a/src/Fantomas.Tests/Fantomas.Tests.fsproj
+++ b/src/Fantomas.Tests/Fantomas.Tests.fsproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
false
false
FS0988
diff --git a/src/Fantomas.Tests/packages.lock.json b/src/Fantomas.Tests/packages.lock.json
index c69c2a15ac..6019930d87 100644
--- a/src/Fantomas.Tests/packages.lock.json
+++ b/src/Fantomas.Tests/packages.lock.json
@@ -1,7 +1,7 @@
{
"version": 2,
"dependencies": {
- "net8.0": {
+ "net10.0": {
"FsCheck": {
"type": "Direct",
"requested": "[2.16.5, )",
@@ -108,23 +108,10 @@
"resolved": "17.6.3",
"contentHash": "N0ZIanl1QCgvUumEL1laasU0a7sOE5ZwLZVTn0pAePnfhq8P7SvTjF8Axq+CnavuQkmdQpGNXQ1efZtu5kDFbA=="
},
- "Microsoft.NETCore.Platforms": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "TMBuzAHpTenGbGgk0SMTwyEkyijY/Eae4ZGsFNYJvAr/LDn1ku3Etp3FPxChmDp5HHF3kzJuoaa08N0xjqAJfQ=="
- },
- "Microsoft.NETCore.Targets": {
- "type": "Transitive",
- "resolved": "1.1.3",
- "contentHash": "3Wrmi0kJDzClwAC+iBdUBpEKmEle8FQNsCs77fkiOIw/9oYA07bL1EZNX0kQ2OMN3xpwvl0vAtOCYY3ndDNlhQ=="
- },
"Microsoft.TestPlatform.ObjectModel": {
"type": "Transitive",
"resolved": "17.12.0",
- "contentHash": "TDqkTKLfQuAaPcEb3pDDWnh7b3SyZF+/W9OZvWFp6eJCIiiYFdSB6taE2I6tWrFw5ywhzOb6sreoGJTI6m3rSQ==",
- "dependencies": {
- "System.Reflection.Metadata": "1.6.0"
- }
+ "contentHash": "TDqkTKLfQuAaPcEb3pDDWnh7b3SyZF+/W9OZvWFp6eJCIiiYFdSB6taE2I6tWrFw5ywhzOb6sreoGJTI6m3rSQ=="
},
"Microsoft.TestPlatform.TestHost": {
"type": "Transitive",
@@ -160,8 +147,7 @@
"contentHash": "r4G7uHHfoo8LCilPOdtf2C+Q5ymHOAXtciT4ZtB2xRlAvv4gPkWBYNAijFblStv3+uidp81j5DP11jMZl4BfJw==",
"dependencies": {
"Microsoft.VisualStudio.Threading": "17.10.48",
- "Microsoft.VisualStudio.Validation": "17.8.8",
- "System.IO.Pipelines": "8.0.0"
+ "Microsoft.VisualStudio.Validation": "17.8.8"
}
},
"System.Configuration.ConfigurationManager": {
@@ -172,16 +158,6 @@
"System.Security.Cryptography.ProtectedData": "4.4.0"
}
},
- "System.IO.Pipelines": {
- "type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA=="
- },
- "System.Reflection.Metadata": {
- "type": "Transitive",
- "resolved": "1.6.0",
- "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ=="
- },
"System.Security.Cryptography.ProtectedData": {
"type": "Transitive",
"resolved": "4.4.0",
@@ -245,11 +221,7 @@
"fantomas.fcs": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[9.0.300, )",
- "System.Collections.Immutable": "[8.0.0, )",
- "System.Diagnostics.DiagnosticSource": "[8.0.1, )",
- "System.Memory": "[4.6.0, )",
- "System.Runtime": "[4.3.1, )"
+ "FSharp.Core": "[9.0.300, )"
}
},
"Argu": {
@@ -327,22 +299,9 @@
"Microsoft.VisualStudio.Threading.Analyzers": "17.10.48",
"Microsoft.VisualStudio.Validation": "17.8.8",
"Nerdbank.Streams": "2.11.74",
- "Newtonsoft.Json": "13.0.1",
- "System.IO.Pipelines": "8.0.0"
+ "Newtonsoft.Json": "13.0.1"
}
},
- "System.Collections.Immutable": {
- "type": "CentralTransitive",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg=="
- },
- "System.Diagnostics.DiagnosticSource": {
- "type": "CentralTransitive",
- "requested": "[8.0.1, )",
- "resolved": "8.0.1",
- "contentHash": "vaoWjvkG1aenR2XdjaVivlCV9fADfgyhW5bZtXT23qaEea0lWiUljdQuze4E31vKM7ZWJaSUsbYIKE3rnzfZUg=="
- },
"System.IO.Abstractions": {
"type": "CentralTransitive",
"requested": "[21.1.3, )",
@@ -353,22 +312,6 @@
"TestableIO.System.IO.Abstractions.Wrappers": "21.1.3"
}
},
- "System.Memory": {
- "type": "CentralTransitive",
- "requested": "[4.6.0, )",
- "resolved": "4.6.0",
- "contentHash": "OEkbBQoklHngJ8UD8ez2AERSk2g+/qpAaSWWCBFbpH727HxDq5ydVkuncBaKcKfwRqXGWx64dS6G1SUScMsitg=="
- },
- "System.Runtime": {
- "type": "CentralTransitive",
- "requested": "[4.3.1, )",
- "resolved": "4.3.1",
- "contentHash": "abhfv1dTK6NXOmu4bgHIONxHyEqFjW8HwXPmpY9gmll+ix9UNo4XDcmzJn6oLooftxNssVHdJC1pGT9jkSynQg==",
- "dependencies": {
- "Microsoft.NETCore.Platforms": "1.1.1",
- "Microsoft.NETCore.Targets": "1.1.3"
- }
- },
"Thoth.Json.Net": {
"type": "CentralTransitive",
"requested": "[12.0.0, )",
diff --git a/src/Fantomas/Fantomas.fsproj b/src/Fantomas/Fantomas.fsproj
index 08a87ac2bd..cb1f9b3788 100644
--- a/src/Fantomas/Fantomas.fsproj
+++ b/src/Fantomas/Fantomas.fsproj
@@ -1,7 +1,7 @@
Exe
- net8.0
+ net10.0
en
diff --git a/src/Fantomas/packages.lock.json b/src/Fantomas/packages.lock.json
index 86e7420ce4..48c198f8dc 100644
--- a/src/Fantomas/packages.lock.json
+++ b/src/Fantomas/packages.lock.json
@@ -1,7 +1,7 @@
{
"version": 2,
"dependencies": {
- "net8.0": {
+ "net10.0": {
"Argu": {
"type": "Direct",
"requested": "[6.2.4, )",
@@ -107,8 +107,7 @@
"Microsoft.VisualStudio.Threading.Analyzers": "17.10.48",
"Microsoft.VisualStudio.Validation": "17.8.8",
"Nerdbank.Streams": "2.11.74",
- "Newtonsoft.Json": "13.0.1",
- "System.IO.Pipelines": "8.0.0"
+ "Newtonsoft.Json": "13.0.1"
}
},
"System.IO.Abstractions": {
@@ -164,16 +163,6 @@
"resolved": "17.6.3",
"contentHash": "N0ZIanl1QCgvUumEL1laasU0a7sOE5ZwLZVTn0pAePnfhq8P7SvTjF8Axq+CnavuQkmdQpGNXQ1efZtu5kDFbA=="
},
- "Microsoft.NETCore.Platforms": {
- "type": "Transitive",
- "resolved": "1.1.1",
- "contentHash": "TMBuzAHpTenGbGgk0SMTwyEkyijY/Eae4ZGsFNYJvAr/LDn1ku3Etp3FPxChmDp5HHF3kzJuoaa08N0xjqAJfQ=="
- },
- "Microsoft.NETCore.Targets": {
- "type": "Transitive",
- "resolved": "1.1.3",
- "contentHash": "3Wrmi0kJDzClwAC+iBdUBpEKmEle8FQNsCs77fkiOIw/9oYA07bL1EZNX0kQ2OMN3xpwvl0vAtOCYY3ndDNlhQ=="
- },
"Microsoft.SourceLink.AzureRepos.Git": {
"type": "Transitive",
"resolved": "1.1.1",
@@ -240,8 +229,7 @@
"contentHash": "r4G7uHHfoo8LCilPOdtf2C+Q5ymHOAXtciT4ZtB2xRlAvv4gPkWBYNAijFblStv3+uidp81j5DP11jMZl4BfJw==",
"dependencies": {
"Microsoft.VisualStudio.Threading": "17.10.48",
- "Microsoft.VisualStudio.Validation": "17.8.8",
- "System.IO.Pipelines": "8.0.0"
+ "Microsoft.VisualStudio.Validation": "17.8.8"
}
},
"System.Configuration.ConfigurationManager": {
@@ -252,11 +240,6 @@
"System.Security.Cryptography.ProtectedData": "4.4.0"
}
},
- "System.IO.Pipelines": {
- "type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA=="
- },
"System.Security.Cryptography.ProtectedData": {
"type": "Transitive",
"resolved": "4.4.0",
@@ -293,11 +276,7 @@
"fantomas.fcs": {
"type": "Project",
"dependencies": {
- "FSharp.Core": "[9.0.300, )",
- "System.Collections.Immutable": "[8.0.0, )",
- "System.Diagnostics.DiagnosticSource": "[8.0.1, )",
- "System.Memory": "[4.6.0, )",
- "System.Runtime": "[4.3.1, )"
+ "FSharp.Core": "[9.0.300, )"
}
},
"Newtonsoft.Json": {
@@ -311,34 +290,6 @@
"requested": "[2.0.2, )",
"resolved": "2.0.2",
"contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA=="
- },
- "System.Collections.Immutable": {
- "type": "CentralTransitive",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg=="
- },
- "System.Diagnostics.DiagnosticSource": {
- "type": "CentralTransitive",
- "requested": "[8.0.1, )",
- "resolved": "8.0.1",
- "contentHash": "vaoWjvkG1aenR2XdjaVivlCV9fADfgyhW5bZtXT23qaEea0lWiUljdQuze4E31vKM7ZWJaSUsbYIKE3rnzfZUg=="
- },
- "System.Memory": {
- "type": "CentralTransitive",
- "requested": "[4.6.0, )",
- "resolved": "4.6.0",
- "contentHash": "OEkbBQoklHngJ8UD8ez2AERSk2g+/qpAaSWWCBFbpH727HxDq5ydVkuncBaKcKfwRqXGWx64dS6G1SUScMsitg=="
- },
- "System.Runtime": {
- "type": "CentralTransitive",
- "requested": "[4.3.1, )",
- "resolved": "4.3.1",
- "contentHash": "abhfv1dTK6NXOmu4bgHIONxHyEqFjW8HwXPmpY9gmll+ix9UNo4XDcmzJn6oLooftxNssVHdJC1pGT9jkSynQg==",
- "dependencies": {
- "Microsoft.NETCore.Platforms": "1.1.1",
- "Microsoft.NETCore.Targets": "1.1.3"
- }
}
}
}
From b3db7ec73703bfb7fc70425234a3b02007ce3277 Mon Sep 17 00:00:00 2001
From: nojaf
Date: Fri, 14 Nov 2025 06:29:57 +0100
Subject: [PATCH 05/11] Don't print formatted code
---
src/Fantomas.Core.Tests/CodeFormatterTests.fs | 1 -
src/Fantomas.Core.Tests/TestHelpers.fs | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/Fantomas.Core.Tests/CodeFormatterTests.fs b/src/Fantomas.Core.Tests/CodeFormatterTests.fs
index f44801cc39..89e0f862cf 100644
--- a/src/Fantomas.Core.Tests/CodeFormatterTests.fs
+++ b/src/Fantomas.Core.Tests/CodeFormatterTests.fs
@@ -4,7 +4,6 @@ open Fantomas.Core.SyntaxOak
open NUnit.Framework
open Fantomas.FCS.Text
open Fantomas.Core
-open Fantomas.Core.SyntaxOak
open Fantomas.Core.Tests.TestHelpers
[]
diff --git a/src/Fantomas.Core.Tests/TestHelpers.fs b/src/Fantomas.Core.Tests/TestHelpers.fs
index 616b5e2d8e..76c88a3d35 100644
--- a/src/Fantomas.Core.Tests/TestHelpers.fs
+++ b/src/Fantomas.Core.Tests/TestHelpers.fs
@@ -31,7 +31,7 @@ let formatFSharpString isFsiFile (s: string) config =
if formattedCode <> secondFormattedCode then
failwith $"The formatted result was not idempotent.\n%s{formattedCode}\n%s{secondFormattedCode}"
- printfn "formatted code:\n%s\n" formattedCode
+ // printfn "formatted code:\n%s\n" formattedCode
return formattedCode
}
From 13b26a70ed6144d21522edc0e528f2e24c47fb5f Mon Sep 17 00:00:00 2001
From: nojaf
Date: Fri, 14 Nov 2025 06:44:53 +0100
Subject: [PATCH 06/11] Fix parsing errors using anonymous records and code
quotations (#18603)
---
Directory.Build.props | 2 +-
src/Fantomas.Core.Tests/QuotationTests.fs | 16 ++++++++++++++++
src/Fantomas.Core/ASTTransformer.fs | 5 +++--
src/Fantomas.Core/Trivia.fs | 15 +++++++++------
4 files changed, 29 insertions(+), 9 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 1d03c11ff1..7289a2d9f9 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -45,7 +45,7 @@ Some common use cases include:
- 20ff6a94300b5f2f5498d3d8ad1a44abaabc5c22
+ a1a156d3b64814ad28d53cc51848f423b0c5bad3
diff --git a/src/Fantomas.Core.Tests/QuotationTests.fs b/src/Fantomas.Core.Tests/QuotationTests.fs
index 39f40f8a02..7e6d84f67a 100644
--- a/src/Fantomas.Core.Tests/QuotationTests.fs
+++ b/src/Fantomas.Core.Tests/QuotationTests.fs
@@ -170,3 +170,19 @@ test
Pop = null } }
@>
"""
+
+[]
+let ``quotation in anonymous record`` () =
+ formatSourceString
+ """
+{| A= <@ 1 + 1 @>|}
+{| A = <@@ 1 + 1 @@>|}
+"""
+ { config with IndentSize = 2 }
+ |> prepend newline
+ |> should
+ equal
+ """
+{| A = <@ 1 + 1 @> |}
+{| A = <@@ 1 + 1 @@> |}
+"""
diff --git a/src/Fantomas.Core/ASTTransformer.fs b/src/Fantomas.Core/ASTTransformer.fs
index 8916c767d8..5c41e2b3ef 100644
--- a/src/Fantomas.Core/ASTTransformer.fs
+++ b/src/Fantomas.Core/ASTTransformer.fs
@@ -3618,11 +3618,12 @@ let includeTrivia (baseRange: range) (trivia: ParsedInputTrivia) : range =
| ConditionalDirectiveTrivia.Else(range = range)
| ConditionalDirectiveTrivia.EndIf(range = range) -> range)
trivia.ConditionalDirectives
+
yield!
List.map
(function
- | WarnDirectiveTrivia.Nowarn range
- | WarnDirectiveTrivia.Warnon range -> range)
+ | WarnDirectiveTrivia.Nowarn(_, range)
+ | WarnDirectiveTrivia.Warnon(_, range) -> range)
trivia.WarnDirectives ]
(baseRange, ranges)
diff --git a/src/Fantomas.Core/Trivia.fs b/src/Fantomas.Core/Trivia.fs
index 4d243ee753..efa9dcf169 100644
--- a/src/Fantomas.Core/Trivia.fs
+++ b/src/Fantomas.Core/Trivia.fs
@@ -136,12 +136,12 @@ type ConditionalDirectiveTrivia with
| ConditionalDirectiveTrivia.Else m
| ConditionalDirectiveTrivia.EndIf m -> m
-type WarnDirectiveTrivia with
+// type WarnDirectiveTrivia with
- member x.Range =
- match x with
- | WarnDirectiveTrivia.Nowarn m
- | WarnDirectiveTrivia.Warnon m -> m
+// member x.Range =
+// match x with
+// | WarnDirectiveTrivia.Nowarn m
+// | WarnDirectiveTrivia.Warnon m -> m
let internal collectTriviaFromDirectiveRanges
(source: ISourceText)
@@ -335,7 +335,10 @@ let enrichTree (config: FormatConfig) (sourceText: ISourceText) (ast: ParsedInpu
let directiveRanges =
(parsedTrivia.ConditionalDirectives |> List.map _.Range)
- @ (parsedTrivia.WarnDirectives |> List.map _.Range)
+ @ (parsedTrivia.WarnDirectives
+ |> List.map (function
+ | WarnDirectiveTrivia.Nowarn(_, m)
+ | WarnDirectiveTrivia.Warnon(_, m) -> m))
let directives =
collectTriviaFromDirectiveRanges sourceText directiveRanges fullTreeRange
From 736b616d6f69460884e3e4e2e96b16414733b3bc Mon Sep 17 00:00:00 2001
From: nojaf
Date: Fri, 14 Nov 2025 06:47:26 +0100
Subject: [PATCH 07/11] Fix warn scopes trivia for fantomas #18637
---
Directory.Build.props | 2 +-
src/Fantomas.Core/ASTTransformer.fs | 4 ++--
src/Fantomas.Core/Trivia.fs | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 7289a2d9f9..175c26f631 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -45,7 +45,7 @@ Some common use cases include:
- a1a156d3b64814ad28d53cc51848f423b0c5bad3
+ a3e51909bdeca89357a97e516503e20fd7254f45
diff --git a/src/Fantomas.Core/ASTTransformer.fs b/src/Fantomas.Core/ASTTransformer.fs
index 5c41e2b3ef..fc642da385 100644
--- a/src/Fantomas.Core/ASTTransformer.fs
+++ b/src/Fantomas.Core/ASTTransformer.fs
@@ -3622,8 +3622,8 @@ let includeTrivia (baseRange: range) (trivia: ParsedInputTrivia) : range =
yield!
List.map
(function
- | WarnDirectiveTrivia.Nowarn(_, range)
- | WarnDirectiveTrivia.Warnon(_, range) -> range)
+ | WarnDirectiveTrivia.Nowarn(range)
+ | WarnDirectiveTrivia.Warnon(range) -> range)
trivia.WarnDirectives ]
(baseRange, ranges)
diff --git a/src/Fantomas.Core/Trivia.fs b/src/Fantomas.Core/Trivia.fs
index efa9dcf169..3c8712a931 100644
--- a/src/Fantomas.Core/Trivia.fs
+++ b/src/Fantomas.Core/Trivia.fs
@@ -337,8 +337,8 @@ let enrichTree (config: FormatConfig) (sourceText: ISourceText) (ast: ParsedInpu
(parsedTrivia.ConditionalDirectives |> List.map _.Range)
@ (parsedTrivia.WarnDirectives
|> List.map (function
- | WarnDirectiveTrivia.Nowarn(_, m)
- | WarnDirectiveTrivia.Warnon(_, m) -> m))
+ | WarnDirectiveTrivia.Nowarn(m)
+ | WarnDirectiveTrivia.Warnon(m) -> m))
let directives =
collectTriviaFromDirectiveRanges sourceText directiveRanges fullTreeRange
From 599c6d5ecc50ebdad4d6b4cc4a10ff7f2fbcd412 Mon Sep 17 00:00:00 2001
From: nojaf
Date: Fri, 14 Nov 2025 07:27:31 +0100
Subject: [PATCH 08/11] Mark Range.Zero as obsolete in favor of Range.range0
#18664
---
Directory.Build.props | 2 +-
.../ASTTransformerTests.fs | 14 ++---
.../CodePrinterHelperFunctionsTests.fs | 4 +-
src/Fantomas.Core.Tests/SynLongIdentTests.fs | 10 ++--
src/Fantomas.Core/ASTTransformer.fs | 20 +++----
src/Fantomas.Core/CodePrinter.fs | 12 ++--
src/Fantomas.Core/RangeHelpers.fs | 3 +
src/Fantomas.Core/RangeHelpers.fsi | 3 +
src/Fantomas.Core/Selection.fs | 2 +-
src/Fantomas.Core/SyntaxOak.fs | 58 ++++++++++++++++++-
10 files changed, 94 insertions(+), 34 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 175c26f631..9487c38e23 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -45,7 +45,7 @@ Some common use cases include:
- a3e51909bdeca89357a97e516503e20fd7254f45
+ ee71c6a065bdf57409b16a6bbbfcc3afa2fbef89
diff --git a/src/Fantomas.Core.Tests/ASTTransformerTests.fs b/src/Fantomas.Core.Tests/ASTTransformerTests.fs
index 41a5b7c9e0..2cb7409581 100644
--- a/src/Fantomas.Core.Tests/ASTTransformerTests.fs
+++ b/src/Fantomas.Core.Tests/ASTTransformerTests.fs
@@ -11,8 +11,8 @@ open Fantomas.Core
let ``avoid stack-overflow in long array/list, 2485`` () =
let mkStringExpr () =
SynExpr.Const(
- SynConst.String((System.Guid.NewGuid().ToString("N"), SynStringKind.Regular, Range.Zero)),
- Range.Zero
+ SynConst.String((System.Guid.NewGuid().ToString("N"), SynStringKind.Regular, Range.range0)),
+ Range.range0
)
let longArrayExpr: SynExpr =
@@ -27,28 +27,28 @@ let ``avoid stack-overflow in long array/list, 2485`` () =
true,
mkStringExpr (),
childExpr,
- Range.Zero,
+ Range.range0,
SynExprSequentialTrivia.Zero
))
- SynExpr.ArrayOrListComputed(true, mkArray 0 (mkStringExpr ()), Range.Zero)
+ SynExpr.ArrayOrListComputed(true, mkArray 0 (mkStringExpr ()), Range.range0)
let ast =
ParsedInput.ImplFile(
ParsedImplFileInput(
"filename.fsx",
true,
- QualifiedNameOfFile(Ident("", Range.Zero)),
+ QualifiedNameOfFile(Ident("", Range.range0)),
[],
[ SynModuleOrNamespace(
[],
false,
SynModuleOrNamespaceKind.AnonModule,
- [ SynModuleDecl.Expr(longArrayExpr, Range.Zero) ],
+ [ SynModuleDecl.Expr(longArrayExpr, Range.range0) ],
PreXmlDoc.Empty,
[],
None,
- Range.Zero,
+ Range.range0,
{ LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.None }
) ],
(false, false),
diff --git a/src/Fantomas.Core.Tests/CodePrinterHelperFunctionsTests.fs b/src/Fantomas.Core.Tests/CodePrinterHelperFunctionsTests.fs
index 82d131e21a..5e28a189ab 100644
--- a/src/Fantomas.Core.Tests/CodePrinterHelperFunctionsTests.fs
+++ b/src/Fantomas.Core.Tests/CodePrinterHelperFunctionsTests.fs
@@ -209,7 +209,7 @@ let a =
// Let's create a dummy Oak
// In practise, a FCS Syntax tree will be transformed to an Oak
- let zeroRange = Fantomas.FCS.Text.Range.Zero
+ let zeroRange = Fantomas.FCS.Text.Range.range0
let stn text = SingleTextNode(text, zeroRange)
let tree =
@@ -321,7 +321,7 @@ let b = 2
"""
// Imagine that we always want to print a new line between let bindings.
- let zeroRange = Fantomas.FCS.Text.Range.Zero
+ let zeroRange = Fantomas.FCS.Text.Range.range0
let stn text = SingleTextNode(text, zeroRange)
let mkBinding name body =
diff --git a/src/Fantomas.Core.Tests/SynLongIdentTests.fs b/src/Fantomas.Core.Tests/SynLongIdentTests.fs
index c10079c6c1..ef99c6e95a 100644
--- a/src/Fantomas.Core.Tests/SynLongIdentTests.fs
+++ b/src/Fantomas.Core.Tests/SynLongIdentTests.fs
@@ -344,7 +344,7 @@ let path =
[]
let ``backticks can be added from AST only scenarios`` () =
let tree =
- let testIdent = Ident("Test", Range.Zero)
+ let testIdent = Ident("Test", Range.range0)
ParsedInput.ImplFile(
ParsedImplFileInput(
@@ -360,19 +360,19 @@ let ``backticks can be added from AST only scenarios`` () =
SynExpr.LongIdent(
false,
SynLongIdent(
- [ Ident("new", Range.Zero) ],
+ [ Ident("new", Range.range0) ],
[],
[ Some(IdentTrivia.OriginalNotation "``new``") ]
),
None,
- Range.Zero
+ Range.range0
),
- Range.Zero
+ Range.range0
) ],
PreXmlDoc.Empty,
[],
None,
- Range.Zero,
+ Range.range0,
{ LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.None }
) ],
(true, false),
diff --git a/src/Fantomas.Core/ASTTransformer.fs b/src/Fantomas.Core/ASTTransformer.fs
index fc642da385..cc06be3ffc 100644
--- a/src/Fantomas.Core/ASTTransformer.fs
+++ b/src/Fantomas.Core/ASTTransformer.fs
@@ -1276,7 +1276,7 @@ let mkExpr (creationAide: CreationAide) (e: SynExpr) : Expr =
ExprNamedComputationNode(
mkExpr creationAide expr,
stn "{" mOpen,
- Expr.Ident(stn "" Range.Zero),
+ Expr.Ident(stn "" Range.range0),
stn "}" mClose,
m
)
@@ -1810,7 +1810,7 @@ let mkPat (creationAide: CreationAide) (p: SynPat) =
| None -> unionRanges ident.idRange pat.Range
| Some prefix -> unionRanges prefix.Range pat.Range
- let eqNode = stn "=" (Option.defaultValue Range.Zero eq)
+ let eqNode = stn "=" (Option.defaultValue Range.range0 eq)
PatRecordField(prefix, mkIdent ident, eqNode, mkPat creationAide pat, range))
PatRecordNode(stn "{" o, fields, stn "}" c, patternRange) |> Pattern.Record
@@ -3222,7 +3222,7 @@ let mkModuleOrNamespace
| SynModuleOrNamespaceLeadingKeyword.Namespace mNamespace ->
match kind with
| SynModuleOrNamespaceKind.GlobalNamespace ->
- Some(MultipleTextsNode([ stn "namespace" mNamespace; stn "global" Range.Zero ], mNamespace))
+ Some(MultipleTextsNode([ stn "namespace" mNamespace; stn "global" Range.range0 ], mNamespace))
| _ -> Some(MultipleTextsNode([ stn "namespace" mNamespace ], mNamespace))
| SynModuleOrNamespaceLeadingKeyword.None -> None
@@ -3547,7 +3547,7 @@ let mkModuleOrNamespaceSig
| SynModuleOrNamespaceLeadingKeyword.Namespace mNamespace ->
match kind with
| SynModuleOrNamespaceKind.GlobalNamespace ->
- Some(MultipleTextsNode([ stn "namespace" mNamespace; stn "global" Range.Zero ], mNamespace))
+ Some(MultipleTextsNode([ stn "namespace" mNamespace; stn "global" Range.range0 ], mNamespace))
| _ -> Some(MultipleTextsNode([ stn "namespace" mNamespace ], mNamespace))
| SynModuleOrNamespaceLeadingKeyword.None -> None
@@ -3639,7 +3639,7 @@ let mkSynModuleOrNamespaceFullRange (mn: SynModuleOrNamespace) =
match mn with
| SynModuleOrNamespace(kind = SynModuleOrNamespaceKind.AnonModule; decls = decls) ->
match List.tryHead decls, List.tryLast decls with
- | None, None -> Range.Zero
+ | None, None -> RangeHelpers.absoluteZeroRange
| Some d, None
| None, Some d -> d.Range
| Some s, Some e -> unionRanges s.Range e.Range
@@ -3649,7 +3649,7 @@ let mkSynModuleOrNamespaceSigFullRange (mn: SynModuleOrNamespaceSig) =
match mn with
| SynModuleOrNamespaceSig(kind = SynModuleOrNamespaceKind.AnonModule; decls = decls) ->
match List.tryHead decls, List.tryLast decls with
- | None, None -> Range.Zero
+ | None, None -> RangeHelpers.absoluteZeroRange
| Some d, None
| None, Some d -> d.Range
| Some s, Some e -> unionRanges s.Range e.Range
@@ -3665,13 +3665,13 @@ let mkFullTreeRange ast =
| [] ->
match modules with
| m :: _ -> mkSynModuleOrNamespaceFullRange m
- | _ -> Range.Zero
+ | _ -> RangeHelpers.absoluteZeroRange
let endPos =
match List.tryLast modules with
| None ->
match List.tryLast directives with
- | None -> Range.Zero
+ | None -> RangeHelpers.absoluteZeroRange
| Some(ParsedHashDirective(range = r)) -> r
| Some lastModule -> mkSynModuleOrNamespaceFullRange lastModule
@@ -3685,13 +3685,13 @@ let mkFullTreeRange ast =
| [] ->
match modules with
| m :: _ -> mkSynModuleOrNamespaceSigFullRange m
- | _ -> Range.Zero
+ | _ -> RangeHelpers.absoluteZeroRange
let endPos =
match List.tryLast modules with
| None ->
match List.tryLast directives with
- | None -> Range.Zero
+ | None -> RangeHelpers.absoluteZeroRange
| Some(ParsedHashDirective(range = r)) -> r
| Some lastModule -> mkSynModuleOrNamespaceSigFullRange lastModule
diff --git a/src/Fantomas.Core/CodePrinter.fs b/src/Fantomas.Core/CodePrinter.fs
index 4d46481517..ffe7117d83 100644
--- a/src/Fantomas.Core/CodePrinter.fs
+++ b/src/Fantomas.Core/CodePrinter.fs
@@ -1049,9 +1049,9 @@ let genExpr (e: Expr) =
let parenExpr =
mkExprParenNode
node.OpeningParen
- (Expr.Null(SingleTextNode("", Fantomas.FCS.Text.Range.Zero)))
+ (Expr.Null(SingleTextNode("", Fantomas.FCS.Text.Range.range0)))
node.ClosingParen
- Fantomas.FCS.Text.Range.Zero
+ Fantomas.FCS.Text.Range.range0
sepSpaceBeforeParenInFuncInvocation node.FunctionName parenExpr
| _ -> sepSpace
@@ -1886,16 +1886,16 @@ let genTupleExpr (node: ExprTupleNode) =
| IsLambdaOrIfThenElse e ->
let parenNode =
mkExprParenNode
- (SingleTextNode("(", Fantomas.FCS.Text.Range.Zero))
+ (SingleTextNode("(", Fantomas.FCS.Text.Range.range0))
e
- (SingleTextNode(")", Fantomas.FCS.Text.Range.Zero))
- Fantomas.FCS.Text.Range.Zero
+ (SingleTextNode(")", Fantomas.FCS.Text.Range.range0))
+ Fantomas.FCS.Text.Range.range0
ExprInfixAppNode(
exprInfixAppNode.LeftHandSide,
exprInfixAppNode.Operator,
parenNode,
- Fantomas.FCS.Text.range.Zero
+ Fantomas.FCS.Text.Range.range0
)
|> Expr.InfixApp
| _ -> expr
diff --git a/src/Fantomas.Core/RangeHelpers.fs b/src/Fantomas.Core/RangeHelpers.fs
index 16f3863cd6..bacfae40bc 100644
--- a/src/Fantomas.Core/RangeHelpers.fs
+++ b/src/Fantomas.Core/RangeHelpers.fs
@@ -27,6 +27,9 @@ module RangeHelpers =
startRange, endRange
+ let absoluteZeroRange =
+ Range.mkRange Range.range0.FileName (Position.mkPos 0 0) (Position.mkPos 0 0)
+
module RangePatterns =
let (|StartEndRange|) (size: int) (range: range) =
let o, c = RangeHelpers.mkStartEndRange size range
diff --git a/src/Fantomas.Core/RangeHelpers.fsi b/src/Fantomas.Core/RangeHelpers.fsi
index 36033b7534..7e156375e7 100644
--- a/src/Fantomas.Core/RangeHelpers.fsi
+++ b/src/Fantomas.Core/RangeHelpers.fsi
@@ -8,6 +8,9 @@ module RangeHelpers =
val rangeContainsRange: a: Range -> b: Range -> bool
val rangeEq: (range -> range -> bool)
val isAdjacentTo: r1: Range -> r2: Range -> bool
+ /// Range.range0 starts at line 1, column 0
+ /// This range starts at line 0, column 0
+ val absoluteZeroRange: Range
module RangePatterns =
val (|StartEndRange|): size: int -> range: range -> range * range * range
diff --git a/src/Fantomas.Core/Selection.fs b/src/Fantomas.Core/Selection.fs
index 66d4ad3400..25f68136a8 100644
--- a/src/Fantomas.Core/Selection.fs
+++ b/src/Fantomas.Core/Selection.fs
@@ -95,7 +95,7 @@ let mkExtractableOakFromModule (md: ModuleDecl) (t: System.Type) =
TreeForSelection.RequiresExtraction(Oak([], [ ModuleOrNamespaceNode(None, [ md ], m) ], m), t)
let dummyUnit: Expr =
- UnitNode(SingleTextNode("(", Range.Zero), SingleTextNode(")", Range.Zero), Range.Zero)
+ UnitNode(SingleTextNode("(", Range.range0), SingleTextNode(")", Range.range0), Range.range0)
|> Constant.Unit
|> Expr.Constant
diff --git a/src/Fantomas.Core/SyntaxOak.fs b/src/Fantomas.Core/SyntaxOak.fs
index c15dc6f0da..79e0c4a557 100644
--- a/src/Fantomas.Core/SyntaxOak.fs
+++ b/src/Fantomas.Core/SyntaxOak.fs
@@ -1,6 +1,7 @@
module rec Fantomas.Core.SyntaxOak
open System.Collections.Generic
+open System.Text
open Fantomas.FCS.Text
type TriviaContent =
@@ -15,6 +16,18 @@ type TriviaNode(content: TriviaContent, range: range) =
member val Content = content
member val Range = range
+ override x.ToString() =
+ let rangeStr = $"range: %A{x.Range}"
+
+ match x.Content with
+ | CommentOnSingleLine s -> $"CommentOnSingleLine(%s{rangeStr}, \"%s{s}\")"
+ | LineCommentAfterSourceCode s -> $"LineCommentAfterSourceCode(%s{rangeStr}, \"%s{s}\")"
+ | BlockComment(s, before, after) ->
+ $"BlockComment(%s{rangeStr}, \"%s{s}\", newlineBefore: %b{before}, newlineAfter: %b{after})"
+ | Newline -> $"Newline(%s{rangeStr})"
+ | Directive s -> $"Directive(%s{rangeStr}, \"%s{s}\")"
+ | Cursor -> $"Cursor(%s{rangeStr})"
+
[]
type Node =
abstract ContentBefore: TriviaNode seq
@@ -63,6 +76,47 @@ type NodeBase(range: range) =
member _.AddCursor cursor = potentialCursor <- Some cursor
member _.TryGetCursor = potentialCursor
+ member private x.AppendToStringWithIndent(sb: StringBuilder, depth: int) =
+ let indent = String.replicate depth " "
+ let contentIndent = String.replicate (depth + 1) " "
+
+ sb.Append(indent).Append(x.GetType().Name).Append("(").Append(x.Range) |> ignore
+
+ let hasContentBefore = not (Seq.isEmpty x.ContentBefore)
+ let hasChildren = not (Array.isEmpty x.Children)
+ let hasContentAfter = not (Seq.isEmpty x.ContentAfter)
+ let hasContent = hasContentBefore || hasChildren || hasContentAfter
+
+ if hasContent then
+ sb.AppendLine() |> ignore
+
+ if hasContentBefore then
+ for tn in x.ContentBefore do
+ sb.Append(contentIndent).Append(tn.ToString()).AppendLine() |> ignore
+
+ if hasChildren then
+ for n in x.Children do
+ match n with
+ | :? NodeBase as nb ->
+ nb.AppendToStringWithIndent(sb, depth + 1)
+ sb.AppendLine() |> ignore
+ | _ -> sb.Append(contentIndent).Append(n.ToString()).AppendLine() |> ignore
+
+ if hasContentAfter then
+ for tn in x.ContentAfter do
+ sb.Append(contentIndent).Append(tn.ToString()).AppendLine() |> ignore
+
+ sb.Append(indent).Append(")") |> ignore
+ else
+ sb.Append(")") |> ignore
+
+ member private x.ToStringWithIndent(depth: int) =
+ let sb = StringBuilder()
+ x.AppendToStringWithIndent(sb, depth)
+ sb.ToString()
+
+ override x.ToString() = x.ToStringWithIndent(0)
+
interface Node with
member x.ContentBefore = x.ContentBefore
member x.HasContentBefore = x.HasContentBefore
@@ -91,7 +145,7 @@ let nodeRange (n: Node) = n.Range
let combineRanges (ranges: range seq) =
if Seq.isEmpty ranges then
- Range.Zero
+ Range.range0
else
Seq.reduce Range.unionRanges ranges
@@ -111,7 +165,7 @@ type IdentListNode(content: IdentifierOrDot list, range) =
inherit NodeBase(range)
member val IsEmpty = content.IsEmpty
member val Content = content
- static member Empty = IdentListNode(List.empty, Range.Zero)
+ static member Empty = IdentListNode(List.empty, Range.range0)
override x.Children =
x.Content
From c888913296deea2d6ad1f6f4d397b9b5175830d1 Mon Sep 17 00:00:00 2001
From: nojaf
Date: Fri, 14 Nov 2025 07:45:24 +0100
Subject: [PATCH 09/11] Allow typed bindings(and!) in CE without parentheses
#18682
---
Directory.Build.props | 2 +-
.../ComputationExpressionTests.fs | 62 +++++++++++++++++++
2 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 9487c38e23..5b652b0638 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -45,7 +45,7 @@ Some common use cases include:
- ee71c6a065bdf57409b16a6bbbfcc3afa2fbef89
+ e7abd441a96d555549bfc6e6f84cd3feb897e478
diff --git a/src/Fantomas.Core.Tests/ComputationExpressionTests.fs b/src/Fantomas.Core.Tests/ComputationExpressionTests.fs
index 1b7912be90..42c926327e 100644
--- a/src/Fantomas.Core.Tests/ComputationExpressionTests.fs
+++ b/src/Fantomas.Core.Tests/ComputationExpressionTests.fs
@@ -2467,3 +2467,65 @@ A() {}
"""
A() { }
"""
+
+[]
+let ``typed let bang expression`` () =
+ formatSourceString
+ """
+async {
+ let! { Name = name }: Person = asyncPerson()
+ return name
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+async {
+ let! { Name = name }: Person = asyncPerson ()
+ return name
+}
+"""
+
+[]
+let ``unwrap union case in computation expression`` () =
+ formatSourceString
+ """
+async {
+ let! Union value = asyncOption()
+ ()
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+async {
+ let! Union value = asyncOption ()
+ ()
+}
+"""
+
+[]
+let ``typed and bang expression`` () =
+ formatSourceString
+ """
+async {
+ let! x: int = doX()
+ and! y: int = doY()
+ return x + y
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+async {
+ let! x: int = doX ()
+ and! y: int = doY ()
+ return x + y
+}
+"""
From 2aa9efd1a72c8c2d1ece4fcd7975fcbbddcb23e8 Mon Sep 17 00:00:00 2001
From: nojaf
Date: Fri, 14 Nov 2025 08:57:30 +0100
Subject: [PATCH 10/11] Use Synbinding to model and! #18805
---
Directory.Build.props | 2 +-
docs/docs/contributors/Transforming.md | 9 +++++
.../ComputationExpressionTests.fs | 5 +++
src/Fantomas.Core/ASTTransformer.fs | 35 ++++++++++++-------
src/Fantomas.Core/CodePrinter.fs | 12 ++-----
src/Fantomas.Core/SyntaxOak.fs | 16 +--------
src/Fantomas.Core/Trivia.fs | 1 -
7 files changed, 41 insertions(+), 39 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 67ddff7f00..2db80d1750 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -45,7 +45,7 @@ Some common use cases include:
- e7abd441a96d555549bfc6e6f84cd3feb897e478
+ 8680acde3363052f114d73b0fe21bb3f4cf82b28
diff --git a/docs/docs/contributors/Transforming.md b/docs/docs/contributors/Transforming.md
index 0b96378684..b4ecfddde0 100644
--- a/docs/docs/contributors/Transforming.md
+++ b/docs/docs/contributors/Transforming.md
@@ -74,6 +74,15 @@ let a =
Depending on the defines `[]` or `["DEBUG"]`, the AST will be different.
The tree will also be created based on a single code path.
+You can use your locally installed F# compiler to parse a file and view the AST via:
+
+```shell
+# Tip: figure out the location of your installed sdk
+whereis dotnet
+# Invoke the parser
+dotnet '/Users/nojaf/Library/Application Support/dnvm/dn/sdk/10.0.100/FSharp/fsc.dll' --parseonly --ast foo.fs
+```
+
### Transform untyped AST to Oak
The untyped syntax tree from the F# compiler is used as an intermediate representation of source code in the process of transforming a text file to binary.
diff --git a/src/Fantomas.Core.Tests/ComputationExpressionTests.fs b/src/Fantomas.Core.Tests/ComputationExpressionTests.fs
index 42c926327e..db7038620c 100644
--- a/src/Fantomas.Core.Tests/ComputationExpressionTests.fs
+++ b/src/Fantomas.Core.Tests/ComputationExpressionTests.fs
@@ -1360,6 +1360,11 @@ let loginHandler =
"""
[]
+[]
let ``all keywords`` () =
formatSourceString
"""
diff --git a/src/Fantomas.Core/ASTTransformer.fs b/src/Fantomas.Core/ASTTransformer.fs
index ef999ef55a..dc39d12700 100644
--- a/src/Fantomas.Core/ASTTransformer.fs
+++ b/src/Fantomas.Core/ASTTransformer.fs
@@ -349,18 +349,29 @@ let rec collectComputationExpressionStatements
let andBangs =
andBangs
- |> List.map
- (fun
- (SynExprAndBang(_,
- _,
- _,
- ap,
- ae,
- m,
- { AndBangKeyword = mAnd
- EqualsRange = mEq })) ->
- ExprAndBang(stn "and!" mAnd, mkPat creationAide ap, stn "=" mEq, mkExpr creationAide ae, m)
- |> ComputationExpressionStatement.AndBangStatement)
+ |> List.map (fun binding ->
+ let bindingNode = mkBinding creationAide binding
+ // let SynBinding(trivia = { LeadingKeyword = lk }) = binding is "and" and not "and!"
+
+ BindingNode(
+ bindingNode.XmlDoc,
+ bindingNode.Attributes,
+ MultipleTextsNode(
+ [ stn "and!" bindingNode.LeadingKeyword.Range ],
+ bindingNode.LeadingKeyword.Range
+ ),
+ bindingNode.IsMutable,
+ bindingNode.Inline,
+ bindingNode.Accessibility,
+ bindingNode.FunctionName,
+ bindingNode.GenericTypeParameters,
+ bindingNode.Parameters,
+ bindingNode.ReturnType,
+ bindingNode.Equals,
+ bindingNode.Expr,
+ bindingNode.Range
+ )
+ |> ComputationExpressionStatement.AndBangStatement)
collectComputationExpressionStatements creationAide body (fun bodyStatements ->
[ letOrUseBang; yield! andBangs; yield! bodyStatements ] |> finalContinuation)
diff --git a/src/Fantomas.Core/CodePrinter.fs b/src/Fantomas.Core/CodePrinter.fs
index cdeda4f1be..31337f5436 100644
--- a/src/Fantomas.Core/CodePrinter.fs
+++ b/src/Fantomas.Core/CodePrinter.fs
@@ -663,15 +663,7 @@ let genExpr (e: Expr) =
ColMultilineItem(expr, sepNlnUnlessContentBefore node)
| ComputationExpressionStatement.AndBangStatement node ->
- let expr =
- genSingleTextNode node.LeadingKeyword
- +> sepSpace
- +> genPat node.Pattern
- +> sepSpace
- +> genSingleTextNode node.Equals
- +> sepSpaceOrIndentAndNlnIfExpressionExceedsPageWidthUnlessStroustrup genExpr node.Expression
- |> genNode node
-
+ let expr = genBinding node
ColMultilineItem(expr, sepNlnUnlessContentBefore node)
| ComputationExpressionStatement.OtherStatement e ->
ColMultilineItem(genExpr e, sepNlnUnlessContentBefore (Expr.Node e)))
@@ -2831,7 +2823,7 @@ let genBinding (b: BindingNode) (ctx: Context) : Context =
let isRecursiveLetOrUseFunction =
match b.LeadingKeyword.Content with
- | [ singleText ] -> singleText.Text = "and"
+ | [ singleText ] -> singleText.Text = "and" || singleText.Text = "and!"
| _ -> false
let binding =
diff --git a/src/Fantomas.Core/SyntaxOak.fs b/src/Fantomas.Core/SyntaxOak.fs
index 79e0c4a557..27074f18e8 100644
--- a/src/Fantomas.Core/SyntaxOak.fs
+++ b/src/Fantomas.Core/SyntaxOak.fs
@@ -1070,25 +1070,11 @@ type ExprLetOrUseBangNode(leadingKeyword: SingleTextNode, pat: Pattern, equals:
member val Equals = equals
member val Expression = expr
-type ExprAndBang(leadingKeyword: SingleTextNode, pat: Pattern, equals: SingleTextNode, expr: Expr, range) =
- inherit NodeBase(range)
-
- override val Children: Node array =
- [| yield leadingKeyword
- yield Pattern.Node pat
- yield equals
- yield Expr.Node expr |]
-
- member val LeadingKeyword = leadingKeyword
- member val Pattern = pat
- member val Equals = equals
- member val Expression = expr
-
[]
type ComputationExpressionStatement =
| LetOrUseStatement of ExprLetOrUseNode
| LetOrUseBangStatement of ExprLetOrUseBangNode
- | AndBangStatement of ExprAndBang
+ | AndBangStatement of BindingNode
| OtherStatement of Expr
static member Node(ces: ComputationExpressionStatement) : Node =
diff --git a/src/Fantomas.Core/Trivia.fs b/src/Fantomas.Core/Trivia.fs
index 9e0c24057a..eb1faafbd4 100644
--- a/src/Fantomas.Core/Trivia.fs
+++ b/src/Fantomas.Core/Trivia.fs
@@ -188,7 +188,6 @@ let rec visitLastChildNode (node: Node) : Node =
| :? ExprLambdaNode
| :? ExprLetOrUseNode
| :? ExprLetOrUseBangNode
- | :? ExprAndBang
| :? BindingNode
| :? TypeDefnEnumNode
| :? TypeDefnUnionNode
From e95be8919a360b27556bbab9a73401cd93e7ad1c Mon Sep 17 00:00:00 2001
From: nojaf
Date: Fri, 14 Nov 2025 13:39:22 +0100
Subject: [PATCH 11/11] Update FCS to Remove LetOrUseKeyword from
SynExprLetOrUseTrivia #19090
---
Directory.Build.props | 2 +-
build.fsx | 4 +-
.../ComputationExpressionTests.fs | 4 +-
src/Fantomas.Core/ASTTransformer.fs | 77 ++++---------------
src/Fantomas.Core/CodePrinter.fs | 64 ++++-----------
src/Fantomas.Core/SyntaxOak.fs | 29 ++-----
src/Fantomas.FCS/Fantomas.FCS.fsproj | 6 ++
7 files changed, 50 insertions(+), 136 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 2db80d1750..cb27543393 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -45,7 +45,7 @@ Some common use cases include:
- 8680acde3363052f114d73b0fe21bb3f4cf82b28
+ 44c58e9663ebcb52f0eebd618af50852a831a50d
diff --git a/build.fsx b/build.fsx
index d05a14437d..11246e57c0 100644
--- a/build.fsx
+++ b/build.fsx
@@ -210,7 +210,7 @@ let downloadCompilerFile commitHash relativePath =
let fs = file.Create()
let fileName = Path.GetFileName(relativePath)
let url =
- $"https://raw.githubusercontent.com/dotnet/fsharp/{commitHash}/{relativePath}"
+ $"https://raw.githubusercontent.com/nojaf/fsharp/{commitHash}/{relativePath}"
let! response =
Http.AsyncRequestStream(
url,
@@ -233,6 +233,8 @@ pipeline "Init" {
"src/Compiler/Utilities/NullnessShims.fs"
"src/Compiler/Utilities/Activity.fsi"
"src/Compiler/Utilities/Activity.fs"
+ "src/Compiler/Utilities/Caches.fsi"
+ "src/Compiler/Utilities/Caches.fs"
"src/Compiler/Utilities/sformat.fsi"
"src/Compiler/Utilities/sformat.fs"
"src/Compiler/Utilities/sr.fsi"
diff --git a/src/Fantomas.Core.Tests/ComputationExpressionTests.fs b/src/Fantomas.Core.Tests/ComputationExpressionTests.fs
index db7038620c..aeaff8d4ec 100644
--- a/src/Fantomas.Core.Tests/ComputationExpressionTests.fs
+++ b/src/Fantomas.Core.Tests/ComputationExpressionTests.fs
@@ -1647,7 +1647,9 @@ let private removeSubscription (log : ILogger) (req : HttpRequest) =
return sendText "Subscription removed"
}
"""
- { config with SpaceBeforeColon = true }
+ { config with
+ SpaceBeforeColon = true
+ MaxValueBindingWidth = 120 }
|> prepend newline
|> should
equal
diff --git a/src/Fantomas.Core/ASTTransformer.fs b/src/Fantomas.Core/ASTTransformer.fs
index dc39d12700..a7db1b7842 100644
--- a/src/Fantomas.Core/ASTTransformer.fs
+++ b/src/Fantomas.Core/ASTTransformer.fs
@@ -298,10 +298,10 @@ let mkTuple (creationAide: CreationAide) (exprs: SynExpr list) (commas: range li
/// Recursive and use properties have to be determined at this point
let rec (|LetOrUses|_|) =
function
- | SynExpr.LetOrUse(_, _, xs, LetOrUses(ys, e), _, trivia) ->
+ | SynExpr.LetOrUse(bindings = xs; body = LetOrUses(ys, e); trivia = trivia) ->
let xs' = List.mapWithLast (fun b -> b, None) (fun b -> b, trivia.InKeyword) xs
Some(xs' @ ys, e)
- | SynExpr.LetOrUse(_, _, xs, e, _, trivia) ->
+ | SynExpr.LetOrUse(bindings = xs; body = e; trivia = trivia) ->
let xs' = List.mapWithLast (fun b -> b, None) (fun b -> b, trivia.InKeyword) xs
Some(xs', e)
| _ -> None
@@ -324,57 +324,10 @@ let rec collectComputationExpressionStatements
| Some mIn -> Some(stn "in" mIn), unionRanges b.Range mIn
ExprLetOrUseNode(b, inNode, m)
- |> ComputationExpressionStatement.LetOrUseStatement)
+ |> ComputationExpressionStatement.BindingStatement)
collectComputationExpressionStatements creationAide body (fun bodyStatements ->
[ yield! bindings; yield! bodyStatements ] |> finalContinuation)
- | SynExpr.LetOrUseBang(_,
- isUse,
- _,
- pat,
- expr,
- andBangs,
- body,
- StartRange 4 (mLeading, _m),
- { EqualsRange = Some mEq }) ->
- let letOrUseBang =
- ExprLetOrUseBangNode(
- stn (if isUse then "use!" else "let!") mLeading,
- mkPat creationAide pat,
- stn "=" mEq,
- mkExpr creationAide expr,
- unionRanges mLeading expr.Range
- )
- |> ComputationExpressionStatement.LetOrUseBangStatement
-
- let andBangs =
- andBangs
- |> List.map (fun binding ->
- let bindingNode = mkBinding creationAide binding
- // let SynBinding(trivia = { LeadingKeyword = lk }) = binding is "and" and not "and!"
-
- BindingNode(
- bindingNode.XmlDoc,
- bindingNode.Attributes,
- MultipleTextsNode(
- [ stn "and!" bindingNode.LeadingKeyword.Range ],
- bindingNode.LeadingKeyword.Range
- ),
- bindingNode.IsMutable,
- bindingNode.Inline,
- bindingNode.Accessibility,
- bindingNode.FunctionName,
- bindingNode.GenericTypeParameters,
- bindingNode.Parameters,
- bindingNode.ReturnType,
- bindingNode.Equals,
- bindingNode.Expr,
- bindingNode.Range
- )
- |> ComputationExpressionStatement.AndBangStatement)
-
- collectComputationExpressionStatements creationAide body (fun bodyStatements ->
- [ letOrUseBang; yield! andBangs; yield! bodyStatements ] |> finalContinuation)
| SynExpr.Sequential(expr1 = e1; expr2 = e2; trivia = trivia) ->
let continuations
: ((ComputationExpressionStatement list -> ComputationExpressionStatement list)
@@ -1192,7 +1145,6 @@ let mkExpr (creationAide: CreationAide) (e: SynExpr) : Expr =
|> Expr.Computation
| SynExpr.LetOrUse _
- | SynExpr.LetOrUseBang _
| SynExpr.Sequential _ ->
ExprCompExprBodyNode(collectComputationExpressionStatements creationAide e id, exprRange)
|> Expr.CompExprBody
@@ -1767,14 +1719,14 @@ let mkPat (creationAide: CreationAide) (p: SynPat) =
let pairs =
nps
- |> List.choose (fun (ident, eq, pat) ->
+ |> List.choose (fun (NamePatPairField(fieldName = fieldName; equalsRange = eq; pat = pat)) ->
eq
|> Option.map (fun eq ->
- NamePatPair(
- mkIdent ident,
+ NamePatPairNode(
+ mkSynLongIdent creationAide fieldName,
stn "=" eq,
mkPat creationAide pat,
- unionRanges ident.idRange pat.Range
+ unionRanges fieldName.Range pat.Range
)))
PatNamePatPairsNode(
@@ -1813,16 +1765,10 @@ let mkPat (creationAide: CreationAide) (p: SynPat) =
| SynPat.Record(fields, StartEndRange 1 (o, _, c)) ->
let fields =
fields
- |> List.map (fun ((lid, ident), eq, pat) ->
- let prefix = if lid.IsEmpty then None else Some(mkLongIdent lid)
-
- let range =
- match prefix with
- | None -> unionRanges ident.idRange pat.Range
- | Some prefix -> unionRanges prefix.Range pat.Range
-
+ |> List.map (fun (NamePatPairField(fieldName = fieldName; equalsRange = eq; pat = pat) as np) ->
+ let range = np.Range // TODO: might be wrong unionRanges prefix.Range pat.Range
let eqNode = stn "=" (Option.defaultValue Range.range0 eq)
- PatRecordField(prefix, mkIdent ident, eqNode, mkPat creationAide pat, range))
+ NamePatPairNode(mkSynLongIdent creationAide fieldName, eqNode, mkPat creationAide pat, range))
PatRecordNode(stn "{" o, fields, stn "}" c, patternRange) |> Pattern.Record
| SynPat.Const(c, r) -> mkConstant creationAide c r |> Pattern.Const
@@ -2410,9 +2356,12 @@ let mkSynLeadingKeyword (lk: SynLeadingKeyword) =
match lk with
| SynLeadingKeyword.Let letRange -> mtn [ "let", letRange ]
+ | SynLeadingKeyword.LetBang letBangRange -> mtn [ "let!", letBangRange ]
| SynLeadingKeyword.LetRec(letRange, recRange) -> mtn [ "let", letRange; "rec", recRange ]
| SynLeadingKeyword.And andRange -> mtn [ "and", andRange ]
+ | SynLeadingKeyword.AndBang andBangRange -> mtn [ "and!", andBangRange ]
| SynLeadingKeyword.Use useRange -> mtn [ "use", useRange ]
+ | SynLeadingKeyword.UseBang useBangRange -> mtn [ "use!", useBangRange ]
| SynLeadingKeyword.UseRec(useRange, recRange) -> mtn [ "use", useRange; "rec", recRange ]
| SynLeadingKeyword.Extern externRange -> mtn [ "extern", externRange ]
| SynLeadingKeyword.Member memberRange -> mtn [ "member", memberRange ]
diff --git a/src/Fantomas.Core/CodePrinter.fs b/src/Fantomas.Core/CodePrinter.fs
index 31337f5436..dd54fb589a 100644
--- a/src/Fantomas.Core/CodePrinter.fs
+++ b/src/Fantomas.Core/CodePrinter.fs
@@ -644,26 +644,12 @@ let genExpr (e: Expr) =
let genStatements =
node.Statements
|> List.map (function
- | ComputationExpressionStatement.LetOrUseStatement node ->
+ | ComputationExpressionStatement.BindingStatement node ->
let expr =
genBinding node.Binding
+> optSingle (fun inNode -> sepSpace +> genSingleTextNode inNode) node.In
|> genNode node
- ColMultilineItem(expr, sepNlnUnlessContentBefore node)
- | ComputationExpressionStatement.LetOrUseBangStatement node ->
- let expr =
- genSingleTextNode node.LeadingKeyword
- +> sepSpace
- +> genPat node.Pattern
- +> sepSpace
- +> genSingleTextNode node.Equals
- +> sepSpaceOrIndentAndNlnIfExpressionExceedsPageWidthUnlessStroustrup genExpr node.Expression
- |> genNode node
-
- ColMultilineItem(expr, sepNlnUnlessContentBefore node)
- | ComputationExpressionStatement.AndBangStatement node ->
- let expr = genBinding node
ColMultilineItem(expr, sepNlnUnlessContentBefore node)
| ComputationExpressionStatement.OtherStatement e ->
ColMultilineItem(genExpr e, sepNlnUnlessContentBefore (Expr.Node e)))
@@ -671,7 +657,7 @@ let genExpr (e: Expr) =
|> genNode node
match node.Statements with
- | [ ComputationExpressionStatement.LetOrUseStatement letOrUseNode
+ | [ ComputationExpressionStatement.BindingStatement letOrUseNode
ComputationExpressionStatement.OtherStatement inExpr ] when letOrUseNode.In.IsSome ->
let short =
(genBinding letOrUseNode.Binding
@@ -2232,7 +2218,7 @@ let genExprInMultilineInfixExpr (e: Expr) =
node.Statements
|> List.mapWithLast
(function
- | ComputationExpressionStatement.LetOrUseStatement _ -> true
+ | ComputationExpressionStatement.BindingStatement _ -> true
| _ -> false)
(function
| ComputationExpressionStatement.OtherStatement _ -> true
@@ -2247,7 +2233,7 @@ let genExprInMultilineInfixExpr (e: Expr) =
ComputationExpressionStatement.Node
(fun ces ->
match ces with
- | ComputationExpressionStatement.LetOrUseStatement letOrUseNode ->
+ | ComputationExpressionStatement.BindingStatement letOrUseNode ->
let genIn =
match letOrUseNode.In with
| None -> !-"in"
@@ -2618,6 +2604,14 @@ let genTuplePat (node: PatTupleNode) =
atCurrentColumn (expressionFitsOnRestOfLine short (atCurrentColumn (genTuplePatLong node)))
|> genNode node
+let genNamePatPair (node: NamePatPairNode) =
+ genIdentListNode node.FieldName
+ +> sepSpace
+ +> genSingleTextNode node.Equals
+ +> sepSpace
+ +> genPat node.Pattern
+ |> genNode node
+
let genPat (p: Pattern) =
match p with
| Pattern.OptionalVal n -> genSingleTextNode n
@@ -2646,18 +2640,11 @@ let genPat (p: Pattern) =
| Pattern.As node
| Pattern.ListCons node -> genPatLeftMiddleRight node
| Pattern.NamePatPairs node ->
- let genPatWithIdent (node: NamePatPair) =
- genSingleTextNode node.Ident
- +> sepSpace
- +> genSingleTextNode node.Equals
- +> sepSpace
- +> genPat node.Pattern
- |> genNode node
let pats =
expressionFitsOnRestOfLine
- (atCurrentColumn (col sepSemi node.Pairs genPatWithIdent))
- (atCurrentColumn (col sepNln node.Pairs genPatWithIdent))
+ (atCurrentColumn (col sepSemi node.Pairs genNamePatPair))
+ (atCurrentColumn (col sepNln node.Pairs genNamePatPair))
genIdentListNode node.Identifier
+> optSingle genTyparDecls node.TyparDecls
@@ -2724,14 +2711,14 @@ let genPat (p: Pattern) =
let smallRecordExpr =
genSingleTextNode node.OpeningNode
+> addSpaceIfSpaceAroundDelimiter
- +> col sepSemi node.Fields genPatRecordFieldName
+ +> col sepSemi node.Fields genNamePatPair
+> addSpaceIfSpaceAroundDelimiter
+> genSingleTextNode node.ClosingNode
let multilineRecordExpr =
genSingleTextNode node.OpeningNode
+> addSpaceIfSpaceAroundDelimiter
- +> atCurrentColumn (col sepNln node.Fields genPatRecordFieldName)
+ +> atCurrentColumn (col sepNln node.Fields genNamePatPair)
+> addSpaceIfSpaceAroundDelimiter
+> genSingleTextNode node.ClosingNode
@@ -2739,7 +2726,7 @@ let genPat (p: Pattern) =
genSingleTextNode node.OpeningNode
+> indent
+> sepNln
- +> atCurrentColumn (col sepNln node.Fields genPatRecordFieldName)
+ +> atCurrentColumn (col sepNln node.Fields genNamePatPair)
+> unindent
+> sepNln
+> genSingleTextNode node.ClosingNode
@@ -2782,23 +2769,6 @@ let genPatInClause (pat: Pattern) =
genPatMultiline pat
-let genPatRecordFieldName (node: PatRecordField) =
- match node.Prefix with
- | None ->
- genSingleTextNode node.FieldName
- +> sepSpace
- +> genSingleTextNode node.Equals
- +> sepSpace
- +> genPat node.Pattern
- | Some prefix ->
- genIdentListNode prefix
- +> sepDot
- +> genSingleTextNode node.FieldName
- +> sepSpace
- +> genSingleTextNode node.Equals
- +> sepSpace
- +> genPat node.Pattern
-
let genReturnTypeBinding (node: BindingReturnInfoNode option) =
match node with
| None -> sepNone
diff --git a/src/Fantomas.Core/SyntaxOak.fs b/src/Fantomas.Core/SyntaxOak.fs
index 27074f18e8..d0c41d7d9d 100644
--- a/src/Fantomas.Core/SyntaxOak.fs
+++ b/src/Fantomas.Core/SyntaxOak.fs
@@ -531,10 +531,10 @@ type PatNamedNode(accessibility: SingleTextNode option, name: SingleTextNode, ra
member val Name = name
member val Accessibility = accessibility
-type NamePatPair(ident: SingleTextNode, equals: SingleTextNode, pat: Pattern, range) =
+type NamePatPairNode(fieldName: IdentListNode, equals: SingleTextNode, pat: Pattern, range) =
inherit NodeBase(range)
- override val Children: Node array = [| yield ident; yield equals; yield Pattern.Node pat |]
- member val Ident = ident
+ override val Children: Node array = [| yield fieldName; yield equals; yield Pattern.Node pat |]
+ member val FieldName = fieldName
member val Equals = equals
member val Pattern = pat
@@ -543,7 +543,7 @@ type PatNamePatPairsNode
identifier: IdentListNode,
typarDecls: TyparDecls option,
openingParen: SingleTextNode,
- pairs: NamePatPair list,
+ pairs: NamePatPairNode list,
closingParen: SingleTextNode,
range
) =
@@ -618,18 +618,7 @@ type PatArrayOrListNode(openToken: SingleTextNode, pats: Pattern list, closeToke
member val Patterns = pats
member val CloseToken = closeToken
-type PatRecordField
- (prefix: IdentListNode option, fieldName: SingleTextNode, equals: SingleTextNode, pat: Pattern, range) =
- inherit NodeBase(range)
-
- override val Children: Node array = [| yield! noa prefix; yield fieldName; yield equals; yield Pattern.Node pat |]
-
- member val Prefix = prefix
- member val FieldName = fieldName
- member val Equals = equals
- member val Pattern = pat
-
-type PatRecordNode(openingNode: SingleTextNode, fields: PatRecordField list, closingNode: SingleTextNode, range) =
+type PatRecordNode(openingNode: SingleTextNode, fields: NamePatPairNode list, closingNode: SingleTextNode, range) =
inherit NodeBase(range)
override val Children: Node array = [| yield openingNode; yield! nodes fields; yield closingNode |]
@@ -1072,16 +1061,12 @@ type ExprLetOrUseBangNode(leadingKeyword: SingleTextNode, pat: Pattern, equals:
[]
type ComputationExpressionStatement =
- | LetOrUseStatement of ExprLetOrUseNode
- | LetOrUseBangStatement of ExprLetOrUseBangNode
- | AndBangStatement of BindingNode
+ | BindingStatement of ExprLetOrUseNode
| OtherStatement of Expr
static member Node(ces: ComputationExpressionStatement) : Node =
match ces with
- | LetOrUseStatement n -> n
- | LetOrUseBangStatement n -> n
- | AndBangStatement n -> n
+ | BindingStatement n -> n
| OtherStatement o -> Expr.Node o
type ExprCompExprBodyNode(statements: ComputationExpressionStatement list, range) =
diff --git a/src/Fantomas.FCS/Fantomas.FCS.fsproj b/src/Fantomas.FCS/Fantomas.FCS.fsproj
index 26de30e34b..dbc05bc235 100644
--- a/src/Fantomas.FCS/Fantomas.FCS.fsproj
+++ b/src/Fantomas.FCS/Fantomas.FCS.fsproj
@@ -33,6 +33,12 @@
Utilities\Activity.fs
+
+ Utilities\Caches.fsi
+
+
+ Utilities\Caches.fs
+
Utilities\sformat.fsi