vendor tsgo
This commit is contained in:
159
tools/tsgo/internal/diagnostics/diagnostics.go
Normal file
159
tools/tsgo/internal/diagnostics/diagnostics.go
Normal file
@@ -0,0 +1,159 @@
|
||||
// Package diagnostics contains generated localizable diagnostic messages.
|
||||
package diagnostics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/locale"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
//go:generate go run generate.go -diagnostics ./diagnostics_generated.go -loc ./loc_generated.go -locdir ./loc
|
||||
//go:generate go tool golang.org/x/tools/cmd/stringer -type=Category -output=stringer_generated.go
|
||||
//go:generate npx dprint fmt diagnostics_generated.go loc_generated.go stringer_generated.go
|
||||
|
||||
type Category int32
|
||||
|
||||
const (
|
||||
CategoryWarning Category = iota
|
||||
CategoryError
|
||||
CategorySuggestion
|
||||
CategoryMessage
|
||||
)
|
||||
|
||||
func (category Category) Name() string {
|
||||
switch category {
|
||||
case CategoryWarning:
|
||||
return "warning"
|
||||
case CategoryError:
|
||||
return "error"
|
||||
case CategorySuggestion:
|
||||
return "suggestion"
|
||||
case CategoryMessage:
|
||||
return "message"
|
||||
}
|
||||
panic("Unhandled diagnostic category")
|
||||
}
|
||||
|
||||
type Key string
|
||||
|
||||
type Message struct {
|
||||
code int32
|
||||
category Category
|
||||
key Key
|
||||
text string
|
||||
reportsUnnecessary bool
|
||||
elidedInCompatibilityPyramid bool
|
||||
reportsDeprecated bool
|
||||
}
|
||||
|
||||
func (m *Message) Code() int32 { return m.code }
|
||||
func (m *Message) Category() Category { return m.category }
|
||||
func (m *Message) Key() Key { return m.key }
|
||||
func (m *Message) ReportsUnnecessary() bool { return m.reportsUnnecessary }
|
||||
func (m *Message) ElidedInCompatibilityPyramid() bool { return m.elidedInCompatibilityPyramid }
|
||||
func (m *Message) ReportsDeprecated() bool { return m.reportsDeprecated }
|
||||
|
||||
// For debugging only.
|
||||
func (m *Message) String() string {
|
||||
return m.text
|
||||
}
|
||||
|
||||
func (m *Message) Localize(locale locale.Locale, args ...any) string {
|
||||
return Localize(locale, m, "", StringifyArgs(args)...)
|
||||
}
|
||||
|
||||
func Localize(locale locale.Locale, message *Message, key Key, args ...string) string {
|
||||
if message == nil {
|
||||
message = keyToMessage(key)
|
||||
}
|
||||
if message == nil {
|
||||
panic("Unknown diagnostic message: " + string(key))
|
||||
}
|
||||
|
||||
text := message.text
|
||||
if localized, ok := getLocalizedMessages(language.Tag(locale))[message.key]; ok {
|
||||
text = localized
|
||||
}
|
||||
|
||||
return Format(text, args)
|
||||
}
|
||||
|
||||
var localizedMessagesCache sync.Map // map[language.Tag]map[Key]string
|
||||
|
||||
func getLocalizedMessages(loc language.Tag) map[Key]string {
|
||||
if loc == language.Und {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check cache first
|
||||
if cached, ok := localizedMessagesCache.Load(loc); ok {
|
||||
if cached == nil {
|
||||
return nil
|
||||
}
|
||||
return cached.(map[Key]string)
|
||||
}
|
||||
|
||||
var messages map[Key]string
|
||||
|
||||
_, index, confidence := matcher.Match(loc)
|
||||
if confidence >= language.Low && index >= 0 && index < len(localeFuncs) {
|
||||
if fn := localeFuncs[index]; fn != nil {
|
||||
messages = fn()
|
||||
}
|
||||
}
|
||||
|
||||
localizedMessagesCache.Store(loc, messages)
|
||||
return messages
|
||||
}
|
||||
|
||||
var placeholderRegexp = regexp.MustCompile(`{(\d+)}`)
|
||||
|
||||
func Format(text string, args []string) string {
|
||||
if len(args) == 0 {
|
||||
return text
|
||||
}
|
||||
|
||||
// Replace invalid UTF-8 with Unicode replacement character
|
||||
args = core.SameMap(args, func(arg string) string {
|
||||
return strings.ToValidUTF8(arg, "\uFFFD")
|
||||
})
|
||||
|
||||
return placeholderRegexp.ReplaceAllStringFunc(text, func(match string) string {
|
||||
index, err := strconv.ParseInt(match[1:len(match)-1], 10, 0)
|
||||
if err != nil || int(index) >= len(args) {
|
||||
panic("Invalid formatting placeholder")
|
||||
}
|
||||
return args[int(index)]
|
||||
})
|
||||
}
|
||||
|
||||
func StringifyArgs(args []any) []string {
|
||||
if len(args) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
result := make([]string, len(args))
|
||||
for i, arg := range args {
|
||||
if s, ok := arg.(string); ok {
|
||||
result[i] = s
|
||||
} else {
|
||||
result[i] = fmt.Sprintf("%v", arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func NewAdHocMessage(message string) *Message {
|
||||
return &Message{
|
||||
code: -1,
|
||||
category: CategoryError,
|
||||
key: "-1",
|
||||
text: message,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user