Skip to content
Closed

WIP #4840

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion internal/debug/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package debug

import (
"fmt"

"github.com/microsoft/typescript-go/internal/typeutil"
)

func Fail(reason string) {
Expand All @@ -14,7 +16,7 @@ func Fail(reason string) {
panic(reason)
}

func FailBadSyntaxKind(node interface{ KindString() string }, message ...any) {
func FailBadSyntaxKind(node interface{ KindString() string } /*ref:nonnil*/, message ...any) {
var msg string
if len(message) == 0 {
msg = "Unexpected node."
Expand Down Expand Up @@ -42,6 +44,25 @@ func AssertNever(member any, message ...any) {
Fail(fmt.Sprintf("%s %s", msg, detail))
}

func AssertNeverR[T any](member typeutil.Never, message ...any) T {
var msg string
if len(message) == 0 {
msg = "Illegal value:"
} else {
msg = fmt.Sprint(message...)
}
var detail string
if m, ok := member.(interface{ KindString() string }); ok {
detail = m.KindString()
} else if m, ok := member.(fmt.Stringer); ok {
detail = m.String()
} else {
detail = fmt.Sprintf("%v", member)
}
Fail(fmt.Sprintf("%s %s", msg, detail))
panic("unreachable")
}

func Assert(value bool, message ...any) {
if value {
return
Expand Down
32 changes: 19 additions & 13 deletions internal/glob/glob.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"fmt"
"strings"
"unicode/utf8"

"github.com/microsoft/typescript-go/internal/typeutil"
)

// A Glob is an LSP-compliant glob pattern, as defined by the spec:
Expand Down Expand Up @@ -42,14 +44,18 @@ type Glob struct {
elems []element // pattern elements
}

var _ typeutil.UnusedAny = nil

type DefGlob = *Glob /* ref: nonnil */

// Parse builds a Glob for the given pattern, returning an error if the pattern
// is invalid.
func Parse(pattern string) (*Glob, error) {
g, _, err := parse(pattern, false)
return g, err
}

func parse(pattern string, nested bool) (*Glob, string, error) {
func parse(pattern string, nested bool) (*Glob, string, error) /* ref: (DefGlob, string, nil) | (nil, string, typeutil.DefError) */ {
g := new(Glob)
for len(pattern) > 0 {
switch pattern[0] {
Expand Down Expand Up @@ -150,11 +156,11 @@ func readRangeRune(input string) (rune, int, error) {
}

var (
errBadRange = errors.New("'[' patterns must be of the form [x-y]")
errInvalidUTF8 = errors.New("invalid UTF-8 encoding")
errBadRange typeutil.DefError = errors.New("'[' patterns must be of the form [x-y]")
errInvalidUTF8 typeutil.DefError = errors.New("invalid UTF-8 encoding")
)

func (g *Glob) parseLiteral(pattern string, nested bool) string {
func (g DefGlob) parseLiteral(pattern string, nested bool) string {
var specialChars string
if nested {
specialChars = "*?{[/},"
Expand All @@ -169,7 +175,7 @@ func (g *Glob) parseLiteral(pattern string, nested bool) string {
return pattern[end:]
}

func (g *Glob) String() string {
func (g DefGlob) String() string {
var b strings.Builder
for _, e := range g.elems {
fmt.Fprint(&b, e)
Expand All @@ -182,13 +188,13 @@ type element fmt.Stringer

// element types.
type (
slash struct{} // One or more '/' separators
literal string // string literal, not containing /, *, ?, {}, or []
star struct{} // *
anyChar struct{} // ?
starStar struct{} // **
group []*Glob // {foo, bar, ...} grouping
charRange struct { // [a-z] character range
slash struct{} // One or more '/' separators
literal string // string literal, not containing /, *, ?, {}, or []
star struct{} // *
anyChar struct{} // ?
starStar struct{} // **
group []DefGlob // {foo, bar, ...} grouping
charRange struct { // [a-z] character range
negate bool
low, high rune
}
Expand All @@ -212,7 +218,7 @@ func (r charRange) String() string {
}

// Match reports whether the input string matches the glob pattern.
func (g *Glob) Match(input string) bool {
func (g DefGlob) Match(input string) bool {
return match(g.elems, input)
}

Expand Down
17 changes: 9 additions & 8 deletions internal/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/go-json-experiment/json"
"github.com/go-json-experiment/json/jsontext"
"github.com/microsoft/typescript-go/internal/typeutil"
)

var allowInvalid []json.Options = slices.Clip([]json.Options{jsontext.AllowInvalidUTF8(true)})
Expand All @@ -20,7 +21,7 @@ func Marshal(in any, opts ...json.Options) (out []byte, err error) {
return json.Marshal(in, opts...)
}

func MarshalEncode(out *jsontext.Encoder, in any, opts ...json.Options) (err error) {
func MarshalEncode(out typeutil.DefPtr[jsontext.Encoder], in any, opts ...json.Options) (err error) {
if len(opts) == 0 {
opts = allowInvalid
} else {
Expand All @@ -29,7 +30,7 @@ func MarshalEncode(out *jsontext.Encoder, in any, opts ...json.Options) (err err
return json.MarshalEncode(out, in, opts...)
}

func MarshalWrite(out io.Writer, in any, opts ...json.Options) (err error) {
func MarshalWrite(out io.Writer /* ref: nonnil */, in any, opts ...json.Options) (err error) {
if len(opts) == 0 {
opts = allowInvalid
} else {
Expand All @@ -46,23 +47,23 @@ func MarshalIndent(in any, prefix, indent string) (out []byte, err error) {
return Marshal(in, jsontext.WithIndentPrefix(prefix), jsontext.WithIndent(indent))
}

func MarshalIndentWrite(out io.Writer, in any, prefix, indent string) (err error) {
func MarshalIndentWrite(out io.Writer /* ref: nonnil */, in any, prefix, indent string) (err error) {
if prefix == "" && indent == "" {
// WithIndentPrefix and WithIndent imply multiline output, so skip them.
return MarshalWrite(out, in)
}
return MarshalWrite(out, in, jsontext.WithIndentPrefix(prefix), jsontext.WithIndent(indent))
}

func Unmarshal(in []byte, out any, opts ...json.Options) (err error) {
func Unmarshal(in []byte, out typeutil.DefAny, opts ...json.Options) (err error) {
return json.Unmarshal(in, out, opts...)
}

func UnmarshalDecode(in *jsontext.Decoder, out any, opts ...json.Options) (err error) {
func UnmarshalDecode(in typeutil.DefPtr[jsontext.Decoder], out typeutil.DefAny, opts ...json.Options) (err error) {
return json.UnmarshalDecode(in, out, opts...)
}

func UnmarshalRead(in io.Reader, out any, opts ...json.Options) (err error) {
func UnmarshalRead(in io.Reader /* ref: nonnil */, out typeutil.DefAny, opts ...json.Options) (err error) {
return json.UnmarshalRead(in, out, opts...)
}

Expand All @@ -78,8 +79,8 @@ func WithIndent(indent string) json.Options {
return jsontext.WithIndent(indent)
}

func NewDecoder(r io.Reader) *jsontext.Decoder {
return jsontext.NewDecoder(r)
func NewDecoder(r io.Reader /* ref: nonnil */) typeutil.DefPtr[jsontext.Decoder] {
return typeutil.NonNil(jsontext.NewDecoder(r))
}

type (
Expand Down
4 changes: 2 additions & 2 deletions internal/locale/locale.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ type Locale language.Tag

var Default Locale

func WithLocale(ctx context.Context, locale Locale) context.Context {
func WithLocale(ctx context.Context /* ref: nonnil */, locale Locale) context.Context {
return context.WithValue(ctx, contextKey(0), locale)
}

func FromContext(ctx context.Context) Locale {
func FromContext(ctx context.Context /* ref: nonnil */) Locale {
locale, _ := ctx.Value(contextKey(0)).(Locale)
return locale
}
Expand Down
2 changes: 1 addition & 1 deletion internal/nativepath/eintr_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package nativepath

import "syscall"

func ignoringEINTR[T any](fn func() (T, error)) (T, error) {
func ignoringEINTR[T any](fn func() (T, error) /* ref: nonnil */) (T, error) {
for {
v, err := fn()
if err != syscall.EINTR { //nolint:errorlint // syscall functions return raw syscall.Errno, never wrapped
Expand Down
12 changes: 8 additions & 4 deletions internal/pprof/pprof.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ type ProfileSession struct {
logWriter io.Writer
}

type DefProfileSession = *ProfileSession /* ref: nonnil */

// BeginProfiling starts CPU and memory profiling, writing the profiles to the specified directory.
func BeginProfiling(profileDir string, logWriter io.Writer) *ProfileSession {
func BeginProfiling(profileDir string, logWriter io.Writer) DefProfileSession {
if err := os.MkdirAll(profileDir, 0o755); err != nil {
panic(err)
}
Expand All @@ -46,7 +48,7 @@ func BeginProfiling(profileDir string, logWriter io.Writer) *ProfileSession {
}
}

func (p *ProfileSession) Stop() {
func (p DefProfileSession) Stop() {
pprof.StopCPUProfile()
p.cpuFile.Close()

Expand All @@ -71,8 +73,10 @@ type CPUProfiler struct {
session *ProfileSession
}

type DefCPUProfiler = *CPUProfiler /* ref: nonnil */

// StartCPUProfile starts CPU profiling, writing to the specified directory when stopped.
func (c *CPUProfiler) StartCPUProfile(profileDir string) error {
func (c DefCPUProfiler) StartCPUProfile(profileDir string) error {
c.mu.Lock()
defer c.mu.Unlock()

Expand Down Expand Up @@ -105,7 +109,7 @@ func (c *CPUProfiler) StartCPUProfile(profileDir string) error {
}

// StopCPUProfile stops CPU profiling and returns the path to the profile file.
func (c *CPUProfiler) StopCPUProfile() (string, error) {
func (c DefCPUProfiler) StopCPUProfile() (string, error) {
c.mu.Lock()
defer c.mu.Unlock()

Expand Down
13 changes: 9 additions & 4 deletions internal/project/background/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ type Queue struct {
closed bool
}

type (
DefQueue = *Queue /* ref: nonnil */
DefContext = context.Context /* ref: nonnil */
)

// NewQueue creates a new background queue for managing background tasks execution.
func NewQueue() *Queue {
func NewQueue() DefQueue {
return &Queue{}
}

func (q *Queue) Enqueue(ctx context.Context, fn func(context.Context)) {
func (q DefQueue) Enqueue(ctx DefContext, fn func(DefContext) /* ref: nonnil */) {
q.mu.RLock()
if q.closed {
q.mu.RUnlock()
Expand All @@ -41,11 +46,11 @@ func (q *Queue) Enqueue(ctx context.Context, fn func(context.Context)) {

// Wait waits for all active tasks to complete.
// It does not prevent new tasks from being enqueued while waiting.
func (q *Queue) Wait() {
func (q DefQueue) Wait() {
q.wg.Wait()
}

func (q *Queue) Close() {
func (q DefQueue) Close() {
q.mu.Lock()
q.closed = true
q.mu.Unlock()
Expand Down
12 changes: 9 additions & 3 deletions internal/project/logging/logcollector.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,29 @@ import (
"fmt"
"strings"
"time"

"github.com/microsoft/typescript-go/internal/typeutil"
)

type LogCollector interface {
fmt.Stringer
Logger
}

type DefLogCollector = LogCollector /* ref: nonnil */

type logCollector struct {
logger
builder *strings.Builder
builder typeutil.DefPtr[strings.Builder]
}

func (lc *logCollector) String() string {
type defLogCollectorImpl = *logCollector /* ref: nonnil */

func (lc defLogCollectorImpl) String() string {
return lc.builder.String()
}

func NewTestLogger() LogCollector {
func NewTestLogger() DefLogCollector {
var builder strings.Builder
return &logCollector{
logger: logger{
Expand Down
13 changes: 9 additions & 4 deletions internal/project/logging/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,18 @@ type Logger interface {
SetVerbose(verbose bool)
}

type (
DefLogger = Logger /* ref: nonnil */
DefWriter = io.Writer /* ref: nonnil */
)

var _ Logger = (*logger)(nil)

type logger struct {
mu sync.Mutex
verbose bool
writer io.Writer
prefix func() string
writer DefWriter
prefix func() string /* ref: nonnil */
}

func (l *logger) Log(msg ...any) {
Expand Down Expand Up @@ -115,7 +120,7 @@ func (l *logger) Infof(format string, args ...any) {
l.Logf(format, args...)
}

func NewLogger(output io.Writer) Logger {
func NewLogger(output DefWriter) DefLogger {
return &logger{
writer: output,
prefix: func() string {
Expand All @@ -126,7 +131,7 @@ func NewLogger(output io.Writer) Logger {

// NewNopLogger returns a no-op Logger that discards all log messages.
// It is safe to call any method on the returned Logger.
func NewNopLogger() Logger {
func NewNopLogger() DefLogger {
return (*logger)(nil)
}

Expand Down
Loading