diff --git a/src/fsharp/CheckExpressions.fs b/src/fsharp/CheckExpressions.fs index 352aa63278a..6bb4f426722 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -810,7 +810,8 @@ let TcConst cenv ty m env c = | SynConst.Measure(SynConst.UInt64 i, _, _) when expandedMeasurablesEnabled -> unifyMeasureArg (i=0UL) cenv.g.puint64_tcr c; Const.UInt64 i | SynConst.Measure(SynConst.UIntPtr i, _, _) when expandedMeasurablesEnabled -> unifyMeasureArg (i=0UL) cenv.g.punativeint_tcr c; Const.UIntPtr i | SynConst.Char c -> unif cenv.g.char_ty; Const.Char c - | SynConst.String (s, _, _) -> unif cenv.g.string_ty; Const.String s + | SynConst.String (s, _, _) + | SynConst.SourceIdentifier (_, s, _) -> unif cenv.g.string_ty; Const.String s | SynConst.UserNum _ -> error (InternalError(FSComp.SR.tcUnexpectedBigRationalConstant(), m)) | SynConst.Measure _ -> error (Error(FSComp.SR.tcInvalidTypeForUnitsOfMeasure(), m)) | SynConst.UInt16s _ -> error (InternalError(FSComp.SR.tcUnexpectedConstUint16Array(), m)) diff --git a/src/fsharp/SyntaxTree.fs b/src/fsharp/SyntaxTree.fs index 415055ac092..703fe29e5a6 100644 --- a/src/fsharp/SyntaxTree.fs +++ b/src/fsharp/SyntaxTree.fs @@ -116,10 +116,14 @@ type SynConst = | UInt16s of uint16[] | Measure of constant: SynConst * constantRange: Range * SynMeasure + + | SourceIdentifier of constant: string * value: string * range: Range member c.Range dflt = match c with - | SynConst.String (_, _, m0) | SynConst.Bytes (_, _, m0) -> m0 + | SynConst.String (_, _, m0) + | SynConst.Bytes (_, _, m0) + | SynConst.SourceIdentifier(_, _, m0) -> m0 | _ -> dflt [] diff --git a/src/fsharp/SyntaxTree.fsi b/src/fsharp/SyntaxTree.fsi index 4e94d6d86ed..8d2d4414912 100644 --- a/src/fsharp/SyntaxTree.fsi +++ b/src/fsharp/SyntaxTree.fsi @@ -152,6 +152,10 @@ type SynConst = /// Old comment: "we never iterate, so the const here is not another SynConst.Measure" | Measure of constant: SynConst * constantRange: range * SynMeasure + + /// Source Line, File, and Path Identifiers + /// Containing both the original value as the evaluated value. + | SourceIdentifier of constant: string * value: string * range: Range /// Gets the syntax range of this construct member Range: dflt: range -> range diff --git a/src/fsharp/lexhelp.fs b/src/fsharp/lexhelp.fs index 94c4be068d4..8fa659de6ee 100644 --- a/src/fsharp/lexhelp.fs +++ b/src/fsharp/lexhelp.fs @@ -396,11 +396,11 @@ module Keywords = if String.IsNullOrEmpty dirname then dirname else PathMap.applyDir args.pathMap dirname - |> KEYWORD_STRING + |> fun dir -> KEYWORD_STRING(s, dir) | "__SOURCE_FILE__" -> - KEYWORD_STRING (System.IO.Path.GetFileName((FileIndex.fileOfFileIndex lexbuf.StartPos.FileIndex))) + KEYWORD_STRING (s, System.IO.Path.GetFileName((FileIndex.fileOfFileIndex lexbuf.StartPos.FileIndex))) | "__LINE__" -> - KEYWORD_STRING (string lexbuf.StartPos.Line) + KEYWORD_STRING (s, string lexbuf.StartPos.Line) | _ -> IdentifierToken args lexbuf s diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index a287f3ad149..97b866b7695 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -202,7 +202,7 @@ let rangeOfLongIdent(lid:LongIdent) = %token INTERP_STRING_END %token LBRACE RBRACE -%token KEYWORD_STRING // Like __SOURCE_DIRECTORY__ +%token KEYWORD_STRING // Like __SOURCE_DIRECTORY__ %token IDENT %token HASH_IDENT %token INFIX_STAR_STAR_OP @@ -646,7 +646,7 @@ hashDirectiveArgs: /* One argument to a #directive */ hashDirectiveArg: - | stringOrKeywordString + | string { let s, _ = $1 s } @@ -2214,7 +2214,7 @@ tyconDefnOrSpfnSimpleRepr: SynTypeDefnSimpleRepr.Record ($2, $3, lhs parseState) } /* An inline-assembly type definition, for FSharp.Core library only */ - | opt_attributes opt_declVisibility LPAREN HASH stringOrKeywordString HASH rparen + | opt_attributes opt_declVisibility LPAREN HASH string HASH rparen { if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesIllegalHere(), rhs parseState 1)) let lhsm = lhs parseState libraryOnlyError lhsm @@ -2922,10 +2922,14 @@ rawConstant: | BIGNUM { SynConst.UserNum $1 } - | stringOrKeywordString + | string { let s, synStringKind = $1 SynConst.String (s, synStringKind, lhs parseState) } + | sourceIdentifier + { let c,v = $1 + SynConst.SourceIdentifier (c, v, lhs parseState) } + | BYTEARRAY { let (v, synByteStringKind, _) = $1 SynConst.Bytes (v, synByteStringKind, lhs parseState) } @@ -4518,7 +4522,7 @@ forLoopDirection: | DOWNTO { false } inlineAssemblyExpr: - | HASH stringOrKeywordString opt_inlineAssemblyTypeArg optCurriedArgExprs optInlineAssemblyReturnTypes HASH + | HASH string opt_inlineAssemblyTypeArg optCurriedArgExprs optInlineAssemblyReturnTypes HASH { libraryOnlyWarning (lhs parseState) let (s, _), sm = $2, rhs parseState 2 (fun m -> @@ -5556,11 +5560,13 @@ colonOrEquals: | EQUALS { } /* A literal string or a string from a keyword like __SOURCE_FILE__ */ -stringOrKeywordString: +string: | STRING { let (s, synStringKind, _) = $1 s, synStringKind } - | KEYWORD_STRING { $1, SynStringKind.Regular } + +sourceIdentifier: + | KEYWORD_STRING { $1 } interpolatedStringFill: | declExpr diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index ab20cf8f211..00665a2e22c 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -5788,6 +5788,12 @@ FSharp.Compiler.Syntax.SynConst+SByte: SByte Item FSharp.Compiler.Syntax.SynConst+SByte: SByte get_Item() FSharp.Compiler.Syntax.SynConst+Single: Single Item FSharp.Compiler.Syntax.SynConst+Single: Single get_Item() +FSharp.Compiler.Syntax.SynConst+SourceIdentifier: FSharp.Compiler.Text.Range get_range() +FSharp.Compiler.Syntax.SynConst+SourceIdentifier: FSharp.Compiler.Text.Range range +FSharp.Compiler.Syntax.SynConst+SourceIdentifier: System.String constant +FSharp.Compiler.Syntax.SynConst+SourceIdentifier: System.String get_constant() +FSharp.Compiler.Syntax.SynConst+SourceIdentifier: System.String get_value() +FSharp.Compiler.Syntax.SynConst+SourceIdentifier: System.String value FSharp.Compiler.Syntax.SynConst+String: FSharp.Compiler.Syntax.SynStringKind get_synStringKind() FSharp.Compiler.Syntax.SynConst+String: FSharp.Compiler.Syntax.SynStringKind synStringKind FSharp.Compiler.Syntax.SynConst+String: FSharp.Compiler.Text.Range get_range() @@ -5807,6 +5813,7 @@ FSharp.Compiler.Syntax.SynConst+Tags: Int32 IntPtr FSharp.Compiler.Syntax.SynConst+Tags: Int32 Measure FSharp.Compiler.Syntax.SynConst+Tags: Int32 SByte FSharp.Compiler.Syntax.SynConst+Tags: Int32 Single +FSharp.Compiler.Syntax.SynConst+Tags: Int32 SourceIdentifier FSharp.Compiler.Syntax.SynConst+Tags: Int32 String FSharp.Compiler.Syntax.SynConst+Tags: Int32 UInt16 FSharp.Compiler.Syntax.SynConst+Tags: Int32 UInt16s @@ -5842,6 +5849,7 @@ FSharp.Compiler.Syntax.SynConst: Boolean IsIntPtr FSharp.Compiler.Syntax.SynConst: Boolean IsMeasure FSharp.Compiler.Syntax.SynConst: Boolean IsSByte FSharp.Compiler.Syntax.SynConst: Boolean IsSingle +FSharp.Compiler.Syntax.SynConst: Boolean IsSourceIdentifier FSharp.Compiler.Syntax.SynConst: Boolean IsString FSharp.Compiler.Syntax.SynConst: Boolean IsUInt16 FSharp.Compiler.Syntax.SynConst: Boolean IsUInt16s @@ -5863,6 +5871,7 @@ FSharp.Compiler.Syntax.SynConst: Boolean get_IsIntPtr() FSharp.Compiler.Syntax.SynConst: Boolean get_IsMeasure() FSharp.Compiler.Syntax.SynConst: Boolean get_IsSByte() FSharp.Compiler.Syntax.SynConst: Boolean get_IsSingle() +FSharp.Compiler.Syntax.SynConst: Boolean get_IsSourceIdentifier() FSharp.Compiler.Syntax.SynConst: Boolean get_IsString() FSharp.Compiler.Syntax.SynConst: Boolean get_IsUInt16() FSharp.Compiler.Syntax.SynConst: Boolean get_IsUInt16s() @@ -5884,6 +5893,7 @@ FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst NewIntPtr(Int64 FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst NewMeasure(FSharp.Compiler.Syntax.SynConst, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynMeasure) FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst NewSByte(SByte) FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst NewSingle(Single) +FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst NewSourceIdentifier(System.String, System.String, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst NewString(System.String, FSharp.Compiler.Syntax.SynStringKind, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst NewUInt16(UInt16) FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst NewUInt16s(UInt16[]) @@ -5906,6 +5916,7 @@ FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst+IntPtr FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst+Measure FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst+SByte FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst+Single +FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst+SourceIdentifier FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst+String FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst+Tags FSharp.Compiler.Syntax.SynConst: FSharp.Compiler.Syntax.SynConst+UInt16 diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index d62e57c930a..03e32098547 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -764,4 +764,47 @@ with ]) ])) -> assertRange (6, 2) (6, 21) range assertRange (6, 2) (6, 21) clause.Range + | _ -> Assert.Fail "Could not get valid AST" + +module SourceIdentifiers = + [] + let ``__LINE__`` () = + let parseResults = + getParseResults + """ +__LINE__""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.DoExpr(expr = SynExpr.Const(SynConst.SourceIdentifier("__LINE__", "2", range), _)) + ]) ])) -> + assertRange (2, 0) (2, 8) range + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``__SOURCE_DIRECTORY__`` () = + let parseResults = + getParseResults + """ +__SOURCE_DIRECTORY__""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.DoExpr(expr = SynExpr.Const(SynConst.SourceIdentifier("__SOURCE_DIRECTORY__", _, range), _)) + ]) ])) -> + assertRange (2, 0) (2, 20) range + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``__SOURCE_FILE__`` () = + let parseResults = + getParseResults + """ +__SOURCE_FILE__""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.DoExpr(expr = SynExpr.Const(SynConst.SourceIdentifier("__SOURCE_FILE__", _, range), _)) + ]) ])) -> + assertRange (2, 0) (2, 15) range | _ -> Assert.Fail "Could not get valid AST" \ No newline at end of file