diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 965957dbc0..4c84e8f68b 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -75,6 +75,7 @@ ([PR #19724](https://github.com/dotnet/fsharp/pull/19724)) * Emit debug points at a stack-empty position ([PR #19877](https://github.com/dotnet/fsharp/pull/19877)) * Fix spurious XmlDoc warnings (unknown parameter / no documentation for parameter) under `--warnon:3390` when a get/set property documents the full parameter set across both accessors. ([Issue #13684](https://github.com/dotnet/fsharp/issues/13684), [PR #19884](https://github.com/dotnet/fsharp/pull/19884)) +* Fix Go to Metadata rendering of IL literal (`const`) fields - they now appear with `[]` and their constant value, e.g. `System.Char.MaxValue` no longer shows as a plain `static val`. ([Issue #11526](https://github.com/dotnet/fsharp/issues/11526), [PR #19922](https://github.com/dotnet/fsharp/pull/19922)) ### Added diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs index de8daffa7c..fdd2899bfa 100644 --- a/src/Compiler/Checking/NicePrint.fs +++ b/src/Compiler/Checking/NicePrint.fs @@ -1954,6 +1954,11 @@ module TastDefinitionPrinting = let nameL = ConvertLogicalNameToDisplayLayout (tagField >> wordL) finfo.FieldName let typL = layoutType denv (finfo.FieldType(infoReader.amap, m)) let fieldL = staticL ^^ WordL.keywordVal ^^ (nameL |> addColonL) ^^ typL + let isLiteral = finfo.LiteralValue.IsSome + let fieldL = + if isLiteral then fieldL ^^ PrintIL.layoutILFieldInit finfo.LiteralValue + else fieldL + let fieldL = fieldL |> PrintTypes.layoutAttribs denv None isLiteral TyparKind.Type [] layoutXmlDocOfILFieldInfo denv infoReader finfo fieldL let layoutEventInfo denv (infoReader: InfoReader) m (einfo: EventInfo) = diff --git a/tests/FSharp.Compiler.Service.Tests/Symbols.fs b/tests/FSharp.Compiler.Service.Tests/Symbols.fs index 25cc0cd4b6..ffce69cd9a 100644 --- a/tests/FSharp.Compiler.Service.Tests/Symbols.fs +++ b/tests/FSharp.Compiler.Service.Tests/Symbols.fs @@ -1445,6 +1445,65 @@ let test = System.DateTimeKind.Utc failwith "Expected metadata text, got None" | _ -> failwith "Expected FSharpEntity symbol" +module MetadataAsTextILField = + + let private getMetadataTextForEntity (entityName: string) (source: string) : string = + let _, checkResults = getParseAndCheckResults source + let symbolUse = checkResults |> findSymbolUseByName entityName + match symbolUse.Symbol with + | :? FSharpEntity as entity -> + match entity.TryGetMetadataText() with + | Some text -> text.ToString() + | None -> failwithf "Expected metadata text for %s, got None" entityName + | other -> failwithf "Expected FSharpEntity for %s, got %A" entityName other + + [] + [] + [] + [] + [] + [] + let ``IL literal static field renders with [] attribute and value`` + (typeName: string, fieldName: string, expectedValueText: string) = + let source = $"let _ = typeof<{typeName}>" + let shortName = typeName.Substring(typeName.LastIndexOf('.') + 1) + let metadataText = getMetadataTextForEntity shortName source + + Assert.Contains(fieldName, metadataText) + + let line = + metadataText.Split('\n') + |> Array.tryFind (fun l -> l.Contains("val " + fieldName + ":")) + |> Option.defaultWith (fun () -> failwithf "field declaration for %s not found in metadata text:\n%s" fieldName metadataText) + + Assert.Contains("[]", metadataText) + Assert.Contains("= " + expectedValueText, line) + + [] + let ``System.Char.MaxValue renders as a literal field`` () = + let metadataText = getMetadataTextForEntity "Char" "let _ = typeof" + + Assert.Contains("[]", metadataText) + let line = + metadataText.Split('\n') + |> Array.tryFind (fun l -> l.Contains("val MaxValue:")) + |> Option.defaultWith (fun () -> failwithf "MaxValue declaration not found:\n%s" metadataText) + Assert.Contains("=", line) + Assert.False(line.TrimEnd().EndsWith(": char"), + sprintf "MaxValue line is missing its literal value: %s" line) + + [] + let ``System.String.Empty (initonly, non-literal) renders without [] and without value`` () = + let metadataText = getMetadataTextForEntity "String" "let _ = typeof" + + let line = + metadataText.Split('\n') + |> Array.tryFind (fun l -> l.Contains("val Empty:")) + |> Option.defaultWith (fun () -> failwithf "Empty not found:\n%s" metadataText) + + Assert.Contains("static val", line) + Assert.DoesNotContain("=", line) + module IsByRef = // https://github.com/dotnet/fsharp/issues/3532 []