22
33module FSharp.Compiler.SyntaxTreeOps
44
5+ open Internal.Utilities
56open Internal.Utilities .Library
67open FSharp.Compiler .DiagnosticsLogger
78open FSharp.Compiler .Features
9+ open FSharp.Compiler .IO
810open FSharp.Compiler .Syntax
911open FSharp.Compiler .SyntaxTrivia
1012open FSharp.Compiler .Syntax .PrettyNaming
1113open FSharp.Compiler .Text
1214open FSharp.Compiler .Text .Range
1315open FSharp.Compiler .Xml
16+ open System
1417
1518/// Generate implicit argument names in parsing
1619type SynArgNameGenerator () =
@@ -992,11 +995,47 @@ let rec synExprContainsError inpExpr =
992995let longIdentToString ( ident : SynLongIdent ) =
993996 System.String.Join( " ." , ident.LongIdent |> List.map ( fun ident -> ident.idText.ToString()))
994997
998+ /// The "mock" file name used by fsi.exe when reading from stdin.
999+ /// Has special treatment, i.e. __SOURCE_DIRECTORY__ becomes GetCurrentDirectory()
1000+ let stdinMockFileName = " stdin"
1001+
1002+ let getSourceIdentifierValue pathMap s ( m : range ) =
1003+ match s with
1004+ | " __SOURCE_DIRECTORY__" ->
1005+ let fileName = FileIndex.fileOfFileIndex m.FileIndex
1006+
1007+ let dirname =
1008+ if String.IsNullOrWhiteSpace fileName then
1009+ String.Empty
1010+ else if fileName = stdinMockFileName then
1011+ System.IO.Directory.GetCurrentDirectory()
1012+ else
1013+ fileName
1014+ |> FileSystem.GetFullPathShim (* asserts that path is already absolute *)
1015+ |> System.IO.Path.GetDirectoryName
1016+ |> (!!)
1017+
1018+ if String.IsNullOrEmpty dirname then
1019+ dirname
1020+ else
1021+ PathMap.applyDir pathMap dirname
1022+ | " __SOURCE_FILE__" -> !! System.IO.Path.GetFileName( FileIndex.fileOfFileIndex m.FileIndex)
1023+ | " __LINE__" -> string m.StartLine
1024+ | _ -> failwith " getSourceIdentifierValue: unexpected identifier"
1025+
1026+ let applyLineDirectivesToSourceIdentifier s value ( m : range ) =
1027+ let mm = m.ApplyLineDirectives()
1028+
1029+ if mm = m then
1030+ value // keep the value that was assigned during lexing (when line directives were not yet evaluated)
1031+ else
1032+ getSourceIdentifierValue PathMap.empty s mm // update because of line directive
1033+
9951034let parsedHashDirectiveArguments ( input : ParsedHashDirectiveArgument list ) ( langVersion : LanguageVersion ) =
9961035 List.choose
9971036 ( function
9981037 | ParsedHashDirectiveArgument.String( s, _, _) -> Some s
999- | ParsedHashDirectiveArgument.SourceIdentifier(_ , v, _ ) -> Some v
1038+ | ParsedHashDirectiveArgument.SourceIdentifier( s , v, m ) -> Some( applyLineDirectivesToSourceIdentifier s v m )
10001039 | ParsedHashDirectiveArgument.Int32( n, m) ->
10011040 match tryCheckLanguageFeatureAndRecover langVersion LanguageFeature.ParsedHashDirectiveArgumentNonQuotes m with
10021041 | true -> Some( string n)
@@ -1015,7 +1054,7 @@ let parsedHashDirectiveArgumentsNoCheck (input: ParsedHashDirectiveArgument list
10151054 List.map
10161055 ( function
10171056 | ParsedHashDirectiveArgument.String( s, _, _) -> s
1018- | ParsedHashDirectiveArgument.SourceIdentifier(_ , v, _ ) -> v
1057+ | ParsedHashDirectiveArgument.SourceIdentifier( s , v, m ) -> applyLineDirectivesToSourceIdentifier s v m
10191058 | ParsedHashDirectiveArgument.Int32( n, _) -> string n
10201059 | ParsedHashDirectiveArgument.Ident( ident, _) -> ident.idText
10211060 | ParsedHashDirectiveArgument.LongIdent( ident, _) -> longIdentToString ident)
@@ -1028,7 +1067,7 @@ let parsedHashDirectiveStringArguments (input: ParsedHashDirectiveArgument list)
10281067 | ParsedHashDirectiveArgument.Int32( n, m) ->
10291068 errorR ( Error( FSComp.SR.featureParsedHashDirectiveUnexpectedInteger ( n), m))
10301069 None
1031- | ParsedHashDirectiveArgument.SourceIdentifier(_ , v, _ ) -> Some v
1070+ | ParsedHashDirectiveArgument.SourceIdentifier( s , v, m ) -> Some( applyLineDirectivesToSourceIdentifier s v m )
10321071 | ParsedHashDirectiveArgument.Ident( ident, m) ->
10331072 errorR ( Error( FSComp.SR.featureParsedHashDirectiveUnexpectedIdentifier ( ident.idText), m))
10341073 None
0 commit comments