Source File
logger.go
Belonging Package
github.com/evanw/esbuild/internal/logger
package logger
AlmostDone func()
Done func() []Msg
}
type LogLevel int8
const (
LevelNone LogLevel = iota
LevelInfo
LevelWarning
LevelError
LevelSilent
)
type MsgKind uint8
const (
Error MsgKind = iota
Warning
Note
)
func ( MsgKind) () string {
switch {
case Error:
return "error"
case Warning:
return "warning"
case Note:
return "note"
default:
panic("Internal error")
}
}
type Msg struct {
Kind MsgKind
Data MsgData
Notes []MsgData
}
type MsgData struct {
Text string
Location *MsgLocation
type SortableMsgs []Msg
func ( SortableMsgs) () int { return len() }
func ( SortableMsgs) ( int, int) { [], [] = [], [] }
func ( SortableMsgs) ( int, int) bool {
:= []
:= []
:= .Data.Location
:= .Data.Location
if == nil || == nil {
return == nil && != nil
}
if .File != .File {
return .File < .File
}
if .Line != .Line {
return .Line < .Line
}
if .Column != .Column {
return .Column < .Column
}
if .Kind != .Kind {
return .Kind < .Kind
}
return .Data.Text < .Data.Text
}
PathDisabled PathFlags = 1 << iota
)
func ( Path) () bool {
return (.Flags & PathDisabled) != 0
}
func ( Path) ( Path) bool {
return .Namespace > .Namespace ||
(.Namespace == .Namespace && (.Text < .Text ||
(.Text == .Text && (.Flags < .Flags ||
(.Flags == .Flags && .IgnoredSuffix < .IgnoredSuffix)))))
}
if < 0 {
=
break
}
if +1 != len() {
, = [:], [+1:]
break
}
= [:]
}
if := strings.LastIndexByte(, '.'); >= 0 {
, = [:], [:]
}
return
}
type Source struct {
Index uint32
IdentifierName string
Contents string
}
func ( *Source) ( Range) string {
return .Contents[.Loc.Start : .Loc.Start+.Len]
}
func ( *Source) ( Loc, string) Range {
:= .Contents[:.Start]
:= strings.LastIndex(, )
if >= 0 {
return Range{Loc: Loc{Start: int32()}, Len: int32(len())}
}
return Range{Loc: }
}
func ( *Source) ( Loc, string) Range {
:= .Contents[.Start:]
:= strings.Index(, )
if >= 0 {
return Range{Loc: Loc{Start: .Start + int32()}, Len: int32(len())}
}
return Range{Loc: }
}
func ( *Source) ( Loc) Range {
:= .Contents[.Start:]
if len() == 0 {
return Range{Loc: , Len: 0}
}
:= [0]
for := 1; < len(); ++ {
:= []
if == {
return Range{Loc: , Len: int32( + 1)}
} else if == '\\' {
+= 1
}
}
}
return Range{Loc: , Len: 0}
}
func ( *Source) ( Loc) ( Range) {
:= .Contents[.Start:]
= Range{Loc: , Len: 0}
if len() > 0 {
if := [0]; >= '0' && <= '9' {
.Len = 1
for int(.Len) < len() {
:= [.Len]
if ( < '0' || > '9') && ( < 'a' || > 'z') && ( < 'A' || > 'Z') && != '.' && != '_' {
break
}
.Len++
}
}
}
return
}
func ( *Source) ( Loc) ( Range) {
:= .Contents[.Start:]
= Range{Loc: , Len: 0}
if len() >= 2 && [0] == '\\' {
.Len = 2
for .Len < 4 && int(.Len) < len() {
:= [.Len]
if < '0' || > '9' {
break
}
.Len++
}
}
return
}
func ( string, int, int, bool) string {
var string
if == 1 {
= fmt.Sprintf("%d %s", , )
} else {
= fmt.Sprintf("%d %ss", , )
}
if < {
= fmt.Sprintf("%d of %s", , )
} else if && > 1 {
= "all " +
}
return
}
func ( int, int, int, int) string {
:= < || <
switch {
case == 0:
return plural("warning", , , )
case == 0:
return plural("error", , , )
default:
return fmt.Sprintf("%s and %s",
plural("warning", , , ),
plural("error", , , ))
}
}
type TerminalInfo struct {
IsTTY bool
UseColorEscapes bool
Width int
Height int
}
func ( OutputOptions) Log {
var sync.Mutex
var SortableMsgs
:= GetTerminalInfo(os.Stderr)
:= 0
:= 0
:= 0
:= 0
:= false
:= .MessageLimit
if == 0 {
= 0x7FFFFFFF
}
var []Msg
:= false
:= func() {
if {
return
}
= true
for > 0 && len() > 0 {
++
writeStringWithColor(os.Stderr, [0].String(, ))
= [1:]
--
}
if .MessageLimit > 0 && + > .MessageLimit {
writeStringWithColor(os.Stderr, fmt.Sprintf("%s shown (disable the message limit with --error-limit=0)\n",
errorAndWarningSummary(, , , )))
} else if .LogLevel <= LevelInfo && ( != 0 || != 0) {
writeStringWithColor(os.Stderr, fmt.Sprintf("%s\n",
errorAndWarningSummary(, , , )))
}
}
switch .Color {
case ColorNever:
.UseColorEscapes = false
case ColorAlways:
.UseColorEscapes = SupportsColorEscapes
}
return Log{
AddMsg: func( Msg) {
.Lock()
defer .Unlock()
= append(, )
switch .Kind {
case Error:
= true
if .LogLevel <= LevelError {
++
}
case Warning:
if .LogLevel <= LevelWarning {
++
}
}
if == 0 {
return
}
switch .Kind {
case Error:
if .LogLevel <= LevelError {
++
writeStringWithColor(os.Stderr, .String(, ))
--
}
case Warning:
if .LogLevel <= LevelWarning {
if > (.MessageLimit+1)/2 {
++
writeStringWithColor(os.Stderr, .String(, ))
--
= append(, )
}
}
}
},
HasErrors: func() bool {
.Lock()
defer .Unlock()
return
},
AlmostDone: func() {
.Lock()
defer .Unlock()
()
},
Done: func() []Msg {
.Lock()
defer .Unlock()
()
sort.Stable()
return
},
}
}
func ( []string, string) {
PrintMessageToStderr(, Msg{Kind: Error, Data: MsgData{Text: }})
}
func ( []string) OutputOptions {
:= OutputOptions{IncludeSource: true}
for , := range {
switch {
case "--color=false":
.Color = ColorNever
case "--color=true":
.Color = ColorAlways
case "--log-level=info":
.LogLevel = LevelInfo
case "--log-level=warning":
.LogLevel = LevelWarning
case "--log-level=error":
.LogLevel = LevelError
case "--log-level=silent":
.LogLevel = LevelSilent
}
}
return
}
func ( []string, Msg) {
:= NewStderrLog(OutputOptionsForArgs())
.AddMsg()
.Done()
}
type Colors struct {
Default string
Bold string
Dim string
Red string
Green string
Blue string
Cyan string
Magenta string
Yellow string
Underline string
}
func ( *os.File, LogLevel, []string, func(Colors) string) {
:= OutputOptionsForArgs()
if .LogLevel > {
return
}
PrintTextWithColor(, .Color, )
}
func ( *os.File, UseColor, func(Colors) string) {
var bool
switch {
case ColorNever:
= false
case ColorAlways:
= SupportsColorEscapes
case ColorIfTerminal:
= GetTerminalInfo().UseColorEscapes
}
var Colors
if {
.Default = colorReset
.Bold = colorResetBold
.Dim = colorResetDim
.Red = colorRed
.Green = colorGreen
.Blue = colorBlue
.Cyan = colorCyan
.Magenta = colorMagenta
.Yellow = colorYellow
.Underline = colorResetUnderline
}
writeStringWithColor(, ())
}
type SummaryTableEntry struct {
Dir string
Base string
Size string
Bytes int
IsSourceMap bool
}
type SummaryTable []SummaryTableEntry
func ( SummaryTable) () int { return len() }
func ( SummaryTable) ( int, int) { [], [] = [], [] }
func ( SummaryTable) ( int, int) bool {
:= []
:= []
if !.IsSourceMap && .IsSourceMap {
return true
}
if .IsSourceMap && !.IsSourceMap {
return false
}
:= 2
:= false
:= 0
:= 0
for , := range {
:= len(.Dir) + len(.Base)
:= len(.Size) +
if > {
=
}
if > {
=
}
if !.IsSourceMap && .Bytes >= sizeWarningThreshold {
= true
}
}
:= " "
:= .Width
if < 1 {
= defaultTerminalWidth
}
-= 2 * len()
-= 2
}
if > + {
= +
}
.WriteString("\n")
for , := range {
, := .Dir, .Base
:= -
:= .Cyan
:= ""
if !.IsSourceMap && .Bytes >= sizeWarningThreshold {
= .Yellow
if > {
:= "s"
if == +1 {
= ""
}
.WriteString(fmt.Sprintf("%s%s...and %d more output file%s...%s\n", , .Dim, -, , .Default))
}
}
:= "⚡ "
if {
= ""
}
.WriteString(fmt.Sprintf("\n%s%sDone in %dms%s\n\n",
,
.Green,
time.Since().Milliseconds(),
.Default,
))
return .String()
})
}
func () Log {
var SortableMsgs
var sync.Mutex
var bool
return Log{
AddMsg: func( Msg) {
.Lock()
defer .Unlock()
if .Kind == Error {
= true
}
= append(, )
},
HasErrors: func() bool {
.Lock()
defer .Unlock()
return
},
AlmostDone: func() {
},
Done: func() []Msg {
.Lock()
defer .Unlock()
sort.Stable()
return
},
}
}
const colorReset = "\033[0m"
const colorRed = "\033[31m"
const colorGreen = "\033[32m"
const colorBlue = "\033[34m"
const colorCyan = "\033[36m"
const colorMagenta = "\033[35m"
const colorYellow = "\033[33m"
const colorResetDim = "\033[0;37m"
const colorBold = "\033[1m"
const colorResetBold = "\033[0;1m"
const colorResetUnderline = "\033[0;4m"
type UseColor uint8
const (
ColorIfTerminal UseColor = iota
ColorNever
ColorAlways
)
type OutputOptions struct {
IncludeSource bool
MessageLimit int
Color UseColor
LogLevel LogLevel
}
if .IncludeSource {
+= "\n"
}
return
}
const extraMarginChars = 7
func ( int, int) string {
:= fmt.Sprintf("%d", )
return fmt.Sprintf(" %s%s │ ", strings.Repeat(" ", -len()), )
}
func ( int, bool) string {
:= strings.Repeat(" ", )
if {
return fmt.Sprintf(" %s ╵ ", )
}
return fmt.Sprintf(" %s │ ", )
}
func ( OutputOptions, TerminalInfo, MsgKind, MsgData, int) string {
var string
:= colorBold
:= colorResetBold
:= ""
if .IncludeSource {
= " > "
}
switch {
case Error:
= colorRed
case Warning:
= colorMagenta
case Note:
= colorReset
= colorResetBold
= colorReset
if .IncludeSource {
= " "
}
default:
panic("Internal error")
}
if .Location == nil {
if .UseColorEscapes {
return fmt.Sprintf("%s%s%s%s: %s%s%s\n",
, , , .String(),
, .Text,
colorReset)
}
return fmt.Sprintf("%s%s: %s\n", , .String(), .Text)
}
if !.IncludeSource {
if .UseColorEscapes {
return fmt.Sprintf("%s%s%s: %s%s: %s%s%s\n",
, , .Location.File,
, .String(),
, .Text,
colorReset)
}
return fmt.Sprintf("%s%s: %s: %s\n",
, .Location.File, .String(), .Text)
}
:= detailStruct(, , )
if .UseColorEscapes {
if .Suggestion != "" {
return fmt.Sprintf("%s%s%s:%d:%d: %s%s: %s%s\n%s%s%s%s%s%s\n%s%s%s%s%s\n%s%s%s%s%s%s%s\n",
, , .Path, .Line, .Column,
, .String(),
, .Message,
colorResetDim, .SourceBefore, colorGreen, .SourceMarked, colorResetDim, .SourceAfter,
emptyMarginText(, false), .Indent, colorGreen, .Marker, colorResetDim,
emptyMarginText(, true), .Indent, colorGreen, .Suggestion, colorResetDim,
.ContentAfter, colorReset)
}
return fmt.Sprintf("%s%s%s:%d:%d: %s%s: %s%s\n%s%s%s%s%s%s\n%s%s%s%s%s%s%s\n",
, , .Path, .Line, .Column,
, .String(),
, .Message,
colorResetDim, .SourceBefore, colorGreen, .SourceMarked, colorResetDim, .SourceAfter,
emptyMarginText(, true), .Indent, colorGreen, .Marker, colorResetDim,
.ContentAfter, colorReset)
}
if .Suggestion != "" {
return fmt.Sprintf("%s%s:%d:%d: %s: %s\n%s%s%s\n%s%s%s\n%s%s%s%s\n",
, .Path, .Line, .Column,
.String(), .Message,
.SourceBefore, .SourceMarked, .SourceAfter,
emptyMarginText(, false), .Indent, .Marker,
emptyMarginText(, true), .Indent, .Suggestion,
.ContentAfter)
}
return fmt.Sprintf("%s%s:%d:%d: %s: %s\n%s%s%s\n%s%s%s%s\n",
, .Path, .Line, .Column,
.String(), .Message,
.SourceBefore, .SourceMarked, .SourceAfter,
emptyMarginText(, true), .Indent, .Marker,
.ContentAfter)
}
type MsgDetail struct {
Path string
Line int
Column int
Message string
SourceBefore string
SourceMarked string
SourceAfter string
Indent string
Marker string
Suggestion string
ContentAfter string
}
func ( string, int) ( int, int, int, int) {
var rune
if > len() {
= len()
}
for , := range [:] {
switch {
case '\n':
= + 1
if != '\r' {
++
}
case '\r':
= + 1
++
case '\u2028', '\u2029':
= + 3 // These take three bytes to encode in UTF-8
++
}
=
}
, , , := computeLineAndColumn(.Contents, int(.Loc.Start))
return &MsgLocation{
File: .PrettyPath,
Line: + 1, // 0-based to 1-based
Column: ,
Length: int(.Len),
LineText: .Contents[:],
}
}
if .Length > 0 {
= len(renderTabStops([:.Column+.Length], ))
}
:= .Width
if < 1 {
= defaultTerminalWidth
}
-= + extraMarginChars
if < 1 {
= 1
}
-= 1
}
=
= strings.Repeat(" ", estimateWidthInTerminal([:]))
}
if - > 1 {
= strings.Repeat("~", estimateWidthInTerminal([:]))
}
:= marginWithLineText(, .Line)
return MsgDetail{
Path: .File,
Line: .Line,
Column: .Column,
Message: .Text,
SourceBefore: + [:],
SourceMarked: [:],
SourceAfter: [:],
Indent: ,
Marker: ,
Suggestion: .Suggestion,
ContentAfter: ,
}
}
:= 0
for != "" {
, := utf8.DecodeRuneInString()
= [:]
if != 0xFEFF {
++
}
}
return
}
func ( string, int) string {
if !strings.ContainsRune(, '\t') {
return
}
:= strings.Builder{}
:= 0
for , := range {
if == '\t' {
:= - %
for := 0; < ; ++ {
.WriteRune(' ')
++
}
} else {
.WriteRune()
++
}
}
return .String()
}
func ( Log) ( *Source, Loc, string) {
.AddMsg(Msg{
Kind: Error,
Data: RangeData(, Range{Loc: }, ),
})
}
func ( Log) ( *Source, Loc, string, []MsgData) {
.AddMsg(Msg{
Kind: Error,
Data: RangeData(, Range{Loc: }, ),
Notes: ,
})
}
func ( Log) ( *Source, Loc, string) {
.AddMsg(Msg{
Kind: Warning,
Data: RangeData(, Range{Loc: }, ),
})
}
func ( Log) ( *Source, Range, string) {
.AddMsg(Msg{
Kind: Error,
Data: RangeData(, , ),
})
}
func ( Log) ( *Source, Range, string) {
.AddMsg(Msg{
Kind: Warning,
Data: RangeData(, , ),
})
}
func ( Log) ( *Source, Range, string, []MsgData) {
.AddMsg(Msg{
Kind: Error,
Data: RangeData(, , ),
Notes: ,
})
}
func ( Log) ( *Source, Range, string, []MsgData) {
.AddMsg(Msg{
Kind: Warning,
Data: RangeData(, , ),
Notes: ,
})
}
func ( *Source, Range, string) MsgData {
return MsgData{
Text: ,
Location: LocationOrNil(, ),
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |