-
Notifications
You must be signed in to change notification settings - Fork 872
Expand file tree
/
Copy pathFSBuild.fs
More file actions
125 lines (103 loc) · 5.05 KB
/
Copy pathFSBuild.fs
File metadata and controls
125 lines (103 loc) · 5.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// This is a generated file; the original input is 'FSBuild.txt'
namespace FSBuild
open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
open Microsoft.FSharp.Reflection
open System.Reflection
// (namespaces below for specific case of using the tool to compile FSharp.Core itself)
open Microsoft.FSharp.Core
open Microsoft.FSharp.Core.Operators
open Microsoft.FSharp.Text
open Microsoft.FSharp.Collections
open Printf
type internal SR private() =
// BEGIN BOILERPLATE
static let getCurrentAssembly () =
#if FX_RESHAPED_REFLECTION
typeof<SR>.GetTypeInfo().Assembly
#else
System.Reflection.Assembly.GetExecutingAssembly()
#endif
static let getTypeInfo (t: System.Type) =
#if FX_RESHAPED_REFLECTION
t.GetTypeInfo()
#else
t
#endif
static let resources = lazy (new System.Resources.ResourceManager("FSBuild", getCurrentAssembly()))
static let GetString(name:string) =
let s = resources.Value.GetString(name, System.Globalization.CultureInfo.CurrentUICulture)
#if DEBUG
if null = s then
System.Diagnostics.Debug.Assert(false, sprintf "**RESOURCE ERROR**: Resource token %s does not exist!" name)
#endif
s
static let mkFunctionValue (tys: System.Type[]) (impl:obj->obj) =
FSharpValue.MakeFunction(FSharpType.MakeFunctionType(tys.[0],tys.[1]), impl)
static let funTyC = typeof<(obj -> obj)>.GetGenericTypeDefinition()
static let isNamedType(ty:System.Type) = not (ty.IsArray || ty.IsByRef || ty.IsPointer)
static let isFunctionType (ty1:System.Type) =
isNamedType(ty1) && getTypeInfo(ty1).IsGenericType && (ty1.GetGenericTypeDefinition()).Equals(funTyC)
static let rec destFunTy (ty:System.Type) =
if isFunctionType ty then
ty, ty.GetGenericArguments()
else
match getTypeInfo(ty).BaseType with
| null -> failwith "destFunTy: not a function type"
| b -> destFunTy b
static let buildFunctionForOneArgPat (ty: System.Type) impl =
let _,tys = destFunTy ty
let rty = tys.[1]
// PERF: this technique is a bit slow (e.g. in simple cases, like 'sprintf "%x"')
mkFunctionValue tys (fun inp -> impl rty inp)
static let capture1 (fmt:string) i args ty (go : obj list -> System.Type -> int -> obj) : obj =
match fmt.[i] with
| '%' -> go args ty (i+1)
| 'd'
| 'f'
| 's' -> buildFunctionForOneArgPat ty (fun rty n -> go (n :: args) rty (i+1))
| _ -> failwith "bad format specifier"
// newlines and tabs get converted to strings when read from a resource file
// this will preserve their original intention
static let postProcessString (s : string) =
s.Replace("\\n","\n").Replace("\\t","\t").Replace("\\r","\r").Replace("\\\"", "\"")
static let createMessageString (messageString : string) (fmt : Printf.StringFormat<'T>) : 'T =
let fmt = fmt.Value // here, we use the actual error string, as opposed to the one stored as fmt
let len = fmt.Length
/// Function to capture the arguments and then run.
let rec capture args ty i =
if i >= len || (fmt.[i] = '%' && i+1 >= len) then
let b = new System.Text.StringBuilder()
b.AppendFormat(messageString, [| for x in List.rev args -> x |]) |> ignore
box(b.ToString())
// REVIEW: For these purposes, this should be a nop, but I'm leaving it
// in incase we ever decide to support labels for the error format string
// E.g., "<name>%s<foo>%d"
elif System.Char.IsSurrogatePair(fmt,i) then
capture args ty (i+2)
else
match fmt.[i] with
| '%' ->
let i = i+1
capture1 fmt i args ty capture
| _ ->
capture args ty (i+1)
(unbox (capture [] (typeof<'T>) 0) : 'T)
static let mutable swallowResourceText = false
static let GetStringFunc((messageID : string),(fmt : Printf.StringFormat<'T>)) : 'T =
if swallowResourceText then
sprintf fmt
else
let mutable messageString = GetString(messageID)
messageString <- postProcessString messageString
createMessageString messageString fmt
/// If set to true, then all error messages will just return the filled 'holes' delimited by ',,,'s - this is for language-neutral testing (e.g. localization-invariant baselines).
static member SwallowResourceText with get () = swallowResourceText
and set (b) = swallowResourceText <- b
// END BOILERPLATE
/// ToolPath is unknown; specify the path to fsc.exe as the ToolPath property.
/// (Originally from FSBuild.txt:2)
static member toolpathUnknown() = (GetStringFunc("toolpathUnknown",",,,") )
/// Call this method once to validate that all known resources are valid; throws if not
static member RunStartupValidation() =
ignore(GetString("toolpathUnknown"))
()