github.com/syumai/protoreflect@v1.7.1-0.20200810020253-2ac7e3b3a321/desc/protoparse/errors.go (about) 1 package protoparse 2 3 import ( 4 "errors" 5 "fmt" 6 ) 7 8 // ErrInvalidSource is a sentinel error that is returned by calls to 9 // Parser.ParseFiles and Parser.ParseFilesButDoNotLink in the event that syntax 10 // or link errors are encountered, but the parser's configured ErrorReporter 11 // always returns nil. 12 var ErrInvalidSource = errors.New("parse failed: invalid proto source") 13 14 // ErrNoSyntax is a sentinel error that may be passed to a warning reporter. 15 // The error the reporter receives will be wrapped with source position that 16 // indicates the file that had no syntax statement. 17 var ErrNoSyntax = errors.New("no syntax specified; defaulting to proto2 syntax") 18 19 // ErrLookupImportAndProtoSet is the error returned if both LookupImport and LookupImportProto are set. 20 var ErrLookupImportAndProtoSet = errors.New("both LookupImport and LookupImportProto set") 21 22 // ErrorReporter is responsible for reporting the given error. If the reporter 23 // returns a non-nil error, parsing/linking will abort with that error. If the 24 // reporter returns nil, parsing will continue, allowing the parser to try to 25 // report as many syntax and/or link errors as it can find. 26 type ErrorReporter func(err ErrorWithPos) error 27 28 // WarningReporter is responsible for reporting the given warning. This is used 29 // for indicating non-error messages to the calling program for things that do 30 // not cause the parse to fail but are considered bad practice. Though they are 31 // just warnings, the details are supplied to the reporter via an error type. 32 type WarningReporter func(ErrorWithPos) 33 34 func defaultErrorReporter(err ErrorWithPos) error { 35 // abort parsing after first error encountered 36 return err 37 } 38 39 type errorHandler struct { 40 errReporter ErrorReporter 41 errsReported int 42 err error 43 44 warnReporter WarningReporter 45 } 46 47 func newErrorHandler(errRep ErrorReporter, warnRep WarningReporter) *errorHandler { 48 if errRep == nil { 49 errRep = defaultErrorReporter 50 } 51 return &errorHandler{ 52 errReporter: errRep, 53 warnReporter: warnRep, 54 } 55 } 56 57 func (h *errorHandler) handleErrorWithPos(pos *SourcePos, format string, args ...interface{}) error { 58 if h.err != nil { 59 return h.err 60 } 61 h.errsReported++ 62 err := h.errReporter(errorWithPos(pos, format, args...)) 63 h.err = err 64 return err 65 } 66 67 func (h *errorHandler) handleError(err error) error { 68 if h.err != nil { 69 return h.err 70 } 71 if ewp, ok := err.(ErrorWithPos); ok { 72 h.errsReported++ 73 err = h.errReporter(ewp) 74 } 75 h.err = err 76 return err 77 } 78 79 func (h *errorHandler) warn(pos *SourcePos, err error) { 80 if h.warnReporter != nil { 81 h.warnReporter(ErrorWithSourcePos{Pos: pos, Underlying: err}) 82 } 83 } 84 85 func (h *errorHandler) getError() error { 86 if h.errsReported > 0 && h.err == nil { 87 return ErrInvalidSource 88 } 89 return h.err 90 } 91 92 // ErrorWithPos is an error about a proto source file that includes information 93 // about the location in the file that caused the error. 94 // 95 // The value of Error() will contain both the SourcePos and Underlying error. 96 // The value of Unwrap() will only be the Underlying error. 97 type ErrorWithPos interface { 98 error 99 GetPosition() SourcePos 100 Unwrap() error 101 } 102 103 // ErrorWithSourcePos is an error about a proto source file that includes 104 // information about the location in the file that caused the error. 105 // 106 // Errors that include source location information *might* be of this type. 107 // However, calling code that is trying to examine errors with location info 108 // should instead look for instances of the ErrorWithPos interface, which 109 // will find other kinds of errors. This type is only exported for backwards 110 // compatibility. 111 // 112 // SourcePos should always be set and never nil. 113 type ErrorWithSourcePos struct { 114 Underlying error 115 Pos *SourcePos 116 } 117 118 // Error implements the error interface 119 func (e ErrorWithSourcePos) Error() string { 120 sourcePos := e.GetPosition() 121 return fmt.Sprintf("%s: %v", sourcePos, e.Underlying) 122 } 123 124 // GetPosition implements the ErrorWithPos interface, supplying a location in 125 // proto source that caused the error. 126 func (e ErrorWithSourcePos) GetPosition() SourcePos { 127 if e.Pos == nil { 128 return SourcePos{Filename: "<input>"} 129 } 130 return *e.Pos 131 } 132 133 // Unwrap implements the ErrorWithPos interface, supplying the underlying 134 // error. This error will not include location information. 135 func (e ErrorWithSourcePos) Unwrap() error { 136 return e.Underlying 137 } 138 139 var _ ErrorWithPos = ErrorWithSourcePos{} 140 141 func errorWithPos(pos *SourcePos, format string, args ...interface{}) ErrorWithPos { 142 return ErrorWithSourcePos{Pos: pos, Underlying: fmt.Errorf(format, args...)} 143 } 144 145 type errorWithFilename struct { 146 underlying error 147 filename string 148 } 149 150 func (e errorWithFilename) Error() string { 151 return fmt.Sprintf("%s: %v", e.filename, e.underlying) 152 } 153 154 func (e errorWithFilename) Unwrap() error { 155 return e.underlying 156 }