From e19fc35ea17b8cf4451808fe8924c782c3388bbb Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Wed, 6 Mar 2024 15:12:01 +0100 Subject: [PATCH] net 8.0 (#146) * Upgrade to .NET 8.0 * Fix compiler errors * Fix Dockerfile --- Dockerfile | 4 +- Exercism.Representers.FSharp.sln | 8 +-- .../Exercism.Representers.FSharp.fsproj | 8 +-- src/Exercism.Representers.FSharp/Syntax.fs | 15 +++-- src/Exercism.Representers.FSharp/Visitor.fs | 66 +++++++++---------- .../Lambdas/expected_representation.txt | 1 - 6 files changed, 48 insertions(+), 54 deletions(-) diff --git a/Dockerfile b/Dockerfile index fa2d99b..f6462ee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:7.0.306-alpine3.18-amd64 AS build +FROM mcr.microsoft.com/dotnet/sdk:8.0.201-alpine3.19-amd64 AS build WORKDIR /app # Copy fsproj and restore as distinct layers @@ -10,7 +10,7 @@ COPY src/Exercism.Representers.FSharp/ ./ RUN dotnet publish -r linux-musl-x64 -c Release -o /opt/representer --no-restore --self-contained true # Build runtime image -FROM mcr.microsoft.com/dotnet/runtime-deps:7.0.9-alpine3.18-amd64 AS runtime +FROM mcr.microsoft.com/dotnet/runtime-deps:8.0.2-alpine3.19-amd64 AS runtime WORKDIR /opt/representer COPY --from=build /opt/representer/ . diff --git a/Exercism.Representers.FSharp.sln b/Exercism.Representers.FSharp.sln index 3801479..840d46a 100644 --- a/Exercism.Representers.FSharp.sln +++ b/Exercism.Representers.FSharp.sln @@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Exercism.Representers.FSharp", "src\Exercism.Representers.FSharp\Exercism.Representers.FSharp.fsproj", "{9428D8F1-00A3-4246-85DE-F0D31978D853}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Exercism.Representers.FSharp.Bulk", "src\Exercism.Representers.FSharp.Bulk\Exercism.Representers.FSharp.Bulk.fsproj", "{93AB5F81-CE6D-47A0-BAB8-8FF66D1F53E2}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -14,10 +12,6 @@ Global {9428D8F1-00A3-4246-85DE-F0D31978D853}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9428D8F1-00A3-4246-85DE-F0D31978D853}.Debug|Any CPU.Build.0 = Debug|Any CPU {9428D8F1-00A3-4246-85DE-F0D31978D853}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9428D8F1-00A3-4246-85DE-F0D31978D853}.Release|Any CPU.Build.0 = Release|Any CPU - {93AB5F81-CE6D-47A0-BAB8-8FF66D1F53E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {93AB5F81-CE6D-47A0-BAB8-8FF66D1F53E2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {93AB5F81-CE6D-47A0-BAB8-8FF66D1F53E2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {93AB5F81-CE6D-47A0-BAB8-8FF66D1F53E2}.Release|Any CPU.Build.0 = Release|Any CPU + {9428D8F1-00A3-4246-85DE-F0D31978D853}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/src/Exercism.Representers.FSharp/Exercism.Representers.FSharp.fsproj b/src/Exercism.Representers.FSharp/Exercism.Representers.FSharp.fsproj index 20dddcf..b3ec586 100644 --- a/src/Exercism.Representers.FSharp/Exercism.Representers.FSharp.fsproj +++ b/src/Exercism.Representers.FSharp/Exercism.Representers.FSharp.fsproj @@ -2,7 +2,7 @@ Exe - net7.0 + net8.0 @@ -12,10 +12,10 @@ - + - - + + diff --git a/src/Exercism.Representers.FSharp/Syntax.fs b/src/Exercism.Representers.FSharp/Syntax.fs index 42ee6fe..b758c41 100644 --- a/src/Exercism.Representers.FSharp/Syntax.fs +++ b/src/Exercism.Representers.FSharp/Syntax.fs @@ -3,10 +3,10 @@ module Exercism.Representers.FSharp.Syntax open Exercism.Representers.FSharp.Visitor open System.IO open System.Text.Json -open FSharp.Compiler.Syntax -open FSharp.Compiler.SyntaxTrivia -open FSharp.Compiler.Text -open FSharp.Compiler.Xml +open Fantomas.FCS.Syntax +open Fantomas.FCS.SyntaxTrivia +open Fantomas.FCS.Text +open Fantomas.FCS.Xml open Fantomas.Core open Fantomas.FCS.Parse @@ -127,9 +127,10 @@ let toSimplifiedTreeAndMapping (tree, source) = (simplifiedTree, placeholdersToIdentifiers, source, metadata) let private treeToRepresentation tree source = - let config = { FormatConfig.FormatConfig.Default with KeepMaxNumberOfBlankLines = 1 } - let code = CodeFormatter.FormatASTAsync(tree, source, config) |> Async.RunSynchronously - CodeFormatter.FormatDocumentAsync(false, code, config) |> Async.RunSynchronously // The second pass is needed to remove empty lines + let config = { FormatConfig.Default with KeepMaxNumberOfBlankLines = 1 } + let code = CodeFormatter.FormatASTAsync(tree, config) |> Async.RunSynchronously + let formatResult = CodeFormatter.FormatDocumentAsync(false, code, config) |> Async.RunSynchronously // The second pass is needed to remove empty lines + formatResult.Code let private mappingToJson mapping = JsonSerializer.Serialize(mapping) diff --git a/src/Exercism.Representers.FSharp/Visitor.fs b/src/Exercism.Representers.FSharp/Visitor.fs index 9bc8393..48595ba 100644 --- a/src/Exercism.Representers.FSharp/Visitor.fs +++ b/src/Exercism.Representers.FSharp/Visitor.fs @@ -1,22 +1,22 @@ module Exercism.Representers.FSharp.Visitor -open FSharp.Compiler.Syntax -open FSharp.Compiler.SyntaxTrivia -open FSharp.Compiler.Text -open FSharp.Compiler.Xml +open Fantomas.FCS.Syntax +open Fantomas.FCS.SyntaxTrivia +open Fantomas.FCS.Text +open Fantomas.FCS.Xml type SyntaxVisitor() = abstract VisitInput: ParsedInput -> ParsedInput default this.VisitInput(input: ParsedInput): ParsedInput = match input with - | ParsedInput.ImplFile(ParsedImplFileInput(file, isScript, qualName, pragmas, hashDirectives, modules, isLastCompiland, trivia)) -> + | ParsedInput.ImplFile(ParsedImplFileInput(file, isScript, qualName, pragmas, hashDirectives, modules, isLastCompiland, trivia, identifiers)) -> ParsedInput.ImplFile (ParsedImplFileInput (file, isScript, qualName, pragmas, hashDirectives, - List.map this.VisitSynModuleOrNamespace modules, isLastCompiland, this.VisitParsedImplFileInputTrivia(trivia))) - | ParsedInput.SigFile(ParsedSigFileInput(file, qualifiedName, pragmas, directives, synModuleOrNamespaceSigs, trivia)) -> - ParsedInput.SigFile(ParsedSigFileInput(file, qualifiedName, pragmas, directives, synModuleOrNamespaceSigs, trivia)) + List.map this.VisitSynModuleOrNamespace modules, isLastCompiland, this.VisitParsedImplFileInputTrivia(trivia), identifiers)) + | ParsedInput.SigFile(ParsedSigFileInput(file, qualifiedName, pragmas, directives, synModuleOrNamespaceSigs, trivia, identifiers)) -> + ParsedInput.SigFile(ParsedSigFileInput(file, qualifiedName, pragmas, directives, synModuleOrNamespaceSigs, trivia, identifiers)) abstract VisitParsedImplFileInputTrivia : ParsedImplFileInputTrivia -> ParsedImplFileInputTrivia default this.VisitParsedImplFileInputTrivia(trivia: ParsedImplFileInputTrivia) = trivia @@ -108,10 +108,10 @@ type SyntaxVisitor() = (this.VisitSynType typ, this.VisitSynExpr expr, leftParenRange, sep, rightParentRange)), copyInfo |> Option.map (fun (expr, opt) -> (this.VisitSynExpr expr, opt)), recordFields |> List.map this.VisitRecordField, range) - | SynExpr.AnonRecd(isStruct, copyInfo, recordFields, range) -> + | SynExpr.AnonRecd(isStruct, copyInfo, recordFields, range, trivia) -> SynExpr.AnonRecd (isStruct, copyInfo |> Option.map (fun (expr, opt) -> (this.VisitSynExpr expr, opt)), - recordFields |> List.map this.VisitAnonRecordField, range) + recordFields |> List.map this.VisitAnonRecordField, range, trivia) | SynExpr.New(isProtected, typeName, expr, range) -> SynExpr.New(isProtected, this.VisitSynType typeName, this.VisitSynExpr expr, range) | SynExpr.ObjExpr(objType, argOptions, withKeyword, bindings, members, extraImpls, newExprRange, range) -> @@ -233,11 +233,13 @@ type SyntaxVisitor() = (this.VisitSynExpr e1, this.VisitLongIdent longId, i, this.VisitSynExpr e2, range) | SynExpr.ArbitraryAfterError(debugStr, range) -> SynExpr.ArbitraryAfterError(debugStr, range) | SynExpr.FromParseError(expr, range) -> SynExpr.FromParseError(this.VisitSynExpr expr, range) - | SynExpr.DiscardAfterMissingQualificationAfterDot(expr, range) -> - SynExpr.DiscardAfterMissingQualificationAfterDot(this.VisitSynExpr expr, range) + | SynExpr.DiscardAfterMissingQualificationAfterDot(expr, dotRange, range) -> + SynExpr.DiscardAfterMissingQualificationAfterDot(this.VisitSynExpr expr, dotRange, range) | SynExpr.Fixed(expr, range) -> SynExpr.Fixed(this.VisitSynExpr expr, range) | SynExpr.InterpolatedString(contents, kind, range) -> SynExpr.InterpolatedString(List.map this.VisitSynInterpolatedStringPart contents, kind, range) | SynExpr.Typar(synTypar, range) -> SynExpr.Typar(this.VisitSynTypar synTypar, range) + | SynExpr.DotLambda(expr, range, trivia) -> SynExpr.DotLambda(this.VisitSynExpr expr, range, trivia) + | SynExpr.WhileBang(whileDebugPoint, whileExpr, doExpr, range) -> SynExpr.WhileBang(whileDebugPoint, this.VisitSynExpr whileExpr, this.VisitSynExpr doExpr, range) abstract VisitSynInterpolatedStringPart: SynInterpolatedStringPart -> SynInterpolatedStringPart @@ -255,8 +257,8 @@ type SyntaxVisitor() = abstract VisitRecordFieldName: RecordFieldName -> RecordFieldName default this.VisitRecordFieldName((ident: SynLongIdent, correct: bool)) = (this.VisitSynLongIdent ident, correct) - abstract VisitAnonRecordField: (Ident * range option * SynExpr) -> Ident * range option * SynExpr - default this.VisitAnonRecordField((ident: Ident, r: range option, expr: SynExpr)) = (this.VisitIdent ident, r, this.VisitSynExpr expr) + abstract VisitAnonRecordField: (SynLongIdent * range option * SynExpr) -> SynLongIdent * range option * SynExpr + default this.VisitAnonRecordField((ident: SynLongIdent, r: range option, expr: SynExpr)) = (this.VisitSynLongIdent ident, r, this.VisitSynExpr expr) abstract VisitAnonRecordTypeField: (Ident * SynType) -> Ident * SynType default this.VisitAnonRecordTypeField((ident: Ident, t: SynType)) = (this.VisitIdent ident, this.VisitSynType t) @@ -265,7 +267,7 @@ type SyntaxVisitor() = default this.VisitSynMemberSig(ms: SynMemberSig): SynMemberSig = match ms with - | SynMemberSig.Member(valSig, flags, range) -> SynMemberSig.Member(this.VisitSynValSig valSig, flags, range) + | SynMemberSig.Member(valSig, flags, range, trivia) -> SynMemberSig.Member(this.VisitSynValSig valSig, flags, range, trivia) | SynMemberSig.Interface(typeName, range) -> SynMemberSig.Interface(this.VisitSynType typeName, range) | SynMemberSig.Inherit(typeName, range) -> SynMemberSig.Inherit(this.VisitSynType typeName, range) | SynMemberSig.ValField(f, range) -> SynMemberSig.ValField(this.VisitSynField f, range) @@ -323,18 +325,18 @@ type SyntaxVisitor() = SynMemberDefn.GetSetMember(memberDefnForGet |> Option.map this.VisitSynBinding, memberDefnForSet |> Option.map this.VisitSynBinding, range1, synMemberGetSetTrivia) | SynMemberDefn.Open(target, range) -> SynMemberDefn.Open(this.VisitSynOpenDeclTarget target, range) | SynMemberDefn.Member(memberDefn, range) -> SynMemberDefn.Member(this.VisitSynBinding memberDefn, range) - | SynMemberDefn.ImplicitCtor(access, attrs, ctorArgs, selfIdentifier, doc, range) -> + | SynMemberDefn.ImplicitCtor(access, attrs, ctorArgs, selfIdentifier, doc, range, trivia) -> SynMemberDefn.ImplicitCtor (Option.map this.VisitSynAccess access, attrs |> List.map this.VisitSynAttributeList, - this.VisitSynSimplePats ctorArgs, Option.map this.VisitIdent selfIdentifier, this.VisitPreXmlDoc(doc), range) + this.VisitSynSimplePats ctorArgs, Option.map this.VisitIdent selfIdentifier, this.VisitPreXmlDoc(doc), range, trivia) | SynMemberDefn.ImplicitInherit(inheritType, inheritArgs, inheritAlias, range) -> SynMemberDefn.ImplicitInherit (this.VisitSynType inheritType, this.VisitSynExpr inheritArgs, Option.map this.VisitIdent inheritAlias, range) | SynMemberDefn.LetBindings(bindings, isStatic, isRecursive, range) -> SynMemberDefn.LetBindings(bindings |> List.map this.VisitSynBinding, isStatic, isRecursive, range) - | SynMemberDefn.AbstractSlot(valSig, flags, range) -> - SynMemberDefn.AbstractSlot(this.VisitSynValSig valSig, flags, range) + | SynMemberDefn.AbstractSlot(valSig, flags, range, trivia) -> + SynMemberDefn.AbstractSlot(this.VisitSynValSig valSig, flags, range, trivia) | SynMemberDefn.Interface(typ, withKeyword, members, range) -> SynMemberDefn.Interface (this.VisitSynType typ, withKeyword, Option.map (List.map this.VisitSynMemberDefn) members, range) @@ -364,10 +366,8 @@ type SyntaxVisitor() = default this.VisitSynSimplePats(sp: SynSimplePats): SynSimplePats = match sp with - | SynSimplePats.SimplePats(pats, range) -> - SynSimplePats.SimplePats(pats |> List.map this.VisitSynSimplePat, range) - | SynSimplePats.Typed(pats, typ, range) -> - SynSimplePats.Typed(this.VisitSynSimplePats pats, this.VisitSynType typ, range) + | SynSimplePats.SimplePats(pats, commaRanges, range) -> + SynSimplePats.SimplePats(pats |> List.map this.VisitSynSimplePat, commaRanges, range) abstract VisitSynBinding: SynBinding -> SynBinding @@ -384,8 +384,8 @@ type SyntaxVisitor() = default this.VisitSynValData(svd: SynValData): SynValData = match svd with - | SynValData(flags, svi, ident) -> - SynValData(flags, this.VisitSynValInfo svi, Option.map this.VisitIdent ident) + | SynValData(flags, svi, ident, transformedFromProperty) -> + SynValData(flags, this.VisitSynValInfo svi, Option.map this.VisitIdent ident, Option.map this.VisitIdent transformedFromProperty) abstract VisitSynValSig: SynValSig -> SynValSig @@ -420,7 +420,8 @@ type SyntaxVisitor() = default this.VisitSynTyparDecl(std: SynTyparDecl): SynTyparDecl = match std with - | SynTyparDecl(attrs, typar) -> SynTyparDecl(attrs |> List.map this.VisitSynAttributeList, this.VisitSynTypar typar) + | SynTyparDecl(attrs, typar, intersectionConstraints, trivia) -> + SynTyparDecl(attrs |> List.map this.VisitSynAttributeList, this.VisitSynTypar typar, intersectionConstraints |> List.map this.VisitSynType, trivia) abstract VisitSynTypar: SynTypar -> SynTypar @@ -459,7 +460,7 @@ type SyntaxVisitor() = (this.VisitSynLongIdent longDotId, Option.map this.VisitIdent ident, Option.map this.VisitSynValTyparDecls svtd, this.VisitSynArgPats ctorArgs, Option.map this.VisitSynAccess access, range) - | SynPat.Tuple(isStruct, pats, range) -> SynPat.Tuple(isStruct, pats |> List.map this.VisitSynPat, range) + | SynPat.Tuple(isStruct, pats, commaRanges, range) -> SynPat.Tuple(isStruct, pats |> List.map this.VisitSynPat, commaRanges, range) | SynPat.Paren(pat, range) -> SynPat.Paren(this.VisitSynPat pat, range) | SynPat.ArrayOrList(isList, pats, range) -> SynPat.ArrayOrList(isList, pats |> List.map this.VisitSynPat, range) @@ -473,7 +474,6 @@ type SyntaxVisitor() = | SynPat.OptionalVal(ident, range) -> SynPat.OptionalVal(this.VisitIdent ident, range) | SynPat.IsInst(typ, range) -> SynPat.IsInst(this.VisitSynType typ, range) | SynPat.QuoteExpr(expr, range) -> SynPat.QuoteExpr(this.VisitSynExpr expr, range) - | SynPat.DeprecatedCharRange(c, c2, range) -> SynPat.DeprecatedCharRange(c, c2, range) | SynPat.InstanceMember(ident, ident2, ident3, access, range) -> SynPat.InstanceMember (this.VisitIdent ident, this.VisitIdent ident2, Option.map this.VisitIdent ident3, @@ -580,10 +580,10 @@ type SyntaxVisitor() = default this.VisitSynEnumCase(sec: SynEnumCase): SynEnumCase = match sec with - | SynEnumCase(attrs, ident, cnst, cnstRange, doc, trivia, range) -> + | SynEnumCase(attrs, ident, expr, doc, trivia, range) -> SynEnumCase - (attrs |> List.map this.VisitSynAttributeList, this.VisitSynIdent ident, this.VisitSynConst cnst, - cnstRange, this.VisitPreXmlDoc(doc), trivia, range) + (attrs |> List.map this.VisitSynAttributeList, this.VisitSynIdent ident, this.VisitSynExpr expr, + this.VisitPreXmlDoc(doc), trivia, range) abstract VisitSynField: SynField -> SynField @@ -618,8 +618,6 @@ type SyntaxVisitor() = | SynType.WithGlobalConstraints(typeName, constraints, range) -> SynType.WithGlobalConstraints(this.VisitSynType typeName, constraints, range) | SynType.HashConstraint(synType, range) -> SynType.HashConstraint(this.VisitSynType synType, range) - | SynType.MeasureDivide(dividendType, divisorType, range) -> - SynType.MeasureDivide(this.VisitSynType dividendType, this.VisitSynType divisorType, range) | SynType.MeasurePower(measureType, cnst, range) -> SynType.MeasurePower(this.VisitSynType measureType, cnst, range) | SynType.StaticConstant(constant, range) -> SynType.StaticConstant(this.VisitSynConst constant, range) @@ -632,6 +630,8 @@ type SyntaxVisitor() = SynType.Or(this.VisitSynType lhsType, this.VisitSynType rhsType, range, this.VisitSynTypeOrTrivia synTypeOrTrivia) | SynType.SignatureParameter(synAttributeLists, optional, identOption, usedType, range) -> SynType.SignatureParameter(List.map this.VisitSynAttributeList synAttributeLists, optional, Option.map this.VisitIdent identOption, this.VisitSynType usedType, range) + | SynType.FromParseError range -> SynType.FromParseError range + | SynType.Intersection(typar, types, range, trivia) -> SynType.Intersection(Option.map this.VisitSynTypar typar, types |> List.map this.VisitSynType, range, trivia) abstract VisitSynTypeOrTrivia: SynTypeOrTrivia -> SynTypeOrTrivia default this.VisitSynTypeOrTrivia(synTypeOrTrivia: SynTypeOrTrivia): SynTypeOrTrivia = synTypeOrTrivia diff --git a/tests/Identifiers/Lambdas/expected_representation.txt b/tests/Identifiers/Lambdas/expected_representation.txt index 7f10024..82a7d2b 100644 --- a/tests/Identifiers/Lambdas/expected_representation.txt +++ b/tests/Identifiers/Lambdas/expected_representation.txt @@ -1,5 +1,4 @@ module placeholder_1 let placeholder_4 = fun placeholder_2 placeholder_3 -> 1 + 2 - let placeholder_5 placeholder_2 = fun placeholder_3 -> 4 - 3