github.com/jd-ly/cmd@v1.0.10/utils/error.go (about)

     1  package utils
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  )
     8  
     9  // The error is a wrapper for the
    10  type (
    11  	SourceError struct {
    12  		SourceType               string   // The type of source that failed to build.
    13  		Title, Path, Description string   // Description of the error, as presented to the user.
    14  		Line, Column             int      // Where the error was encountered.
    15  		SourceLines              []string // The entire source file, split into lines.
    16  		Stack                    string   // The raw stack trace string from debug.Stack().
    17  		MetaError                string   // Error that occurred producing the error page.
    18  		Link                     string   // A configurable link to wrap the error source in
    19  	}
    20  	SourceLine struct {
    21  		Source  string
    22  		Line    int
    23  		IsError bool
    24  	}
    25  )
    26  // Return a new error object
    27  func NewError(source, title, path, description string) *SourceError {
    28  	return &SourceError{
    29  		SourceType:source,
    30  		Title:title,
    31  		Path:path,
    32  		Description:description,
    33  	}
    34  }
    35  
    36  // Creates a link based on the configuration setting "errors.link"
    37  func (e *SourceError) SetLink(errorLink string) {
    38  	errorLink = strings.Replace(errorLink, "{{Path}}", e.Path, -1)
    39  	errorLink = strings.Replace(errorLink, "{{Line}}", strconv.Itoa(e.Line), -1)
    40  
    41  	e.Link = "<a href=" + errorLink + ">" + e.Path + ":" + strconv.Itoa(e.Line) + "</a>"
    42  }
    43  
    44  // Error method constructs a plaintext version of the error, taking
    45  // account that fields are optionally set. Returns e.g. Compilation Error
    46  // (in views/header.html:51): expected right delim in end; got "}"
    47  func (e *SourceError) Error() string {
    48  	if e == nil {
    49  		panic("opps")
    50  	}
    51  	loc := ""
    52  	if e.Path != "" {
    53  		line := ""
    54  		if e.Line != 0 {
    55  			line = fmt.Sprintf(":%d", e.Line)
    56  		}
    57  		loc = fmt.Sprintf("(in %s%s)", e.Path, line)
    58  	}
    59  	header := loc
    60  	if e.Title != "" {
    61  		if loc != "" {
    62  			header = fmt.Sprintf("%s %s: ", e.Title, loc)
    63  		} else {
    64  			header = fmt.Sprintf("%s: ", e.Title)
    65  		}
    66  	}
    67  	return fmt.Sprintf("%s%s", header, e.Description)
    68  }
    69  
    70  // ContextSource method returns a snippet of the source around
    71  // where the error occurred.
    72  func (e *SourceError) ContextSource() []SourceLine {
    73  	if e.SourceLines == nil {
    74  		return nil
    75  	}
    76  	start := (e.Line - 1) - 5
    77  	if start < 0 {
    78  		start = 0
    79  	}
    80  	end := (e.Line - 1) + 5
    81  	if end > len(e.SourceLines) {
    82  		end = len(e.SourceLines)
    83  	}
    84  
    85  	lines := make([]SourceLine, end - start)
    86  	for i, src := range e.SourceLines[start:end] {
    87  		fileLine := start + i + 1
    88  		lines[i] = SourceLine{src, fileLine, fileLine == e.Line}
    89  	}
    90  	return lines
    91  }