From 4795f27e36c96369bab5ecf444adebce3f8242ae Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 24 Mar 2021 12:20:46 -0700 Subject: [PATCH 01/14] Initial commit for signature generation --- src/fsharp/NicePrint.fs | 8 ++++++++ src/fsharp/NicePrint.fsi | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index a91660a6bf4..d8dc30726ea 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -2085,3 +2085,11 @@ let minimalStringOfType denv ty = let denvMin = { denv with showImperativeTyparAnnotations=false; showConstraintTyparAnnotations=false } showL (PrintTypes.layoutTypeWithInfoAndPrec denvMin SimplifyTypes.typeSimplificationInfo0 2 ty) +let layoutOfModuleOrNamespaceType (_denv: DisplayEnv) (mty: ModuleOrNamespaceType) = + let top = + if mty.ModuleOrNamespaceKind = ModuleOrNamespaceKind.Namespace then + wordL (tagKeyword "namespace") + else + wordL (tagKeyword "module") + + top \ No newline at end of file diff --git a/src/fsharp/NicePrint.fsi b/src/fsharp/NicePrint.fsi index 59e436b5312..22bfc2a252e 100644 --- a/src/fsharp/NicePrint.fsi +++ b/src/fsharp/NicePrint.fsi @@ -113,3 +113,5 @@ val minimalStringsOfTwoTypes: denv:DisplayEnv -> t1:TType -> t2:TType -> string val minimalStringsOfTwoValues: denv:DisplayEnv -> v1:Val -> v2:Val -> string * string val minimalStringOfType: denv:DisplayEnv -> ty:TType -> string + +val layoutOfModuleOrNamespaceType: _denv:DisplayEnv -> mty:ModuleOrNamespaceType -> Layout From 6faf000af00eedb0cc5d2c79edef12b7dca01666 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 24 Mar 2021 13:13:21 -0700 Subject: [PATCH 02/14] Basic generation --- src/fsharp/NicePrint.fs | 6 +-- src/fsharp/NicePrint.fsi | 2 +- src/fsharp/service/FSharpCheckerResults.fs | 46 +++++++++++++++++++++ src/fsharp/service/FSharpCheckerResults.fsi | 4 ++ 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index d8dc30726ea..1e9f35ab425 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -2085,11 +2085,11 @@ let minimalStringOfType denv ty = let denvMin = { denv with showImperativeTyparAnnotations=false; showConstraintTyparAnnotations=false } showL (PrintTypes.layoutTypeWithInfoAndPrec denvMin SimplifyTypes.typeSimplificationInfo0 2 ty) -let layoutOfModuleOrNamespaceType (_denv: DisplayEnv) (mty: ModuleOrNamespaceType) = +let layoutOfModuleOrNamespaceType (_denv: DisplayEnv) (mty: ModuleOrNamespaceType, mtyQualifiedName: string list) = let top = if mty.ModuleOrNamespaceKind = ModuleOrNamespaceKind.Namespace then - wordL (tagKeyword "namespace") + wordL (tagKeyword "namespace") ^^ wordL (tagKeyword "rec") ^^ sepListL SepL.dot (List.map (tagNamespace >> wordL) mtyQualifiedName) else - wordL (tagKeyword "module") + wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ sepListL SepL.dot (List.map (tagNamespace >> wordL) mtyQualifiedName) top \ No newline at end of file diff --git a/src/fsharp/NicePrint.fsi b/src/fsharp/NicePrint.fsi index 22bfc2a252e..4b820c29ac3 100644 --- a/src/fsharp/NicePrint.fsi +++ b/src/fsharp/NicePrint.fsi @@ -114,4 +114,4 @@ val minimalStringsOfTwoValues: denv:DisplayEnv -> v1:Val -> v2:Val -> string * s val minimalStringOfType: denv:DisplayEnv -> ty:TType -> string -val layoutOfModuleOrNamespaceType: _denv:DisplayEnv -> mty:ModuleOrNamespaceType -> Layout +val layoutOfModuleOrNamespaceType: _denv:DisplayEnv -> mty:ModuleOrNamespaceType * mtyQualifiedName: string list -> Layout diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index 3690154175d..60abd7cb4a9 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -1969,6 +1969,52 @@ type FSharpCheckFileResults threadSafeOp (fun () -> None) (fun scope -> let (nenv, _), _ = scope.GetBestDisplayEnvForPos cursorPos Some(FSharpDisplayContext(fun _ -> nenv.DisplayEnv))) + + member _.GenerateSignatureText() = + threadSafeOp (fun () -> None) (fun scope -> + match scope.ThisCcu.QualifiedName with + | None -> None + | Some qualifiedName -> + + let tcGlobals = scope.TcGlobals + + let denv = DisplayEnv.Empty tcGlobals + let denv = + { denv with + showImperativeTyparAnnotations=true + showHiddenMembers=true + showObsoleteMembers=true + showAttributes=true } + + let rec pathForSynTy (_synTy: SynType) = + List.empty + + let extraOpenPaths = + scope.OpenDeclarations + |> Seq.map (fun x -> + match x.Target with + | SynOpenDeclTarget.ModuleOrNamespace(lid, _) -> lid |> List.map (fun x -> x.idText) + | SynOpenDeclTarget.Type(synTy, _) -> pathForSynTy synTy + ) + |> List.ofSeq + + let denv = + denv.SetOpenPaths + ([ FSharpLib.RootPath + FSharpLib.CorePath + FSharpLib.CollectionsPath + FSharpLib.ControlPath + (IL.splitNamespace FSharpLib.ExtraTopLevelOperatorsName) + ] @ extraOpenPaths) + + let mtyQualifiedName = + qualifiedName + |> String.split StringSplitOptions.RemoveEmptyEntries [|"."|] + |> List.ofArray + NicePrint.layoutOfModuleOrNamespaceType denv (scope.CcuSigForFile, mtyQualifiedName) |> LayoutRender.showL + |> SourceText.ofString + |> Some + ) member _.ImplementationFile = if not keepAssemblyContents then invalidOp "The 'keepAssemblyContents' flag must be set to true on the FSharpChecker in order to access the checked contents of assemblies" diff --git a/src/fsharp/service/FSharpCheckerResults.fsi b/src/fsharp/service/FSharpCheckerResults.fsi index 93ab0cfcf05..072a24f3e12 100644 --- a/src/fsharp/service/FSharpCheckerResults.fsi +++ b/src/fsharp/service/FSharpCheckerResults.fsi @@ -296,6 +296,10 @@ type public FSharpCheckFileResults = /// Determines if a long ident is resolvable at a specific point. member IsRelativeNameResolvableFromSymbol: cursorPos : pos * plid : string list * symbol: FSharpSymbol -> bool + /// Generates a signature of the file as source text. + /// Internal for the time being. + member internal GenerateSignatureText: unit -> ISourceText option + /// Represents complete typechecked implementation file, including its typechecked signatures if any. member ImplementationFile: FSharpImplementationFileContents option From 38fbcca8681578a5561ad5764758ecb18a413f61 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 24 Mar 2021 13:59:48 -0700 Subject: [PATCH 03/14] Added basic namespace test --- src/fsharp/NicePrint.fs | 41 +++++++++++++++---- src/fsharp/NicePrint.fsi | 2 +- src/fsharp/service/FSharpCheckerResults.fs | 10 +---- src/fsharp/service/FSharpCheckerResults.fsi | 3 +- tests/FSharp.Test.Utilities/Compiler.fs | 11 +++++ tests/FSharp.Test.Utilities/CompilerAssert.fs | 23 +++++++++++ .../Service/SignatureGenerationTests.fs | 33 +++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + 8 files changed, 104 insertions(+), 20 deletions(-) create mode 100644 tests/fsharp/Compiler/Service/SignatureGenerationTests.fs diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 1e9f35ab425..166538dee5e 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -2085,11 +2085,36 @@ let minimalStringOfType denv ty = let denvMin = { denv with showImperativeTyparAnnotations=false; showConstraintTyparAnnotations=false } showL (PrintTypes.layoutTypeWithInfoAndPrec denvMin SimplifyTypes.typeSimplificationInfo0 2 ty) -let layoutOfModuleOrNamespaceType (_denv: DisplayEnv) (mty: ModuleOrNamespaceType, mtyQualifiedName: string list) = - let top = - if mty.ModuleOrNamespaceKind = ModuleOrNamespaceKind.Namespace then - wordL (tagKeyword "namespace") ^^ wordL (tagKeyword "rec") ^^ sepListL SepL.dot (List.map (tagNamespace >> wordL) mtyQualifiedName) - else - wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ sepListL SepL.dot (List.map (tagNamespace >> wordL) mtyQualifiedName) - - top \ No newline at end of file +let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (mty: ModuleOrNamespaceType) = + ((denv, Layout.emptyL), mty.ModuleAndNamespaceDefinitions) + ||> List.fold (fun (denv, currentL) (mspec: ModuleOrNamespace) -> + let nm = mspec.DemangledModuleOrNamespaceName + let innerPath = (fullCompPathOfModuleOrNamespace mspec).AccessPath + let outerPath = mspec.CompilationPath.AccessPath + + let denv = denv.AddOpenPath (List.map fst innerPath) + let nextL = + if mspec.IsNamespace then + // This is a container namespace. We print the header when we get to the first concrete module. + wordL (tagKeyword "namespace") ^^ wordL (tagKeyword "rec") ^^ sepListL SepL.dot (List.map (fst >> tagNamespace >> wordL) innerPath) + else + // This is a module + let nmL = wordL (tagModule nm) + // Check if its an outer module or a nested module + if (outerPath |> List.forall (fun (_, istype) -> istype = Namespace)) then + // OK, we're not in F# Interactive + // Check if this is an outer module with no namespace + if isNil outerPath then + // If so print a "module" declaration + (wordL (tagKeyword "module") ^^ nmL) + else + // Otherwise this is an outer module contained immediately in a namespace + // We already printed the namespace declaration earlier. So just print the + // module now. + (wordL (tagKeyword"module") ^^ nmL ^^ WordL.equals) + else + // OK, this is a nested module + (wordL (tagKeyword "module") ^^ nmL ^^ WordL.equals) + (denv, currentL ^^ nextL) + ) + |> snd \ No newline at end of file diff --git a/src/fsharp/NicePrint.fsi b/src/fsharp/NicePrint.fsi index 4b820c29ac3..e76e7967d62 100644 --- a/src/fsharp/NicePrint.fsi +++ b/src/fsharp/NicePrint.fsi @@ -114,4 +114,4 @@ val minimalStringsOfTwoValues: denv:DisplayEnv -> v1:Val -> v2:Val -> string * s val minimalStringOfType: denv:DisplayEnv -> ty:TType -> string -val layoutOfModuleOrNamespaceType: _denv:DisplayEnv -> mty:ModuleOrNamespaceType * mtyQualifiedName: string list -> Layout +val layoutOfModuleOrNamespaceType: denv:DisplayEnv -> mty:ModuleOrNamespaceType -> Layout diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index 60abd7cb4a9..53b2432248c 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -1972,10 +1972,6 @@ type FSharpCheckFileResults member _.GenerateSignatureText() = threadSafeOp (fun () -> None) (fun scope -> - match scope.ThisCcu.QualifiedName with - | None -> None - | Some qualifiedName -> - let tcGlobals = scope.TcGlobals let denv = DisplayEnv.Empty tcGlobals @@ -2007,11 +2003,7 @@ type FSharpCheckFileResults (IL.splitNamespace FSharpLib.ExtraTopLevelOperatorsName) ] @ extraOpenPaths) - let mtyQualifiedName = - qualifiedName - |> String.split StringSplitOptions.RemoveEmptyEntries [|"."|] - |> List.ofArray - NicePrint.layoutOfModuleOrNamespaceType denv (scope.CcuSigForFile, mtyQualifiedName) |> LayoutRender.showL + NicePrint.layoutOfModuleOrNamespaceType denv scope.CcuSigForFile |> LayoutRender.showL |> SourceText.ofString |> Some ) diff --git a/src/fsharp/service/FSharpCheckerResults.fsi b/src/fsharp/service/FSharpCheckerResults.fsi index 072a24f3e12..36353a69a63 100644 --- a/src/fsharp/service/FSharpCheckerResults.fsi +++ b/src/fsharp/service/FSharpCheckerResults.fsi @@ -297,8 +297,7 @@ type public FSharpCheckFileResults = member IsRelativeNameResolvableFromSymbol: cursorPos : pos * plid : string list * symbol: FSharpSymbol -> bool /// Generates a signature of the file as source text. - /// Internal for the time being. - member internal GenerateSignatureText: unit -> ISourceText option + member GenerateSignatureText: unit -> ISourceText option /// Represents complete typechecked implementation file, including its typechecked signatures if any. member ImplementationFile: FSharpImplementationFileContents option diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index 70a0b001238..76b2b3e3539 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -426,6 +426,17 @@ module rec Compiler = | FS fs -> typecheckFSharp fs | _ -> failwith "Typecheck only supports F#" + let typecheckResults (cUnit: CompilationUnit) : FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults = + match cUnit with + | FS fsSource -> + let source = getSource fsSource.Source + let options = fsSource.Options |> Array.ofList + + let name = match fsSource.Name with | None -> "test.fs" | Some n -> n + + CompilerAssert.TypeCheck(options, name, source) + | _ -> failwith "Typecheck only supports F#" + let run (result: TestResult) : TestResult = match result with | Failure f -> failwith (sprintf "Compilation should be successfull in order to run.\n Errors: %A" (f.Diagnostics)) diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs index e41689f3bba..ad96fb7e93d 100644 --- a/tests/FSharp.Test.Utilities/CompilerAssert.fs +++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs @@ -649,6 +649,29 @@ let main argv = 0""" errors + /// Parses and type checks the given source. Fails if type checker is aborted. + static member ParseAndTypeCheck(options, name, source: string) = + lock gate <| fun () -> + let parseResults, fileAnswer = + checker.ParseAndCheckFileInProject( + name, + 0, + SourceText.ofString source, + { defaultProjectOptions with OtherOptions = Array.append options defaultProjectOptions.OtherOptions}) + |> Async.RunSynchronously + + match fileAnswer with + | FSharpCheckFileAnswer.Aborted _ -> Assert.Fail("Type Checker Aborted"); failwith "Type Checker Aborted" + | FSharpCheckFileAnswer.Succeeded(typeCheckResults) -> parseResults, typeCheckResults + + /// Parses and type checks the given source. Fails if the type checker is aborted or the parser returns any diagnostics. + static member TypeCheck(options, name, source: string) = + let parseResults, checkResults = CompilerAssert.ParseAndTypeCheck(options, name, source) + + Assert.IsEmpty(parseResults.Diagnostics, sprintf "Parse errors: %A" parseResults.Diagnostics) + + checkResults + static member TypeCheckWithErrorsAndOptionsAndAdjust options libAdjust (source: string) expectedTypeErrors = lock gate <| fun () -> let errors = diff --git a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs new file mode 100644 index 00000000000..b35c7181d6f --- /dev/null +++ b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open FSharp.Compiler.Diagnostics +open NUnit.Framework +open FSharp.Test.Utilities +open FSharp.Test.Utilities.Utilities +open FSharp.Test.Utilities.Compiler +open FSharp.Tests + +[] +module SignatureGenerationTests = + + let sigText (checkResults: FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults) = + match checkResults.GenerateSignatureText() with + | None -> failwith "Unable to generate signature text." + | Some text -> text + + [] + let ``Generate signature with correct namespace``() = + let text = + FSharp """ +namespace ANamespaceForSignature + """ + |> withLangVersion50 + |> typecheckResults + |> sigText + + let expected = + """namespace rec ANamespaceForSignature""" + + Assert.shouldBeEquivalentTo expected (text.ToString()) diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index a6f0066aca0..952372043cf 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -25,6 +25,7 @@ + From 0a547d93f2ea6acd742d55822fa77f5d2e957b4d Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 24 Mar 2021 14:42:37 -0700 Subject: [PATCH 04/14] Added another test --- src/fsharp/NicePrint.fs | 7 +++---- .../Compiler/Service/SignatureGenerationTests.fs | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 166538dee5e..914863bc8b9 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -2102,19 +2102,18 @@ let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (mty: ModuleOrNamespaceType let nmL = wordL (tagModule nm) // Check if its an outer module or a nested module if (outerPath |> List.forall (fun (_, istype) -> istype = Namespace)) then - // OK, we're not in F# Interactive // Check if this is an outer module with no namespace if isNil outerPath then // If so print a "module" declaration - (wordL (tagKeyword "module") ^^ nmL) + (wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ nmL) else // Otherwise this is an outer module contained immediately in a namespace // We already printed the namespace declaration earlier. So just print the // module now. - (wordL (tagKeyword"module") ^^ nmL ^^ WordL.equals) + (wordL (tagKeyword"module") ^^ wordL (tagKeyword "rec") ^^ nmL ^^ WordL.equals) else // OK, this is a nested module - (wordL (tagKeyword "module") ^^ nmL ^^ WordL.equals) + (wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ nmL ^^ WordL.equals) (denv, currentL ^^ nextL) ) |> snd \ No newline at end of file diff --git a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs index b35c7181d6f..c420e2a7cea 100644 --- a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs +++ b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs @@ -31,3 +31,18 @@ namespace ANamespaceForSignature """namespace rec ANamespaceForSignature""" Assert.shouldBeEquivalentTo expected (text.ToString()) + + [] + let ``Generate signature with correct module``() = + let text = + FSharp """ +module AModuleForSignature + """ + |> withLangVersion50 + |> typecheckResults + |> sigText + + let expected = + """module rec AModuleForSignature""" + + Assert.shouldBeEquivalentTo expected (text.ToString()) From 37d15a1a4f61889fa943b592427e15f191178280 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 24 Mar 2021 15:10:21 -0700 Subject: [PATCH 05/14] Added another test --- src/fsharp/NicePrint.fs | 20 +++++++++++++++---- .../Service/SignatureGenerationTests.fs | 15 ++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 914863bc8b9..f2c245cf6da 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -2086,17 +2086,29 @@ let minimalStringOfType denv ty = showL (PrintTypes.layoutTypeWithInfoAndPrec denvMin SimplifyTypes.typeSimplificationInfo0 2 ty) let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (mty: ModuleOrNamespaceType) = + + let rec fullPath (mspec: ModuleOrNamespace) acc = + if mspec.IsNamespace then + match mspec.ModuleOrNamespaceType.ModuleAndNamespaceDefinitions |> List.tryHead with + | Some next when next.IsModuleOrNamespace -> + fullPath next (acc @ [next.DemangledModuleOrNamespaceName]) + | _ -> + acc + else + acc + ((denv, Layout.emptyL), mty.ModuleAndNamespaceDefinitions) ||> List.fold (fun (denv, currentL) (mspec: ModuleOrNamespace) -> - let nm = mspec.DemangledModuleOrNamespaceName - let innerPath = (fullCompPathOfModuleOrNamespace mspec).AccessPath let outerPath = mspec.CompilationPath.AccessPath + + let path = fullPath mspec [mspec.DemangledModuleOrNamespaceName] + let nm = path |> List.last - let denv = denv.AddOpenPath (List.map fst innerPath) + let denv = denv.AddOpenPath path let nextL = if mspec.IsNamespace then // This is a container namespace. We print the header when we get to the first concrete module. - wordL (tagKeyword "namespace") ^^ wordL (tagKeyword "rec") ^^ sepListL SepL.dot (List.map (fst >> tagNamespace >> wordL) innerPath) + wordL (tagKeyword "namespace") ^^ wordL (tagKeyword "rec") ^^ sepListL SepL.dot (List.map (tagNamespace >> wordL) path) else // This is a module let nmL = wordL (tagModule nm) diff --git a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs index c420e2a7cea..6ba728f8b2c 100644 --- a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs +++ b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs @@ -32,6 +32,21 @@ namespace ANamespaceForSignature Assert.shouldBeEquivalentTo expected (text.ToString()) + [] + let ``Generate signature with correct namespace 2``() = + let text = + FSharp """ +namespace Test.ANamespaceForSignature + """ + |> withLangVersion50 + |> typecheckResults + |> sigText + + let expected = + """namespace rec Test.ANamespaceForSignature""" + + Assert.shouldBeEquivalentTo expected (text.ToString()) + [] let ``Generate signature with correct module``() = let text = From 786168f1e9a1183971867ccd00f06cba11e1497d Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 24 Mar 2021 15:24:59 -0700 Subject: [PATCH 06/14] Added another test --- src/fsharp/NicePrint.fs | 17 +++++++++++------ .../Service/SignatureGenerationTests.fs | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index f2c245cf6da..cec07b1ebc6 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -2093,25 +2093,30 @@ let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (mty: ModuleOrNamespaceType | Some next when next.IsModuleOrNamespace -> fullPath next (acc @ [next.DemangledModuleOrNamespaceName]) | _ -> - acc + acc, mspec.IsNamespace else - acc + acc, mspec.IsNamespace ((denv, Layout.emptyL), mty.ModuleAndNamespaceDefinitions) ||> List.fold (fun (denv, currentL) (mspec: ModuleOrNamespace) -> let outerPath = mspec.CompilationPath.AccessPath - let path = fullPath mspec [mspec.DemangledModuleOrNamespaceName] - let nm = path |> List.last + let path, isNamespace = fullPath mspec [mspec.DemangledModuleOrNamespaceName] let denv = denv.AddOpenPath path let nextL = - if mspec.IsNamespace then + if isNamespace then // This is a container namespace. We print the header when we get to the first concrete module. wordL (tagKeyword "namespace") ^^ wordL (tagKeyword "rec") ^^ sepListL SepL.dot (List.map (tagNamespace >> wordL) path) else // This is a module - let nmL = wordL (tagModule nm) + let nmL = + match path with + | [nm] -> wordL (tagModule nm) + | _ -> + let nm = path |> List.last + let innerPath = path.[..path.Length - 2] + sepListL SepL.dot (List.map (tagNamespace >> wordL) innerPath) ^^ SepL.dot ^^ wordL (tagModule nm) // Check if its an outer module or a nested module if (outerPath |> List.forall (fun (_, istype) -> istype = Namespace)) then // Check if this is an outer module with no namespace diff --git a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs index 6ba728f8b2c..4f89b5fb02f 100644 --- a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs +++ b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs @@ -61,3 +61,18 @@ module AModuleForSignature """module rec AModuleForSignature""" Assert.shouldBeEquivalentTo expected (text.ToString()) + + [] + let ``Generate signature with correct module 2``() = + let text = + FSharp """ +module Test.AModuleForSignature + """ + |> withLangVersion50 + |> typecheckResults + |> sigText + + let expected = + """module rec Test.AModuleForSignature""" + + Assert.shouldBeEquivalentTo expected (text.ToString()) From 7d6ec7120ac961d36b5bee2b062074158934bab4 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 24 Mar 2021 16:15:42 -0700 Subject: [PATCH 07/14] Simplifying tests. Added linebreaks --- src/fsharp/NicePrint.fs | 19 +++-- .../Service/SignatureGenerationTests.fs | 72 ++++++++----------- 2 files changed, 43 insertions(+), 48 deletions(-) diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index cec07b1ebc6..83038f76d0e 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -2097,13 +2097,12 @@ let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (mty: ModuleOrNamespaceType else acc, mspec.IsNamespace - ((denv, Layout.emptyL), mty.ModuleAndNamespaceDefinitions) - ||> List.fold (fun (denv, currentL) (mspec: ModuleOrNamespace) -> + let moduleOrNamespaceL (denv: DisplayEnv) (mspec: ModuleOrNamespace) = let outerPath = mspec.CompilationPath.AccessPath let path, isNamespace = fullPath mspec [mspec.DemangledModuleOrNamespaceName] - let denv = denv.AddOpenPath path + let _denv = denv.AddOpenPath path let nextL = if isNamespace then // This is a container namespace. We print the header when we get to the first concrete module. @@ -2127,10 +2126,16 @@ let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (mty: ModuleOrNamespaceType // Otherwise this is an outer module contained immediately in a namespace // We already printed the namespace declaration earlier. So just print the // module now. - (wordL (tagKeyword"module") ^^ wordL (tagKeyword "rec") ^^ nmL ^^ WordL.equals) + (wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ nmL ^^ WordL.equals) else // OK, this is a nested module (wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ nmL ^^ WordL.equals) - (denv, currentL ^^ nextL) - ) - |> snd \ No newline at end of file + nextL + + let moduleOrNamespaces = + mty.ModuleAndNamespaceDefinitions + |> List.map (fun mspec -> + moduleOrNamespaceL denv mspec + ) + + sepListL (sepL lineBreak ^^ sepL lineBreak) moduleOrNamespaces \ No newline at end of file diff --git a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs index 4f89b5fb02f..2744acf046b 100644 --- a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs +++ b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs @@ -17,62 +17,52 @@ module SignatureGenerationTests = | None -> failwith "Unable to generate signature text." | Some text -> text - [] - let ``Generate signature with correct namespace``() = + let sigShouldBe (expected: string) src = let text = - FSharp """ -namespace ANamespaceForSignature - """ + FSharp src |> withLangVersion50 |> typecheckResults |> sigText - let expected = - """namespace rec ANamespaceForSignature""" - - Assert.shouldBeEquivalentTo expected (text.ToString()) + let textString = text.ToString() + let expected = expected.Replace("\r\n", "\n") + Assert.shouldBeEquivalentTo expected textString + + [] + let ``Generate signature with correct namespace``() = + """ +namespace ANamespaceForSignature + """ + |> sigShouldBe """namespace rec ANamespaceForSignature""" [] let ``Generate signature with correct namespace 2``() = - let text = - FSharp """ + """ namespace Test.ANamespaceForSignature - """ - |> withLangVersion50 - |> typecheckResults - |> sigText + """ + |> sigShouldBe """namespace rec Test.ANamespaceForSignature""" - let expected = - """namespace rec Test.ANamespaceForSignature""" - - Assert.shouldBeEquivalentTo expected (text.ToString()) + [] + let ``Generate signature with correct namespace 3``() = + """ +namespace Test.ANamespaceForSignature + +namespace Test2.ANamespaceForSignature2 + """ + |> sigShouldBe """namespace rec Test.ANamespaceForSignature + +namespace rec Test2.ANamespaceForSignature2""" [] let ``Generate signature with correct module``() = - let text = - FSharp """ + """ module AModuleForSignature - """ - |> withLangVersion50 - |> typecheckResults - |> sigText - - let expected = - """module rec AModuleForSignature""" - - Assert.shouldBeEquivalentTo expected (text.ToString()) + """ + |> sigShouldBe """module rec AModuleForSignature""" [] let ``Generate signature with correct module 2``() = - let text = - FSharp """ + """ module Test.AModuleForSignature - """ - |> withLangVersion50 - |> typecheckResults - |> sigText - - let expected = - """module rec Test.AModuleForSignature""" - - Assert.shouldBeEquivalentTo expected (text.ToString()) + """ + |> sigShouldBe """module rec Test.AModuleForSignature""" From b025e209435a0402011f2dca501f907ac29c057d Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 24 Mar 2021 17:43:50 -0700 Subject: [PATCH 08/14] More tests --- src/fsharp/NicePrint.fs | 43 ++++++++++++++----- src/fsharp/NicePrint.fsi | 2 +- src/fsharp/service/FSharpCheckerResults.fs | 3 +- .../Service/SignatureGenerationTests.fs | 28 +++++++++++- 4 files changed, 62 insertions(+), 14 deletions(-) diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 83038f76d0e..f7a2edf0482 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -2085,7 +2085,9 @@ let minimalStringOfType denv ty = let denvMin = { denv with showImperativeTyparAnnotations=false; showConstraintTyparAnnotations=false } showL (PrintTypes.layoutTypeWithInfoAndPrec denvMin SimplifyTypes.typeSimplificationInfo0 2 ty) -let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (mty: ModuleOrNamespaceType) = +let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (infoReader: InfoReader) (ad: AccessibilityLogic.AccessorDomain) (mty: ModuleOrNamespaceType) = + + let sepDoubleLineBreakL = (sepL lineBreak ^^ sepL lineBreak) let rec fullPath (mspec: ModuleOrNamespace) acc = if mspec.IsNamespace then @@ -2093,18 +2095,18 @@ let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (mty: ModuleOrNamespaceType | Some next when next.IsModuleOrNamespace -> fullPath next (acc @ [next.DemangledModuleOrNamespaceName]) | _ -> - acc, mspec.IsNamespace + acc, mspec else - acc, mspec.IsNamespace + acc, mspec - let moduleOrNamespaceL (denv: DisplayEnv) (mspec: ModuleOrNamespace) = + let rec moduleOrNamespaceL isFirstTopLevel (denv: DisplayEnv) (mspec: ModuleOrNamespace) = let outerPath = mspec.CompilationPath.AccessPath - let path, isNamespace = fullPath mspec [mspec.DemangledModuleOrNamespaceName] + let path, mspec = fullPath mspec [mspec.DemangledModuleOrNamespaceName] - let _denv = denv.AddOpenPath path + let denv = denv.AddOpenPath path let nextL = - if isNamespace then + if mspec.IsNamespace then // This is a container namespace. We print the header when we get to the first concrete module. wordL (tagKeyword "namespace") ^^ wordL (tagKeyword "rec") ^^ sepListL SepL.dot (List.map (tagNamespace >> wordL) path) else @@ -2130,12 +2132,33 @@ let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (mty: ModuleOrNamespaceType else // OK, this is a nested module (wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ nmL ^^ WordL.equals) - nextL + + let entityLs = + mspec.ModuleOrNamespaceType.AllEntities + |> QueueList.toList + |> List.map (fun entity -> + if entity.IsModuleOrNamespace then + moduleOrNamespaceL false denv entity + else + layoutTycon denv infoReader ad Range.range0 entity + ) + + if List.isEmpty entityLs then + nextL + else + let entitiesL = + entityLs + |> sepListL sepDoubleLineBreakL + + if isFirstTopLevel then + nextL ++ sepL lineBreak @@ entitiesL + else + nextL ++ sepL lineBreak @@- entitiesL let moduleOrNamespaces = mty.ModuleAndNamespaceDefinitions |> List.map (fun mspec -> - moduleOrNamespaceL denv mspec + moduleOrNamespaceL true denv mspec ) - sepListL (sepL lineBreak ^^ sepL lineBreak) moduleOrNamespaces \ No newline at end of file + sepListL sepDoubleLineBreakL moduleOrNamespaces \ No newline at end of file diff --git a/src/fsharp/NicePrint.fsi b/src/fsharp/NicePrint.fsi index e76e7967d62..9792aafda48 100644 --- a/src/fsharp/NicePrint.fsi +++ b/src/fsharp/NicePrint.fsi @@ -114,4 +114,4 @@ val minimalStringsOfTwoValues: denv:DisplayEnv -> v1:Val -> v2:Val -> string * s val minimalStringOfType: denv:DisplayEnv -> ty:TType -> string -val layoutOfModuleOrNamespaceType: denv:DisplayEnv -> mty:ModuleOrNamespaceType -> Layout +val layoutOfModuleOrNamespaceType: denv:DisplayEnv -> infoReader: InfoReader -> ad: AccessibilityLogic.AccessorDomain -> mty:ModuleOrNamespaceType -> Layout diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index 53b2432248c..b36b22929c7 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -2003,7 +2003,8 @@ type FSharpCheckFileResults (IL.splitNamespace FSharpLib.ExtraTopLevelOperatorsName) ] @ extraOpenPaths) - NicePrint.layoutOfModuleOrNamespaceType denv scope.CcuSigForFile |> LayoutRender.showL + let infoReader = InfoReader(scope.SymbolEnv.g, scope.SymbolEnv.amap) + NicePrint.layoutOfModuleOrNamespaceType denv infoReader scope.AccessRights scope.CcuSigForFile |> LayoutRender.showL |> SourceText.ofString |> Some ) diff --git a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs index 2744acf046b..8303110b24c 100644 --- a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs +++ b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs @@ -25,8 +25,8 @@ module SignatureGenerationTests = |> sigText let textString = text.ToString() - let expected = expected.Replace("\r\n", "\n") - Assert.shouldBeEquivalentTo expected textString + let expected2 = expected.Replace("\r\n", "\n") + Assert.shouldBeEquivalentTo expected2 textString [] let ``Generate signature with correct namespace``() = @@ -53,6 +53,30 @@ namespace Test2.ANamespaceForSignature2 namespace rec Test2.ANamespaceForSignature2""" + + [] + let ``Generate signature with correct namespace and type``() = + """ +namespace Test.ANamespaceForSignature + +type TestType = class end + """ + |> sigShouldBe """namespace rec Test.ANamespaceForSignature + +type TestType""" + + [] + let ``Generate signature with correct namespace and private inner record type``() = + """ +namespace Test.ANamespaceForSignature + +type TestType = private { x: int } + """ + |> sigShouldBe """namespace rec Test.ANamespaceForSignature + +type TestType = + private { x: int }""" + [] let ``Generate signature with correct module``() = """ From 68e60996af0674e7321654c0a92e874263dabaa7 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 24 Mar 2021 18:55:34 -0700 Subject: [PATCH 09/14] one test fails --- src/fsharp/NicePrint.fs | 26 ++++++++++++------- .../Service/SignatureGenerationTests.fs | 20 +++++++++++++- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index f7a2edf0482..aca12d1182e 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -2092,7 +2092,7 @@ let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (infoReader: InfoReader) (a let rec fullPath (mspec: ModuleOrNamespace) acc = if mspec.IsNamespace then match mspec.ModuleOrNamespaceType.ModuleAndNamespaceDefinitions |> List.tryHead with - | Some next when next.IsModuleOrNamespace -> + | Some next when next.IsNamespace -> fullPath next (acc @ [next.DemangledModuleOrNamespaceName]) | _ -> acc, mspec @@ -2125,13 +2125,19 @@ let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (infoReader: InfoReader) (a // If so print a "module" declaration (wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ nmL) else - // Otherwise this is an outer module contained immediately in a namespace - // We already printed the namespace declaration earlier. So just print the - // module now. - (wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ nmL ^^ WordL.equals) + if mspec.ModuleOrNamespaceType.AllEntities |> Seq.isEmpty && mspec.ModuleOrNamespaceType.AllValsAndMembers |> Seq.isEmpty then + (wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ nmL ^^ WordL.equals ^^ wordL (tagKeyword "begin") ^^ wordL (tagKeyword "end")) + else + // Otherwise this is an outer module contained immediately in a namespace + // We already printed the namespace declaration earlier. So just print the + // module now. + (wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ nmL ^^ WordL.equals) else - // OK, this is a nested module - (wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ nmL ^^ WordL.equals) + if mspec.ModuleOrNamespaceType.AllEntities |> Seq.isEmpty && mspec.ModuleOrNamespaceType.AllValsAndMembers |> Seq.isEmpty then + (wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ nmL ^^ WordL.equals ^^ wordL (tagKeyword "begin") ^^ wordL (tagKeyword "end")) + else + // OK, this is a nested module + (wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ nmL ^^ WordL.equals) let entityLs = mspec.ModuleOrNamespaceType.AllEntities @@ -2151,9 +2157,11 @@ let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (infoReader: InfoReader) (a |> sepListL sepDoubleLineBreakL if isFirstTopLevel then - nextL ++ sepL lineBreak @@ entitiesL + aboveL + (nextL ^^ sepL lineBreak) + entitiesL else - nextL ++ sepL lineBreak @@- entitiesL + nextL ^^ entitiesL let moduleOrNamespaces = mty.ModuleAndNamespaceDefinitions diff --git a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs index 8303110b24c..197c0519567 100644 --- a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs +++ b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs @@ -74,6 +74,22 @@ type TestType = private { x: int } """ |> sigShouldBe """namespace rec Test.ANamespaceForSignature +type TestType = + private { x: int }""" + + [] + let ``Generate signature with correct namespace and private inner record type and module with private inner record type``() = + """ +namespace Test.ANamespaceForSignature + +type TestType = private { x: int } + +module ModuleA = + + type TestType2 = private { x: float32 } + """ + |> sigShouldBe """namespace rec Test.ANamespaceForSignature + type TestType = private { x: int }""" @@ -89,4 +105,6 @@ module AModuleForSignature """ module Test.AModuleForSignature """ - |> sigShouldBe """module rec Test.AModuleForSignature""" + |> sigShouldBe """namespace rec Test + +module rec AModuleForSignature = begin end""" From e6c4facbc99d5c2ebf7aef6e2fdff213c5785d42 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Mon, 29 Mar 2021 17:59:51 -0700 Subject: [PATCH 10/14] Tests finally pass --- src/fsharp/NicePrint.fs | 14 +++++++++++--- .../Compiler/Service/SignatureGenerationTests.fs | 11 ++++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index aca12d1182e..740dc0fa0f7 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -2153,15 +2153,23 @@ let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (infoReader: InfoReader) (a nextL else let entitiesL = - entityLs - |> sepListL sepDoubleLineBreakL + match entityLs with + | [] -> emptyL + | [entityL] -> entityL + | entityL :: entityLs -> + entityL @@ + ( + entityLs + |> List.map (fun entityL -> sepL lineBreak ^^ entityL) + |> aboveListL + ) if isFirstTopLevel then aboveL (nextL ^^ sepL lineBreak) entitiesL else - nextL ^^ entitiesL + (nextL ^^ sepL lineBreak) @@-- entitiesL let moduleOrNamespaces = mty.ModuleAndNamespaceDefinitions diff --git a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs index 197c0519567..46d0bbdb1ac 100644 --- a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs +++ b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs @@ -24,9 +24,9 @@ module SignatureGenerationTests = |> typecheckResults |> sigText - let textString = text.ToString() + let actual = text.ToString() let expected2 = expected.Replace("\r\n", "\n") - Assert.shouldBeEquivalentTo expected2 textString + Assert.shouldBeEquivalentTo expected2 actual [] let ``Generate signature with correct namespace``() = @@ -91,7 +91,12 @@ module ModuleA = |> sigShouldBe """namespace rec Test.ANamespaceForSignature type TestType = - private { x: int }""" + private { x: int } + +module rec ModuleA = + + type TestType2 = + private { x: float32 }""" [] let ``Generate signature with correct module``() = From b50208879399860f7be7ae262d28c893179b27a0 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Mon, 29 Mar 2021 18:02:41 -0700 Subject: [PATCH 11/14] Better indent --- src/fsharp/NicePrint.fs | 2 +- tests/fsharp/Compiler/Service/SignatureGenerationTests.fs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 740dc0fa0f7..5a3269c5ff8 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -2169,7 +2169,7 @@ let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (infoReader: InfoReader) (a (nextL ^^ sepL lineBreak) entitiesL else - (nextL ^^ sepL lineBreak) @@-- entitiesL + (nextL ^^ sepL lineBreak) @@- entitiesL let moduleOrNamespaces = mty.ModuleAndNamespaceDefinitions diff --git a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs index 46d0bbdb1ac..336431d6193 100644 --- a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs +++ b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs @@ -95,8 +95,8 @@ type TestType = module rec ModuleA = - type TestType2 = - private { x: float32 }""" + type TestType2 = + private { x: float32 }""" [] let ``Generate signature with correct module``() = From be3410b3276df0754b8920d896d0a46280039fca Mon Sep 17 00:00:00 2001 From: Will Smith Date: Mon, 29 Mar 2021 18:05:36 -0700 Subject: [PATCH 12/14] Added a failing test --- .../fsharp/Compiler/Service/SignatureGenerationTests.fs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs index 336431d6193..58fd314c4b1 100644 --- a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs +++ b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs @@ -113,3 +113,12 @@ module Test.AModuleForSignature |> sigShouldBe """namespace rec Test module rec AModuleForSignature = begin end""" + + [] + let ``Generate signature with correct module includes attributes``() = + """ +[] +module AModuleForSignature + """ + |> sigShouldBe """[] +module rec AModuleForSignature""" From 9179b458432b054e0f6afcbcd5cf8d1f1dc036d2 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Mon, 29 Mar 2021 18:23:36 -0700 Subject: [PATCH 13/14] Verifying area --- src/fsharp/NicePrint.fs | 3 +++ tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs | 3 ++- tests/fsharp/Compiler/Service/SignatureGenerationTests.fs | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 5a3269c5ff8..4422b93e9d7 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -2139,6 +2139,9 @@ let layoutOfModuleOrNamespaceType (denv: DisplayEnv) (infoReader: InfoReader) (a // OK, this is a nested module (wordL (tagKeyword "module") ^^ wordL (tagKeyword "rec") ^^ nmL ^^ WordL.equals) + let nextL = + PrintTypes.layoutAttribs denv false (generalizedTyconRef(mkLocalEntityRef mspec)) mspec.TypeOrMeasureKind mspec.Attribs nextL + let entityLs = mspec.ModuleOrNamespaceType.AllEntities |> QueueList.toList diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index a577dacb842..9e4f2c129f1 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -1395,6 +1395,7 @@ FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FShar FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Symbols.FSharpDisplayContext] GetDisplayContextForPos(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Symbols.FSharpImplementationFileContents] ImplementationFile FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Symbols.FSharpImplementationFileContents] get_ImplementationFile() +FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.ISourceText] GenerateSignatureText() FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpSymbolUse]] GetMethodsAsSymbols(Int32, Int32, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FSharpOption`1[System.String] GetF1Keyword(Int32, Int32, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: System.Collections.Generic.IEnumerable`1[FSharp.Compiler.CodeAnalysis.FSharpSymbolUse] GetAllUsesOfAllSymbolsInFile(Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken]) @@ -1494,11 +1495,11 @@ FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: FSharp.Compiler.Syntax.Pars FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: FSharp.Compiler.Syntax.ParsedInput get_ParseTree() FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.ParameterLocations] FindParameterLocations(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] TryRangeOfExprInYieldOrReturn(FSharp.Compiler.Text.Position) +FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] TryRangeOfExpressionBeingDereferencedContainingPos(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] TryRangeOfFunctionOrMethodBeingApplied(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] TryRangeOfNameOfNearestOuterBindingContainingPos(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] TryRangeOfRecordExpressionContainingPos(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] TryRangeOfRefCellDereferenceContainingPos(FSharp.Compiler.Text.Position) -FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] TryRangeOfExpressionBeingDereferencedContainingPos(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] ValidateBreakpointLocation(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range]] GetAllArgumentsForFunctionApplicationAtPostion(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Syntax.Ident,System.Int32]] TryIdentOfPipelineContainingPosAndNumArgsApplied(FSharp.Compiler.Text.Position) diff --git a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs index 58fd314c4b1..174493fe065 100644 --- a/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs +++ b/tests/fsharp/Compiler/Service/SignatureGenerationTests.fs @@ -116,9 +116,10 @@ module rec AModuleForSignature = begin end""" [] let ``Generate signature with correct module includes attributes``() = + // TODO: This should trim the "Attribute ()". """ [] module AModuleForSignature """ - |> sigShouldBe """[] + |> sigShouldBe """[] module rec AModuleForSignature""" From 2de2390fe7e955b1c239cb1f5f3bc7aa7f9302ff Mon Sep 17 00:00:00 2001 From: Will Smith Date: Mon, 29 Mar 2021 18:35:19 -0700 Subject: [PATCH 14/14] Do not shrink overloads --- src/fsharp/service/FSharpCheckerResults.fs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index b36b22929c7..7d4a97adc31 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -1980,7 +1980,9 @@ type FSharpCheckFileResults showImperativeTyparAnnotations=true showHiddenMembers=true showObsoleteMembers=true - showAttributes=true } + showAttributes=true + shrinkOverloads=false + printVerboseSignatures=false } let rec pathForSynTy (_synTy: SynType) = List.empty