github.com/hoveychen/protoreflect@v1.4.7-0.20221103114119-0b4b3385ec76/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  // ErrorReporter is responsible for reporting the given error. If the reporter
    15  // returns a non-nil error, parsing/linking will abort with that error. If the
    16  // reporter returns nil, parsing will continue, allowing the parser to try to
    17  // report as many syntax and/or link errors as it can find.
    18  type ErrorReporter func(err ErrorWithPos) error
    19  
    20  func defaultErrorReporter(err ErrorWithPos) error {
    21  	// abort parsing after first error encountered
    22  	return err
    23  }
    24  
    25  type errorHandler struct {
    26  	reporter     ErrorReporter
    27  	errsReported bool
    28  	err          error
    29  }
    30  
    31  func newErrorHandler(reporter ErrorReporter) *errorHandler {
    32  	if reporter == nil {
    33  		reporter = defaultErrorReporter
    34  	}
    35  	return &errorHandler{
    36  		reporter: reporter,
    37  	}
    38  }
    39  
    40  func (h *errorHandler) handleError(err error) error {
    41  	if h.err != nil {
    42  		return h.err
    43  	}
    44  	if ewp, ok := err.(ErrorWithPos); ok {
    45  		h.errsReported = true
    46  		err = h.reporter(ewp)
    47  	}
    48  	h.err = err
    49  	return err
    50  }
    51  
    52  func (h *errorHandler) getError() error {
    53  	if h.errsReported && h.err == nil {
    54  		return ErrInvalidSource
    55  	}
    56  	return h.err
    57  }
    58  
    59  // ErrorWithPos is an error about a proto source file that includes information
    60  // about the location in the file that caused the error.
    61  type ErrorWithPos interface {
    62  	error
    63  	GetPosition() SourcePos
    64  }
    65  
    66  // ErrorWithSourcePos is an error about a proto source file that includes
    67  // information about the location in the file that caused the error.
    68  //
    69  // Errors that include source location information *might* be of this type.
    70  // However, calling code that is trying to examine errors with location info
    71  // should instead look for instances of the ErrorWithPos interface, which
    72  // will find other kinds of errors. This type is only exported for backwards
    73  // compatibility.
    74  type ErrorWithSourcePos struct {
    75  	Underlying error
    76  	Pos        *SourcePos
    77  }
    78  
    79  // Error implements the error interface
    80  func (e ErrorWithSourcePos) Error() string {
    81  	if e.Pos.Line <= 0 || e.Pos.Col <= 0 {
    82  		return fmt.Sprintf("%s: %v", e.Pos.Filename, e.Underlying)
    83  	}
    84  	return fmt.Sprintf("%s:%d:%d: %v", e.Pos.Filename, e.Pos.Line, e.Pos.Col, e.Underlying)
    85  }
    86  
    87  // GetPosition implements the ErrorWithPos interface, supplying a location in
    88  // proto source that caused the error.
    89  func (e ErrorWithSourcePos) GetPosition() SourcePos {
    90  	return *e.Pos
    91  }
    92  
    93  var _ ErrorWithPos = ErrorWithSourcePos{}