diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 084ce71ec..bda0692f1 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:8.0.300 +FROM mcr.microsoft.com/dotnet/sdk:8.0.400 # Avoid warnings by switching to noninteractive ENV DEBIAN_FRONTEND=noninteractive diff --git a/CHANGELOG.md b/CHANGELOG.md index 62c59b864..356ba2f48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 7.0.0-alpha-001 - 2024-09-16 + +### Added +* Add initial support for Nullness syntax. [#3118](https://github.com/fsprojects/fantomas/pull/3118) + +### Changed +* Update FCS to 'Add trivia to Nullness nodes in SyntaxTree', commit 836d4e0603442d6053c8d439993a022501cae494 [#3118](https://github.com/fsprojects/fantomas/pull/3118) + ## 6.3.15 - 2024-09-14 ### Fixed diff --git a/Directory.Build.props b/Directory.Build.props index 7c22db742..26e34508a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -40,12 +40,12 @@ Some common use cases include: true true - $(OtherFlags) --test:GraphBasedChecking --test:ParallelOptimization --test:ParallelIlxGen --strict-indentation+ + $(OtherFlags) --test:GraphBasedChecking --test:ParallelOptimization --test:ParallelIlxGen --strict-indentation+ --realsig+ - 836d4e0603442d6053c8d439993a022501cae494 + e668b90e3c087e5fba8a855e502af60bf35be45e diff --git a/Directory.Packages.props b/Directory.Packages.props index 12d2619ec..37b265adc 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,6 +1,7 @@ true + true @@ -18,6 +19,7 @@ + diff --git a/build.fsx b/build.fsx index bd18e4e44..49be79b35 100644 --- a/build.fsx +++ b/build.fsx @@ -194,6 +194,8 @@ let updateFileRaw (file: FileInfo) = |> Array.map (fun line -> if line.Contains("FSharp.Compiler") then line.Replace("FSharp.Compiler", "Fantomas.FCS") + elif line.Contains("[]") then + line.Replace("[]", "[]") else line) File.WriteAllLines(file.FullName, updatedLines) @@ -228,6 +230,7 @@ pipeline "Init" { run (fun _ -> [| "src/Compiler/FSComp.txt" "src/Compiler/FSStrings.resx" + "src/Compiler/Utilities/NullnessShims.fs" "src/Compiler/Utilities/Activity.fsi" "src/Compiler/Utilities/Activity.fs" "src/Compiler/Utilities/sformat.fsi" diff --git a/global.json b/global.json index 8d0a1c0ac..6f6aff9de 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.300", - "rollForward": "latestMinor" + "version": "8.0.400", + "rollForward": "latestPatch" } } \ No newline at end of file diff --git a/src/Fantomas.Client.Tests/packages.lock.json b/src/Fantomas.Client.Tests/packages.lock.json index 995df0067..c3cc3d7db 100644 --- a/src/Fantomas.Client.Tests/packages.lock.json +++ b/src/Fantomas.Client.Tests/packages.lock.json @@ -91,8 +91,8 @@ }, "Microsoft.NETCore.Targets": { "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + "resolved": "1.1.3", + "contentHash": "3Wrmi0kJDzClwAC+iBdUBpEKmEle8FQNsCs77fkiOIw/9oYA07bL1EZNX0kQ2OMN3xpwvl0vAtOCYY3ndDNlhQ==" }, "Microsoft.TestPlatform.ObjectModel": { "type": "Transitive", @@ -166,11 +166,6 @@ "System.Runtime.CompilerServices.Unsafe": "4.7.1" } }, - "Newtonsoft.Json": { - "type": "Transitive", - "resolved": "13.0.1", - "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" - }, "NuGet.Frameworks": { "type": "Transitive", "resolved": "6.5.0", @@ -765,6 +760,12 @@ "StreamJsonRpc": "[2.8.28, )" } }, + "Newtonsoft.Json": { + "type": "CentralTransitive", + "requested": "[13.0.3, )", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, "SemanticVersioning": { "type": "CentralTransitive", "requested": "[2.0.2, )", @@ -796,29 +797,29 @@ "System.Collections.Immutable": { "type": "CentralTransitive", "requested": "[7.0.0, )", - "resolved": "5.0.0", - "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" + "resolved": "7.0.0", + "contentHash": "dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ==" }, "System.Diagnostics.DiagnosticSource": { "type": "CentralTransitive", "requested": "[7.0.0, )", - "resolved": "5.0.1", - "contentHash": "uXQEYqav2V3zP6OwkOKtLv+qIi6z3m1hsGyKwXX7ZA7htT4shoVccGxnJ9kVRFPNAsi1ArZTq2oh7WOto6GbkQ==" + "resolved": "7.0.0", + "contentHash": "9W0ewWDuAyDqS2PigdTxk6jDKonfgscY/hP8hm7VpxYhNHZHKvZTdRckberlFk3VnCmr3xBUyMBut12Q+T2aOw==" }, "System.Memory": { "type": "CentralTransitive", "requested": "[4.5.5, )", - "resolved": "4.5.4", - "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + "resolved": "4.5.5", + "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==" }, "System.Runtime": { "type": "CentralTransitive", "requested": "[4.3.1, )", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "resolved": "4.3.1", + "contentHash": "abhfv1dTK6NXOmu4bgHIONxHyEqFjW8HwXPmpY9gmll+ix9UNo4XDcmzJn6oLooftxNssVHdJC1pGT9jkSynQg==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" + "Microsoft.NETCore.Platforms": "1.1.1", + "Microsoft.NETCore.Targets": "1.1.3" } } } diff --git a/src/Fantomas.Client/packages.lock.json b/src/Fantomas.Client/packages.lock.json index 484f33f58..57fc70151 100644 --- a/src/Fantomas.Client/packages.lock.json +++ b/src/Fantomas.Client/packages.lock.json @@ -121,8 +121,8 @@ }, "Microsoft.NETCore.Targets": { "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + "resolved": "1.1.3", + "contentHash": "3Wrmi0kJDzClwAC+iBdUBpEKmEle8FQNsCs77fkiOIw/9oYA07bL1EZNX0kQ2OMN3xpwvl0vAtOCYY3ndDNlhQ==" }, "Microsoft.SourceLink.AzureRepos.Git": { "type": "Transitive", @@ -221,11 +221,6 @@ "System.Runtime.CompilerServices.Unsafe": "4.7.1" } }, - "Newtonsoft.Json": { - "type": "Transitive", - "resolved": "12.0.2", - "contentHash": "rTK0s2EKlfHsQsH6Yx2smvcTCeyoDNgCW7FEYyV01drPlh2T243PR2DiDXqtC5N4GDm4Ma/lkxfW5a/4793vbA==" - }, "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { "type": "Transitive", "resolved": "4.3.2", @@ -584,8 +579,8 @@ }, "System.Runtime.CompilerServices.Unsafe": { "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "ZD9TMpsmYJLrxbbmdvhwt9YEgG5WntEnZ/d1eH8JBX9LBp+Ju8BSBhUGbZMNVHHomWo2KVImJhTDl2hIgw/6MA==" + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" }, "System.Runtime.Extensions": { "type": "Transitive", @@ -830,30 +825,37 @@ "System.Runtime.CompilerServices.Unsafe": "4.5.3" } }, + "Newtonsoft.Json": { + "type": "CentralTransitive", + "requested": "[13.0.3, )", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, "System.Collections.Immutable": { "type": "CentralTransitive", "requested": "[7.0.0, )", - "resolved": "5.0.0", - "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==", + "resolved": "7.0.0", + "contentHash": "dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ==", "dependencies": { - "System.Memory": "4.5.4" + "System.Memory": "4.5.5", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Diagnostics.DiagnosticSource": { "type": "CentralTransitive", "requested": "[7.0.0, )", - "resolved": "5.0.1", - "contentHash": "uXQEYqav2V3zP6OwkOKtLv+qIi6z3m1hsGyKwXX7ZA7htT4shoVccGxnJ9kVRFPNAsi1ArZTq2oh7WOto6GbkQ==", + "resolved": "7.0.0", + "contentHash": "9W0ewWDuAyDqS2PigdTxk6jDKonfgscY/hP8hm7VpxYhNHZHKvZTdRckberlFk3VnCmr3xBUyMBut12Q+T2aOw==", "dependencies": { - "System.Memory": "4.5.4", - "System.Runtime.CompilerServices.Unsafe": "5.0.0" + "System.Memory": "4.5.5", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Memory": { "type": "CentralTransitive", "requested": "[4.5.5, )", - "resolved": "4.5.4", - "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==", + "resolved": "4.5.5", + "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==", "dependencies": { "System.Buffers": "4.5.1", "System.Numerics.Vectors": "4.4.0", @@ -863,11 +865,11 @@ "System.Runtime": { "type": "CentralTransitive", "requested": "[4.3.1, )", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "resolved": "4.3.1", + "contentHash": "abhfv1dTK6NXOmu4bgHIONxHyEqFjW8HwXPmpY9gmll+ix9UNo4XDcmzJn6oLooftxNssVHdJC1pGT9jkSynQg==", "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" + "Microsoft.NETCore.Platforms": "1.1.1", + "Microsoft.NETCore.Targets": "1.1.3" } } } diff --git a/src/Fantomas.Core.Tests/AutoPropertiesTests.fs b/src/Fantomas.Core.Tests/AutoPropertiesTests.fs new file mode 100644 index 000000000..ab6a962df --- /dev/null +++ b/src/Fantomas.Core.Tests/AutoPropertiesTests.fs @@ -0,0 +1,95 @@ +module Fantomas.Core.Tests.AutoPropertiesTests + +open NUnit.Framework +open FsUnit +open Fantomas.Core.Tests.TestHelpers + +[] +let ``public get, private set`` () = + formatSourceString + """ +type X() = + member val Y: int = 7 with public get, private set +""" + config + |> prepend newline + |> should + equal + """ +type X() = + member val Y: int = 7 with public get, private set +""" + +[] +let ``plain get, private set`` () = + formatSourceString + """ +type X() = + member val Y: int = 7 with get, private set +""" + config + |> prepend newline + |> should + equal + """ +type X() = + member val Y: int = 7 with get, private set +""" + +[] +let ``internal get, plain set`` () = + formatSourceString + """ +type X() = + member val Y: int = 7 with internal get, set +""" + config + |> prepend newline + |> should + equal + """ +type X() = + member val Y: int = 7 with internal get, set +""" + +[] +let ``public get, private set in signature`` () = + formatSignatureString + """ +module A + +type X = + new: unit -> X + member internal Y: int with public get, private set +""" + config + |> prepend newline + |> should + equal + """ +module A + +type X = + new: unit -> X + member internal Y: int with public get, private set +""" + +[] +let ``abstract member with public get, private set`` () = + formatSignatureString + """ +namespace Meh + +type X = + abstract Y: int with public get, private set +""" + config + |> prepend newline + |> should + equal + """ +namespace Meh + +type X = + abstract Y: int with public get, private set +""" diff --git a/src/Fantomas.Core.Tests/Fantomas.Core.Tests.fsproj b/src/Fantomas.Core.Tests/Fantomas.Core.Tests.fsproj index 78718e432..f764d1de9 100644 --- a/src/Fantomas.Core.Tests/Fantomas.Core.Tests.fsproj +++ b/src/Fantomas.Core.Tests/Fantomas.Core.Tests.fsproj @@ -132,6 +132,8 @@ + + diff --git a/src/Fantomas.Core.Tests/NullnessTests.fs b/src/Fantomas.Core.Tests/NullnessTests.fs new file mode 100644 index 000000000..2f80450a3 --- /dev/null +++ b/src/Fantomas.Core.Tests/NullnessTests.fs @@ -0,0 +1,150 @@ +module Fantomas.Core.Tests.NullnessTests + +open NUnit.Framework +open FsUnit +open Fantomas.Core.Tests.TestHelpers + +[] +let ``du case of string or null`` () = + formatSourceString + """ +type DU = MyCase of (string | null) +""" + config + |> prepend newline + |> should + equal + """ +type DU = MyCase of (string | null) +""" + +[] +let ``multiple or type`` () = + formatSourceString + """ +let myFunc ("abc" | "" : string | null | "123") = 15 +""" + config + |> prepend newline + |> should + equal + """ +let myFunc ("abc" | "": string | null | "123") = 15 +""" + +[] +let ``null type constraint`` () = + formatSourceString + """ +let myFunc() : 'T when 'T : not struct and 'T:null = null +""" + config + |> prepend newline + |> should + equal + """ +let myFunc () : 'T when 'T: not struct and 'T: null = null +""" + +[] +let ``not null type constraint`` () = + formatSourceString + """ +let myFunc (x: 'T when 'T: not null) = 42 +""" + config + |> prepend newline + |> should + equal + """ +let myFunc (x: 'T when 'T: not null) = 42 +""" + +[] +let ``not null in type constraints`` () = + formatSourceString + """ +type C<'T when 'T: not null> = class end +""" + config + |> prepend newline + |> should + equal + """ +type C<'T when 'T: not null> = class end +""" + +[] +let ``or null pattern`` () = + formatSourceString + """ +match x with +| :? string | null -> () +""" + config + |> prepend newline + |> should + equal + """ +match x with +| :? string +| null -> () +""" + +[] +let ``nullness in signature file`` () = + formatSignatureString + """ +namespace Meh + +type DU = MyCase of (string | null) +""" + config + |> prepend newline + |> should + equal + """ +namespace Meh + +type DU = MyCase of (string | null) +""" + +[] +let ``trivia in SynType.WithNull`` () = + formatSourceString + """ +type DU = MyCase of (string + | // but why? + null) +""" + config + |> prepend newline + |> should + equal + """ +type DU = + | MyCase of + (string | // but why? + null) +""" + +[] +let ``trivia in SynTypeConstraint.WhereTyparNotSupportsNull`` () = + formatSourceString + """ +type C<'T when + 'T + : // comment 1 + not // comment 2 + null> = class end +""" + config + |> prepend newline + |> should + equal + """ +type C<'T + when 'T: // comment 1 + not // comment 2 + null> = class end +""" diff --git a/src/Fantomas.Core.Tests/packages.lock.json b/src/Fantomas.Core.Tests/packages.lock.json index 4a095303b..9da29aaa1 100644 --- a/src/Fantomas.Core.Tests/packages.lock.json +++ b/src/Fantomas.Core.Tests/packages.lock.json @@ -109,11 +109,6 @@ "Newtonsoft.Json": "13.0.1" } }, - "Newtonsoft.Json": { - "type": "Transitive", - "resolved": "13.0.1", - "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" - }, "NuGet.Frameworks": { "type": "Transitive", "resolved": "6.5.0", @@ -163,6 +158,12 @@ "System.Runtime": "[4.3.1, )" } }, + "Newtonsoft.Json": { + "type": "CentralTransitive", + "requested": "[13.0.3, )", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, "System.Collections.Immutable": { "type": "CentralTransitive", "requested": "[7.0.0, )", diff --git a/src/Fantomas.Core/ASTTransformer.fs b/src/Fantomas.Core/ASTTransformer.fs index 5544c7022..93240f743 100644 --- a/src/Fantomas.Core/ASTTransformer.fs +++ b/src/Fantomas.Core/ASTTransformer.fs @@ -78,6 +78,16 @@ let mkSynAccess (vis: SynAccess option) = | Some(SynAccess.Private range) -> Some(stn "private" range) | Some(SynAccess.Public range) -> Some(stn "public" range) +let (|AccessSynValSigAccess|) (valSigAccess: SynValSigAccess) = + match valSigAccess with + | SynValSigAccess.Single(accessibility = vis) + | SynValSigAccess.GetSet(accessibility = vis) -> vis + +let (|SynValSigAccessAll|) (valSigAccess: SynValSigAccess) = + match valSigAccess with + | SynValSigAccess.Single(vis) -> vis, None, None + | SynValSigAccess.GetSet(vis, g, s) -> vis, g, s + let parseExpressionInSynBinding returnInfo expr = match returnInfo, expr with | Some(SynBindingReturnInfo(typeName = t1)), SynExpr.Typed(e, t2, _) when RangeHelpers.rangeEq t1.Range t2.Range -> @@ -329,15 +339,18 @@ let rec collectComputationExpressionStatements let andBangs = andBangs - |> List.map (fun (SynExprAndBang(_, _, _, ap, ae, StartRange 4 (mAnd, m), trivia)) -> - ExprAndBang( - stn "and!" mAnd, - mkPat creationAide ap, - stn "=" trivia.EqualsRange, - mkExpr creationAide ae, - m - ) - |> ComputationExpressionStatement.AndBangStatement) + |> 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) collectComputationExpressionStatements creationAide body (fun bodyStatements -> [ letOrUseBang; yield! andBangs; yield! bodyStatements ] |> finalContinuation) @@ -2168,6 +2181,9 @@ let mkSynTypeConstraint (creationAide: CreationAide) (tc: SynTypeConstraint) : T TypeConstraintEnumOrDelegateNode(mkSynTypar tp, "delegate", List.map (mkType creationAide) ts, m) |> TypeConstraint.EnumOrDelegate | SynTypeConstraint.WhereSelfConstrained(t, _) -> mkType creationAide t |> TypeConstraint.WhereSelfConstrained + | SynTypeConstraint.WhereTyparNotSupportsNull(typar, EndRange 4 (mNull, m), { ColonRange = mColon; NotRange = mNot }) -> + TypeConstraintWhereNotSupportsNull(mkSynTypar typar, stn ":" mColon, stn "not" mNot, stn "null" mNull, m) + |> TypeConstraint.WhereNotSupportsNull // Arrow type is right-associative let rec (|TFuns|_|) = @@ -2309,6 +2325,12 @@ let mkType (creationAide: CreationAide) (t: SynType) : Type = yield Choice1Of2(mkType creationAide t) ] TypeIntersectionNode(typesAndSeparators, m) |> Type.Intersection + | SynType.StaticConstantNull(m) -> stn "null" m |> Type.Var + // string | null + | SynType.WithNull(innerType, _, EndRange 4 (mNull, m), { BarRange = mBar }) -> + let nullType = stn "null" mNull |> Type.Var + + TypeOrNode(mkType creationAide innerType, stn "|" mBar, nullType, m) |> Type.Or | t -> failwith $"unexpected type: %A{t}" let rec (|OpenL|_|) = @@ -2632,20 +2654,44 @@ let mkTypeDefn TypeDefnRegularNode(typeNameNode, allMembers, typeDefnRange) |> TypeDefn.Regular | _ -> failwithf "Could not create a TypeDefn for %A" typeRepr -let mkWithGetSet (withKeyword: range option) (getSet: GetSetKeywords option) = +let mkWithGetSet + (withKeyword: range option) + (getSet: GetSetKeywords option) + (visGet: SynAccess option) + (visSet: SynAccess option) + = match withKeyword, getSet with | Some mWith, Some gs -> let withNode = stn "with" mWith let m = unionRanges mWith gs.Range + let visNodes vis = Option.toList (mkSynAccess vis) match gs with - | GetSetKeywords.Get mGet -> Some(MultipleTextsNode([ withNode; stn "get" mGet ], m)) - | GetSetKeywords.Set mSet -> Some(MultipleTextsNode([ withNode; stn "set" mSet ], m)) + | GetSetKeywords.Get mGet -> Some(MultipleTextsNode([ withNode; yield! visNodes visGet; stn "get" mGet ], m)) + | GetSetKeywords.Set mSet -> Some(MultipleTextsNode([ withNode; yield! visNodes visSet; stn "set" mSet ], m)) | GetSetKeywords.GetSet(mGet, mSet) -> if rangeBeforePos mGet mSet.Start then - Some(MultipleTextsNode([ withNode; stn "get," mGet; stn "set" mSet ], m)) + Some( + MultipleTextsNode( + [ withNode + yield! visNodes visGet + stn "get," mGet + yield! visNodes visSet + stn "set" mSet ], + m + ) + ) else - Some(MultipleTextsNode([ withNode; stn "set," mSet; stn "get" mGet ], m)) + Some( + MultipleTextsNode( + [ withNode + yield! visNodes visSet + stn "set," mSet + yield! visNodes visGet + stn "get" mGet ], + m + ) + ) | _ -> None let mkPropertyGetSetBinding @@ -2826,35 +2872,41 @@ let mkMemberDefn (creationAide: CreationAide) (md: SynMemberDefn) = memberDefinitionRange ) |> MemberDefn.Interface - | SynMemberDefn.AutoProperty(ats, - _isStatic, - ident, - typeOpt, - _, - _, - _, - px, - ao, - e, - _, - { LeadingKeyword = lk - EqualsRange = Some mEq - WithKeyword = mWith - GetSetKeywords = mGS }) -> + | SynMemberDefn.AutoProperty( + attributes = ats + ident = ident + typeOpt = typeOpt + xmlDoc = px + accessibility = SynValSigAccessAll(vis, getVis, setVis) + synExpr = e + trivia = { LeadingKeyword = lk + EqualsRange = Some mEq + WithKeyword = mWith + GetSetKeywords = mGS }) -> + MemberDefnAutoPropertyNode( mkXmlDoc px, mkAttributes creationAide ats, mkSynLeadingKeyword lk, - mkSynAccess ao, + mkSynAccess vis, mkIdent ident, Option.map (mkType creationAide) typeOpt, stn "=" mEq, mkExpr creationAide e, - mkWithGetSet mWith mGS, + mkWithGetSet mWith mGS getVis setVis, memberDefinitionRange ) |> MemberDefn.AutoProperty - | SynMemberDefn.AbstractSlot(SynValSig(ats, ident, tds, t, _, _, _, px, _ao, _, _, trivia), _, _, abstractSlotTrivia) -> + | SynMemberDefn.AbstractSlot( + slotSig = SynValSig( + attributes = ats + ident = ident + explicitTypeParams = tds + synType = t + xmlDoc = px + accessibility = SynValSigAccessAll(_ao, visGet, visSet) + trivia = trivia) + trivia = abstractSlotTrivia) -> MemberDefnAbstractSlotNode( mkXmlDoc px, mkAttributes creationAide ats, @@ -2862,7 +2914,7 @@ let mkMemberDefn (creationAide: CreationAide) (md: SynMemberDefn) = mkSynIdent ident, mkSynValTyparDecls creationAide (Some tds), mkType creationAide t, - mkWithGetSet trivia.WithKeyword abstractSlotTrivia.GetSetKeywords, + mkWithGetSet trivia.WithKeyword abstractSlotTrivia.GetSetKeywords visGet visSet, memberDefinitionRange ) |> MemberDefn.AbstractSlot @@ -3014,7 +3066,7 @@ let mkMemberDefn (creationAide: CreationAide) (md: SynMemberDefn) = let mkVal (creationAide: CreationAide) - (SynValSig(ats, synIdent, vtd, t, _vi, _isInline, isMutable, px, ao, eo, range, trivia)) + (SynValSig(ats, synIdent, vtd, t, _vi, _isInline, isMutable, px, AccessSynValSigAccess(ao), eo, range, trivia)) : ValNode = let lk = match trivia.LeadingKeyword with @@ -3041,11 +3093,12 @@ let mkMemberSig (creationAide: CreationAide) (ms: SynMemberSig) = match ms with | SynMemberSig.Member(vs, _, _, memberTrivia) -> - let (SynValSig(trivia = trivia)) = vs + let (SynValSig(trivia = trivia; accessibility = SynValSigAccessAll(_ao, visGet, visSet))) = + vs MemberDefnSigMemberNode( mkVal creationAide vs, - mkWithGetSet trivia.WithKeyword memberTrivia.GetSetKeywords, + mkWithGetSet trivia.WithKeyword memberTrivia.GetSetKeywords visGet visSet, memberSigRange ) |> MemberDefn.SigMember diff --git a/src/Fantomas.Core/CodePrinter.fs b/src/Fantomas.Core/CodePrinter.fs index 357eaf63a..bcddf6700 100644 --- a/src/Fantomas.Core/CodePrinter.fs +++ b/src/Fantomas.Core/CodePrinter.fs @@ -3155,6 +3155,27 @@ let genTypeConstraint (tc: TypeConstraint) = +> !- ">" |> genNode node | TypeConstraint.WhereSelfConstrained t -> genType t + | TypeConstraint.WhereNotSupportsNull node -> + let short = + genSingleTextNode node.Typar + +> onlyIfCtx (fun ctx -> ctx.Config.SpaceBeforeColon) sepSpace + +> genSingleTextNode node.Colon + +> sepSpace + +> genSingleTextNode node.Not + +> sepSpace + +> genSingleTextNode node.Null + + let long = + genSingleTextNode node.Typar + +> onlyIfCtx (fun ctx -> ctx.Config.SpaceBeforeColon) sepSpace + +> genSingleTextNode node.Colon + +> indentSepNlnUnindent ( + genSingleTextNode node.Not + +> sepNlnWhenWriteBeforeNewlineNotEmptyOr sepSpace + +> genSingleTextNode node.Null + ) + + expressionFitsOnRestOfLine short long |> genNode node let genTypeConstraints (tcs: TypeConstraint list) = let short = colPre (sepSpace +> !- "when ") wordAnd tcs genTypeConstraint @@ -3292,12 +3313,20 @@ let genType (t: Type) = +> autoIndentAndNlnIfExpressionExceedsPageWidth (genType node.Type) |> genNode node | Type.Or node -> - genType node.LeftHandSide - +> sepSpace - +> genSingleTextNode node.Or - +> sepSpace - +> genType node.RightHandSide - |> genNode node + let short = + genType node.LeftHandSide + +> sepSpace + +> genSingleTextNode node.Or + +> sepSpace + +> genType node.RightHandSide + + let long = + genType node.LeftHandSide + +> sepSpace + +> genSingleTextNode node.Or + +> indentSepNlnUnindent (genType node.RightHandSide) + + expressionFitsOnRestOfLine short long |> genNode node | Type.LongIdentApp node -> genType node.AppType +> sepDot +> genIdentListNode node.LongIdent |> genNode node diff --git a/src/Fantomas.Core/SyntaxOak.fs b/src/Fantomas.Core/SyntaxOak.fs index 5d2de5a89..c15dc6f0d 100644 --- a/src/Fantomas.Core/SyntaxOak.fs +++ b/src/Fantomas.Core/SyntaxOak.fs @@ -2787,6 +2787,17 @@ type TypeConstraintEnumOrDelegateNode(typar: SingleTextNode, verb: string, ts: T member val Verb = verb member val Types = ts +/// `'T: not null` in `type C<'T when 'T: not null> = class end` +type TypeConstraintWhereNotSupportsNull + (typar: SingleTextNode, colon: SingleTextNode, notNode: SingleTextNode, nullNode: SingleTextNode, range) = + inherit NodeBase(range) + + override val Children: Node array = [| yield typar; yield colon; yield notNode; yield nullNode |] + member val Typar = typar + member val Colon = colon + member val Not = notNode + member val Null = nullNode + [] type TypeConstraint = | Single of TypeConstraintSingleNode @@ -2795,6 +2806,7 @@ type TypeConstraint = | SupportsMember of TypeConstraintSupportsMemberNode | EnumOrDelegate of TypeConstraintEnumOrDelegateNode | WhereSelfConstrained of Type + | WhereNotSupportsNull of TypeConstraintWhereNotSupportsNull static member Node(tc: TypeConstraint) : Node = match tc with @@ -2804,6 +2816,7 @@ type TypeConstraint = | SupportsMember n -> n | EnumOrDelegate n -> n | WhereSelfConstrained t -> Type.Node t + | WhereNotSupportsNull n -> n type UnitOfMeasureNode(lessThan: SingleTextNode, measure: Measure, greaterThan: SingleTextNode, range) = inherit NodeBase(range) diff --git a/src/Fantomas.FCS/Fantomas.FCS.fsproj b/src/Fantomas.FCS/Fantomas.FCS.fsproj index 0b8e460ff..db012a03f 100644 --- a/src/Fantomas.FCS/Fantomas.FCS.fsproj +++ b/src/Fantomas.FCS/Fantomas.FCS.fsproj @@ -6,7 +6,7 @@ $(NoWarn);57; $(NoWarn);1204 $(NoWarn);1178 - $(DefineConstants);COMPILER;FSHARPCORE_USE_PACKAGE + $(DefineConstants);COMPILER;FSHARPCORE_USE_PACKAGE;NO_CHECKNULLS generated\$(TargetFramework)\ generated\$(TargetFramework)\ true @@ -16,6 +16,7 @@ + FSComp.txt @@ -23,6 +24,9 @@ FSStrings.resx FSStrings.resources + + Utilities\NullnessShims.fs + Utilities\Activity.fsi diff --git a/src/Fantomas.FCS/TailCall.fs b/src/Fantomas.FCS/TailCall.fs new file mode 100644 index 000000000..5088f93a3 --- /dev/null +++ b/src/Fantomas.FCS/TailCall.fs @@ -0,0 +1,7 @@ +module Microsoft.FSharp.Core + +open System + +[] +type TailCallAttribute() = + inherit Attribute() diff --git a/src/Fantomas.Tests/packages.lock.json b/src/Fantomas.Tests/packages.lock.json index 781cd7336..2d6c37764 100644 --- a/src/Fantomas.Tests/packages.lock.json +++ b/src/Fantomas.Tests/packages.lock.json @@ -196,11 +196,6 @@ "System.Runtime.CompilerServices.Unsafe": "4.7.1" } }, - "Newtonsoft.Json": { - "type": "Transitive", - "resolved": "13.0.1", - "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" - }, "NuGet.Frameworks": { "type": "Transitive", "resolved": "6.5.0", @@ -887,6 +882,12 @@ "resolved": "0.1.50", "contentHash": "nr7/KaY5KP9QvCEf478w1k9Yz+dXQZKLEAsjfhIjuneScmyLvMKoItPL6OfkNODeCrINtHEBt8A7q7yETS1PQQ==" }, + "Newtonsoft.Json": { + "type": "CentralTransitive", + "requested": "[13.0.3, )", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, "SemanticVersioning": { "type": "CentralTransitive", "requested": "[2.0.2, )", diff --git a/src/Fantomas/EditorConfig.fs b/src/Fantomas/EditorConfig.fs index f362fe4ba..87af71998 100644 --- a/src/Fantomas/EditorConfig.fs +++ b/src/Fantomas/EditorConfig.fs @@ -16,7 +16,7 @@ module Reflection = DisplayName: string option Description: string option } - let inline getCustomAttribute<'t, 'v when 't :> Attribute and 't: null> + let inline getCustomAttribute<'t, 'v when 't :> Attribute and 't: null and 't: not struct> (projection: 't -> 'v) (property: PropertyInfo) : 'v option = diff --git a/src/Fantomas/Fantomas.fsproj b/src/Fantomas/Fantomas.fsproj index 6210ac75a..08a87ac2b 100644 --- a/src/Fantomas/Fantomas.fsproj +++ b/src/Fantomas/Fantomas.fsproj @@ -1,7 +1,7 @@ Exe - net6.0 + net8.0 en diff --git a/src/Fantomas/Logging.fs b/src/Fantomas/Logging.fs index c6ebda69a..c5a4d53be 100644 --- a/src/Fantomas/Logging.fs +++ b/src/Fantomas/Logging.fs @@ -20,15 +20,13 @@ let initLogger (level: VerbosityLevel) : VerbosityLevel = Log.Logger <- logger level -let logger = Log.Logger - /// log a message -let stdlog (s: string) = logger.Information(s) +let stdlog (s: string) = Log.Logger.Information(s) /// log an error -let elog (s: string) = logger.Error(s) +let elog (s: string) = Log.Logger.Error(s) /// log a message if the verbosity level is >= Detailed -let logGrEqDetailed s = logger.Debug(s) +let logGrEqDetailed s = Log.Logger.Debug(s) let closeAndFlushLog () = Log.CloseAndFlush() diff --git a/src/Fantomas/packages.lock.json b/src/Fantomas/packages.lock.json index 5a219fa80..d0d3541ea 100644 --- a/src/Fantomas/packages.lock.json +++ b/src/Fantomas/packages.lock.json @@ -1,7 +1,7 @@ { "version": 2, "dependencies": { - "net6.0": { + "net8.0": { "Argu": { "type": "Direct", "requested": "[6.2.4, )", @@ -285,11 +285,6 @@ "System.Runtime.CompilerServices.Unsafe": "4.7.1" } }, - "Newtonsoft.Json": { - "type": "Transitive", - "resolved": "12.0.2", - "contentHash": "rTK0s2EKlfHsQsH6Yx2smvcTCeyoDNgCW7FEYyV01drPlh2T243PR2DiDXqtC5N4GDm4Ma/lkxfW5a/4793vbA==" - }, "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { "type": "Transitive", "resolved": "4.3.2", @@ -630,8 +625,8 @@ }, "System.Runtime.CompilerServices.Unsafe": { "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + "resolved": "4.7.1", + "contentHash": "zOHkQmzPCn5zm/BH+cxC1XbUS3P4Yoi3xzW7eRgVpDR2tPGSzyMZ17Ig1iRkfJuY0nhxkQQde8pgePNiA7z7TQ==" }, "System.Runtime.Extensions": { "type": "Transitive", @@ -917,6 +912,12 @@ "System.Runtime": "[4.3.1, )" } }, + "Newtonsoft.Json": { + "type": "CentralTransitive", + "requested": "[13.0.3, )", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, "SemanticVersioning": { "type": "CentralTransitive", "requested": "[2.0.2, )", @@ -927,19 +928,13 @@ "type": "CentralTransitive", "requested": "[7.0.0, )", "resolved": "7.0.0", - "contentHash": "dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } + "contentHash": "dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ==" }, "System.Diagnostics.DiagnosticSource": { "type": "CentralTransitive", "requested": "[7.0.0, )", "resolved": "7.0.0", - "contentHash": "9W0ewWDuAyDqS2PigdTxk6jDKonfgscY/hP8hm7VpxYhNHZHKvZTdRckberlFk3VnCmr3xBUyMBut12Q+T2aOw==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } + "contentHash": "9W0ewWDuAyDqS2PigdTxk6jDKonfgscY/hP8hm7VpxYhNHZHKvZTdRckberlFk3VnCmr3xBUyMBut12Q+T2aOw==" }, "System.Memory": { "type": "CentralTransitive",