55///
66public struct LeafError : Error {
77 /// Possible cases of a LeafError.Reason, with applicable stored values where useful for the type
8- public enum Reason {
8+ public enum Reason : Equatable {
99 // MARK: Errors related to loading raw templates
1010 /// Attempted to access a template blocked for security reasons
1111 case illegalAccess( String )
@@ -34,13 +34,43 @@ public struct LeafError: Error {
3434
3535 // MARK: Wrapped Errors related to Lexing or Parsing
3636 /// Errors due to malformed template syntax or grammar
37- case lexerError( LexerError )
37+ case lexerError( LeafScannerError )
3838
3939 // MARK: Errors lacking specificity
4040 /// Errors from protocol adherents that do not support newer features
4141 case unsupportedFeature( String )
4242 /// Errors only when no existing error reason is adequately clear
4343 case unknownError( String )
44+
45+ /// Errors when something goes wrong internally
46+ case internalError( what: String )
47+
48+ /// Errors when an import is not found
49+ case importNotFound( name: String )
50+
51+ /// Errors when a tag is not found
52+ case tagNotFound( name: String )
53+
54+ /// Errors when one type was expected, but another was obtained
55+ case typeError( shouldHaveBeen: LeafData . NaturalType , got: LeafData . NaturalType )
56+
57+ /// A typeError specialised for Double | Int
58+ case expectedNumeric( got: LeafData . NaturalType )
59+
60+ /// A typeError specialised for binary operators of (T, T) -> T
61+ case badOperation( on: LeafData . NaturalType , what: String )
62+
63+ /// Errors when a tag receives a bad parameter count
64+ case badParameterCount( tag: String , expected: Int , got: Int )
65+
66+ /// Errors when a tag receives a body, but doesn't want one
67+ case extraneousBody( tag: String )
68+
69+ /// Errors when a tag doesn't receive a body, but wants one
70+ case missingBody( tag: String )
71+
72+ /// Serialization error
73+ case serializationError
4474 }
4575
4676 /// Source file name causing error
@@ -84,7 +114,27 @@ public struct LeafError: Error {
84114 return " \( src) - \( key) cyclically referenced in [ \( chain. joined ( separator: " -> " ) ) ] "
85115 case . lexerError( let e) :
86116 return " Lexing error - \( e. localizedDescription) "
87- }
117+ case . importNotFound( let name) :
118+ return " Import \( name) was not found "
119+ case . internalError( let what) :
120+ return " Something in Leaf broke: \( what) \n Please report this to https://github.com/vapor/leaf-kit "
121+ case . tagNotFound( let name) :
122+ return " Tag \( name) was not found "
123+ case . typeError( let shouldHaveBeen, let got) :
124+ return " Type error: I was expecting \( shouldHaveBeen) , but I got \( got) instead "
125+ case . badOperation( let on, let what) :
126+ return " Type error: \( on) cannot do \( what) "
127+ case . expectedNumeric( let got) :
128+ return " Type error: I was expecting a numeric type, but I got \( got) instead "
129+ case . badParameterCount( let tag, let expected, let got) :
130+ return " Type error: \( tag) was expecting \( expected) parameters, but got \( got) parameters instead "
131+ case . extraneousBody( let tag) :
132+ return " Type error: \( tag) wasn't expecting a body, but got one "
133+ case . missingBody( let tag) :
134+ return " Type error: \( tag) was expecting a body, but didn't get one "
135+ case . serializationError:
136+ return " Serialization error "
137+ }
88138 }
89139
90140 /// Create a `LeafError` - only `reason` typically used as source locations are auto-grabbed
@@ -102,63 +152,3 @@ public struct LeafError: Error {
102152 self . reason = reason
103153 }
104154}
105-
106- // MARK: - `LexerError` Summary (Wrapped by LeafError)
107-
108- /// `LexerError` reports errors during the stage.
109- public struct LexerError : Error {
110- // MARK: - Public
111-
112- public enum Reason {
113- // MARK: Errors occuring during Lexing
114- /// A character not usable in parameters is present when Lexer is not expecting it
115- case invalidParameterToken( Character )
116- /// A string was opened but never terminated by end of file
117- case unterminatedStringLiteral
118- /// Use in place of fatalError to indicate extreme issue
119- case unknownError( String )
120- }
121-
122- /// Template source file line where error occured
123- public let line : Int
124- /// Template source column where error occured
125- public let column : Int
126- /// Name of template error occured in
127- public let name : String
128- /// Stated reason for error
129- public let reason : Reason
130-
131- // MARK: - Internal Only
132-
133- /// State of tokens already processed by Lexer prior to error
134- internal let lexed : [ LeafToken ]
135- /// Flag to true if lexing error is something that may be recoverable during parsing;
136- /// EG, `"#anhtmlanchor"` may lex as a tag name but fail to tokenize to tag because it isn't
137- /// followed by a left paren. Parser may be able to recover by decaying it to `.raw`.
138- internal let recoverable : Bool
139-
140- /// Create a `LexerError`
141- /// - Parameters:
142- /// - reason: The specific reason for the error
143- /// - src: File being lexed
144- /// - lexed: `LeafTokens` already lexed prior to error
145- /// - recoverable: Flag to say whether the error can potentially be recovered during Parse
146- internal init (
147- _ reason: Reason ,
148- src: LeafRawTemplate ,
149- lexed: [ LeafToken ] = [ ] ,
150- recoverable: Bool = false
151- ) {
152- self . line = src. line
153- self . column = src. column
154- self . reason = reason
155- self . lexed = lexed
156- self . name = src. name
157- self . recoverable = recoverable
158- }
159-
160- /// Convenience description of source file name, error reason, and location in file of error source
161- var localizedDescription : String {
162- return " \" \( name) \" : \( reason) - \( line) : \( column) "
163- }
164- }
0 commit comments