PageRenderTime 48ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/3.0/Sep2012/src/fsharp/tainted.fs

#
F# | 163 lines | 121 code | 33 blank | 9 comment | 11 complexity | 726c0a7c81adf8bfa3ed4ca26cfe587a MD5 | raw file
Possible License(s): CC-BY-SA-3.0, Apache-2.0
  1. namespace Microsoft.FSharp.Compiler
  2. open System
  3. open Microsoft.FSharp.Compiler.Range
  4. open Microsoft.FSharp.Core.CompilerServices
  5. open Microsoft.FSharp.Compiler.AbstractIL.IL
  6. open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library
  7. open System.Reflection
  8. open System.Collections.Generic
  9. open ErrorLogger
  10. type internal TypeProviderError
  11. (
  12. errNum : int,
  13. tpDesignation : string,
  14. m:Microsoft.FSharp.Compiler.Range.range,
  15. errors : string list,
  16. typeNameContext : string option,
  17. methodNameContext : string option
  18. ) =
  19. inherit System.Exception()
  20. new((errNum, msg : string), tpDesignation,m) =
  21. TypeProviderError(errNum, tpDesignation, m, [msg])
  22. new(errNum, tpDesignation, m, messages : seq<string>) =
  23. TypeProviderError(errNum, tpDesignation, m, List.ofSeq messages, None, None)
  24. member this.Number = errNum
  25. member this.Range = m
  26. override this.Message =
  27. match errors with
  28. | [text] -> text
  29. | inner ->
  30. // imitates old-fashioned behavior with merged text
  31. // usually should not fall into this case (only if someone takes Message directly instead of using Iter)
  32. inner
  33. |> String.concat Environment.NewLine
  34. member this.MapText(f, tpDesignation, m) =
  35. let (errNum : int), _ = f ""
  36. new TypeProviderError(errNum, tpDesignation, m, (Seq.map (f >> snd) errors))
  37. member this.WithContext(typeNameContext:string, methodNameContext:string) =
  38. new TypeProviderError(errNum, tpDesignation, m, errors, Some typeNameContext, Some methodNameContext)
  39. // .Message is just the error, whereas .ContextualErrorMessage has contextual prefix information
  40. // for example if InvokeCode in provided method is not set or has value that cannot be translated -then initial TPE will be wrapped in
  41. // TPE having type\method name as contextual information
  42. // without context: Type Provider 'TP' has reported the error: MSG
  43. // with context: Type Provider 'TP' has reported the error in method M of type T: MSG
  44. member this.ContextualErrorMessage=
  45. match typeNameContext, methodNameContext with
  46. | Some tc, Some mc ->
  47. let _,msgWithPrefix = FSComp.SR.etProviderErrorWithContext(tpDesignation, tc, mc, this.Message)
  48. msgWithPrefix
  49. | _ ->
  50. let _,msgWithPrefix = FSComp.SR.etProviderError(tpDesignation, this.Message)
  51. msgWithPrefix
  52. /// provides uniform way to handle plain and composite instances of TypeProviderError
  53. member this.Iter f =
  54. match errors with
  55. | [_] -> f this
  56. | errors ->
  57. for msg in errors do
  58. f (new TypeProviderError(errNum, tpDesignation, m, [msg], typeNameContext, methodNameContext))
  59. type TaintedContext = { TypeProvider : ITypeProvider; TypeProviderAssemblyRef : ILScopeRef }
  60. [<NoEquality>][<NoComparison>]
  61. type internal Tainted<'T> (context : TaintedContext, value : 'T) =
  62. do
  63. match box context.TypeProvider with
  64. | null ->
  65. assert false
  66. failwith "null ITypeProvider in Tainted constructor"
  67. | _ -> ()
  68. member this.TypeProviderDesignation =
  69. context.TypeProvider.GetType().FullName
  70. member this.TypeProviderAssemblyRef =
  71. context.TypeProviderAssemblyRef
  72. member this.Protect f (range:range) =
  73. try
  74. f value
  75. with
  76. | :? TypeProviderError -> reraise()
  77. | :? AggregateException as ae ->
  78. let errNum,_ = FSComp.SR.etProviderError("", "")
  79. let messages = [for e in ae.InnerExceptions -> e.Message]
  80. raise <| TypeProviderError(errNum, this.TypeProviderDesignation, range, messages)
  81. | e ->
  82. let errNum,_ = FSComp.SR.etProviderError("", "")
  83. raise <| TypeProviderError((errNum, e.Message), this.TypeProviderDesignation, range)
  84. member this.TypeProvider = Tainted<_>(context, context.TypeProvider)
  85. member this.PApply(f,range:range) =
  86. let u = this.Protect f range
  87. Tainted(context, u)
  88. member this.PApply2(f,range:range) =
  89. let u1,u2 = this.Protect f range
  90. Tainted(context, u1), Tainted(context, u2)
  91. member this.PApply3(f,range:range) =
  92. let u1,u2,u3 = this.Protect f range
  93. Tainted(context, u1), Tainted(context, u2), Tainted(context, u3)
  94. member this.PApply4(f,range:range) =
  95. let u1,u2,u3,u4 = this.Protect f range
  96. Tainted(context, u1), Tainted(context, u2), Tainted(context, u3), Tainted(context, u4)
  97. member this.PApplyNoFailure f = this.PApply (f, range0)
  98. member this.PApplyWithProvider(f,range:range) =
  99. let u = this.Protect (fun x -> f (x,context.TypeProvider)) range
  100. Tainted(context, u)
  101. member this.PApplyArray(f,methodName,range:range) =
  102. let a = this.Protect f range
  103. match a with
  104. | null -> raise <| TypeProviderError(FSComp.SR.etProviderReturnedNull(methodName), this.TypeProviderDesignation, range)
  105. | _ -> a |> Array.map (fun u -> Tainted(context,u))
  106. member this.PApplyOption(f,range:range) =
  107. let a = this.Protect f range
  108. match a with
  109. | None -> None
  110. | Some x -> Some (Tainted(context,x))
  111. member this.PUntaint(f,range:range) = this.Protect f range
  112. member this.PUntaintNoFailure f = this.PUntaint(f, range0)
  113. /// Access the target object directly. Use with extreme caution.
  114. member this.AccessObjectDirectly = value
  115. static member CreateAll(providerSpecs : (ITypeProvider * ILScopeRef) list) =
  116. [for (tp,nm) in providerSpecs do
  117. yield Tainted<_>({ TypeProvider=tp; TypeProviderAssemblyRef=nm },tp) ]
  118. member this.OfType<'U> () =
  119. match box value with
  120. | :? 'U as u -> Some (Tainted(context,u))
  121. | _ -> None
  122. member this.Coerce<'U> (range:range) =
  123. Tainted(context, this.Protect(fun value -> box value :?> 'U) range)
  124. module internal Tainted =
  125. let (|Null|_|) (p:Tainted<'T>) =
  126. if p.PUntaintNoFailure(fun p -> match p with null -> true | _ -> false) then Some() else None
  127. let Eq (p:Tainted<'T>) (v:'T) = p.PUntaintNoFailure((fun pv -> pv = v))
  128. let EqTainted (t1:Tainted<'T>) (t2:Tainted<'T>) =
  129. t1.PUntaintNoFailure(fun t1 -> t1 === t2.AccessObjectDirectly)
  130. let GetHashCodeTainted (t:Tainted<'T>) = t.PUntaintNoFailure(fun t -> hash t)