Skip to content

Commit 86d05ef

Browse files
authored
Prefixed module nameof (#16743) (#16747)
1 parent 4c93c63 commit 86d05ef

File tree

3 files changed

+67
-7
lines changed

3 files changed

+67
-7
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
### Fixed
22

3-
* `nameof Module` expressions and patterns are processed to link files in `--test:GraphBasedChecking`. ([PR #16570](https://github.com/dotnet/fsharp/pull/16570))
3+
`nameof Module` expressions and patterns are processed to link files in `--test:GraphBasedChecking`. ([PR #16570](https://github.com/dotnet/fsharp/pull/16570), [PR #16747](https://github.com/dotnet/fsharp/pull/16747))

src/Compiler/Driver/GraphChecking/FileContentMapping.fs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,27 @@ let visitSynTypeConstraint (tc: SynTypeConstraint) : FileContentEntry list =
311311
let inline (|NameofIdent|_|) (ident: Ident) =
312312
if ident.idText = "nameof" then ValueSome() else ValueNone
313313

314+
/// nameof X.Y.Z can be used in expressions and patterns
315+
[<RequireQualifiedAccess; NoComparison>]
316+
type NameofResult =
317+
/// Example: nameof X
318+
/// Where X is a module name
319+
| SingleIdent of potentialModuleName: Ident
320+
/// Example: nameof X.Y.Z
321+
/// Where Z is either a module name or something from inside module or namespace Y.
322+
/// Both options need to be explored.
323+
| LongIdent of longIdent: LongIdent
324+
325+
let visitNameofResult (nameofResult: NameofResult) : FileContentEntry =
326+
match nameofResult with
327+
| NameofResult.SingleIdent moduleName -> visitIdentAsPotentialModuleName moduleName
328+
| NameofResult.LongIdent longIdent ->
329+
// In this case the last part of the LongIdent could be a module name.
330+
// So we should not cut off the last part.
331+
FileContentEntry.PrefixedIdentifier(longIdentToPath false longIdent)
332+
314333
/// Special case of `nameof Module` type of expression
315-
let (|NameofExpr|_|) (e: SynExpr) =
334+
let (|NameofExpr|_|) (e: SynExpr) : NameofResult option =
316335
let rec stripParen (e: SynExpr) =
317336
match e with
318337
| SynExpr.Paren(expr = expr) -> stripParen expr
@@ -321,14 +340,20 @@ let (|NameofExpr|_|) (e: SynExpr) =
321340
match e with
322341
| SynExpr.App(flag = ExprAtomicFlag.NonAtomic; isInfix = false; funcExpr = SynExpr.Ident NameofIdent; argExpr = moduleNameExpr) ->
323342
match stripParen moduleNameExpr with
324-
| SynExpr.Ident moduleNameIdent -> Some moduleNameIdent
343+
| SynExpr.Ident moduleNameIdent -> Some(NameofResult.SingleIdent moduleNameIdent)
344+
| SynExpr.LongIdent(longDotId = longIdent) ->
345+
match longIdent.LongIdent with
346+
| [] -> None
347+
// This is highly unlikely to be produced by the parser
348+
| [ moduleNameIdent ] -> Some(NameofResult.SingleIdent moduleNameIdent)
349+
| lid -> Some(NameofResult.LongIdent(lid))
325350
| _ -> None
326351
| _ -> None
327352

328353
let visitSynExpr (e: SynExpr) : FileContentEntry list =
329354
let rec visit (e: SynExpr) (continuation: FileContentEntry list -> FileContentEntry list) : FileContentEntry list =
330355
match e with
331-
| NameofExpr moduleNameIdent -> continuation [ visitIdentAsPotentialModuleName moduleNameIdent ]
356+
| NameofExpr nameofResult -> continuation [ visitNameofResult nameofResult ]
332357
| SynExpr.Const _ -> continuation []
333358
| SynExpr.Paren(expr = expr) -> visit expr continuation
334359
| SynExpr.Quote(operator = operator; quotedExpr = quotedExpr) ->
@@ -552,18 +577,22 @@ let (|NameofPat|_|) (pat: SynPat) =
552577
| SynPat.LongIdent(longDotId = SynLongIdent(id = [ NameofIdent ]); typarDecls = None; argPats = SynArgPats.Pats [ moduleNamePat ]) ->
553578
match stripPats moduleNamePat with
554579
| SynPat.LongIdent(
555-
longDotId = SynLongIdent.SynLongIdent(id = [ moduleNameIdent ]; dotRanges = []; trivia = [ None ])
580+
longDotId = SynLongIdent.SynLongIdent(id = longIdent)
556581
extraId = None
557582
typarDecls = None
558583
argPats = SynArgPats.Pats []
559-
accessibility = None) -> Some moduleNameIdent
584+
accessibility = None) ->
585+
match longIdent with
586+
| [] -> None
587+
| [ moduleNameIdent ] -> Some(NameofResult.SingleIdent moduleNameIdent)
588+
| lid -> Some(NameofResult.LongIdent lid)
560589
| _ -> None
561590
| _ -> None
562591

563592
let visitPat (p: SynPat) : FileContentEntry list =
564593
let rec visit (p: SynPat) (continuation: FileContentEntry list -> FileContentEntry list) : FileContentEntry list =
565594
match p with
566-
| NameofPat moduleNameIdent -> continuation [ visitIdentAsPotentialModuleName moduleNameIdent ]
595+
| NameofPat moduleNameIdent -> continuation [ visitNameofResult moduleNameIdent ]
567596
| SynPat.Paren(pat = pat) -> visit pat continuation
568597
| SynPat.Typed(pat = pat; targetType = t) -> visit pat (fun nodes -> nodes @ visitSynType t)
569598
| SynPat.Const _ -> continuation []

tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/Scenarios.fs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,8 @@ type Foo = class end
796796
sourceFile
797797
"Program"
798798
"""
799+
module Program
800+
799801
printfn "Hello"
800802
"""
801803
Set.empty
@@ -907,6 +909,35 @@ do
907909
module Bar
908910
909911
let _ = nameof ((Foo))
912+
"""
913+
(set [| 0 |])
914+
]
915+
scenario
916+
"prefixed module name in nameof expression"
917+
[
918+
sourceFile "A.fs" "module X.Y.Z" Set.empty
919+
sourceFile
920+
"B.fs"
921+
"""
922+
module B
923+
924+
open System.ComponentModel
925+
926+
[<Description(nameof X.Y.Z)>]
927+
let v = 2
928+
"""
929+
(set [| 0 |])
930+
]
931+
scenario
932+
"prefixed module name in nameof pattern"
933+
[
934+
sourceFile "A.fs" "module X.Y.Z" Set.empty
935+
sourceFile
936+
"B.fs"
937+
"""
938+
module B
939+
940+
do ignore (match "" with | nameof X.Y.Z -> () | _ -> ())
910941
"""
911942
(set [| 0 |])
912943
]

0 commit comments

Comments
 (0)