11module Errors
22open System
33open System.Runtime .ExceptionServices
4+ open System.Collections .Generic
5+ open System.Threading
46
57[<RequireQualifiedAccess>]
68type ErrorArea =
@@ -16,6 +18,52 @@ type TerrabuildException(msg, area, ?innerException: Exception) =
1618 inherit Exception( msg, innerException |> Option.toObj)
1719 member _.Area : ErrorArea = area
1820
21+ type private ParseErrorCollector =
22+ { Errors: ResizeArray < TerrabuildException >
23+ PosProvider: ( unit -> ( int * int ) option ) option }
24+
25+ let private parseErrorCollector = AsyncLocal< ParseErrorCollector option>()
26+
27+ let beginParseErrorCollection ( posProvider : unit -> ( int * int ) option ) =
28+ parseErrorCollector.Value <- Some { Errors = ResizeArray(); PosProvider = Some posProvider }
29+
30+ let endParseErrorCollection () =
31+ let errors =
32+ match parseErrorCollector.Value with
33+ | Some collector -> collector.Errors |> Seq.toList
34+ | None -> []
35+
36+ parseErrorCollector.Value <- None
37+ errors
38+
39+ let private formatParseError ( msg : string ) ( pos : ( int * int ) option ) =
40+ if msg.StartsWith( " Parse error at" , StringComparison.Ordinal) then
41+ msg
42+ else
43+ match pos with
44+ | Some ( line, col) -> sprintf " Parse error at (%d ,%d ): %s " line col msg
45+ | None -> msg
46+
47+ let private tryCollectParseError ( msg : string ) ( inner : Exception option ) ( pos : ( int * int ) option ) =
48+ match parseErrorCollector.Value with
49+ | Some collector ->
50+ let pos =
51+ match pos with
52+ | Some _ -> pos
53+ | None ->
54+ collector.PosProvider
55+ |> Option.bind ( fun provider -> provider())
56+
57+ let fullMsg = formatParseError msg pos
58+ let ex =
59+ match inner with
60+ | Some inner -> TerrabuildException( fullMsg, ErrorArea.Parse, inner)
61+ | None -> TerrabuildException( fullMsg, ErrorArea.Parse)
62+
63+ collector.Errors.Add( ex)
64+ true
65+ | None -> false
66+
1967
2068let raiseInvalidArg ( msg ) =
2169 TerrabuildException( msg, ErrorArea.InvalidArg) |> raise
@@ -24,10 +72,23 @@ let forwardInvalidArg(msg, innerException) =
2472 TerrabuildException( msg, ErrorArea.InvalidArg, innerException) |> raise
2573
2674let raiseParseError ( msg ) =
27- TerrabuildException( msg, ErrorArea.Parse) |> raise
75+ if not ( tryCollectParseError msg None None) then
76+ TerrabuildException( msg, ErrorArea.Parse) |> raise
77+ Unchecked.defaultof< 'T>
2878
2979let forwardParseError ( msg , innerException ) =
30- TerrabuildException( msg, ErrorArea.Parse, innerException) |> raise
80+ if not ( tryCollectParseError msg ( Some innerException) None) then
81+ TerrabuildException( msg, ErrorArea.Parse, innerException) |> raise
82+ Unchecked.defaultof< 'T>
83+
84+ let reportParseError ( msg ) =
85+ if not ( tryCollectParseError msg None None) then
86+ TerrabuildException( msg, ErrorArea.Parse) |> raise
87+
88+ let reportParseErrorAt ( line , col , msg ) =
89+ if not ( tryCollectParseError msg None ( Some ( line, col))) then
90+ let fullMsg = formatParseError msg ( Some ( line, col))
91+ TerrabuildException( fullMsg, ErrorArea.Parse) |> raise
3192
3293let raiseTypeError ( msg ) =
3394 TerrabuildException( msg, ErrorArea.Type) |> raise
@@ -74,5 +135,3 @@ let tryInvoke action =
74135 None
75136 with
76137 exn -> ExceptionDispatchInfo.Capture( exn) |> Some
77-
78-
0 commit comments