Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `[<Literal>]` 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

Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/Checking/NicePrint.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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) =
Expand Down
59 changes: 59 additions & 0 deletions tests/FSharp.Compiler.Service.Tests/Symbols.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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

[<Theory>]
[<InlineData("System.Int32", "MaxValue", "2147483647")>]
[<InlineData("System.Int32", "MinValue", "-2147483648")>]
[<InlineData("System.Int64", "MaxValue", "9223372036854775807L")>]
[<InlineData("System.Byte", "MaxValue", "255uy")>]
[<InlineData("System.SByte", "MinValue", "-128y")>]
let ``IL literal static field renders with [<Literal>] 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("[<Literal>]", metadataText)
Assert.Contains("= " + expectedValueText, line)

[<Fact>]
let ``System.Char.MaxValue renders as a literal field`` () =
let metadataText = getMetadataTextForEntity "Char" "let _ = typeof<System.Char>"

Assert.Contains("[<Literal>]", 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)

[<Fact>]
let ``System.String.Empty (initonly, non-literal) renders without [<Literal>] and without value`` () =
let metadataText = getMetadataTextForEntity "String" "let _ = typeof<System.String>"

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
[<Fact>]
Expand Down
Loading