vendor tsgo
This commit is contained in:
226
tools/tsgo/internal/api/callbackfs.go
Normal file
226
tools/tsgo/internal/api/callbackfs.go
Normal file
@@ -0,0 +1,226 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/json"
|
||||
"github.com/microsoft/typescript-go/internal/vfs"
|
||||
)
|
||||
|
||||
// callbackFS wraps a base filesystem and delegates certain operations
|
||||
// to the client via RPC callbacks. This allows the API client to provide
|
||||
// a virtual filesystem (e.g., in-memory files for testing).
|
||||
//
|
||||
// The callbacks to enable are specified at construction time via the
|
||||
// --callbacks CLI flag. The connection is set via SetConnection after
|
||||
// the transport connection is established.
|
||||
type callbackFS struct {
|
||||
base vfs.FS
|
||||
enabledCallbacks map[string]bool
|
||||
|
||||
// conn and ctx are set after connection is established
|
||||
conn Conn
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// Callback names that can be enabled
|
||||
const (
|
||||
callbackReadFile = "readFile"
|
||||
callbackFileExists = "fileExists"
|
||||
callbackDirectoryExists = "directoryExists"
|
||||
callbackGetAccessibleEntries = "getAccessibleEntries"
|
||||
callbackRealpath = "realpath"
|
||||
)
|
||||
|
||||
func isCallbackName(name string) bool {
|
||||
switch name {
|
||||
case callbackReadFile,
|
||||
callbackFileExists,
|
||||
callbackDirectoryExists,
|
||||
callbackGetAccessibleEntries,
|
||||
callbackRealpath:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// newCallbackFS creates a new callbackFS wrapping the given base filesystem.
|
||||
// The callbacks slice specifies which filesystem operations should be delegated
|
||||
// to the client (e.g., "readFile", "fileExists").
|
||||
func newCallbackFS(base vfs.FS, callbacks []string) *callbackFS {
|
||||
enabled := make(map[string]bool, len(callbacks))
|
||||
for _, cb := range callbacks {
|
||||
if !isCallbackName(cb) {
|
||||
panic("unknown callback name: " + cb)
|
||||
}
|
||||
enabled[cb] = true
|
||||
}
|
||||
return &callbackFS{
|
||||
base: base,
|
||||
enabledCallbacks: enabled,
|
||||
}
|
||||
}
|
||||
|
||||
// SetConnection sets the RPC connection for callbacks.
|
||||
// This must be called after the transport connection is established
|
||||
// but before any filesystem operations that need callbacks.
|
||||
func (fs *callbackFS) SetConnection(ctx context.Context, conn Conn) {
|
||||
fs.ctx = ctx
|
||||
fs.conn = conn
|
||||
}
|
||||
|
||||
// isEnabled returns true if the named callback is enabled.
|
||||
func (fs *callbackFS) isEnabled(name string) bool {
|
||||
return fs.enabledCallbacks[name]
|
||||
}
|
||||
|
||||
// call invokes a callback on the client and returns the result.
|
||||
func (fs *callbackFS) call(name string, arg any) ([]byte, error) {
|
||||
if fs.conn == nil {
|
||||
return nil, fmt.Errorf("CallbackFS: %s called before connection set", name)
|
||||
}
|
||||
|
||||
result, err := fs.conn.Call(fs.ctx, name, arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// UseCaseSensitiveFileNames implements vfs.FS.
|
||||
func (fs *callbackFS) UseCaseSensitiveFileNames() bool {
|
||||
return fs.base.UseCaseSensitiveFileNames()
|
||||
}
|
||||
|
||||
// ReadFile implements vfs.FS.
|
||||
//
|
||||
// The readFile callback uses a wrapped response format to distinguish three states:
|
||||
// - undefined (fall back to real FS): null or empty on wire
|
||||
// - null (not found, no fallback): {"content": null}
|
||||
// - string content: {"content": "..."}
|
||||
func (fs *callbackFS) ReadFile(path string) (contents string, ok bool) {
|
||||
if fs.isEnabled(callbackReadFile) {
|
||||
result, err := fs.call(callbackReadFile, path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(result) > 0 && string(result) != "null" {
|
||||
var wrapper struct {
|
||||
Content *string `json:"content"`
|
||||
}
|
||||
if err := json.Unmarshal(result, &wrapper); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if wrapper.Content == nil {
|
||||
return "", false
|
||||
}
|
||||
return *wrapper.Content, true
|
||||
}
|
||||
}
|
||||
return fs.base.ReadFile(path)
|
||||
}
|
||||
|
||||
// FileExists implements vfs.FS.
|
||||
func (fs *callbackFS) FileExists(path string) bool {
|
||||
if fs.isEnabled(callbackFileExists) {
|
||||
result, err := fs.call(callbackFileExists, path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(result) > 0 && string(result) != "null" {
|
||||
return string(result) == "true"
|
||||
}
|
||||
}
|
||||
return fs.base.FileExists(path)
|
||||
}
|
||||
|
||||
// DirectoryExists implements vfs.FS.
|
||||
func (fs *callbackFS) DirectoryExists(path string) bool {
|
||||
if fs.isEnabled(callbackDirectoryExists) {
|
||||
result, err := fs.call(callbackDirectoryExists, path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(result) > 0 && string(result) != "null" {
|
||||
return string(result) == "true"
|
||||
}
|
||||
}
|
||||
return fs.base.DirectoryExists(path)
|
||||
}
|
||||
|
||||
// GetAccessibleEntries implements vfs.FS.
|
||||
func (fs *callbackFS) GetAccessibleEntries(path string) vfs.Entries {
|
||||
if fs.isEnabled(callbackGetAccessibleEntries) {
|
||||
result, err := fs.call(callbackGetAccessibleEntries, path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(result) > 0 {
|
||||
var rawEntries *struct {
|
||||
Files []string `json:"files"`
|
||||
Directories []string `json:"directories"`
|
||||
}
|
||||
if err := json.Unmarshal(result, &rawEntries); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if rawEntries != nil {
|
||||
return vfs.Entries{
|
||||
Files: rawEntries.Files,
|
||||
Directories: rawEntries.Directories,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fs.base.GetAccessibleEntries(path)
|
||||
}
|
||||
|
||||
// Realpath implements vfs.FS.
|
||||
func (fs *callbackFS) Realpath(path string) string {
|
||||
if fs.isEnabled(callbackRealpath) {
|
||||
result, err := fs.call(callbackRealpath, path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(result) > 0 && string(result) != "null" {
|
||||
var realpath string
|
||||
if err := json.Unmarshal(result, &realpath); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return realpath
|
||||
}
|
||||
}
|
||||
return fs.base.Realpath(path)
|
||||
}
|
||||
|
||||
// WriteFile implements vfs.FS - always delegates to base (no callback support).
|
||||
func (fs *callbackFS) WriteFile(path string, data string) error {
|
||||
return fs.base.WriteFile(path, data)
|
||||
}
|
||||
|
||||
// AppendFile implements vfs.FS - always delegates to base (no callback support).
|
||||
func (fs *callbackFS) AppendFile(path string, data string) error {
|
||||
return fs.base.AppendFile(path, data)
|
||||
}
|
||||
|
||||
// Remove implements vfs.FS - always delegates to base (no callback support).
|
||||
func (fs *callbackFS) Remove(path string) error {
|
||||
return fs.base.Remove(path)
|
||||
}
|
||||
|
||||
// Chtimes implements vfs.FS - always delegates to base (no callback support).
|
||||
func (fs *callbackFS) Chtimes(path string, aTime time.Time, mTime time.Time) error {
|
||||
return fs.base.Chtimes(path, aTime, mTime)
|
||||
}
|
||||
|
||||
// Stat implements vfs.FS - always delegates to base (no callback support).
|
||||
func (fs *callbackFS) Stat(path string) vfs.FileInfo {
|
||||
return fs.base.Stat(path)
|
||||
}
|
||||
|
||||
// WalkDir implements vfs.FS - always delegates to base (no callback support).
|
||||
func (fs *callbackFS) WalkDir(root string, walkFn vfs.WalkDirFunc) error {
|
||||
return fs.base.WalkDir(root, walkFn)
|
||||
}
|
||||
46
tools/tsgo/internal/api/conn.go
Normal file
46
tools/tsgo/internal/api/conn.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/json"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrConnClosed = errors.New("api: connection closed")
|
||||
ErrRequestTimeout = errors.New("api: request timeout")
|
||||
)
|
||||
|
||||
// Handler processes incoming API requests and notifications.
|
||||
type Handler interface {
|
||||
// HandleRequest handles an incoming request and returns a result or error.
|
||||
HandleRequest(ctx context.Context, method string, params json.Value) (any, error)
|
||||
// HandleNotification handles an incoming notification.
|
||||
HandleNotification(ctx context.Context, method string, params json.Value) error
|
||||
}
|
||||
|
||||
// Conn represents a bidirectional connection for API communication.
|
||||
type Conn interface {
|
||||
// Run starts processing messages on the connection.
|
||||
// It blocks until the context is cancelled or an error occurs.
|
||||
Run(ctx context.Context) error
|
||||
|
||||
// Call sends a request to the client and waits for a response.
|
||||
Call(ctx context.Context, method string, params any) (json.Value, error)
|
||||
|
||||
// Notify sends a notification to the client (no response expected).
|
||||
Notify(ctx context.Context, method string, params any) error
|
||||
}
|
||||
|
||||
// UnmarshalParams is a helper to unmarshal params into a typed struct.
|
||||
func UnmarshalParams[T any](params json.Value) (*T, error) {
|
||||
if len(params) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var v T
|
||||
if err := json.Unmarshal(params, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &v, nil
|
||||
}
|
||||
231
tools/tsgo/internal/api/conn_async.go
Normal file
231
tools/tsgo/internal/api/conn_async.go
Normal file
@@ -0,0 +1,231 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/json"
|
||||
"github.com/microsoft/typescript-go/internal/jsonrpc"
|
||||
)
|
||||
|
||||
// AsyncConn manages bidirectional JSON-RPC communication with async request handling.
|
||||
// Each incoming request is handled in its own goroutine, allowing concurrent processing.
|
||||
// This is the standard implementation for LSP-style JSON-RPC protocols.
|
||||
type AsyncConn struct {
|
||||
rwc io.ReadWriteCloser
|
||||
protocol Protocol
|
||||
handler Handler
|
||||
|
||||
// timing, when non-nil, accumulates the wall-clock time spent handling each
|
||||
// request. Clients retrieve the collected data via a getServerTiming request.
|
||||
timing *timingCollector
|
||||
|
||||
// For server→client requests
|
||||
seq atomic.Int64
|
||||
pending map[jsonrpc.ID]chan *Message
|
||||
pendingMu sync.Mutex
|
||||
writeMu sync.Mutex
|
||||
}
|
||||
|
||||
// NewAsyncConn creates a new async connection with the given transport and handler.
|
||||
// It uses JSONRPCProtocol (LSP-style Content-Length framing) by default.
|
||||
func NewAsyncConn(rwc io.ReadWriteCloser, handler Handler) *AsyncConn {
|
||||
return NewAsyncConnWithProtocol(rwc, NewJSONRPCProtocol(rwc), handler)
|
||||
}
|
||||
|
||||
// NewAsyncConnWithProtocol creates a new async connection with a custom protocol.
|
||||
func NewAsyncConnWithProtocol(rwc io.ReadWriteCloser, protocol Protocol, handler Handler) *AsyncConn {
|
||||
return &AsyncConn{
|
||||
rwc: rwc,
|
||||
protocol: protocol,
|
||||
handler: handler,
|
||||
pending: make(map[jsonrpc.ID]chan *Message),
|
||||
}
|
||||
}
|
||||
|
||||
// SetCollectTiming enables or disables per-request server processing-time
|
||||
// measurement. When enabled, the connection accumulates timing that clients can
|
||||
// retrieve via a getServerTiming request.
|
||||
func (c *AsyncConn) SetCollectTiming(enabled bool) {
|
||||
if enabled {
|
||||
c.timing = newTimingCollector()
|
||||
} else {
|
||||
c.timing = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Run starts processing messages on the connection.
|
||||
// It blocks until the context is cancelled or an error occurs.
|
||||
func (c *AsyncConn) Run(ctx context.Context) error {
|
||||
for {
|
||||
if ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
msg, err := c.protocol.ReadMessage()
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if msg.IsResponse() {
|
||||
c.handleResponse(msg)
|
||||
} else if msg.IsRequest() {
|
||||
go c.handleRequest(ctx, msg)
|
||||
} else if msg.IsNotification() {
|
||||
go c.handleNotification(ctx, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handleResponse matches a response to a pending request.
|
||||
func (c *AsyncConn) handleResponse(msg *Message) {
|
||||
c.pendingMu.Lock()
|
||||
ch, ok := c.pending[*msg.ID]
|
||||
if ok {
|
||||
delete(c.pending, *msg.ID)
|
||||
}
|
||||
c.pendingMu.Unlock()
|
||||
|
||||
if ok {
|
||||
ch <- msg
|
||||
close(ch)
|
||||
}
|
||||
}
|
||||
|
||||
// handleRequest processes an incoming request.
|
||||
func (c *AsyncConn) handleRequest(ctx context.Context, msg *Message) {
|
||||
// Intercept the meta-requests for collected server timing before dispatching
|
||||
// to the handler, so they are answered directly and not themselves recorded.
|
||||
switch msg.Method {
|
||||
case string(MethodGetServerTiming):
|
||||
c.writeMu.Lock()
|
||||
writeErr := c.protocol.WriteResponse(msg.ID, serverTimingSnapshot(c.timing))
|
||||
c.writeMu.Unlock()
|
||||
if writeErr != nil {
|
||||
panic(fmt.Sprintf("api: failed to write server timing response: %v", writeErr))
|
||||
}
|
||||
return
|
||||
case string(MethodResetServerTiming):
|
||||
if c.timing != nil {
|
||||
c.timing.reset()
|
||||
}
|
||||
c.writeMu.Lock()
|
||||
writeErr := c.protocol.WriteResponse(msg.ID, nil)
|
||||
c.writeMu.Unlock()
|
||||
if writeErr != nil {
|
||||
panic(fmt.Sprintf("api: failed to write reset server timing response: %v", writeErr))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var result any
|
||||
var err error
|
||||
|
||||
start := time.Time{}
|
||||
if c.timing != nil {
|
||||
start = time.Now()
|
||||
}
|
||||
|
||||
// Recover from panics and convert to error response with stack trace
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
stack := string(debug.Stack())
|
||||
err = fmt.Errorf("panic: %v\n%s", r, stack)
|
||||
|
||||
c.writeMu.Lock()
|
||||
writeErr := c.protocol.WriteError(msg.ID, &jsonrpc.ResponseError{
|
||||
Code: jsonrpc.CodeInternalError,
|
||||
Message: err.Error(),
|
||||
})
|
||||
c.writeMu.Unlock()
|
||||
|
||||
if writeErr != nil {
|
||||
panic(fmt.Sprintf("api: failed to write panic error response: %v (original panic: %v)", writeErr, r))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
result, err = c.handler.HandleRequest(ctx, msg.Method, msg.Params)
|
||||
|
||||
if c.timing != nil {
|
||||
c.timing.record(msg.Method, time.Since(start))
|
||||
}
|
||||
|
||||
c.writeMu.Lock()
|
||||
defer c.writeMu.Unlock()
|
||||
|
||||
var writeErr error
|
||||
if err != nil {
|
||||
writeErr = c.protocol.WriteError(msg.ID, &jsonrpc.ResponseError{
|
||||
Code: jsonrpc.CodeInternalError,
|
||||
Message: err.Error(),
|
||||
})
|
||||
} else {
|
||||
writeErr = c.protocol.WriteResponse(msg.ID, result)
|
||||
}
|
||||
|
||||
if writeErr != nil {
|
||||
panic(fmt.Sprintf("api: failed to write response: %v", writeErr))
|
||||
}
|
||||
}
|
||||
|
||||
// handleNotification processes an incoming notification.
|
||||
func (c *AsyncConn) handleNotification(ctx context.Context, msg *Message) {
|
||||
_ = c.handler.HandleNotification(ctx, msg.Method, msg.Params)
|
||||
}
|
||||
|
||||
// Call sends a request to the client and waits for a response.
|
||||
func (c *AsyncConn) Call(ctx context.Context, method string, params any) (json.Value, error) {
|
||||
// Create unique request ID
|
||||
id := jsonrpc.NewIDString(fmt.Sprintf("api%d", c.seq.Add(1)))
|
||||
|
||||
// Register response channel BEFORE sending request to avoid race
|
||||
responseChan := make(chan *Message, 1)
|
||||
c.pendingMu.Lock()
|
||||
c.pending[*id] = responseChan
|
||||
c.pendingMu.Unlock()
|
||||
|
||||
defer func() {
|
||||
c.pendingMu.Lock()
|
||||
defer c.pendingMu.Unlock()
|
||||
if ch, ok := c.pending[*id]; ok {
|
||||
close(ch)
|
||||
delete(c.pending, *id)
|
||||
}
|
||||
}()
|
||||
|
||||
// Send the request
|
||||
c.writeMu.Lock()
|
||||
err := c.protocol.WriteRequest(id, method, params)
|
||||
c.writeMu.Unlock()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
case resp := <-responseChan:
|
||||
if resp.Error != nil {
|
||||
return nil, fmt.Errorf("api: remote error [%d]: %s", resp.Error.Code, resp.Error.Message)
|
||||
}
|
||||
return resp.Result, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Notify sends a notification to the client (no response expected).
|
||||
func (c *AsyncConn) Notify(ctx context.Context, method string, params any) error {
|
||||
c.writeMu.Lock()
|
||||
defer c.writeMu.Unlock()
|
||||
return c.protocol.WriteNotification(method, params)
|
||||
}
|
||||
208
tools/tsgo/internal/api/conn_sync.go
Normal file
208
tools/tsgo/internal/api/conn_sync.go
Normal file
@@ -0,0 +1,208 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/json"
|
||||
"github.com/microsoft/typescript-go/internal/jsonrpc"
|
||||
)
|
||||
|
||||
// SyncConn manages bidirectional communication with synchronous request handling.
|
||||
// Requests are handled one at a time inline, and outgoing calls are serialized.
|
||||
type SyncConn struct {
|
||||
rwc io.ReadWriteCloser
|
||||
protocol Protocol
|
||||
handler Handler
|
||||
|
||||
// timing, when non-nil, accumulates the wall-clock time spent handling each
|
||||
// request. Clients retrieve the collected data via a getServerTiming request.
|
||||
timing *timingCollector
|
||||
|
||||
// mu serializes all protocol operations (reads and writes).
|
||||
// This ensures that concurrent calls from handler goroutines (e.g., project code
|
||||
// spawning goroutines that invoke filesystem callbacks) don't corrupt the stream.
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// NewSyncConn creates a new sync connection with the given transport and handler.
|
||||
func NewSyncConn(rwc io.ReadWriteCloser, protocol Protocol, handler Handler) *SyncConn {
|
||||
return &SyncConn{
|
||||
rwc: rwc,
|
||||
protocol: protocol,
|
||||
handler: handler,
|
||||
}
|
||||
}
|
||||
|
||||
// SetCollectTiming enables or disables per-request server processing-time
|
||||
// measurement. When enabled, the connection accumulates timing that clients can
|
||||
// retrieve via a getServerTiming request.
|
||||
func (c *SyncConn) SetCollectTiming(enabled bool) {
|
||||
if enabled {
|
||||
c.timing = newTimingCollector()
|
||||
} else {
|
||||
c.timing = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Run starts processing messages on the connection.
|
||||
// It blocks until the context is cancelled or an error occurs.
|
||||
func (c *SyncConn) Run(ctx context.Context) error {
|
||||
for {
|
||||
if ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
c.mu.Lock()
|
||||
msg, err := c.protocol.ReadMessage()
|
||||
c.mu.Unlock()
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if msg.IsRequest() {
|
||||
c.handleRequest(ctx, msg)
|
||||
} else if msg.IsNotification() {
|
||||
c.handleNotification(ctx, msg)
|
||||
} else {
|
||||
// Responses are not expected in the main loop - they are read inline by Call().
|
||||
return errors.New("api: unexpected response message in sync connection")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handleRequest processes an incoming request.
|
||||
func (c *SyncConn) handleRequest(ctx context.Context, msg *Message) {
|
||||
// Intercept the meta-requests for collected server timing before dispatching
|
||||
// to the handler, so they are answered directly and not themselves recorded.
|
||||
switch msg.Method {
|
||||
case string(MethodGetServerTiming):
|
||||
c.mu.Lock()
|
||||
writeErr := c.protocol.WriteResponse(msg.ID, serverTimingSnapshot(c.timing))
|
||||
c.mu.Unlock()
|
||||
if writeErr != nil {
|
||||
panic(fmt.Sprintf("api: failed to write server timing response: %v", writeErr))
|
||||
}
|
||||
return
|
||||
case string(MethodResetServerTiming):
|
||||
if c.timing != nil {
|
||||
c.timing.reset()
|
||||
}
|
||||
c.mu.Lock()
|
||||
writeErr := c.protocol.WriteResponse(msg.ID, nil)
|
||||
c.mu.Unlock()
|
||||
if writeErr != nil {
|
||||
panic(fmt.Sprintf("api: failed to write reset server timing response: %v", writeErr))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var result any
|
||||
var err error
|
||||
|
||||
start := time.Time{}
|
||||
if c.timing != nil {
|
||||
start = time.Now()
|
||||
}
|
||||
|
||||
// Recover from panics and convert to error response with stack trace
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
stack := string(debug.Stack())
|
||||
err = fmt.Errorf("panic: %v\n%s", r, stack)
|
||||
|
||||
c.mu.Lock()
|
||||
writeErr := c.protocol.WriteError(msg.ID, &jsonrpc.ResponseError{
|
||||
Code: jsonrpc.CodeInternalError,
|
||||
Message: err.Error(),
|
||||
})
|
||||
c.mu.Unlock()
|
||||
|
||||
if writeErr != nil {
|
||||
panic(fmt.Sprintf("api: failed to write panic error response: %v (original panic: %v)", writeErr, r))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
result, err = c.handler.HandleRequest(ctx, msg.Method, msg.Params)
|
||||
|
||||
if c.timing != nil {
|
||||
c.timing.record(msg.Method, time.Since(start))
|
||||
}
|
||||
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
var writeErr error
|
||||
if err != nil {
|
||||
writeErr = c.protocol.WriteError(msg.ID, &jsonrpc.ResponseError{
|
||||
Code: jsonrpc.CodeInternalError,
|
||||
Message: err.Error(),
|
||||
})
|
||||
} else {
|
||||
writeErr = c.protocol.WriteResponse(msg.ID, result)
|
||||
}
|
||||
|
||||
if writeErr != nil {
|
||||
panic(fmt.Sprintf("api: failed to write response: %v", writeErr))
|
||||
}
|
||||
}
|
||||
|
||||
// handleNotification processes an incoming notification.
|
||||
func (c *SyncConn) handleNotification(ctx context.Context, msg *Message) {
|
||||
_ = c.handler.HandleNotification(ctx, msg.Method, msg.Params)
|
||||
}
|
||||
|
||||
// Call sends a request to the client and waits for a response.
|
||||
// This method is safe to call from multiple goroutines - calls are serialized.
|
||||
func (c *SyncConn) Call(ctx context.Context, method string, params any) (json.Value, error) {
|
||||
// Serialize all Call operations. This is critical because:
|
||||
// 1. The msgpack protocol uses method names as response IDs
|
||||
// 2. The handler code (project internals) may spawn goroutines that call
|
||||
// filesystem callbacks concurrently
|
||||
// 3. We need to ensure write/read pairs are atomic
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
id := jsonrpc.NewIDString(method)
|
||||
|
||||
if err := c.protocol.WriteRequest(id, method, params); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
|
||||
// Read the response inline.
|
||||
msg, err := c.protocol.ReadMessage()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if msg.IsResponse() && msg.ID != nil && msg.ID.String() == method {
|
||||
if msg.Error != nil {
|
||||
return nil, fmt.Errorf("api: remote error [%d]: %s", msg.Error.Code, msg.Error.Message)
|
||||
}
|
||||
return msg.Result, nil
|
||||
}
|
||||
|
||||
// Unexpected message while waiting for response
|
||||
return nil, fmt.Errorf("api: unexpected message while waiting for %q response", method)
|
||||
}
|
||||
|
||||
// Notify sends a notification to the client (no response expected).
|
||||
func (c *SyncConn) Notify(ctx context.Context, method string, params any) error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.protocol.WriteNotification(method, params)
|
||||
}
|
||||
381
tools/tsgo/internal/api/encoder/decoder.go
Normal file
381
tools/tsgo/internal/api/encoder/decoder.go
Normal file
@@ -0,0 +1,381 @@
|
||||
package encoder
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/tspath"
|
||||
)
|
||||
|
||||
// astDecoder reconstructs real *ast.Node objects from binary-encoded data.
|
||||
type astDecoder struct {
|
||||
raw []byte
|
||||
strTable uint32
|
||||
strData uint32
|
||||
extData uint32
|
||||
nodeOff uint32
|
||||
nodeCount int
|
||||
factory *ast.NodeFactory
|
||||
childBuf []int
|
||||
// Single Go string covering all string data; substrings are zero-alloc slices.
|
||||
allStringData string
|
||||
// Arena for batch-allocating []*ast.Node slices used by NodeLists.
|
||||
nodeArena []*ast.Node
|
||||
// Results
|
||||
nodes []*ast.Node
|
||||
nodeLists []*ast.NodeList
|
||||
}
|
||||
|
||||
// DecodeSourceFile decodes binary-encoded data into an *ast.SourceFile.
|
||||
func DecodeSourceFile(data []byte) (*ast.SourceFile, error) {
|
||||
node, err := DecodeNodes(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if node.Kind != ast.KindSourceFile {
|
||||
return nil, fmt.Errorf("expected SourceFile root, got %v", node.Kind)
|
||||
}
|
||||
return node.AsSourceFile(), nil
|
||||
}
|
||||
|
||||
// DecodeNodes decodes binary-encoded AST data into a tree of *ast.Node objects.
|
||||
func DecodeNodes(data []byte) (*ast.Node, error) {
|
||||
d, err := newASTDecoder(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.decode()
|
||||
}
|
||||
|
||||
func newASTDecoder(data []byte) (*astDecoder, error) {
|
||||
if len(data) < HeaderSize {
|
||||
return nil, fmt.Errorf("data too short for header: %d bytes", len(data))
|
||||
}
|
||||
version := data[HeaderOffsetMetadata+3]
|
||||
if version != ProtocolVersion {
|
||||
return nil, fmt.Errorf("unsupported protocol version %d (expected %d)", version, ProtocolVersion)
|
||||
}
|
||||
|
||||
strTable := readLE32(data, HeaderOffsetStringOffsets)
|
||||
strData := readLE32(data, HeaderOffsetStringData)
|
||||
extData := readLE32(data, HeaderOffsetExtendedData)
|
||||
nodeOff := readLE32(data, HeaderOffsetNodes)
|
||||
|
||||
dataLen := uint32(len(data))
|
||||
|
||||
// Validate that all offsets are within the buffer.
|
||||
if strTable > dataLen || strData > dataLen || extData > dataLen || nodeOff > dataLen {
|
||||
return nil, fmt.Errorf("invalid AST header offsets: offsets exceed data length (%d)", dataLen)
|
||||
}
|
||||
|
||||
// Validate monotonic non-decreasing order of regions.
|
||||
if !(strTable <= strData && strData <= extData && extData <= nodeOff) {
|
||||
return nil, fmt.Errorf("invalid AST header offsets: expected strTable <= strData <= extData <= nodeOff (got %d, %d, %d, %d)", strTable, strData, extData, nodeOff)
|
||||
}
|
||||
|
||||
d := &astDecoder{
|
||||
raw: data,
|
||||
strTable: strTable,
|
||||
strData: strData,
|
||||
extData: extData,
|
||||
nodeOff: nodeOff,
|
||||
factory: ast.NewNodeFactory(ast.NodeFactoryHooks{}),
|
||||
}
|
||||
|
||||
d.nodeCount = (len(data) - int(d.nodeOff)) / NodeSize
|
||||
|
||||
// Convert entire string data region to a single Go string upfront.
|
||||
// Substringing a Go string shares the backing array, so subsequent
|
||||
// getString calls produce substrings with zero allocations.
|
||||
d.allStringData = string(data[d.strData:])
|
||||
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// allocNodeSlice returns a zero-length slice with the given capacity, backed by
|
||||
// the pre-allocated nodeArena. This avoids a heap allocation per NodeList.
|
||||
func (d *astDecoder) allocNodeSlice(capacity int) []*ast.Node {
|
||||
start := len(d.nodeArena)
|
||||
d.nodeArena = d.nodeArena[:start+capacity]
|
||||
return d.nodeArena[start : start : start+capacity]
|
||||
}
|
||||
|
||||
// nodeField reads a uint32 field from node i at the given field offset.
|
||||
func (d *astDecoder) nodeField(i int, field int) uint32 {
|
||||
return readLE32(d.raw, int(d.nodeOff)+i*NodeSize+field)
|
||||
}
|
||||
|
||||
func (d *astDecoder) getString(idx uint32) string {
|
||||
offBase := int(d.strTable) + int(idx)*4
|
||||
start := readLE32(d.raw, offBase)
|
||||
end := readLE32(d.raw, offBase+4)
|
||||
return d.allStringData[start:end]
|
||||
}
|
||||
|
||||
// collectChildren returns indices of direct children of node i.
|
||||
// The returned slice is reused across calls; callers must not retain it.
|
||||
func (d *astDecoder) collectChildren(i int) []int {
|
||||
d.childBuf = d.childBuf[:0]
|
||||
if i+1 >= d.nodeCount {
|
||||
return d.childBuf
|
||||
}
|
||||
firstChild := i + 1
|
||||
if d.nodeField(firstChild, NodeOffsetParent) != uint32(i) {
|
||||
return d.childBuf
|
||||
}
|
||||
d.childBuf = append(d.childBuf, firstChild)
|
||||
next := int(d.nodeField(firstChild, NodeOffsetNext))
|
||||
for next != 0 {
|
||||
d.childBuf = append(d.childBuf, next)
|
||||
next = int(d.nodeField(next, NodeOffsetNext))
|
||||
}
|
||||
return d.childBuf
|
||||
}
|
||||
|
||||
func (d *astDecoder) decode() (*ast.Node, error) {
|
||||
if d.nodeCount < 2 {
|
||||
return nil, errors.New("no nodes to decode")
|
||||
}
|
||||
|
||||
d.nodes = make([]*ast.Node, d.nodeCount)
|
||||
d.nodeLists = make([]*ast.NodeList, d.nodeCount)
|
||||
// Pre-allocate arena for NodeList child slices. Each node can appear as a
|
||||
// child at most once, so nodeCount is an upper bound on total child pointers.
|
||||
d.nodeArena = make([]*ast.Node, 0, d.nodeCount)
|
||||
|
||||
// Process bottom-up so children exist before parents.
|
||||
for i := d.nodeCount - 1; i >= 1; i-- {
|
||||
kind := d.nodeField(i, NodeOffsetKind)
|
||||
pos := d.nodeField(i, NodeOffsetPos)
|
||||
end := d.nodeField(i, NodeOffsetEnd)
|
||||
data := d.nodeField(i, NodeOffsetData)
|
||||
childIndices := d.collectChildren(i)
|
||||
|
||||
if kind == SyntaxKindNodeList {
|
||||
childNodes := d.allocNodeSlice(len(childIndices))
|
||||
for _, ci := range childIndices {
|
||||
if d.nodes[ci] != nil {
|
||||
childNodes = append(childNodes, d.nodes[ci])
|
||||
}
|
||||
}
|
||||
nl := d.factory.NewNodeList(childNodes)
|
||||
nl.Loc = core.NewTextRange(int(pos), int(end))
|
||||
d.nodeLists[i] = nl
|
||||
continue
|
||||
}
|
||||
|
||||
node, err := d.createNode(ast.Kind(kind), data, childIndices)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("at node %d (kind %v): %w", i, ast.Kind(kind), err)
|
||||
}
|
||||
node.Loc = core.NewTextRange(int(pos), int(end))
|
||||
node.Flags = ast.NodeFlags(d.nodeField(i, NodeOffsetFlags))
|
||||
d.nodes[i] = node
|
||||
}
|
||||
|
||||
return d.nodes[1], nil
|
||||
}
|
||||
|
||||
// getModifierList creates a *ast.ModifierList from a child index that is a NodeList.
|
||||
func (d *astDecoder) getModifierList(ci int) *ast.ModifierList {
|
||||
nl := d.nodeLists[ci]
|
||||
if nl == nil {
|
||||
return nil
|
||||
}
|
||||
ml := d.factory.NewModifierList(nl.Nodes)
|
||||
ml.Loc = nl.Loc
|
||||
return ml
|
||||
}
|
||||
|
||||
// childIterator helps walk through children based on a bitmask.
|
||||
type childIterator struct {
|
||||
indices []int
|
||||
pos int
|
||||
}
|
||||
|
||||
func newChildIter(indices []int) childIterator {
|
||||
return childIterator{indices: indices}
|
||||
}
|
||||
|
||||
// next returns the index of the next child, advancing the position.
|
||||
func (it *childIterator) next() int {
|
||||
if it.pos >= len(it.indices) {
|
||||
return 0
|
||||
}
|
||||
ci := it.indices[it.pos]
|
||||
it.pos++
|
||||
return ci
|
||||
}
|
||||
|
||||
// nextIf returns the index of the next child if the corresponding mask bit is set.
|
||||
func (it *childIterator) nextIf(mask uint8, bit uint8) int {
|
||||
if mask&(1<<bit) == 0 {
|
||||
return 0
|
||||
}
|
||||
return it.next()
|
||||
}
|
||||
|
||||
func (d *astDecoder) nodeAt(ci int) *ast.Node {
|
||||
if ci == 0 {
|
||||
return nil
|
||||
}
|
||||
return d.nodes[ci]
|
||||
}
|
||||
|
||||
func (d *astDecoder) nodeListAt(ci int) *ast.NodeList {
|
||||
if ci == 0 {
|
||||
return nil
|
||||
}
|
||||
return d.nodeLists[ci]
|
||||
}
|
||||
|
||||
func (d *astDecoder) modifierListAt(ci int) *ast.ModifierList {
|
||||
if ci == 0 {
|
||||
return nil
|
||||
}
|
||||
return d.getModifierList(ci)
|
||||
}
|
||||
|
||||
func (d *astDecoder) createNode(kind ast.Kind, data uint32, childIndices []int) (*ast.Node, error) {
|
||||
dataType := data & NodeDataTypeMask
|
||||
commonData := uint8((data >> 24) & 0x3f)
|
||||
|
||||
switch dataType {
|
||||
case NodeDataTypeString:
|
||||
return d.createStringNode(kind, data, commonData)
|
||||
case NodeDataTypeExtendedData:
|
||||
return d.createExtendedNode(kind, data, childIndices, commonData)
|
||||
default:
|
||||
return d.createChildrenNode(kind, data, childIndices, commonData)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *astDecoder) decodeExtendedData_SourceFile(data uint32, childIndices []int, commonData uint8) (*ast.Node, error) {
|
||||
extOff := int(d.extData) + int(data&NodeDataStringIndexMask)
|
||||
|
||||
textIdx := readLE32(d.raw, extOff)
|
||||
fileNameIdx := readLE32(d.raw, extOff+4)
|
||||
pathIdx := readLE32(d.raw, extOff+8)
|
||||
text := d.getString(textIdx)
|
||||
fileName := d.getString(fileNameIdx)
|
||||
path := d.getString(pathIdx)
|
||||
|
||||
// Recover parse options from header.
|
||||
parseOpts := readLE32(d.raw, HeaderOffsetParseOptions)
|
||||
opts := ast.SourceFileParseOptions{
|
||||
FileName: fileName,
|
||||
Path: tspath.Path(path),
|
||||
ExternalModuleIndicatorOptions: ast.ExternalModuleIndicatorOptions{
|
||||
JSX: parseOpts&1 != 0,
|
||||
Force: parseOpts&2 != 0,
|
||||
},
|
||||
}
|
||||
|
||||
// Collect children: first is statements NodeList, second is EndOfFile.
|
||||
var stmts *ast.NodeList
|
||||
var endOfFile *ast.Node
|
||||
for _, ci := range childIndices {
|
||||
if d.nodeField(ci, NodeOffsetKind) == SyntaxKindNodeList {
|
||||
stmts = d.nodeListAt(ci)
|
||||
} else if d.nodes[ci] != nil && d.nodes[ci].Kind == ast.KindEndOfFile {
|
||||
endOfFile = d.nodes[ci]
|
||||
}
|
||||
}
|
||||
if endOfFile == nil {
|
||||
endOfFile = d.factory.NewToken(ast.KindEndOfFile)
|
||||
}
|
||||
return d.factory.NewSourceFile(opts, text, stmts, endOfFile), nil
|
||||
}
|
||||
|
||||
func (d *astDecoder) decodeExtendedData_TemplateHead(data uint32, childIndices []int, commonData uint8) (*ast.Node, error) {
|
||||
extOff := int(d.extData) + int(data&NodeDataStringIndexMask)
|
||||
textIdx := readLE32(d.raw, extOff)
|
||||
rawTextIdx := readLE32(d.raw, extOff+4)
|
||||
flags := readLE32(d.raw, extOff+8)
|
||||
return d.factory.NewTemplateHead(d.getString(textIdx), d.getString(rawTextIdx), ast.TokenFlags(flags)), nil
|
||||
}
|
||||
|
||||
func (d *astDecoder) decodeExtendedData_TemplateMiddle(data uint32, childIndices []int, commonData uint8) (*ast.Node, error) {
|
||||
extOff := int(d.extData) + int(data&NodeDataStringIndexMask)
|
||||
textIdx := readLE32(d.raw, extOff)
|
||||
rawTextIdx := readLE32(d.raw, extOff+4)
|
||||
flags := readLE32(d.raw, extOff+8)
|
||||
return d.factory.NewTemplateMiddle(d.getString(textIdx), d.getString(rawTextIdx), ast.TokenFlags(flags)), nil
|
||||
}
|
||||
|
||||
func (d *astDecoder) decodeExtendedData_TemplateTail(data uint32, childIndices []int, commonData uint8) (*ast.Node, error) {
|
||||
extOff := int(d.extData) + int(data&NodeDataStringIndexMask)
|
||||
textIdx := readLE32(d.raw, extOff)
|
||||
rawTextIdx := readLE32(d.raw, extOff+4)
|
||||
flags := readLE32(d.raw, extOff+8)
|
||||
return d.factory.NewTemplateTail(d.getString(textIdx), d.getString(rawTextIdx), ast.TokenFlags(flags)), nil
|
||||
}
|
||||
|
||||
func (d *astDecoder) singleChild(childIndices []int) *ast.Node {
|
||||
if len(childIndices) == 0 {
|
||||
return nil
|
||||
}
|
||||
return d.nodes[childIndices[0]]
|
||||
}
|
||||
|
||||
func (d *astDecoder) singleNodeListChild(childIndices []int) *ast.NodeList {
|
||||
if len(childIndices) == 0 {
|
||||
return nil
|
||||
}
|
||||
return d.nodeLists[childIndices[0]]
|
||||
}
|
||||
|
||||
func readLE32(data []byte, offset int) uint32 {
|
||||
if offset < 0 || offset+4 > len(data) {
|
||||
return 0
|
||||
}
|
||||
return binary.LittleEndian.Uint32(data[offset : offset+4])
|
||||
}
|
||||
|
||||
// Hand-written commonData decoding functions. Each extracts the original values
|
||||
// from the 6-bit commonData that were packed by the corresponding
|
||||
// getNodeCommonData_* function.
|
||||
|
||||
func decodeNodeCommonData_SyntheticExpression(_ uint8) (any, bool) {
|
||||
panic("SyntheticExpression should never be decoded")
|
||||
}
|
||||
|
||||
// Hand-written extended data decoding functions for literal nodes.
|
||||
|
||||
func (d *astDecoder) decodeExtendedData_StringLiteral(data uint32, _ []int, _ uint8) (*ast.Node, error) {
|
||||
extOff := int(d.extData) + int(data&NodeDataStringIndexMask)
|
||||
textIdx := readLE32(d.raw, extOff)
|
||||
flags := readLE32(d.raw, extOff+4)
|
||||
return d.factory.NewStringLiteral(d.getString(textIdx), ast.TokenFlags(flags)), nil
|
||||
}
|
||||
|
||||
func (d *astDecoder) decodeExtendedData_NumericLiteral(data uint32, _ []int, _ uint8) (*ast.Node, error) {
|
||||
extOff := int(d.extData) + int(data&NodeDataStringIndexMask)
|
||||
textIdx := readLE32(d.raw, extOff)
|
||||
flags := readLE32(d.raw, extOff+4)
|
||||
return d.factory.NewNumericLiteral(d.getString(textIdx), ast.TokenFlags(flags)), nil
|
||||
}
|
||||
|
||||
func (d *astDecoder) decodeExtendedData_BigIntLiteral(data uint32, _ []int, _ uint8) (*ast.Node, error) {
|
||||
extOff := int(d.extData) + int(data&NodeDataStringIndexMask)
|
||||
textIdx := readLE32(d.raw, extOff)
|
||||
flags := readLE32(d.raw, extOff+4)
|
||||
return d.factory.NewBigIntLiteral(d.getString(textIdx), ast.TokenFlags(flags)), nil
|
||||
}
|
||||
|
||||
func (d *astDecoder) decodeExtendedData_RegularExpressionLiteral(data uint32, _ []int, _ uint8) (*ast.Node, error) {
|
||||
extOff := int(d.extData) + int(data&NodeDataStringIndexMask)
|
||||
textIdx := readLE32(d.raw, extOff)
|
||||
flags := readLE32(d.raw, extOff+4)
|
||||
return d.factory.NewRegularExpressionLiteral(d.getString(textIdx), ast.TokenFlags(flags)), nil
|
||||
}
|
||||
|
||||
func (d *astDecoder) decodeExtendedData_NoSubstitutionTemplateLiteral(data uint32, _ []int, _ uint8) (*ast.Node, error) {
|
||||
extOff := int(d.extData) + int(data&NodeDataStringIndexMask)
|
||||
textIdx := readLE32(d.raw, extOff)
|
||||
flags := readLE32(d.raw, extOff+4)
|
||||
return d.factory.NewNoSubstitutionTemplateLiteral(d.getString(textIdx), ast.TokenFlags(flags)), nil
|
||||
}
|
||||
1140
tools/tsgo/internal/api/encoder/decoder_generated.go
Normal file
1140
tools/tsgo/internal/api/encoder/decoder_generated.go
Normal file
File diff suppressed because it is too large
Load Diff
450
tools/tsgo/internal/api/encoder/decoder_test.go
Normal file
450
tools/tsgo/internal/api/encoder/decoder_test.go
Normal file
@@ -0,0 +1,450 @@
|
||||
package encoder_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/api/encoder"
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/parser"
|
||||
"github.com/microsoft/typescript-go/internal/repo"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func parseSourceFile(code string) *ast.SourceFile {
|
||||
return parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/test.ts",
|
||||
Path: "/test.ts",
|
||||
}, code, core.ScriptKindTS)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_Basic(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("let x = 1;")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, decoded.AsNode().Kind, ast.KindSourceFile)
|
||||
assert.Equal(t, decoded.FileName(), "/test.ts")
|
||||
assert.Equal(t, decoded.Text(), "let x = 1;")
|
||||
assert.Assert(t, decoded.Statements != nil)
|
||||
assert.Assert(t, decoded.EndOfFileToken != nil)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_Statements(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("let a = 1;\nlet b = 2;\nlet c = 3;")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(decoded.Statements.Nodes), 3)
|
||||
for i, stmt := range decoded.Statements.Nodes {
|
||||
assert.Equal(t, stmt.Kind, ast.KindVariableStatement, "statement %d", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_VariableDeclaration(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("let x = 1;")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
varStmt := decoded.Statements.Nodes[0].AsVariableStatement()
|
||||
assert.Assert(t, varStmt.DeclarationList != nil)
|
||||
declList := varStmt.DeclarationList.AsVariableDeclarationList()
|
||||
assert.Assert(t, declList.Declarations != nil)
|
||||
assert.Equal(t, len(declList.Declarations.Nodes), 1)
|
||||
|
||||
decl := declList.Declarations.Nodes[0].AsVariableDeclaration()
|
||||
assert.Equal(t, decl.Name().Kind, ast.KindIdentifier)
|
||||
assert.Equal(t, decl.Name().AsIdentifier().Text, "x")
|
||||
assert.Assert(t, decl.Initializer != nil)
|
||||
assert.Equal(t, decl.Initializer.Kind, ast.KindNumericLiteral)
|
||||
assert.Equal(t, decl.Initializer.AsNumericLiteral().Text, "1")
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_VariableDeclarationListFlags(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
code string
|
||||
expected ast.NodeFlags
|
||||
}{
|
||||
{"const", "const x = 1;", ast.NodeFlagsConst},
|
||||
{"let", "let x = 1;", ast.NodeFlagsLet},
|
||||
{"var", "var x = 1;", ast.NodeFlagsNone},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile(tt.code)
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
declList := decoded.Statements.Nodes[0].AsVariableStatement().DeclarationList.AsVariableDeclarationList()
|
||||
got := declList.Flags & (ast.NodeFlagsLet | ast.NodeFlagsConst)
|
||||
assert.Equal(t, got, tt.expected, "flags for %q: got %d, want %d", tt.code, got, tt.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_FunctionDeclaration(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("function add(a: number, b: number): number { return a + b; }")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
funcDecl := decoded.Statements.Nodes[0].AsFunctionDeclaration()
|
||||
assert.Assert(t, funcDecl.Name() != nil)
|
||||
assert.Equal(t, funcDecl.Name().AsIdentifier().Text, "add")
|
||||
assert.Assert(t, funcDecl.Parameters != nil)
|
||||
assert.Equal(t, len(funcDecl.Parameters.Nodes), 2)
|
||||
assert.Assert(t, funcDecl.Type != nil)
|
||||
assert.Assert(t, funcDecl.Body != nil)
|
||||
|
||||
param0 := funcDecl.Parameters.Nodes[0].AsParameterDeclaration()
|
||||
assert.Equal(t, param0.Name().AsIdentifier().Text, "a")
|
||||
assert.Assert(t, param0.Type != nil)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_ImportDeclaration(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile(`import { bar } from "bar";`)
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
imp := decoded.Statements.Nodes[0].AsImportDeclaration()
|
||||
assert.Assert(t, imp.ImportClause != nil)
|
||||
assert.Assert(t, imp.ModuleSpecifier != nil)
|
||||
assert.Equal(t, imp.ModuleSpecifier.AsStringLiteral().Text, "bar")
|
||||
|
||||
clause := imp.ImportClause.AsImportClause()
|
||||
assert.Assert(t, clause.NamedBindings != nil)
|
||||
namedImports := clause.NamedBindings.AsNamedImports()
|
||||
assert.Assert(t, namedImports.Elements != nil)
|
||||
assert.Equal(t, len(namedImports.Elements.Nodes), 1)
|
||||
spec := namedImports.Elements.Nodes[0].AsImportSpecifier()
|
||||
assert.Equal(t, spec.Name().AsIdentifier().Text, "bar")
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_IfStatement(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("if (true) { } else { }")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
ifStmt := decoded.Statements.Nodes[0].AsIfStatement()
|
||||
assert.Assert(t, ifStmt.Expression != nil)
|
||||
assert.Assert(t, ifStmt.ThenStatement != nil)
|
||||
assert.Assert(t, ifStmt.ElseStatement != nil)
|
||||
assert.Equal(t, ifStmt.ThenStatement.Kind, ast.KindBlock)
|
||||
assert.Equal(t, ifStmt.ElseStatement.Kind, ast.KindBlock)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_TemplateExpression(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("let x = `hello ${name} world`;")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
varDecl := decoded.Statements.Nodes[0].AsVariableStatement().DeclarationList.AsVariableDeclarationList().Declarations.Nodes[0].AsVariableDeclaration()
|
||||
tmplExpr := varDecl.Initializer.AsTemplateExpression()
|
||||
assert.Assert(t, tmplExpr.Head != nil)
|
||||
assert.Equal(t, tmplExpr.Head.AsTemplateHead().Text, "hello ")
|
||||
assert.Assert(t, tmplExpr.TemplateSpans != nil)
|
||||
assert.Equal(t, len(tmplExpr.TemplateSpans.Nodes), 1)
|
||||
|
||||
span := tmplExpr.TemplateSpans.Nodes[0].AsTemplateSpan()
|
||||
assert.Assert(t, span.Expression != nil)
|
||||
assert.Equal(t, span.Expression.Kind, ast.KindIdentifier)
|
||||
assert.Assert(t, span.Literal != nil)
|
||||
assert.Equal(t, span.Literal.AsTemplateTail().Text, " world")
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_ExportModifier(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("export function foo() {}")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
funcDecl := decoded.Statements.Nodes[0].AsFunctionDeclaration()
|
||||
assert.Assert(t, funcDecl.Modifiers() != nil)
|
||||
assert.Equal(t, len(funcDecl.Modifiers().Nodes), 1)
|
||||
assert.Equal(t, funcDecl.Modifiers().Nodes[0].Kind, ast.KindExportKeyword)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_Positions(t *testing.T) {
|
||||
t.Parallel()
|
||||
code := "let x = 1;"
|
||||
sf := parseSourceFile(code)
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, decoded.AsNode().Pos(), 0)
|
||||
assert.Equal(t, decoded.AsNode().End(), len(code))
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_ClassDeclaration(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("class Foo { bar(): void {} }")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
classDecl := decoded.Statements.Nodes[0].AsClassDeclaration()
|
||||
assert.Assert(t, classDecl.Name() != nil)
|
||||
assert.Equal(t, classDecl.Name().AsIdentifier().Text, "Foo")
|
||||
assert.Assert(t, classDecl.Members != nil)
|
||||
assert.Equal(t, len(classDecl.Members.Nodes), 1)
|
||||
assert.Equal(t, classDecl.Members.Nodes[0].Kind, ast.KindMethodDeclaration)
|
||||
}
|
||||
|
||||
func TestDecodeNodes_SubtreeRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("function greet(name: string) { return `Hello, ${name}!`; }")
|
||||
|
||||
var funcNode *ast.Node
|
||||
visitor := &ast.NodeVisitor{}
|
||||
visitor.Visit = func(node *ast.Node) *ast.Node {
|
||||
if node.Kind == ast.KindFunctionDeclaration && funcNode == nil {
|
||||
funcNode = node
|
||||
}
|
||||
return node
|
||||
}
|
||||
visitor.VisitEachChild(sf.AsNode())
|
||||
assert.Assert(t, funcNode != nil)
|
||||
|
||||
buf, _, err := encoder.EncodeNode(funcNode, sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeNodes(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, decoded.Kind, ast.KindFunctionDeclaration)
|
||||
funcDecl := decoded.AsFunctionDeclaration()
|
||||
assert.Assert(t, funcDecl.Name() != nil)
|
||||
assert.Equal(t, funcDecl.Name().AsIdentifier().Text, "greet")
|
||||
assert.Assert(t, funcDecl.Parameters != nil)
|
||||
assert.Equal(t, len(funcDecl.Parameters.Nodes), 1)
|
||||
assert.Assert(t, funcDecl.Body != nil)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_BinaryExpression(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("let x = 1 + 2;")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decl := decoded.Statements.Nodes[0].AsVariableStatement().DeclarationList.AsVariableDeclarationList().Declarations.Nodes[0].AsVariableDeclaration()
|
||||
binExpr := decl.Initializer.AsBinaryExpression()
|
||||
assert.Assert(t, binExpr.Left != nil)
|
||||
assert.Assert(t, binExpr.Right != nil)
|
||||
assert.Assert(t, binExpr.OperatorToken != nil)
|
||||
assert.Equal(t, binExpr.Left.Kind, ast.KindNumericLiteral)
|
||||
assert.Equal(t, binExpr.Right.Kind, ast.KindNumericLiteral)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_KeywordExpressions(t *testing.T) {
|
||||
t.Parallel()
|
||||
// "this" must decode as KeywordExpression, not Token, or the printer panics
|
||||
sf := parseSourceFile("const x = this;")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Navigate: const x = this -> VariableStatement -> declaration -> initializer
|
||||
decl := decoded.Statements.Nodes[0].AsVariableStatement().DeclarationList.AsVariableDeclarationList().Declarations.Nodes[0].AsVariableDeclaration()
|
||||
thisExpr := decl.Initializer
|
||||
assert.Equal(t, thisExpr.Kind, ast.KindThisKeyword)
|
||||
// This would panic if decoded as Token instead of KeywordExpression
|
||||
assert.Assert(t, thisExpr.AsKeywordExpression() != nil)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_EmptyModuleBlock(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("namespace N { }")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Navigate: namespace N { } -> ModuleDeclaration -> ModuleBlock
|
||||
mod := decoded.Statements.Nodes[0].AsModuleDeclaration()
|
||||
assert.Assert(t, mod.Body != nil)
|
||||
block := mod.Body.AsModuleBlock()
|
||||
// Statements must be non-nil even when empty, otherwise the printer panics
|
||||
assert.Assert(t, block.Statements != nil)
|
||||
assert.Equal(t, len(block.Statements.Nodes), 0)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_EmptyBlockAndParams(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Empty blocks and parameter lists must decode with non-nil NodeLists (not nil),
|
||||
// matching parser behavior. Previously the decoder left them nil, crashing the printer.
|
||||
sf := parseSourceFile("function foo() {}")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
funcDecl := decoded.Statements.Nodes[0].AsFunctionDeclaration()
|
||||
assert.Assert(t, funcDecl.Parameters != nil, "FunctionDeclaration.Parameters must be non-nil for foo()")
|
||||
assert.Equal(t, len(funcDecl.Parameters.Nodes), 0)
|
||||
assert.Assert(t, funcDecl.Body != nil)
|
||||
block := funcDecl.Body.AsBlock()
|
||||
assert.Assert(t, block.Statements != nil, "Block.Statements must be non-nil for empty blocks")
|
||||
assert.Equal(t, len(block.Statements.Nodes), 0)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_ArrowFunctionEmptyParams(t *testing.T) {
|
||||
t.Parallel()
|
||||
// `() => {}` must decode with non-nil Parameters (empty NodeList),
|
||||
// matching parser behavior. Previously the decoder left it nil, crashing the printer.
|
||||
sf := parseSourceFile("const f = () => {};")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decl := decoded.Statements.Nodes[0].AsVariableStatement().DeclarationList.AsVariableDeclarationList().Declarations.Nodes[0].AsVariableDeclaration()
|
||||
arrow := decl.Initializer.AsArrowFunction()
|
||||
assert.Assert(t, arrow.Parameters != nil, "ArrowFunction.Parameters must be non-nil for () => {}")
|
||||
assert.Equal(t, len(arrow.Parameters.Nodes), 0)
|
||||
assert.Assert(t, arrow.Body != nil)
|
||||
block := arrow.Body.AsBlock()
|
||||
assert.Assert(t, block.Statements != nil, "Block.Statements must be non-nil for empty body")
|
||||
assert.Equal(t, len(block.Statements.Nodes), 0)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_FunctionExpressionEmptyParams(t *testing.T) {
|
||||
t.Parallel()
|
||||
// `function() {}` must decode with non-nil Parameters (empty NodeList).
|
||||
sf := parseSourceFile("const f = function() {};")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decl := decoded.Statements.Nodes[0].AsVariableStatement().DeclarationList.AsVariableDeclarationList().Declarations.Nodes[0].AsVariableDeclaration()
|
||||
funcExpr := decl.Initializer.AsFunctionExpression()
|
||||
assert.Assert(t, funcExpr.Parameters != nil, "FunctionExpression.Parameters must be non-nil for function() {}")
|
||||
assert.Equal(t, len(funcExpr.Parameters.Nodes), 0)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_PostfixUnaryOperator(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("let i = 0; i++;")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
exprStmt := decoded.Statements.Nodes[1].AsExpressionStatement()
|
||||
postfix := exprStmt.Expression.AsPostfixUnaryExpression()
|
||||
assert.Equal(t, postfix.Operator, ast.KindPlusPlusToken)
|
||||
assert.Equal(t, postfix.Operand.Kind, ast.KindIdentifier)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_PrefixUnaryOperator(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("let x = true; !x;")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
exprStmt := decoded.Statements.Nodes[1].AsExpressionStatement()
|
||||
prefix := exprStmt.Expression.AsPrefixUnaryExpression()
|
||||
assert.Equal(t, prefix.Operator, ast.KindExclamationToken)
|
||||
assert.Equal(t, prefix.Operand.Kind, ast.KindIdentifier)
|
||||
}
|
||||
|
||||
func TestDecodeSourceFile_PostfixDecrement(t *testing.T) {
|
||||
t.Parallel()
|
||||
sf := parseSourceFile("let n = 5; n--;")
|
||||
buf, _, err := encoder.EncodeSourceFile(sf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
decoded, err := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(t, err)
|
||||
|
||||
exprStmt := decoded.Statements.Nodes[1].AsExpressionStatement()
|
||||
postfix := exprStmt.Expression.AsPostfixUnaryExpression()
|
||||
assert.Equal(t, postfix.Operator, ast.KindMinusMinusToken)
|
||||
}
|
||||
|
||||
func BenchmarkDecodeSourceFile(b *testing.B) {
|
||||
repo.SkipIfNoTypeScriptSubmodule(b)
|
||||
filePath := filepath.Join(repo.TypeScriptSubmodulePath(), "src/compiler/checker.ts")
|
||||
fileContent, err := os.ReadFile(filePath)
|
||||
assert.NilError(b, err)
|
||||
code := string(fileContent)
|
||||
sourceFile := parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/checker.ts",
|
||||
Path: "/checker.ts",
|
||||
}, code, core.ScriptKindTS)
|
||||
|
||||
buf, _, err := encoder.EncodeSourceFile(sourceFile)
|
||||
assert.NilError(b, err)
|
||||
|
||||
b.Run("parse", func(b *testing.B) {
|
||||
for b.Loop() {
|
||||
parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/checker.ts",
|
||||
Path: "/checker.ts",
|
||||
}, code, core.ScriptKindTS)
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("decode", func(b *testing.B) {
|
||||
for b.Loop() {
|
||||
_, decodeErr := encoder.DecodeSourceFile(buf)
|
||||
assert.NilError(b, decodeErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
844
tools/tsgo/internal/api/encoder/encoder.go
Normal file
844
tools/tsgo/internal/api/encoder/encoder.go
Normal file
@@ -0,0 +1,844 @@
|
||||
package encoder
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/zeebo/xxh3"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if ast.KindLastUnaryOperator > 0x3f {
|
||||
panic(fmt.Sprintf("KindLastUnaryOperator (%d) exceeds the 6-bit commonData capacity (max 63)", ast.KindLastUnaryOperator))
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
NodeOffsetKind = iota * 4
|
||||
NodeOffsetPos
|
||||
NodeOffsetEnd
|
||||
NodeOffsetNext
|
||||
NodeOffsetParent
|
||||
NodeOffsetData
|
||||
NodeOffsetFlags
|
||||
// NodeSize is the number of bytes that represents a single node in the encoded format.
|
||||
NodeSize
|
||||
)
|
||||
|
||||
const (
|
||||
NodeDataTypeChildren uint32 = iota << 30
|
||||
NodeDataTypeString
|
||||
NodeDataTypeExtendedData
|
||||
)
|
||||
|
||||
const (
|
||||
NodeDataTypeMask uint32 = 0xc0_00_00_00
|
||||
NodeDataChildMask uint32 = 0x00_00_00_ff
|
||||
NodeDataStringIndexMask uint32 = 0x00_ff_ff_ff
|
||||
)
|
||||
|
||||
const (
|
||||
SyntaxKindNodeList uint32 = 1<<32 - 1
|
||||
)
|
||||
|
||||
const (
|
||||
HeaderOffsetMetadata = iota * 4
|
||||
HeaderOffsetHashLo0
|
||||
HeaderOffsetHashLo1
|
||||
HeaderOffsetHashHi0
|
||||
HeaderOffsetHashHi1
|
||||
HeaderOffsetParseOptions
|
||||
HeaderOffsetStringOffsets
|
||||
HeaderOffsetStringData
|
||||
HeaderOffsetExtendedData
|
||||
HeaderOffsetStructuredData
|
||||
HeaderOffsetNodes
|
||||
HeaderSize
|
||||
)
|
||||
|
||||
const (
|
||||
ProtocolVersion uint8 = 5
|
||||
)
|
||||
|
||||
// Source File Binary Format
|
||||
// =========================
|
||||
//
|
||||
// The following defines a protocol for serializing TypeScript SourceFile objects to a compact binary format. All integer
|
||||
// values are little-endian.
|
||||
//
|
||||
// Overview
|
||||
// --------
|
||||
//
|
||||
// The format comprises seven sections:
|
||||
//
|
||||
// | Section | Length | Description |
|
||||
// | ------------------ | ------------------ | ----------------------------------------------------------------------------------------------- |
|
||||
// | Header | 44 bytes | Contains the content hash, parse options, flags, and byte offsets to the start of each section. |
|
||||
// | String offsets | 8 bytes per string | Pairs of starting byte offsets and ending byte offsets into the **string data** section. |
|
||||
// | String data | variable | UTF-8 encoded string data. |
|
||||
// | Extended node data | variable | Extra data for some kinds of nodes. |
|
||||
// | Structured data | variable | Msgpack-encoded metadata blobs (e.g. file references). |
|
||||
// | Nodes | 28 bytes per node | Defines the AST structure of the file, with references to strings and extended data. |
|
||||
//
|
||||
// Header (44 bytes)
|
||||
// -----------------
|
||||
//
|
||||
// The header contains the following fields:
|
||||
//
|
||||
// | Byte offset | Type | Field |
|
||||
// | ----------- | --------- | ------------------------------------------------- |
|
||||
// | 0 | uint8 | Protocol version |
|
||||
// | 1-3 | | Reserved |
|
||||
// | 4-19 | uint128 | Source file content hash (xxh3, LE) |
|
||||
// | 20-23 | uint32 | Parse options (bitmask; bit 0: JSX, bit 1: Force) |
|
||||
// | 24-27 | uint32 | Byte offset to string offsets section |
|
||||
// | 28-31 | uint32 | Byte offset to string data section |
|
||||
// | 32-35 | uint32 | Byte offset to extended node data section |
|
||||
// | 36-39 | uint32 | Byte offset to structured data section |
|
||||
// | 40-43 | uint32 | Byte offset to nodes section |
|
||||
//
|
||||
// String offsets (8 bytes per string)
|
||||
// -----------------------------------
|
||||
//
|
||||
// Each string offset entry consists of two 4-byte unsigned integers, representing the start and end byte offsets into the
|
||||
// **string data** section.
|
||||
//
|
||||
// String data (variable)
|
||||
// ----------------------
|
||||
//
|
||||
// The string data section contains UTF-8 encoded string data, with WTF-8 used for JS strings containing lone UTF-16
|
||||
// surrogates. In typical cases, the entirety of the string data is the source file text, and individual nodes with
|
||||
// string properties reference their positional slice of the file text. In cases where a node's string property is not
|
||||
// equal to the slice of file text at its position, the unique string is appended to the string data section after the
|
||||
// file text.
|
||||
//
|
||||
// Extended node data (variable)
|
||||
// -----------------------------
|
||||
//
|
||||
// The extended node data section contains additional data for specific node types. The length and meaning of each entry
|
||||
// is defined by the node type.
|
||||
//
|
||||
// Currently, the only node types that use this section are `TemplateHead`, `TemplateMiddle`, `TemplateTail`, and
|
||||
// `SourceFile`. The extended data format for the first three is:
|
||||
//
|
||||
// | Byte offset | Type | Field |
|
||||
// | ----------- | ------ | ------------------------------------------------ |
|
||||
// | 0-4 | uint32 | Index of `text` in the string offsets section |
|
||||
// | 4-8 | uint32 | Index of `rawText` in the string offsets section |
|
||||
// | 8-12 | uint32 | Value of `templateFlags` |
|
||||
//
|
||||
// and for `SourceFile` is:
|
||||
//
|
||||
// | Byte offset | Type | Field |
|
||||
// | ----------- | ------ | -------------------------------------------------------------- |
|
||||
// | 0-4 | uint32 | Index of `text` in the string offsets section |
|
||||
// | 4-8 | uint32 | Index of `fileName` in the string offsets section |
|
||||
// | 8-12 | uint32 | Index of `path` in the string offsets section |
|
||||
// | 12-16 | uint32 | Value of `languageVariant` |
|
||||
// | 16-20 | uint32 | Value of `scriptKind` |
|
||||
// | 20-24 | uint32 | Byte offset of `referencedFiles` in structured data section |
|
||||
// | 24-28 | uint32 | Byte offset of `typeReferenceDirectives` in structured data |
|
||||
// | 28-32 | uint32 | Byte offset of `libReferenceDirectives` in structured data |
|
||||
// | 32-36 | uint32 | Byte offset of `imports` node index array in structured data |
|
||||
// | 36-40 | uint32 | Byte offset of `moduleAugmentations` node index array |
|
||||
// | 40-44 | uint32 | Byte offset of `ambientModuleNames` string array |
|
||||
// | 44-48 | uint32 | Node index of `externalModuleIndicator` (0 = nil) |
|
||||
//
|
||||
// Structured data (variable)
|
||||
// --------------------------
|
||||
//
|
||||
// The structured data section contains msgpack-encoded metadata blobs. Each blob is a self-contained
|
||||
// msgpack value. File reference arrays use the following tuple format:
|
||||
//
|
||||
// [pos: uint, end: uint, fileName: string, resolutionMode: uint, preserve: bool]
|
||||
//
|
||||
// Node index arrays (imports, moduleAugmentations) are msgpack arrays of uint values, where each
|
||||
// value is a node index into the nodes section. String arrays (ambientModuleNames) are msgpack
|
||||
// arrays of string values.
|
||||
//
|
||||
// An offset of 0xFFFFFFFF indicates no data (empty array).
|
||||
//
|
||||
// Nodes (28 bytes per node)
|
||||
// -------------------------
|
||||
//
|
||||
// The nodes section contains the AST structure of the file. Nodes are represented in a flat array in source order,
|
||||
// heavily inspired by https://marvinh.dev/blog/speeding-up-javascript-ecosystem-part-11/. Each node has the following
|
||||
// structure:
|
||||
//
|
||||
// | Byte offset | Type | Field |
|
||||
// | ----------- | ------ | -------------------------- |
|
||||
// | 0-4 | uint32 | Kind |
|
||||
// | 4-8 | uint32 | Pos |
|
||||
// | 8-12 | uint32 | End |
|
||||
// | 12-16 | uint32 | Node index of next sibling |
|
||||
// | 16-20 | uint32 | Node index of parent |
|
||||
// | 20-24 | | Node data |
|
||||
// | 24-28 | uint32 | Node flags |
|
||||
//
|
||||
// The first 28 bytes of the nodes section are zeros representing a nil node, such that nodes without a parent or next
|
||||
// sibling can unambiuously use `0` for those indices.
|
||||
//
|
||||
// NodeLists are represented as normal nodes with the special `kind` value `0xff_ff_ff_ff`. They are considered the parent
|
||||
// of their contents in the encoded format. A client reconstructing an AST similar to TypeScript's internal representation
|
||||
// should instead set the `parent` pointers of a NodeList's children to the NodeList's parent. A NodeList's `data` field
|
||||
// is the uint32 length of the list, and does not use one of the data types described below.
|
||||
//
|
||||
// For node types other than NodeList, the node data field encodes one of the following, determined by the first 2 bits of
|
||||
// the field:
|
||||
//
|
||||
// | Value | Data type | Description |
|
||||
// | ----- | --------- | ------------------------------------------------------------------------------------ |
|
||||
// | 0b00 | Children | Disambiguates which named properties of the node its children should be assigned to. |
|
||||
// | 0b01 | String | The index of the node's string property in the **string offsets** section. |
|
||||
// | 0b10 | Extended | The byte offset of the node's extended data into the **extended node data** section. |
|
||||
// | 0b11 | Reserved | Reserved for future use. |
|
||||
//
|
||||
// In all node data types, the remaining 6 bits of the first byte are used to encode small values specific to the node
|
||||
// type. For most node types, these are individual boolean flags. For unary expressions, all 6 bits encode the operator's
|
||||
// SyntaxKind value (e.g., PlusPlusToken=45, TildeToken=54), which fits because KindLastUnaryOperator (54) <= 0x3f (63).
|
||||
//
|
||||
// | Node type | Bits 0-5 | Notes |
|
||||
// | ---------------------------- | ------------------------------------- | ------------------------------ |
|
||||
// | `ImportSpecifier` | Bit 0: `isTypeOnly` | |
|
||||
// | `ImportClause` | Bit 0: `isTypeOnly`, Bit 1: `isDefer` | |
|
||||
// | `ExportSpecifier` | Bit 0: `isTypeOnly` | |
|
||||
// | `ImportEqualsDeclaration` | Bit 0: `isTypeOnly` | |
|
||||
// | `ExportDeclaration` | Bit 0: `isTypeOnly` | |
|
||||
// | `ImportTypeNode` | Bit 0: `isTypeOf` | |
|
||||
// | `ExportAssignment` | Bit 0: `isExportEquals` | |
|
||||
// | `Block` | Bit 0: `multiline` | |
|
||||
// | `ArrayLiteralExpression` | Bit 0: `multiline` | |
|
||||
// | `ObjectLiteralExpression` | Bit 0: `multiline` | |
|
||||
// | `JsxText` | Bit 0: `containsOnlyTriviaWhiteSpaces`| |
|
||||
// | `JSDocTypeLiteral` | Bit 0: `isArrayType` | |
|
||||
// | `JsDocPropertyTag` | Bit 0: `isBracketed`, Bit 1: `isNameFirst` | |
|
||||
// | `JsDocParameterTag` | Bit 0: `isBracketed`, Bit 1: `isNameFirst` | |
|
||||
// | `VariableDeclarationList` | Bit 0: is `let`, Bit 1: is `const` | |
|
||||
// | `ImportAttributes` | Bit 0: `multiline`, Bit 1: is `assert`| |
|
||||
// | `PrefixUnaryExpression` | Bits 0-5: operator SyntaxKind | e.g., `!`, `~`, `++`, `--` |
|
||||
// | `PostfixUnaryExpression` | Bits 0-5: operator SyntaxKind | e.g., `++`, `--` |
|
||||
//
|
||||
// The remaining 3 bytes of the node data field vary by data type:
|
||||
//
|
||||
// ### Children (0b00)
|
||||
//
|
||||
// If a node has fewer children than its type allows, additional data is needed to determine which properties the children
|
||||
// correspond to. The last byte of the 4-byte data field is a bitmask representing the child properties of the node type,
|
||||
// in visitor order, where `1` indicates that the child at that property is present and `0` indicates that the property is
|
||||
// nil. For example, a `MethodDeclaration` has the following child properties:
|
||||
//
|
||||
// | Property name | Bit position |
|
||||
// | -------------- | ------------ |
|
||||
// | modifiers | 0 |
|
||||
// | asteriskToken | 1 |
|
||||
// | name | 2 |
|
||||
// | postfixToken | 3 |
|
||||
// | typeParameters | 4 |
|
||||
// | parameters | 5 |
|
||||
// | returnType | 6 |
|
||||
// | body | 7 |
|
||||
//
|
||||
// A bitmask with value `0b01100101` would indicate that the next four direct descendants (i.e., node records that have a
|
||||
// `parent` set to the node index of the `MethodDeclaration`) of the node are its `modifiers`, `name`, `parameters`, and
|
||||
// `body` properties, in that order. The remaining properties are nil. (To reconstruct the node with named properties, the
|
||||
// client must consult a static table of each node type's child property names.)
|
||||
//
|
||||
// The bitmask may be zero for node types that can only have a single child, since no disambiguation is needed.
|
||||
// Additionally, the children data type may be used for nodes that can never have children, but do not require other
|
||||
// data types.
|
||||
//
|
||||
// ### String (0b01)
|
||||
//
|
||||
// The string data type is used for nodes with a single string property. (Currently, the name of that property is always
|
||||
// `text`.) The last three bytes of the 4-byte data field form a single 24-bit unsigned integer (i.e.,
|
||||
// `uint32(0x00_ff_ff_ff & node.data)`) _N_ that is an index into the **string offsets** section. The *N*th 32-bit
|
||||
// unsigned integer in the **string offsets** section is the byte offset of the start of the string in the **string data**
|
||||
// section, and the *N+1*th 32-bit unsigned integer is the byte offset of the end of the string in the
|
||||
// **string data** section.
|
||||
//
|
||||
// ### Extended (0b10)
|
||||
//
|
||||
// The extended data type is used for nodes with properties that don't fit into either the children or string data types.
|
||||
// The last three bytes of the 4-byte data field form a single 24-bit unsigned integer (i.e.,
|
||||
// `uint32(0x00_ff_ff_ff & node.data)`) _N_ that is a byte offset into the **extended node data** section. The length and
|
||||
// meaning of the data at that offset is defined by the node type. See the **Extended node data** section for details on
|
||||
// the format of the extended data for specific node types.
|
||||
//
|
||||
// Encoding Arbitrary Nodes
|
||||
// ------------------------
|
||||
//
|
||||
// The same binary format can be used to encode an arbitrary subtree of a SourceFile, not just a whole SourceFile. When
|
||||
// encoding a non-SourceFile node, the format is identical with the following differences:
|
||||
//
|
||||
// - The content hash fields in the header (bytes 4-19) are zero.
|
||||
// - The parse options field in the header (bytes 20-23) is zero.
|
||||
// - The root node in the nodes section uses its actual node kind and data encoding (via getNodeData) rather than the
|
||||
// SourceFile-specific extended data format.
|
||||
//
|
||||
// The string data section contains only the strings referenced by nodes in the subtree, rather than the full source
|
||||
// file text. The EncodeNode function provides this entrypoint.
|
||||
|
||||
// SourceFileHash returns the 128-bit content hash for a source file as a hex string.
|
||||
func SourceFileHash(sourceFile *ast.SourceFile) string {
|
||||
h := sourceFile.Hash
|
||||
return fmt.Sprintf("%016x%016x", h.Hi, h.Lo)
|
||||
}
|
||||
|
||||
// encodeParseOptions encodes the per-file ExternalModuleIndicatorOptions as a uint32 bitmask.
|
||||
func encodeParseOptions(opts ast.ExternalModuleIndicatorOptions) uint32 {
|
||||
var bits uint32
|
||||
if opts.JSX {
|
||||
bits |= 1
|
||||
}
|
||||
if opts.Force {
|
||||
bits |= 2
|
||||
}
|
||||
return bits
|
||||
}
|
||||
|
||||
// NodeIndexTable maps between AST nodes and their encoder indices for O(1) node handle resolution.
|
||||
type NodeIndexTable struct {
|
||||
Nodes []*ast.Node // index → node (for resolution)
|
||||
sortedOnce sync.Once
|
||||
sortedIdx []uint32 // indices into Nodes, sorted by node ID; built lazily
|
||||
}
|
||||
|
||||
var nodeIndexTableKey = ast.NewSourceFileDataKey[*NodeIndexTable]()
|
||||
|
||||
// GetIndex returns the encoder index for the given node.
|
||||
// On the first call the sortedIdx array is built (O(n log n) sort on a flat []uint32),
|
||||
// then subsequent calls use binary search (O(log n)). This turns out to be much faster than
|
||||
// building a map[*ast.Node]uint32 and not significantly slower for lookups.
|
||||
func (t *NodeIndexTable) GetIndex(node *ast.Node) uint32 {
|
||||
t.sortedOnce.Do(func() {
|
||||
idx := make([]uint32, 0, len(t.Nodes))
|
||||
for i, n := range t.Nodes {
|
||||
if n != nil {
|
||||
idx = append(idx, uint32(i))
|
||||
}
|
||||
}
|
||||
nodes := t.Nodes
|
||||
slices.SortFunc(idx, func(a, b uint32) int {
|
||||
return cmp.Compare(ast.GetNodeId(nodes[a]), ast.GetNodeId(nodes[b]))
|
||||
})
|
||||
t.sortedIdx = idx
|
||||
})
|
||||
target := ast.GetNodeId(node)
|
||||
i, found := core.BinarySearchUniqueFunc(t.sortedIdx, func(_ int, el uint32) int {
|
||||
return cmp.Compare(ast.GetNodeId(t.Nodes[el]), target)
|
||||
})
|
||||
if found {
|
||||
return t.sortedIdx[i]
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// BuildNodeIndexTable walks the AST in the same order as encodeTree and builds
|
||||
// a NodeIndexTable without performing the full binary encoding. This is used to
|
||||
// eagerly create index tables for files that need node handles before getSourceFile
|
||||
// is called. The indices produced are guaranteed to match those from EncodeSourceFile.
|
||||
func BuildNodeIndexTable(sourceFile *ast.SourceFile) *NodeIndexTable {
|
||||
var nodeCount uint32
|
||||
nodeTable := make([]*ast.Node, 1, sourceFile.NodeCount+1) // index 0 = nil sentinel
|
||||
|
||||
visitor := &ast.NodeVisitor{
|
||||
Hooks: ast.NodeVisitorHooks{
|
||||
VisitNodes: func(nodeList *ast.NodeList, visitor *ast.NodeVisitor) *ast.NodeList {
|
||||
if nodeList == nil {
|
||||
return nodeList
|
||||
}
|
||||
nodeCount++
|
||||
nodeTable = append(nodeTable, nil) // NodeLists are not *ast.Node
|
||||
visitor.VisitSlice(nodeList.Nodes)
|
||||
return nodeList
|
||||
},
|
||||
VisitModifiers: func(modifiers *ast.ModifierList, visitor *ast.NodeVisitor) *ast.ModifierList {
|
||||
if modifiers != nil && len(modifiers.Nodes) > 0 {
|
||||
visitor.Hooks.VisitNodes(&modifiers.NodeList, visitor)
|
||||
}
|
||||
return modifiers
|
||||
},
|
||||
},
|
||||
}
|
||||
visitor.Visit = func(node *ast.Node) *ast.Node {
|
||||
nodeCount++
|
||||
nodeTable = append(nodeTable, node)
|
||||
visitor.VisitEachChild(node)
|
||||
for _, jsdoc := range node.JSDoc(sourceFile) {
|
||||
visitor.Visit(jsdoc)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
rootNode := sourceFile.AsNode()
|
||||
// Index 1 = root node (matches encodeTree)
|
||||
nodeCount++
|
||||
nodeTable = append(nodeTable, rootNode)
|
||||
|
||||
visitor.VisitEachChild(rootNode)
|
||||
for _, jsdoc := range rootNode.JSDoc(sourceFile) {
|
||||
visitor.Visit(jsdoc)
|
||||
}
|
||||
|
||||
return &NodeIndexTable{Nodes: nodeTable}
|
||||
}
|
||||
|
||||
func GetNodeIndexTable(sourceFile *ast.SourceFile) *NodeIndexTable {
|
||||
return ast.GetOrComputeSourceFileData(sourceFile, nodeIndexTableKey, BuildNodeIndexTable)
|
||||
}
|
||||
|
||||
// EncodeSourceFile encodes an entire source file AST into the binary format.
|
||||
// Returns the encoded bytes and a NodeIndexTable mapping encoder indices to AST nodes.
|
||||
func EncodeSourceFile(sourceFile *ast.SourceFile) ([]byte, *NodeIndexTable, error) {
|
||||
data, nodeTable, err := encodeTree(sourceFile.AsNode(), sourceFile)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
nodeTable = ast.GetOrComputeSourceFileData(sourceFile, nodeIndexTableKey, func(*ast.SourceFile) *NodeIndexTable {
|
||||
return nodeTable
|
||||
})
|
||||
return data, nodeTable, nil
|
||||
}
|
||||
|
||||
// EncodeNode encodes an arbitrary AST node and its descendants into the binary format.
|
||||
// The sourceFile is needed to provide the source text for efficient string encoding.
|
||||
// When encoding a non-SourceFile node, the header hash and parse options fields will be zero.
|
||||
// Returns the encoded bytes and a NodeIndexTable mapping encoder indices to AST nodes.
|
||||
func EncodeNode(node *ast.Node, sourceFile *ast.SourceFile) ([]byte, *NodeIndexTable, error) {
|
||||
return encodeTree(node, sourceFile)
|
||||
}
|
||||
|
||||
func encodeTree(rootNode *ast.Node, sourceFile *ast.SourceFile) ([]byte, *NodeIndexTable, error) {
|
||||
var parentIndex, nodeCount, prevIndex uint32
|
||||
var extendedData []byte
|
||||
var structuredData []byte
|
||||
var strs *stringTable
|
||||
var positionMap *ast.PositionMap
|
||||
if rootNode.Kind == ast.KindSourceFile {
|
||||
strs = newStringTable(sourceFile.Text(), sourceFile.TextCount)
|
||||
positionMap = sourceFile.GetPositionMap()
|
||||
} else {
|
||||
strs = newStringTable("", 0)
|
||||
if sourceFile != nil {
|
||||
positionMap = sourceFile.GetPositionMap()
|
||||
}
|
||||
}
|
||||
if positionMap == nil {
|
||||
positionMap = ast.ComputePositionMap("")
|
||||
}
|
||||
utf16 := func(pos int) uint32 {
|
||||
return uint32(positionMap.UTF8ToUTF16(pos))
|
||||
}
|
||||
var initialNodeCount int
|
||||
if sourceFile != nil {
|
||||
initialNodeCount = sourceFile.NodeCount
|
||||
}
|
||||
nodes := make([]byte, 0, (initialNodeCount+1)*NodeSize)
|
||||
|
||||
// Build node index table for O(1) handle resolution.
|
||||
// Index 0 is a nil sentinel; real nodes start at index 1.
|
||||
nodeTable := make([]*ast.Node, 1, initialNodeCount+1) // index 0 = nil sentinel
|
||||
|
||||
// Build a small map of nodes we need to track indices for (imports + moduleAugmentations).
|
||||
// Values start at 0 and are filled in during the walk.
|
||||
var nodeIndexMap map[*ast.Node]uint32
|
||||
var sfExtendedDataOffset int // byte offset in extendedData where SourceFile fields start
|
||||
if rootNode.Kind == ast.KindSourceFile {
|
||||
sf := rootNode.AsSourceFile()
|
||||
total := len(sf.Imports()) + len(sf.ModuleAugmentations)
|
||||
if sf.ExternalModuleIndicator != nil && sf.ExternalModuleIndicator != rootNode {
|
||||
total++
|
||||
}
|
||||
if total > 0 {
|
||||
nodeIndexMap = make(map[*ast.Node]uint32, total)
|
||||
for _, imp := range sf.Imports() {
|
||||
nodeIndexMap[imp.AsNode()] = 0
|
||||
}
|
||||
for _, aug := range sf.ModuleAugmentations {
|
||||
nodeIndexMap[aug.AsNode()] = 0
|
||||
}
|
||||
if sf.ExternalModuleIndicator != nil && sf.ExternalModuleIndicator != rootNode {
|
||||
nodeIndexMap[sf.ExternalModuleIndicator] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitor := &ast.NodeVisitor{
|
||||
Hooks: ast.NodeVisitorHooks{
|
||||
VisitNodes: func(nodeList *ast.NodeList, visitor *ast.NodeVisitor) *ast.NodeList {
|
||||
if nodeList == nil {
|
||||
return nodeList
|
||||
}
|
||||
|
||||
nodeCount++
|
||||
nodeTable = append(nodeTable, nil) // NodeLists are not *ast.Node
|
||||
if prevIndex != 0 {
|
||||
// this is the next sibling of `prevNode`
|
||||
b0, b1, b2, b3 := uint8(nodeCount), uint8(nodeCount>>8), uint8(nodeCount>>16), uint8(nodeCount>>24)
|
||||
nodes[prevIndex*NodeSize+NodeOffsetNext+0] = b0
|
||||
nodes[prevIndex*NodeSize+NodeOffsetNext+1] = b1
|
||||
nodes[prevIndex*NodeSize+NodeOffsetNext+2] = b2
|
||||
nodes[prevIndex*NodeSize+NodeOffsetNext+3] = b3
|
||||
}
|
||||
|
||||
nodes = appendUint32s(nodes, SyntaxKindNodeList, utf16(nodeList.Pos()), utf16(nodeList.End()), 0, parentIndex, uint32(len(nodeList.Nodes)), 0)
|
||||
|
||||
saveParentIndex := parentIndex
|
||||
|
||||
currentIndex := nodeCount
|
||||
prevIndex = 0
|
||||
parentIndex = currentIndex
|
||||
visitor.VisitSlice(nodeList.Nodes)
|
||||
prevIndex = currentIndex
|
||||
parentIndex = saveParentIndex
|
||||
|
||||
return nodeList
|
||||
},
|
||||
VisitModifiers: func(modifiers *ast.ModifierList, visitor *ast.NodeVisitor) *ast.ModifierList {
|
||||
if modifiers != nil && len(modifiers.Nodes) > 0 {
|
||||
visitor.Hooks.VisitNodes(&modifiers.NodeList, visitor)
|
||||
}
|
||||
return modifiers
|
||||
},
|
||||
},
|
||||
}
|
||||
visitor.Visit = func(node *ast.Node) *ast.Node {
|
||||
nodeCount++
|
||||
nodeTable = append(nodeTable, node)
|
||||
if prevIndex != 0 {
|
||||
// this is the next sibling of `prevNode`
|
||||
b0, b1, b2, b3 := uint8(nodeCount), uint8(nodeCount>>8), uint8(nodeCount>>16), uint8(nodeCount>>24)
|
||||
nodes[prevIndex*NodeSize+NodeOffsetNext+0] = b0
|
||||
nodes[prevIndex*NodeSize+NodeOffsetNext+1] = b1
|
||||
nodes[prevIndex*NodeSize+NodeOffsetNext+2] = b2
|
||||
nodes[prevIndex*NodeSize+NodeOffsetNext+3] = b3
|
||||
}
|
||||
|
||||
nodes = appendUint32s(nodes, uint32(node.Kind), utf16(node.Pos()), utf16(node.End()), 0, parentIndex, getNodeData(node, strs, positionMap, &extendedData, &structuredData), uint32(node.Flags))
|
||||
|
||||
if nodeIndexMap != nil {
|
||||
if _, ok := nodeIndexMap[node]; ok {
|
||||
nodeIndexMap[node] = nodeCount
|
||||
}
|
||||
}
|
||||
|
||||
saveParentIndex := parentIndex
|
||||
|
||||
currentIndex := nodeCount
|
||||
prevIndex = 0
|
||||
parentIndex = currentIndex
|
||||
visitor.VisitEachChild(node)
|
||||
if sourceFile != nil {
|
||||
for _, jsdoc := range node.JSDoc(sourceFile) {
|
||||
visitor.Visit(jsdoc)
|
||||
}
|
||||
}
|
||||
prevIndex = currentIndex
|
||||
parentIndex = saveParentIndex
|
||||
return node
|
||||
}
|
||||
|
||||
nodes = appendUint32s(nodes, 0, 0, 0, 0, 0, 0, 0)
|
||||
|
||||
nodeCount++
|
||||
parentIndex++
|
||||
nodeTable = append(nodeTable, rootNode) // index 1 = root node
|
||||
|
||||
sfExtendedDataOffset = len(extendedData)
|
||||
nodes = appendUint32s(nodes, uint32(rootNode.Kind), utf16(rootNode.Pos()), utf16(rootNode.End()), 0, 0, getNodeData(rootNode, strs, positionMap, &extendedData, &structuredData), uint32(rootNode.Flags))
|
||||
|
||||
visitor.VisitEachChild(rootNode)
|
||||
if sourceFile != nil {
|
||||
for _, jsdoc := range rootNode.JSDoc(sourceFile) {
|
||||
visitor.Visit(jsdoc)
|
||||
}
|
||||
}
|
||||
|
||||
var hash xxh3.Uint128
|
||||
var parseOpts uint32
|
||||
if rootNode.Kind == ast.KindSourceFile {
|
||||
hash = sourceFile.Hash
|
||||
parseOpts = encodeParseOptions(sourceFile.ParseOptions().ExternalModuleIndicatorOptions)
|
||||
|
||||
// Encode imports, moduleAugmentations, and ambientModuleNames into structured data,
|
||||
// and patch the placeholder offsets in the SourceFile extended data.
|
||||
sf := rootNode.AsSourceFile()
|
||||
importsOffset := encodeNodeIndexArray(sf.Imports(), nodeIndexMap, &structuredData)
|
||||
moduleAugmentationsOffset := encodeModuleAugmentations(sf.ModuleAugmentations, nodeIndexMap, &structuredData)
|
||||
ambientModuleNamesOffset := encodeStringArray(sf.AmbientModuleNames, &structuredData)
|
||||
// Patch the 3 placeholder uint32s at sfExtendedDataOffset + 32, 36, 40
|
||||
binary.LittleEndian.PutUint32(extendedData[sfExtendedDataOffset+32:], importsOffset)
|
||||
binary.LittleEndian.PutUint32(extendedData[sfExtendedDataOffset+36:], moduleAugmentationsOffset)
|
||||
binary.LittleEndian.PutUint32(extendedData[sfExtendedDataOffset+40:], ambientModuleNamesOffset)
|
||||
// Patch externalModuleIndicator node index at offset 44
|
||||
var externalModuleIndicatorIndex uint32
|
||||
if sf.ExternalModuleIndicator != nil {
|
||||
if sf.ExternalModuleIndicator == rootNode {
|
||||
externalModuleIndicatorIndex = 1 // root node index
|
||||
} else {
|
||||
externalModuleIndicatorIndex = nodeIndexMap[sf.ExternalModuleIndicator]
|
||||
}
|
||||
}
|
||||
binary.LittleEndian.PutUint32(extendedData[sfExtendedDataOffset+44:], externalModuleIndicatorIndex)
|
||||
}
|
||||
|
||||
metadata := uint32(ProtocolVersion) << 24
|
||||
offsetStringTableOffsets := HeaderSize
|
||||
offsetStringTableData := HeaderSize + len(strs.offsets)*4
|
||||
offsetExtendedData := offsetStringTableData + strs.stringLength()
|
||||
offsetStructuredData := offsetExtendedData + len(extendedData)
|
||||
offsetNodes := offsetStructuredData + len(structuredData)
|
||||
|
||||
header := []uint32{
|
||||
metadata,
|
||||
uint32(hash.Lo), uint32(hash.Lo >> 32),
|
||||
uint32(hash.Hi), uint32(hash.Hi >> 32),
|
||||
parseOpts,
|
||||
uint32(offsetStringTableOffsets),
|
||||
uint32(offsetStringTableData),
|
||||
uint32(offsetExtendedData),
|
||||
uint32(offsetStructuredData),
|
||||
uint32(offsetNodes),
|
||||
}
|
||||
|
||||
var headerBytes, strsBytes []byte
|
||||
headerBytes = appendUint32s(nil, header...)
|
||||
strsBytes = strs.encode()
|
||||
|
||||
return slices.Concat(
|
||||
headerBytes,
|
||||
strsBytes,
|
||||
extendedData,
|
||||
structuredData,
|
||||
nodes,
|
||||
), &NodeIndexTable{Nodes: nodeTable}, nil
|
||||
}
|
||||
|
||||
func appendUint32s(buf []byte, values ...uint32) []byte {
|
||||
for _, value := range values {
|
||||
buf = binary.LittleEndian.AppendUint32(buf, value)
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
func getNodeData(node *ast.Node, strs *stringTable, positionMap *ast.PositionMap, extendedData *[]byte, structuredData *[]byte) uint32 {
|
||||
t := getNodeDataType(node)
|
||||
switch t {
|
||||
case NodeDataTypeChildren:
|
||||
return t | getNodeCommonData(node) | uint32(getChildrenPropertyMask(node))
|
||||
case NodeDataTypeString:
|
||||
return t | getNodeCommonData(node) | recordNodeStrings(node, strs)
|
||||
case NodeDataTypeExtendedData:
|
||||
return t | getNodeCommonData(node) | recordExtendedData(node, strs, positionMap, extendedData, structuredData)
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
const noStructuredData = 0xFFFFFFFF
|
||||
|
||||
func recordExtendedData_SourceFile(node *ast.Node, strs *stringTable, positionMap *ast.PositionMap, extendedData *[]byte, structuredData *[]byte) {
|
||||
sf := node.AsSourceFile()
|
||||
textIndex := strs.add(sf.Text(), sf.Kind, sf.Pos(), sf.End())
|
||||
fileNameIndex := strs.add(sf.FileName(), 0, 0, 0)
|
||||
pathIndex := strs.add(string(sf.Path()), 0, 0, 0)
|
||||
referencedFilesOffset := encodeFileReferences(sf.ReferencedFiles, positionMap, structuredData)
|
||||
typeRefDirectivesOffset := encodeFileReferences(sf.TypeReferenceDirectives, positionMap, structuredData)
|
||||
libRefDirectivesOffset := encodeFileReferences(sf.LibReferenceDirectives, positionMap, structuredData)
|
||||
// imports, moduleAugmentations, ambientModuleNames offsets are placeholders;
|
||||
// they will be patched after the tree walk when node indices are known.
|
||||
*extendedData = appendUint32s(*extendedData, textIndex, fileNameIndex, pathIndex, uint32(sf.LanguageVariant), uint32(sf.ScriptKind), referencedFilesOffset, typeRefDirectivesOffset, libRefDirectivesOffset, noStructuredData, noStructuredData, noStructuredData, 0)
|
||||
}
|
||||
|
||||
func recordExtendedData_TemplateHead(node *ast.Node, strs *stringTable, positionMap *ast.PositionMap, extendedData *[]byte, structuredData *[]byte) {
|
||||
n := node.AsTemplateHead()
|
||||
textIndex := strs.add(n.Text, node.Kind, node.Pos(), node.End())
|
||||
rawTextIndex := strs.add(n.RawText, node.Kind, node.Pos(), node.End())
|
||||
*extendedData = appendUint32s(*extendedData, textIndex, rawTextIndex, uint32(n.TemplateFlags))
|
||||
}
|
||||
|
||||
func recordExtendedData_TemplateMiddle(node *ast.Node, strs *stringTable, positionMap *ast.PositionMap, extendedData *[]byte, structuredData *[]byte) {
|
||||
n := node.AsTemplateMiddle()
|
||||
textIndex := strs.add(n.Text, node.Kind, node.Pos(), node.End())
|
||||
rawTextIndex := strs.add(n.RawText, node.Kind, node.Pos(), node.End())
|
||||
*extendedData = appendUint32s(*extendedData, textIndex, rawTextIndex, uint32(n.TemplateFlags))
|
||||
}
|
||||
|
||||
func recordExtendedData_TemplateTail(node *ast.Node, strs *stringTable, positionMap *ast.PositionMap, extendedData *[]byte, structuredData *[]byte) {
|
||||
n := node.AsTemplateTail()
|
||||
textIndex := strs.add(n.Text, node.Kind, node.Pos(), node.End())
|
||||
rawTextIndex := strs.add(n.RawText, node.Kind, node.Pos(), node.End())
|
||||
*extendedData = appendUint32s(*extendedData, textIndex, rawTextIndex, uint32(n.TemplateFlags))
|
||||
}
|
||||
|
||||
func boolToByte(b bool) byte {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// hasModifiers returns true if the modifier list is non-nil and has at least one modifier.
|
||||
func hasModifiers(modifiers *ast.ModifierList) bool {
|
||||
return modifiers != nil && len(modifiers.Nodes) > 0
|
||||
}
|
||||
|
||||
// encodeFileReferences encodes a slice of FileReferences as a msgpack array of tuples
|
||||
// into the structured data buffer. Returns the byte offset into the buffer, or
|
||||
// noStructuredData (0xFFFFFFFF) if the slice is empty.
|
||||
func encodeFileReferences(refs []*ast.FileReference, positionMap *ast.PositionMap, buf *[]byte) uint32 {
|
||||
if len(refs) == 0 {
|
||||
return noStructuredData
|
||||
}
|
||||
offset := uint32(len(*buf))
|
||||
*buf = msgpackWriteArrayHeader(*buf, len(refs))
|
||||
for _, ref := range refs {
|
||||
// Each entry is a 5-element tuple: [pos, end, fileName, resolutionMode, preserve]
|
||||
*buf = msgpackWriteArrayHeader(*buf, 5)
|
||||
*buf = msgpackWriteUint(*buf, uint32(positionMap.UTF8ToUTF16(ref.Pos())))
|
||||
*buf = msgpackWriteUint(*buf, uint32(positionMap.UTF8ToUTF16(ref.End())))
|
||||
*buf = msgpackWriteString(*buf, ref.FileName)
|
||||
*buf = msgpackWriteUint(*buf, uint32(ref.ResolutionMode))
|
||||
*buf = msgpackWriteBool(*buf, ref.Preserve)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
// encodeNodeIndexArray encodes a slice of LiteralLikeNodes as a msgpack array of
|
||||
// uint node indices. Returns the byte offset into the buffer, or noStructuredData
|
||||
// if the slice is empty.
|
||||
func encodeNodeIndexArray(nodes []*ast.LiteralLikeNode, indexMap map[*ast.Node]uint32, buf *[]byte) uint32 {
|
||||
if len(nodes) == 0 {
|
||||
return noStructuredData
|
||||
}
|
||||
offset := uint32(len(*buf))
|
||||
*buf = msgpackWriteArrayHeader(*buf, len(nodes))
|
||||
for _, node := range nodes {
|
||||
*buf = msgpackWriteUint(*buf, indexMap[node.AsNode()])
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
// encodeModuleAugmentations encodes a slice of ModuleName nodes as a msgpack array
|
||||
// of uint node indices. Returns the byte offset into the buffer, or noStructuredData
|
||||
// if the slice is empty.
|
||||
func encodeModuleAugmentations(nodes []*ast.ModuleName, indexMap map[*ast.Node]uint32, buf *[]byte) uint32 {
|
||||
if len(nodes) == 0 {
|
||||
return noStructuredData
|
||||
}
|
||||
offset := uint32(len(*buf))
|
||||
*buf = msgpackWriteArrayHeader(*buf, len(nodes))
|
||||
for _, node := range nodes {
|
||||
*buf = msgpackWriteUint(*buf, indexMap[node.AsNode()])
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
// encodeStringArray encodes a slice of strings as a msgpack array of strings.
|
||||
// Returns the byte offset into the buffer, or noStructuredData if the slice is empty.
|
||||
func encodeStringArray(strs []string, buf *[]byte) uint32 {
|
||||
if len(strs) == 0 {
|
||||
return noStructuredData
|
||||
}
|
||||
offset := uint32(len(*buf))
|
||||
*buf = msgpackWriteArrayHeader(*buf, len(strs))
|
||||
for _, s := range strs {
|
||||
*buf = msgpackWriteString(*buf, s)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
// Minimal msgpack writers for the structured data section.
|
||||
|
||||
func msgpackWriteArrayHeader(buf []byte, length int) []byte {
|
||||
if length <= 0x0f {
|
||||
return append(buf, byte(0x90|length))
|
||||
}
|
||||
if length <= 0xffff {
|
||||
return append(buf, 0xdc, byte(length>>8), byte(length))
|
||||
}
|
||||
return append(buf, 0xdd, byte(length>>24), byte(length>>16), byte(length>>8), byte(length))
|
||||
}
|
||||
|
||||
func msgpackWriteUint(buf []byte, value uint32) []byte {
|
||||
if value <= 0x7f {
|
||||
return append(buf, byte(value))
|
||||
}
|
||||
if value <= 0xff {
|
||||
return append(buf, 0xcc, byte(value))
|
||||
}
|
||||
if value <= 0xffff {
|
||||
return append(buf, 0xcd, byte(value>>8), byte(value))
|
||||
}
|
||||
return append(buf, 0xce, byte(value>>24), byte(value>>16), byte(value>>8), byte(value))
|
||||
}
|
||||
|
||||
func msgpackWriteString(buf []byte, s string) []byte {
|
||||
n := len(s)
|
||||
if n <= 0x1f {
|
||||
buf = append(buf, byte(0xa0|n))
|
||||
} else if n <= 0xff {
|
||||
buf = append(buf, 0xd9, byte(n))
|
||||
} else if n <= 0xffff {
|
||||
buf = append(buf, 0xda, byte(n>>8), byte(n))
|
||||
} else {
|
||||
buf = append(buf, 0xdb, byte(n>>24), byte(n>>16), byte(n>>8), byte(n))
|
||||
}
|
||||
return append(buf, s...)
|
||||
}
|
||||
|
||||
func msgpackWriteBool(buf []byte, value bool) []byte {
|
||||
if value {
|
||||
return append(buf, 0xc3)
|
||||
}
|
||||
return append(buf, 0xc2)
|
||||
}
|
||||
|
||||
// Hand-written commonData encoding functions for nodes whose non-bool data
|
||||
// members cannot be automatically encoded by the generator. Each function
|
||||
// packs relevant fields into the 6-bit commonData area (bits 24-29) of the
|
||||
// 32-bit node data word.
|
||||
|
||||
func getNodeCommonData_SyntheticExpression(_ *ast.Node) uint32 {
|
||||
// SyntheticExpression is an internal compiler node that is never part of a parsed AST.
|
||||
// It should never be encoded.
|
||||
panic("SyntheticExpression should never be encoded")
|
||||
}
|
||||
|
||||
// Hand-written extended data encoding functions for literal nodes that were
|
||||
// previously string-type but whose TokenFlags/TemplateFlags cannot fit in 6 bits.
|
||||
|
||||
func recordExtendedData_StringLiteral(node *ast.Node, strs *stringTable, _ *ast.PositionMap, extendedData *[]byte, _ *[]byte) {
|
||||
n := node.AsStringLiteral()
|
||||
textIndex := strs.add(n.Text, node.Kind, node.Pos(), node.End())
|
||||
*extendedData = appendUint32s(*extendedData, textIndex, uint32(n.TokenFlags))
|
||||
}
|
||||
|
||||
func recordExtendedData_NumericLiteral(node *ast.Node, strs *stringTable, _ *ast.PositionMap, extendedData *[]byte, _ *[]byte) {
|
||||
n := node.AsNumericLiteral()
|
||||
textIndex := strs.add(n.Text, node.Kind, node.Pos(), node.End())
|
||||
*extendedData = appendUint32s(*extendedData, textIndex, uint32(n.TokenFlags))
|
||||
}
|
||||
|
||||
func recordExtendedData_BigIntLiteral(node *ast.Node, strs *stringTable, _ *ast.PositionMap, extendedData *[]byte, _ *[]byte) {
|
||||
n := node.AsBigIntLiteral()
|
||||
textIndex := strs.add(n.Text, node.Kind, node.Pos(), node.End())
|
||||
*extendedData = appendUint32s(*extendedData, textIndex, uint32(n.TokenFlags))
|
||||
}
|
||||
|
||||
func recordExtendedData_RegularExpressionLiteral(node *ast.Node, strs *stringTable, _ *ast.PositionMap, extendedData *[]byte, _ *[]byte) {
|
||||
n := node.AsRegularExpressionLiteral()
|
||||
textIndex := strs.add(n.Text, node.Kind, node.Pos(), node.End())
|
||||
*extendedData = appendUint32s(*extendedData, textIndex, uint32(n.TokenFlags))
|
||||
}
|
||||
|
||||
func recordExtendedData_NoSubstitutionTemplateLiteral(node *ast.Node, strs *stringTable, _ *ast.PositionMap, extendedData *[]byte, _ *[]byte) {
|
||||
n := node.AsNoSubstitutionTemplateLiteral()
|
||||
textIndex := strs.add(n.Text, node.Kind, node.Pos(), node.End())
|
||||
*extendedData = appendUint32s(*extendedData, textIndex, uint32(n.TemplateFlags))
|
||||
}
|
||||
707
tools/tsgo/internal/api/encoder/encoder_generated.go
Normal file
707
tools/tsgo/internal/api/encoder/encoder_generated.go
Normal file
@@ -0,0 +1,707 @@
|
||||
// Code generated by _scripts/generate-encoder.ts. DO NOT EDIT.
|
||||
|
||||
package encoder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
)
|
||||
|
||||
func getNodeDataType(node *ast.Node) uint32 {
|
||||
switch node.Kind {
|
||||
case ast.KindIdentifier,
|
||||
ast.KindPrivateIdentifier,
|
||||
ast.KindJsxText,
|
||||
ast.KindJSDocText,
|
||||
ast.KindJSDocLink,
|
||||
ast.KindJSDocLinkPlain,
|
||||
ast.KindJSDocLinkCode:
|
||||
return NodeDataTypeString
|
||||
case ast.KindStringLiteral,
|
||||
ast.KindNumericLiteral,
|
||||
ast.KindBigIntLiteral,
|
||||
ast.KindRegularExpressionLiteral,
|
||||
ast.KindNoSubstitutionTemplateLiteral,
|
||||
ast.KindTemplateHead,
|
||||
ast.KindTemplateMiddle,
|
||||
ast.KindTemplateTail,
|
||||
ast.KindSourceFile:
|
||||
return NodeDataTypeExtendedData
|
||||
default:
|
||||
return NodeDataTypeChildren
|
||||
}
|
||||
}
|
||||
|
||||
func getChildrenPropertyMask(node *ast.Node) uint8 {
|
||||
switch node.Kind {
|
||||
case ast.KindQualifiedName:
|
||||
n := node.AsQualifiedName()
|
||||
return (boolToByte(n.Left != nil) << 0) | (boolToByte(n.Right != nil) << 1)
|
||||
case ast.KindComputedPropertyName:
|
||||
n := node.AsComputedPropertyName()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindDecorator:
|
||||
n := node.AsDecorator()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindIfStatement:
|
||||
n := node.AsIfStatement()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.ThenStatement != nil) << 1) | (boolToByte(n.ElseStatement != nil) << 2)
|
||||
case ast.KindDoStatement:
|
||||
n := node.AsDoStatement()
|
||||
return (boolToByte(n.Statement != nil) << 0) | (boolToByte(n.Expression != nil) << 1)
|
||||
case ast.KindWhileStatement:
|
||||
n := node.AsWhileStatement()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.Statement != nil) << 1)
|
||||
case ast.KindForStatement:
|
||||
n := node.AsForStatement()
|
||||
return (boolToByte(n.Initializer != nil) << 0) | (boolToByte(n.Condition != nil) << 1) | (boolToByte(n.Incrementor != nil) << 2) | (boolToByte(n.Statement != nil) << 3)
|
||||
case ast.KindForInStatement, ast.KindForOfStatement:
|
||||
n := node.AsForInOrOfStatement()
|
||||
return (boolToByte(n.AwaitModifier != nil) << 0) | (boolToByte(n.Initializer != nil) << 1) | (boolToByte(n.Expression != nil) << 2) | (boolToByte(n.Statement != nil) << 3)
|
||||
case ast.KindBreakStatement:
|
||||
n := node.AsBreakStatement()
|
||||
return (boolToByte(n.Label != nil) << 0)
|
||||
case ast.KindContinueStatement:
|
||||
n := node.AsContinueStatement()
|
||||
return (boolToByte(n.Label != nil) << 0)
|
||||
case ast.KindReturnStatement:
|
||||
n := node.AsReturnStatement()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindWithStatement:
|
||||
n := node.AsWithStatement()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.Statement != nil) << 1)
|
||||
case ast.KindSwitchStatement:
|
||||
n := node.AsSwitchStatement()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.CaseBlock != nil) << 1)
|
||||
case ast.KindCaseBlock:
|
||||
n := node.AsCaseBlock()
|
||||
return (boolToByte(n.Clauses != nil) << 0)
|
||||
case ast.KindCaseClause, ast.KindDefaultClause:
|
||||
n := node.AsCaseOrDefaultClause()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.Statements != nil) << 1)
|
||||
case ast.KindThrowStatement:
|
||||
n := node.AsThrowStatement()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindTryStatement:
|
||||
n := node.AsTryStatement()
|
||||
return (boolToByte(n.TryBlock != nil) << 0) | (boolToByte(n.CatchClause != nil) << 1) | (boolToByte(n.FinallyBlock != nil) << 2)
|
||||
case ast.KindCatchClause:
|
||||
n := node.AsCatchClause()
|
||||
return (boolToByte(n.VariableDeclaration != nil) << 0) | (boolToByte(n.Block != nil) << 1)
|
||||
case ast.KindLabeledStatement:
|
||||
n := node.AsLabeledStatement()
|
||||
return (boolToByte(n.Label != nil) << 0) | (boolToByte(n.Statement != nil) << 1)
|
||||
case ast.KindExpressionStatement:
|
||||
n := node.AsExpressionStatement()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindBlock:
|
||||
n := node.AsBlock()
|
||||
return (boolToByte(n.Statements != nil) << 0)
|
||||
case ast.KindVariableStatement:
|
||||
n := node.AsVariableStatement()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.DeclarationList != nil) << 1)
|
||||
case ast.KindVariableDeclaration:
|
||||
n := node.AsVariableDeclaration()
|
||||
return (boolToByte(n.Name() != nil) << 0) | (boolToByte(n.ExclamationToken != nil) << 1) | (boolToByte(n.Type != nil) << 2) | (boolToByte(n.Initializer != nil) << 3)
|
||||
case ast.KindVariableDeclarationList:
|
||||
n := node.AsVariableDeclarationList()
|
||||
return (boolToByte(n.Declarations != nil) << 0)
|
||||
case ast.KindObjectBindingPattern, ast.KindArrayBindingPattern:
|
||||
n := node.AsBindingPattern()
|
||||
return (boolToByte(n.Elements != nil) << 0)
|
||||
case ast.KindParameter:
|
||||
n := node.AsParameterDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.DotDotDotToken != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.QuestionToken != nil) << 3) | (boolToByte(n.Type != nil) << 4) | (boolToByte(n.Initializer != nil) << 5)
|
||||
case ast.KindBindingElement:
|
||||
n := node.AsBindingElement()
|
||||
return (boolToByte(n.DotDotDotToken != nil) << 0) | (boolToByte(n.PropertyName != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.Initializer != nil) << 3)
|
||||
case ast.KindMissingDeclaration:
|
||||
n := node.AsMissingDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0)
|
||||
case ast.KindFunctionDeclaration:
|
||||
n := node.AsFunctionDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.AsteriskToken != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.TypeParameters != nil) << 3) | (boolToByte(n.Parameters != nil) << 4) | (boolToByte(n.Type != nil) << 5) | (boolToByte(n.Body != nil) << 6)
|
||||
case ast.KindClassDeclaration:
|
||||
n := node.AsClassDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.TypeParameters != nil) << 2) | (boolToByte(n.HeritageClauses != nil) << 3) | (boolToByte(n.Members != nil) << 4)
|
||||
case ast.KindClassExpression:
|
||||
n := node.AsClassExpression()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.TypeParameters != nil) << 2) | (boolToByte(n.HeritageClauses != nil) << 3) | (boolToByte(n.Members != nil) << 4)
|
||||
case ast.KindHeritageClause:
|
||||
n := node.AsHeritageClause()
|
||||
return (boolToByte(n.Types != nil) << 0)
|
||||
case ast.KindInterfaceDeclaration:
|
||||
n := node.AsInterfaceDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.TypeParameters != nil) << 2) | (boolToByte(n.HeritageClauses != nil) << 3) | (boolToByte(n.Members != nil) << 4)
|
||||
case ast.KindTypeAliasDeclaration, ast.KindJSTypeAliasDeclaration:
|
||||
n := node.AsTypeAliasDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.TypeParameters != nil) << 2) | (boolToByte(n.Type != nil) << 3)
|
||||
case ast.KindEnumMember:
|
||||
n := node.AsEnumMember()
|
||||
return (boolToByte(n.Name() != nil) << 0) | (boolToByte(n.Initializer != nil) << 1)
|
||||
case ast.KindEnumDeclaration:
|
||||
n := node.AsEnumDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.Members != nil) << 2)
|
||||
case ast.KindModuleBlock:
|
||||
n := node.AsModuleBlock()
|
||||
return (boolToByte(n.Statements != nil) << 0)
|
||||
case ast.KindImportDeclaration, ast.KindJSImportDeclaration:
|
||||
n := node.AsImportDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.ImportClause != nil) << 1) | (boolToByte(n.ModuleSpecifier != nil) << 2) | (boolToByte(n.Attributes != nil) << 3)
|
||||
case ast.KindExternalModuleReference:
|
||||
n := node.AsExternalModuleReference()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindNamespaceImport:
|
||||
n := node.AsNamespaceImport()
|
||||
return (boolToByte(n.Name() != nil) << 0)
|
||||
case ast.KindNamedImports:
|
||||
n := node.AsNamedImports()
|
||||
return (boolToByte(n.Elements != nil) << 0)
|
||||
case ast.KindExportAssignment:
|
||||
n := node.AsExportAssignment()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Type != nil) << 1) | (boolToByte(n.Expression != nil) << 2)
|
||||
case ast.KindNamespaceExportDeclaration:
|
||||
n := node.AsNamespaceExportDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1)
|
||||
case ast.KindNamespaceExport:
|
||||
n := node.AsNamespaceExport()
|
||||
return (boolToByte(n.Name() != nil) << 0)
|
||||
case ast.KindNamedExports:
|
||||
n := node.AsNamedExports()
|
||||
return (boolToByte(n.Elements != nil) << 0)
|
||||
case ast.KindExportSpecifier:
|
||||
n := node.AsExportSpecifier()
|
||||
return (boolToByte(n.PropertyName != nil) << 0) | (boolToByte(n.Name() != nil) << 1)
|
||||
case ast.KindCallSignature:
|
||||
n := node.AsCallSignatureDeclaration()
|
||||
return (boolToByte(n.TypeParameters != nil) << 0) | (boolToByte(n.Parameters != nil) << 1) | (boolToByte(n.Type != nil) << 2)
|
||||
case ast.KindConstructSignature:
|
||||
n := node.AsConstructSignatureDeclaration()
|
||||
return (boolToByte(n.TypeParameters != nil) << 0) | (boolToByte(n.Parameters != nil) << 1) | (boolToByte(n.Type != nil) << 2)
|
||||
case ast.KindConstructor:
|
||||
n := node.AsConstructorDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.TypeParameters != nil) << 1) | (boolToByte(n.Parameters != nil) << 2) | (boolToByte(n.Type != nil) << 3) | (boolToByte(n.Body != nil) << 4)
|
||||
case ast.KindGetAccessor:
|
||||
n := node.AsGetAccessorDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.TypeParameters != nil) << 2) | (boolToByte(n.Parameters != nil) << 3) | (boolToByte(n.Type != nil) << 4) | (boolToByte(n.Body != nil) << 5)
|
||||
case ast.KindSetAccessor:
|
||||
n := node.AsSetAccessorDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.TypeParameters != nil) << 2) | (boolToByte(n.Parameters != nil) << 3) | (boolToByte(n.Type != nil) << 4) | (boolToByte(n.Body != nil) << 5)
|
||||
case ast.KindIndexSignature:
|
||||
n := node.AsIndexSignatureDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Parameters != nil) << 1) | (boolToByte(n.Type != nil) << 2)
|
||||
case ast.KindMethodSignature:
|
||||
n := node.AsMethodSignatureDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.PostfixToken != nil) << 2) | (boolToByte(n.TypeParameters != nil) << 3) | (boolToByte(n.Parameters != nil) << 4) | (boolToByte(n.Type != nil) << 5)
|
||||
case ast.KindMethodDeclaration:
|
||||
n := node.AsMethodDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.AsteriskToken != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.PostfixToken != nil) << 3) | (boolToByte(n.TypeParameters != nil) << 4) | (boolToByte(n.Parameters != nil) << 5) | (boolToByte(n.Type != nil) << 6) | (boolToByte(n.Body != nil) << 7)
|
||||
case ast.KindPropertySignature:
|
||||
n := node.AsPropertySignatureDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.PostfixToken != nil) << 2) | (boolToByte(n.Type != nil) << 3) | (boolToByte(n.Initializer != nil) << 4)
|
||||
case ast.KindPropertyDeclaration:
|
||||
n := node.AsPropertyDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.PostfixToken != nil) << 2) | (boolToByte(n.Type != nil) << 3) | (boolToByte(n.Initializer != nil) << 4)
|
||||
case ast.KindClassStaticBlockDeclaration:
|
||||
n := node.AsClassStaticBlockDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Body != nil) << 1)
|
||||
case ast.KindBinaryExpression:
|
||||
n := node.AsBinaryExpression()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Left != nil) << 1) | (boolToByte(n.Type != nil) << 2) | (boolToByte(n.OperatorToken != nil) << 3) | (boolToByte(n.Right != nil) << 4)
|
||||
case ast.KindPrefixUnaryExpression:
|
||||
n := node.AsPrefixUnaryExpression()
|
||||
return (boolToByte(n.Operand != nil) << 0)
|
||||
case ast.KindPostfixUnaryExpression:
|
||||
n := node.AsPostfixUnaryExpression()
|
||||
return (boolToByte(n.Operand != nil) << 0)
|
||||
case ast.KindYieldExpression:
|
||||
n := node.AsYieldExpression()
|
||||
return (boolToByte(n.AsteriskToken != nil) << 0) | (boolToByte(n.Expression != nil) << 1)
|
||||
case ast.KindArrowFunction:
|
||||
n := node.AsArrowFunction()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.TypeParameters != nil) << 1) | (boolToByte(n.Parameters != nil) << 2) | (boolToByte(n.Type != nil) << 3) | (boolToByte(n.EqualsGreaterThanToken != nil) << 4) | (boolToByte(n.Body != nil) << 5)
|
||||
case ast.KindFunctionExpression:
|
||||
n := node.AsFunctionExpression()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.AsteriskToken != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.TypeParameters != nil) << 3) | (boolToByte(n.Parameters != nil) << 4) | (boolToByte(n.Type != nil) << 5) | (boolToByte(n.Body != nil) << 6)
|
||||
case ast.KindAsExpression:
|
||||
n := node.AsAsExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.Type != nil) << 1)
|
||||
case ast.KindSatisfiesExpression:
|
||||
n := node.AsSatisfiesExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.Type != nil) << 1)
|
||||
case ast.KindConditionalExpression:
|
||||
n := node.AsConditionalExpression()
|
||||
return (boolToByte(n.Condition != nil) << 0) | (boolToByte(n.QuestionToken != nil) << 1) | (boolToByte(n.WhenTrue != nil) << 2) | (boolToByte(n.ColonToken != nil) << 3) | (boolToByte(n.WhenFalse != nil) << 4)
|
||||
case ast.KindPropertyAccessExpression:
|
||||
n := node.AsPropertyAccessExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.QuestionDotToken != nil) << 1) | (boolToByte(n.Name() != nil) << 2)
|
||||
case ast.KindElementAccessExpression:
|
||||
n := node.AsElementAccessExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.QuestionDotToken != nil) << 1) | (boolToByte(n.ArgumentExpression != nil) << 2)
|
||||
case ast.KindCallExpression:
|
||||
n := node.AsCallExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.QuestionDotToken != nil) << 1) | (boolToByte(n.TypeArguments != nil) << 2) | (boolToByte(n.Arguments != nil) << 3)
|
||||
case ast.KindNewExpression:
|
||||
n := node.AsNewExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.TypeArguments != nil) << 1) | (boolToByte(n.Arguments != nil) << 2)
|
||||
case ast.KindMetaProperty:
|
||||
n := node.AsMetaProperty()
|
||||
return (boolToByte(n.Name() != nil) << 0)
|
||||
case ast.KindNonNullExpression:
|
||||
n := node.AsNonNullExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindSpreadElement:
|
||||
n := node.AsSpreadElement()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindTemplateExpression:
|
||||
n := node.AsTemplateExpression()
|
||||
return (boolToByte(n.Head != nil) << 0) | (boolToByte(n.TemplateSpans != nil) << 1)
|
||||
case ast.KindTemplateSpan:
|
||||
n := node.AsTemplateSpan()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.Literal != nil) << 1)
|
||||
case ast.KindTaggedTemplateExpression:
|
||||
n := node.AsTaggedTemplateExpression()
|
||||
return (boolToByte(n.Tag != nil) << 0) | (boolToByte(n.QuestionDotToken != nil) << 1) | (boolToByte(n.TypeArguments != nil) << 2) | (boolToByte(n.Template != nil) << 3)
|
||||
case ast.KindParenthesizedExpression:
|
||||
n := node.AsParenthesizedExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindArrayLiteralExpression:
|
||||
n := node.AsArrayLiteralExpression()
|
||||
return (boolToByte(n.Elements != nil) << 0)
|
||||
case ast.KindObjectLiteralExpression:
|
||||
n := node.AsObjectLiteralExpression()
|
||||
return (boolToByte(n.Properties != nil) << 0)
|
||||
case ast.KindSpreadAssignment:
|
||||
n := node.AsSpreadAssignment()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindPropertyAssignment:
|
||||
n := node.AsPropertyAssignment()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.PostfixToken != nil) << 2) | (boolToByte(n.Type != nil) << 3) | (boolToByte(n.Initializer != nil) << 4)
|
||||
case ast.KindShorthandPropertyAssignment:
|
||||
n := node.AsShorthandPropertyAssignment()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.PostfixToken != nil) << 2) | (boolToByte(n.Type != nil) << 3) | (boolToByte(n.EqualsToken != nil) << 4) | (boolToByte(n.ObjectAssignmentInitializer != nil) << 5)
|
||||
case ast.KindDeleteExpression:
|
||||
n := node.AsDeleteExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindTypeOfExpression:
|
||||
n := node.AsTypeOfExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindVoidExpression:
|
||||
n := node.AsVoidExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindAwaitExpression:
|
||||
n := node.AsAwaitExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindTypeAssertionExpression:
|
||||
n := node.AsTypeAssertion()
|
||||
return (boolToByte(n.Type != nil) << 0) | (boolToByte(n.Expression != nil) << 1)
|
||||
case ast.KindUnionType:
|
||||
n := node.AsUnionTypeNode()
|
||||
return (boolToByte(n.Types != nil) << 0)
|
||||
case ast.KindIntersectionType:
|
||||
n := node.AsIntersectionTypeNode()
|
||||
return (boolToByte(n.Types != nil) << 0)
|
||||
case ast.KindConditionalType:
|
||||
n := node.AsConditionalTypeNode()
|
||||
return (boolToByte(n.CheckType != nil) << 0) | (boolToByte(n.ExtendsType != nil) << 1) | (boolToByte(n.TrueType != nil) << 2) | (boolToByte(n.FalseType != nil) << 3)
|
||||
case ast.KindTypeOperator:
|
||||
n := node.AsTypeOperatorNode()
|
||||
return (boolToByte(n.Type != nil) << 0)
|
||||
case ast.KindInferType:
|
||||
n := node.AsInferTypeNode()
|
||||
return (boolToByte(n.TypeParameter != nil) << 0)
|
||||
case ast.KindArrayType:
|
||||
n := node.AsArrayTypeNode()
|
||||
return (boolToByte(n.ElementType != nil) << 0)
|
||||
case ast.KindIndexedAccessType:
|
||||
n := node.AsIndexedAccessTypeNode()
|
||||
return (boolToByte(n.ObjectType != nil) << 0) | (boolToByte(n.IndexType != nil) << 1)
|
||||
case ast.KindTypeReference:
|
||||
n := node.AsTypeReferenceNode()
|
||||
return (boolToByte(n.TypeName != nil) << 0) | (boolToByte(n.TypeArguments != nil) << 1)
|
||||
case ast.KindExpressionWithTypeArguments:
|
||||
n := node.AsExpressionWithTypeArguments()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.TypeArguments != nil) << 1)
|
||||
case ast.KindLiteralType:
|
||||
n := node.AsLiteralTypeNode()
|
||||
return (boolToByte(n.Literal != nil) << 0)
|
||||
case ast.KindTypePredicate:
|
||||
n := node.AsTypePredicateNode()
|
||||
return (boolToByte(n.AssertsModifier != nil) << 0) | (boolToByte(n.ParameterName != nil) << 1) | (boolToByte(n.Type != nil) << 2)
|
||||
case ast.KindImportAttribute:
|
||||
n := node.AsImportAttribute()
|
||||
return (boolToByte(n.Name() != nil) << 0) | (boolToByte(n.Value != nil) << 1)
|
||||
case ast.KindImportAttributes:
|
||||
n := node.AsImportAttributes()
|
||||
return (boolToByte(n.Attributes != nil) << 0)
|
||||
case ast.KindTypeQuery:
|
||||
n := node.AsTypeQueryNode()
|
||||
return (boolToByte(n.ExprName != nil) << 0) | (boolToByte(n.TypeArguments != nil) << 1)
|
||||
case ast.KindMappedType:
|
||||
n := node.AsMappedTypeNode()
|
||||
return (boolToByte(n.ReadonlyToken != nil) << 0) | (boolToByte(n.TypeParameter != nil) << 1) | (boolToByte(n.NameType != nil) << 2) | (boolToByte(n.QuestionToken != nil) << 3) | (boolToByte(n.Type != nil) << 4) | (boolToByte(n.Members != nil) << 5)
|
||||
case ast.KindTypeLiteral:
|
||||
n := node.AsTypeLiteralNode()
|
||||
return (boolToByte(n.Members != nil) << 0)
|
||||
case ast.KindTupleType:
|
||||
n := node.AsTupleTypeNode()
|
||||
return (boolToByte(n.Elements != nil) << 0)
|
||||
case ast.KindNamedTupleMember:
|
||||
n := node.AsNamedTupleMember()
|
||||
return (boolToByte(n.DotDotDotToken != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.QuestionToken != nil) << 2) | (boolToByte(n.Type != nil) << 3)
|
||||
case ast.KindOptionalType:
|
||||
n := node.AsOptionalTypeNode()
|
||||
return (boolToByte(n.Type != nil) << 0)
|
||||
case ast.KindRestType:
|
||||
n := node.AsRestTypeNode()
|
||||
return (boolToByte(n.Type != nil) << 0)
|
||||
case ast.KindParenthesizedType:
|
||||
n := node.AsParenthesizedTypeNode()
|
||||
return (boolToByte(n.Type != nil) << 0)
|
||||
case ast.KindFunctionType:
|
||||
n := node.AsFunctionTypeNode()
|
||||
return (boolToByte(n.TypeParameters != nil) << 0) | (boolToByte(n.Parameters != nil) << 1) | (boolToByte(n.Type != nil) << 2)
|
||||
case ast.KindConstructorType:
|
||||
n := node.AsConstructorTypeNode()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.TypeParameters != nil) << 1) | (boolToByte(n.Parameters != nil) << 2) | (boolToByte(n.Type != nil) << 3)
|
||||
case ast.KindTemplateLiteralType:
|
||||
n := node.AsTemplateLiteralTypeNode()
|
||||
return (boolToByte(n.Head != nil) << 0) | (boolToByte(n.TemplateSpans != nil) << 1)
|
||||
case ast.KindTemplateLiteralTypeSpan:
|
||||
n := node.AsTemplateLiteralTypeSpan()
|
||||
return (boolToByte(n.Type != nil) << 0) | (boolToByte(n.Literal != nil) << 1)
|
||||
case ast.KindSyntheticExpression:
|
||||
n := node.AsSyntheticExpression()
|
||||
return (boolToByte(n.TupleNameSource != nil) << 0)
|
||||
case ast.KindPartiallyEmittedExpression:
|
||||
n := node.AsPartiallyEmittedExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindJsxElement:
|
||||
n := node.AsJsxElement()
|
||||
return (boolToByte(n.OpeningElement != nil) << 0) | (boolToByte(n.Children != nil) << 1) | (boolToByte(n.ClosingElement != nil) << 2)
|
||||
case ast.KindJsxAttributes:
|
||||
n := node.AsJsxAttributes()
|
||||
return (boolToByte(n.Properties != nil) << 0)
|
||||
case ast.KindJsxNamespacedName:
|
||||
n := node.AsJsxNamespacedName()
|
||||
return (boolToByte(n.Namespace != nil) << 0) | (boolToByte(n.Name() != nil) << 1)
|
||||
case ast.KindJsxOpeningElement:
|
||||
n := node.AsJsxOpeningElement()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeArguments != nil) << 1) | (boolToByte(n.Attributes != nil) << 2)
|
||||
case ast.KindJsxSelfClosingElement:
|
||||
n := node.AsJsxSelfClosingElement()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeArguments != nil) << 1) | (boolToByte(n.Attributes != nil) << 2)
|
||||
case ast.KindJsxFragment:
|
||||
n := node.AsJsxFragment()
|
||||
return (boolToByte(n.OpeningFragment != nil) << 0) | (boolToByte(n.Children != nil) << 1) | (boolToByte(n.ClosingFragment != nil) << 2)
|
||||
case ast.KindJsxAttribute:
|
||||
n := node.AsJsxAttribute()
|
||||
return (boolToByte(n.Name() != nil) << 0) | (boolToByte(n.Initializer != nil) << 1)
|
||||
case ast.KindJsxSpreadAttribute:
|
||||
n := node.AsJsxSpreadAttribute()
|
||||
return (boolToByte(n.Expression != nil) << 0)
|
||||
case ast.KindJsxClosingElement:
|
||||
n := node.AsJsxClosingElement()
|
||||
return (boolToByte(n.TagName != nil) << 0)
|
||||
case ast.KindJsxExpression:
|
||||
n := node.AsJsxExpression()
|
||||
return (boolToByte(n.DotDotDotToken != nil) << 0) | (boolToByte(n.Expression != nil) << 1)
|
||||
case ast.KindSyntaxList:
|
||||
n := node.AsSyntaxList()
|
||||
return (boolToByte(len(n.Children) > 0) << 0)
|
||||
case ast.KindJSDoc:
|
||||
n := node.AsJSDoc()
|
||||
return (boolToByte(n.Comment != nil) << 0) | (boolToByte(n.Tags != nil) << 1)
|
||||
case ast.KindJSDocTypeExpression:
|
||||
n := node.AsJSDocTypeExpression()
|
||||
return (boolToByte(n.Type != nil) << 0)
|
||||
case ast.KindJSDocNonNullableType:
|
||||
n := node.AsJSDocNonNullableType()
|
||||
return (boolToByte(n.Type != nil) << 0)
|
||||
case ast.KindJSDocNullableType:
|
||||
n := node.AsJSDocNullableType()
|
||||
return (boolToByte(n.Type != nil) << 0)
|
||||
case ast.KindJSDocVariadicType:
|
||||
n := node.AsJSDocVariadicType()
|
||||
return (boolToByte(n.Type != nil) << 0)
|
||||
case ast.KindJSDocOptionalType:
|
||||
n := node.AsJSDocOptionalType()
|
||||
return (boolToByte(n.Type != nil) << 0)
|
||||
case ast.KindJSDocTypeTag:
|
||||
n := node.AsJSDocTypeTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
|
||||
case ast.KindJSDocUnknownTag:
|
||||
n := node.AsJSDocUnknownTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
|
||||
case ast.KindJSDocTemplateTag:
|
||||
n := node.AsJSDocTemplateTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Constraint != nil) << 1) | (boolToByte(n.TypeParameters != nil) << 2) | (boolToByte(n.Comment != nil) << 3)
|
||||
case ast.KindJSDocReturnTag:
|
||||
n := node.AsJSDocReturnTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
|
||||
case ast.KindJSDocPublicTag:
|
||||
n := node.AsJSDocPublicTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
|
||||
case ast.KindJSDocPrivateTag:
|
||||
n := node.AsJSDocPrivateTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
|
||||
case ast.KindJSDocProtectedTag:
|
||||
n := node.AsJSDocProtectedTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
|
||||
case ast.KindJSDocReadonlyTag:
|
||||
n := node.AsJSDocReadonlyTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
|
||||
case ast.KindJSDocOverrideTag:
|
||||
n := node.AsJSDocOverrideTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
|
||||
case ast.KindJSDocDeprecatedTag:
|
||||
n := node.AsJSDocDeprecatedTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
|
||||
case ast.KindJSDocSeeTag:
|
||||
n := node.AsJSDocSeeTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.NameExpression != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
|
||||
case ast.KindJSDocImplementsTag:
|
||||
n := node.AsJSDocImplementsTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.ClassName != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
|
||||
case ast.KindJSDocAugmentsTag:
|
||||
n := node.AsJSDocAugmentsTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.ClassName != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
|
||||
case ast.KindJSDocSatisfiesTag:
|
||||
n := node.AsJSDocSatisfiesTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
|
||||
case ast.KindJSDocThrowsTag:
|
||||
n := node.AsJSDocThrowsTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
|
||||
case ast.KindJSDocThisTag:
|
||||
n := node.AsJSDocThisTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
|
||||
case ast.KindJSDocImportTag:
|
||||
n := node.AsJSDocImportTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.ImportClause != nil) << 1) | (boolToByte(n.ModuleSpecifier != nil) << 2) | (boolToByte(n.Attributes != nil) << 3) | (boolToByte(n.Comment != nil) << 4)
|
||||
case ast.KindJSDocCallbackTag:
|
||||
n := node.AsJSDocCallbackTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.Comment != nil) << 3)
|
||||
case ast.KindJSDocOverloadTag:
|
||||
n := node.AsJSDocOverloadTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
|
||||
case ast.KindJSDocTypedefTag:
|
||||
n := node.AsJSDocTypedefTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.Comment != nil) << 3)
|
||||
case ast.KindJSDocSignature:
|
||||
n := node.AsJSDocSignature()
|
||||
return (boolToByte(n.TypeParameters != nil) << 0) | (boolToByte(n.Parameters != nil) << 1) | (boolToByte(n.Type != nil) << 2)
|
||||
case ast.KindJSDocNameReference:
|
||||
n := node.AsJSDocNameReference()
|
||||
return (boolToByte(n.Name() != nil) << 0)
|
||||
case ast.KindModuleDeclaration:
|
||||
n := node.AsModuleDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.Body != nil) << 2)
|
||||
case ast.KindImportEqualsDeclaration:
|
||||
n := node.AsImportEqualsDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.ModuleReference != nil) << 2)
|
||||
case ast.KindExportDeclaration:
|
||||
n := node.AsExportDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.ExportClause != nil) << 1) | (boolToByte(n.ModuleSpecifier != nil) << 2) | (boolToByte(n.Attributes != nil) << 3)
|
||||
case ast.KindImportType:
|
||||
n := node.AsImportTypeNode()
|
||||
return (boolToByte(n.Argument != nil) << 0) | (boolToByte(n.Attributes != nil) << 1) | (boolToByte(n.Qualifier != nil) << 2) | (boolToByte(n.TypeArguments != nil) << 3)
|
||||
case ast.KindImportClause:
|
||||
n := node.AsImportClause()
|
||||
return (boolToByte(n.Name() != nil) << 0) | (boolToByte(n.NamedBindings != nil) << 1)
|
||||
case ast.KindImportSpecifier:
|
||||
n := node.AsImportSpecifier()
|
||||
return (boolToByte(n.PropertyName != nil) << 0) | (boolToByte(n.Name() != nil) << 1)
|
||||
case ast.KindJSDocLink:
|
||||
n := node.AsJSDocLink()
|
||||
return (boolToByte(n.Name() != nil) << 0)
|
||||
case ast.KindJSDocLinkPlain:
|
||||
n := node.AsJSDocLinkPlain()
|
||||
return (boolToByte(n.Name() != nil) << 0)
|
||||
case ast.KindJSDocLinkCode:
|
||||
n := node.AsJSDocLinkCode()
|
||||
return (boolToByte(n.Name() != nil) << 0)
|
||||
case ast.KindTypeParameter:
|
||||
n := node.AsTypeParameterDeclaration()
|
||||
return (boolToByte(hasModifiers(n.Modifiers())) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.Constraint != nil) << 2) | (boolToByte(n.Expression != nil) << 3) | (boolToByte(n.DefaultType != nil) << 4)
|
||||
case ast.KindSyntheticReferenceExpression:
|
||||
n := node.AsSyntheticReferenceExpression()
|
||||
return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.ThisArg != nil) << 1)
|
||||
case ast.KindJSDocTypeLiteral:
|
||||
n := node.AsJSDocTypeLiteral()
|
||||
return (boolToByte(len(n.JSDocPropertyTags) > 0) << 0)
|
||||
case ast.KindJSDocParameterTag, ast.KindJSDocPropertyTag:
|
||||
n := node.AsJSDocParameterOrPropertyTag()
|
||||
return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.TypeExpression != nil) << 2) | (boolToByte(n.Comment != nil) << 3)
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func getNodeCommonData(node *ast.Node) uint32 {
|
||||
switch node.Kind {
|
||||
case ast.KindBlock:
|
||||
n := node.AsBlock()
|
||||
return uint32(boolToByte(n.MultiLine)) << 24
|
||||
case ast.KindHeritageClause:
|
||||
n := node.AsHeritageClause()
|
||||
var tokenIdx uint32
|
||||
switch n.Token {
|
||||
case ast.KindImplementsKeyword:
|
||||
tokenIdx = 1
|
||||
}
|
||||
return tokenIdx << 24
|
||||
case ast.KindExportAssignment:
|
||||
n := node.AsExportAssignment()
|
||||
return uint32(boolToByte(n.IsExportEquals)) << 24
|
||||
case ast.KindExportSpecifier:
|
||||
n := node.AsExportSpecifier()
|
||||
return uint32(boolToByte(n.IsTypeOnly)) << 24
|
||||
case ast.KindPrefixUnaryExpression:
|
||||
n := node.AsPrefixUnaryExpression()
|
||||
var operatorIdx uint32
|
||||
switch n.Operator {
|
||||
case ast.KindMinusToken:
|
||||
operatorIdx = 1
|
||||
case ast.KindTildeToken:
|
||||
operatorIdx = 2
|
||||
case ast.KindExclamationToken:
|
||||
operatorIdx = 3
|
||||
case ast.KindPlusPlusToken:
|
||||
operatorIdx = 4
|
||||
case ast.KindMinusMinusToken:
|
||||
operatorIdx = 5
|
||||
}
|
||||
return operatorIdx << 24
|
||||
case ast.KindPostfixUnaryExpression:
|
||||
n := node.AsPostfixUnaryExpression()
|
||||
var operatorIdx uint32
|
||||
switch n.Operator {
|
||||
case ast.KindMinusMinusToken:
|
||||
operatorIdx = 1
|
||||
}
|
||||
return operatorIdx << 24
|
||||
case ast.KindMetaProperty:
|
||||
n := node.AsMetaProperty()
|
||||
var keywordTokenIdx uint32
|
||||
switch n.KeywordToken {
|
||||
case ast.KindNewKeyword:
|
||||
keywordTokenIdx = 1
|
||||
}
|
||||
return keywordTokenIdx << 24
|
||||
case ast.KindArrayLiteralExpression:
|
||||
n := node.AsArrayLiteralExpression()
|
||||
return uint32(boolToByte(n.MultiLine)) << 24
|
||||
case ast.KindObjectLiteralExpression:
|
||||
n := node.AsObjectLiteralExpression()
|
||||
return uint32(boolToByte(n.MultiLine)) << 24
|
||||
case ast.KindTypeOperator:
|
||||
n := node.AsTypeOperatorNode()
|
||||
var operatorIdx uint32
|
||||
switch n.Operator {
|
||||
case ast.KindReadonlyKeyword:
|
||||
operatorIdx = 1
|
||||
case ast.KindUniqueKeyword:
|
||||
operatorIdx = 2
|
||||
}
|
||||
return operatorIdx << 24
|
||||
case ast.KindImportAttributes:
|
||||
n := node.AsImportAttributes()
|
||||
var tokenIdx uint32
|
||||
switch n.Token {
|
||||
case ast.KindAssertKeyword:
|
||||
tokenIdx = 1
|
||||
}
|
||||
return uint32(boolToByte(n.MultiLine))<<24 | tokenIdx<<25
|
||||
case ast.KindSyntheticExpression:
|
||||
return getNodeCommonData_SyntheticExpression(node)
|
||||
case ast.KindJsxText:
|
||||
n := node.AsJsxText()
|
||||
return uint32(boolToByte(n.ContainsOnlyTriviaWhiteSpaces)) << 24
|
||||
case ast.KindModuleDeclaration:
|
||||
n := node.AsModuleDeclaration()
|
||||
var keywordIdx uint32
|
||||
switch n.Keyword {
|
||||
case ast.KindNamespaceKeyword:
|
||||
keywordIdx = 1
|
||||
}
|
||||
return keywordIdx << 24
|
||||
case ast.KindImportEqualsDeclaration:
|
||||
n := node.AsImportEqualsDeclaration()
|
||||
return uint32(boolToByte(n.IsTypeOnly)) << 24
|
||||
case ast.KindExportDeclaration:
|
||||
n := node.AsExportDeclaration()
|
||||
return uint32(boolToByte(n.IsTypeOnly)) << 24
|
||||
case ast.KindImportType:
|
||||
n := node.AsImportTypeNode()
|
||||
return uint32(boolToByte(n.IsTypeOf)) << 24
|
||||
case ast.KindImportClause:
|
||||
n := node.AsImportClause()
|
||||
var phaseModifierIdx uint32
|
||||
switch n.PhaseModifier {
|
||||
case ast.KindTypeKeyword:
|
||||
phaseModifierIdx = 1
|
||||
case ast.KindDeferKeyword:
|
||||
phaseModifierIdx = 2
|
||||
}
|
||||
return phaseModifierIdx << 24
|
||||
case ast.KindImportSpecifier:
|
||||
n := node.AsImportSpecifier()
|
||||
return uint32(boolToByte(n.IsTypeOnly)) << 24
|
||||
case ast.KindJSDocTypeLiteral:
|
||||
n := node.AsJSDocTypeLiteral()
|
||||
return uint32(boolToByte(n.IsArrayType)) << 24
|
||||
case ast.KindJSDocParameterTag, ast.KindJSDocPropertyTag:
|
||||
n := node.AsJSDocParameterOrPropertyTag()
|
||||
return uint32(boolToByte(n.IsBracketed))<<24 | uint32(boolToByte(n.IsNameFirst))<<25
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func recordNodeStrings(node *ast.Node, strs *stringTable) uint32 {
|
||||
switch node.Kind {
|
||||
case ast.KindIdentifier:
|
||||
return strs.add(node.AsIdentifier().Text, node.Kind, node.Pos(), node.End())
|
||||
case ast.KindPrivateIdentifier:
|
||||
return strs.add(node.AsPrivateIdentifier().Text, node.Kind, node.Pos(), node.End())
|
||||
case ast.KindJsxText:
|
||||
return strs.add(node.AsJsxText().Text, node.Kind, node.Pos(), node.End())
|
||||
case ast.KindJSDocText:
|
||||
return strs.add(node.AsJSDocText().Text(), node.Kind, node.Pos(), node.End())
|
||||
case ast.KindJSDocLink:
|
||||
return strs.add(node.AsJSDocLink().Text(), node.Kind, node.Pos(), node.End())
|
||||
case ast.KindJSDocLinkPlain:
|
||||
return strs.add(node.AsJSDocLinkPlain().Text(), node.Kind, node.Pos(), node.End())
|
||||
case ast.KindJSDocLinkCode:
|
||||
return strs.add(node.AsJSDocLinkCode().Text(), node.Kind, node.Pos(), node.End())
|
||||
default:
|
||||
panic(fmt.Sprintf("Unexpected node kind %v", node.Kind))
|
||||
}
|
||||
}
|
||||
|
||||
func recordExtendedData(node *ast.Node, strs *stringTable, positionMap *ast.PositionMap, extendedData *[]byte, structuredData *[]byte) uint32 {
|
||||
offset := uint32(len(*extendedData))
|
||||
switch node.Kind {
|
||||
case ast.KindStringLiteral:
|
||||
recordExtendedData_StringLiteral(node, strs, positionMap, extendedData, structuredData)
|
||||
case ast.KindNumericLiteral:
|
||||
recordExtendedData_NumericLiteral(node, strs, positionMap, extendedData, structuredData)
|
||||
case ast.KindBigIntLiteral:
|
||||
recordExtendedData_BigIntLiteral(node, strs, positionMap, extendedData, structuredData)
|
||||
case ast.KindRegularExpressionLiteral:
|
||||
recordExtendedData_RegularExpressionLiteral(node, strs, positionMap, extendedData, structuredData)
|
||||
case ast.KindNoSubstitutionTemplateLiteral:
|
||||
recordExtendedData_NoSubstitutionTemplateLiteral(node, strs, positionMap, extendedData, structuredData)
|
||||
case ast.KindTemplateHead:
|
||||
recordExtendedData_TemplateHead(node, strs, positionMap, extendedData, structuredData)
|
||||
case ast.KindTemplateMiddle:
|
||||
recordExtendedData_TemplateMiddle(node, strs, positionMap, extendedData, structuredData)
|
||||
case ast.KindTemplateTail:
|
||||
recordExtendedData_TemplateTail(node, strs, positionMap, extendedData, structuredData)
|
||||
case ast.KindSourceFile:
|
||||
recordExtendedData_SourceFile(node, strs, positionMap, extendedData, structuredData)
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown extended data node kind %v", node.Kind))
|
||||
}
|
||||
return offset
|
||||
}
|
||||
161
tools/tsgo/internal/api/encoder/encoder_test.go
Normal file
161
tools/tsgo/internal/api/encoder/encoder_test.go
Normal file
@@ -0,0 +1,161 @@
|
||||
package encoder_test
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/api/encoder"
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/parser"
|
||||
"github.com/microsoft/typescript-go/internal/repo"
|
||||
"github.com/microsoft/typescript-go/internal/testutil/baseline"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestEncodeSourceFile(t *testing.T) {
|
||||
t.Parallel()
|
||||
sourceFile := parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/test.ts",
|
||||
Path: "/test.ts",
|
||||
}, "import { bar } from \"bar\";\nexport function foo<T, U>(a: string, b: string): any {}\nfoo();", core.ScriptKindTS)
|
||||
t.Run("baseline", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
buf, _, err := encoder.EncodeSourceFile(sourceFile)
|
||||
assert.NilError(t, err)
|
||||
|
||||
str := formatEncodedSourceFile(buf)
|
||||
baseline.Run(t, "encodeSourceFile.txt", str, baseline.Options{
|
||||
Subfolder: "api",
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestEncodeSourceFileWithUnicodeEscapes(t *testing.T) {
|
||||
t.Parallel()
|
||||
sourceFile := parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/test.ts",
|
||||
Path: "/test.ts",
|
||||
}, `let a = "😃"; let b = "\ud83d\ude03"; let c = "\udc00\ud83d\ude03"; let d = "\ud83d\ud83d\ude03"`, core.ScriptKindTS)
|
||||
t.Run("baseline", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
buf, _, err := encoder.EncodeSourceFile(sourceFile)
|
||||
assert.NilError(t, err)
|
||||
|
||||
str := formatEncodedSourceFile(buf)
|
||||
baseline.Run(t, "encodeSourceFileWithUnicodeEscapes.txt", str, baseline.Options{
|
||||
Subfolder: "api",
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBuildNodeIndexTableMatchesEncode(t *testing.T) {
|
||||
t.Parallel()
|
||||
sourceFile := parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/test.ts",
|
||||
Path: "/test.ts",
|
||||
}, "import { bar } from \"bar\";\nexport function foo<T, U>(a: string, b: string): any {}\nfoo();", core.ScriptKindTS)
|
||||
|
||||
_, encodeTable, err := encoder.EncodeSourceFile(sourceFile)
|
||||
assert.NilError(t, err)
|
||||
|
||||
buildTable := encoder.BuildNodeIndexTable(sourceFile)
|
||||
|
||||
// Both tables should produce identical Nodes slices
|
||||
assert.Equal(t, len(buildTable.Nodes), len(encodeTable.Nodes), "Nodes slice length mismatch")
|
||||
|
||||
// Every index should map to the same node
|
||||
for i := range encodeTable.Nodes {
|
||||
assert.Equal(t, buildTable.Nodes[i], encodeTable.Nodes[i], "node mismatch at index %d", i)
|
||||
}
|
||||
|
||||
// GetIndex on both tables should agree for every non-nil node
|
||||
for i, node := range encodeTable.Nodes {
|
||||
if node == nil {
|
||||
continue
|
||||
}
|
||||
encIdx := encodeTable.GetIndex(node)
|
||||
buildIdx := buildTable.GetIndex(node)
|
||||
assert.Equal(t, encIdx, uint32(i), "encodeTable.GetIndex mismatch at index %d, node kind=%s", i, node.Kind.String())
|
||||
assert.Equal(t, buildIdx, encIdx, "buildTable.GetIndex mismatch for node kind=%s", node.Kind.String())
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodeSourceFile(b *testing.B) {
|
||||
repo.SkipIfNoTypeScriptSubmodule(b)
|
||||
filePath := filepath.Join(repo.TypeScriptSubmodulePath(), "src/compiler/checker.ts")
|
||||
fileContent, err := os.ReadFile(filePath)
|
||||
assert.NilError(b, err)
|
||||
sourceFile := parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/checker.ts",
|
||||
Path: "/checker.ts",
|
||||
}, string(fileContent), core.ScriptKindTS)
|
||||
|
||||
for b.Loop() {
|
||||
_, _, err := encoder.EncodeSourceFile(sourceFile)
|
||||
assert.NilError(b, err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkBuildNodeIndexTable(b *testing.B) {
|
||||
repo.SkipIfNoTypeScriptSubmodule(b)
|
||||
filePath := filepath.Join(repo.TypeScriptSubmodulePath(), "src/compiler/checker.ts")
|
||||
fileContent, err := os.ReadFile(filePath)
|
||||
assert.NilError(b, err)
|
||||
sourceFile := parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/checker.ts",
|
||||
Path: "/checker.ts",
|
||||
}, string(fileContent), core.ScriptKindTS)
|
||||
|
||||
for b.Loop() {
|
||||
encoder.BuildNodeIndexTable(sourceFile)
|
||||
}
|
||||
}
|
||||
|
||||
func readUint32(buf []byte, offset int) uint32 {
|
||||
return binary.LittleEndian.Uint32(buf[offset : offset+4])
|
||||
}
|
||||
|
||||
func formatEncodedSourceFile(encoded []byte) string {
|
||||
var result strings.Builder
|
||||
var getIndent func(parentIndex uint32) string
|
||||
offsetNodes := readUint32(encoded, encoder.HeaderOffsetNodes)
|
||||
offsetStringOffsets := readUint32(encoded, encoder.HeaderOffsetStringOffsets)
|
||||
offsetStrings := readUint32(encoded, encoder.HeaderOffsetStringData)
|
||||
getIndent = func(parentIndex uint32) string {
|
||||
if parentIndex == 0 {
|
||||
return ""
|
||||
}
|
||||
return " " + getIndent(readUint32(encoded, int(offsetNodes)+int(parentIndex)*encoder.NodeSize+encoder.NodeOffsetParent))
|
||||
}
|
||||
j := 1
|
||||
for i := int(offsetNodes) + encoder.NodeSize; i < len(encoded); i += encoder.NodeSize {
|
||||
kind := readUint32(encoded, i+encoder.NodeOffsetKind)
|
||||
pos := readUint32(encoded, i+encoder.NodeOffsetPos)
|
||||
end := readUint32(encoded, i+encoder.NodeOffsetEnd)
|
||||
parentIndex := readUint32(encoded, i+encoder.NodeOffsetParent)
|
||||
result.WriteString(getIndent(parentIndex))
|
||||
if kind == encoder.SyntaxKindNodeList {
|
||||
result.WriteString("NodeList")
|
||||
} else {
|
||||
result.WriteString(ast.Kind(kind).String())
|
||||
}
|
||||
data := readUint32(encoded, i+encoder.NodeOffsetData)
|
||||
dataType := data & encoder.NodeDataTypeMask
|
||||
if ast.Kind(kind) == ast.KindIdentifier || (dataType == encoder.NodeDataTypeString) {
|
||||
stringIndex := data & encoder.NodeDataStringIndexMask
|
||||
strStart := readUint32(encoded, int(offsetStringOffsets+stringIndex*4))
|
||||
strEnd := readUint32(encoded, int(offsetStringOffsets+stringIndex*4)+4)
|
||||
str := string(encoded[offsetStrings+strStart : offsetStrings+strEnd])
|
||||
result.WriteString(fmt.Sprintf(" \"%s\"", str))
|
||||
}
|
||||
fmt.Fprintf(&result, " [%d, %d), i=%d, next=%d", pos, end, j, encoded[i+encoder.NodeOffsetNext])
|
||||
result.WriteString("\n")
|
||||
j++
|
||||
}
|
||||
return result.String()
|
||||
}
|
||||
68
tools/tsgo/internal/api/encoder/stringtable.go
Normal file
68
tools/tsgo/internal/api/encoder/stringtable.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package encoder
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
)
|
||||
|
||||
type stringTable struct {
|
||||
fileText string
|
||||
otherStrings *strings.Builder
|
||||
// offsets are pos/end pairs
|
||||
offsets []uint32
|
||||
}
|
||||
|
||||
func newStringTable(fileText string, stringCount int) *stringTable {
|
||||
builder := &strings.Builder{}
|
||||
return &stringTable{
|
||||
fileText: fileText,
|
||||
otherStrings: builder,
|
||||
offsets: make([]uint32, 0, stringCount*2),
|
||||
}
|
||||
}
|
||||
|
||||
func (t *stringTable) add(text string, kind ast.Kind, pos int, end int) uint32 {
|
||||
index := uint32(len(t.offsets))
|
||||
if kind == ast.KindSourceFile {
|
||||
t.offsets = append(t.offsets, uint32(pos), uint32(end))
|
||||
return index
|
||||
}
|
||||
length := len(text)
|
||||
if end-pos > 0 && end <= len(t.fileText) {
|
||||
// pos includes leading trivia, but we can usually infer the actual start of the
|
||||
// string from the kind and end
|
||||
endOffset := 0
|
||||
if kind == ast.KindStringLiteral || kind == ast.KindTemplateTail || kind == ast.KindNoSubstitutionTemplateLiteral {
|
||||
endOffset = 1
|
||||
}
|
||||
end = end - endOffset
|
||||
start := end - length
|
||||
fileSlice := t.fileText[start:end]
|
||||
if fileSlice == text {
|
||||
t.offsets = append(t.offsets, uint32(start), uint32(end))
|
||||
return index
|
||||
}
|
||||
}
|
||||
// no exact match, so we need to add it to the string table
|
||||
offset := len(t.fileText) + t.otherStrings.Len()
|
||||
t.otherStrings.WriteString(text)
|
||||
t.offsets = append(t.offsets, uint32(offset), uint32(offset+length))
|
||||
return index
|
||||
}
|
||||
|
||||
func (t *stringTable) encode() []byte {
|
||||
result := make([]byte, 0, t.encodedLength())
|
||||
result = appendUint32s(result, t.offsets...)
|
||||
result = append(result, t.fileText...)
|
||||
result = append(result, t.otherStrings.String()...)
|
||||
return result
|
||||
}
|
||||
|
||||
func (t *stringTable) stringLength() int {
|
||||
return len(t.fileText) + t.otherStrings.Len()
|
||||
}
|
||||
|
||||
func (t *stringTable) encodedLength() int {
|
||||
return len(t.offsets)*4 + len(t.fileText) + t.otherStrings.Len()
|
||||
}
|
||||
14
tools/tsgo/internal/api/encoder/testmain_test.go
Normal file
14
tools/tsgo/internal/api/encoder/testmain_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package encoder_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/testutil/baseline"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
core.ApplyDebugStackLimit()
|
||||
defer baseline.Track()()
|
||||
m.Run()
|
||||
}
|
||||
1225
tools/tsgo/internal/api/proto.go
Normal file
1225
tools/tsgo/internal/api/proto.go
Normal file
File diff suppressed because it is too large
Load Diff
83
tools/tsgo/internal/api/proto_test.go
Normal file
83
tools/tsgo/internal/api/proto_test.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package api_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/api"
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/diagnostics"
|
||||
"github.com/microsoft/typescript-go/internal/json"
|
||||
"github.com/microsoft/typescript-go/internal/parser"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestDocumentIdentifierUnmarshalJSON(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
fileName string
|
||||
uri string
|
||||
err string
|
||||
}{
|
||||
{
|
||||
name: "plain string",
|
||||
input: `"foo.ts"`,
|
||||
fileName: "foo.ts",
|
||||
},
|
||||
{
|
||||
name: "uri object",
|
||||
input: `{"uri":"file:///foo.ts"}`,
|
||||
uri: "file:///foo.ts",
|
||||
},
|
||||
{
|
||||
name: "uri object with unknown fields",
|
||||
input: `{"uri":"file:///foo.ts","extra":true}`,
|
||||
uri: "file:///foo.ts",
|
||||
},
|
||||
{
|
||||
name: "empty object",
|
||||
input: `{}`,
|
||||
},
|
||||
{
|
||||
name: "invalid type",
|
||||
input: `42`,
|
||||
err: "expected string or object, got number",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
var d api.DocumentIdentifier
|
||||
err := json.Unmarshal([]byte(tt.input), &d)
|
||||
if tt.err != "" {
|
||||
assert.ErrorContains(t, err, tt.err)
|
||||
return
|
||||
}
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, d.FileName, tt.fileName)
|
||||
assert.Equal(t, string(d.URI), tt.uri)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDiagnosticResponseUsesUTF16Offsets(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
text := "const 💩 = 1;"
|
||||
file := parser.ParseSourceFile(ast.SourceFileParseOptions{FileName: "/unicode.ts"}, text, core.ScriptKindTS)
|
||||
pos := strings.Index(text, "=")
|
||||
assert.Assert(t, pos > 0)
|
||||
end := pos + len("=")
|
||||
|
||||
diag := ast.NewDiagnostic(file, core.NewTextRange(pos, end), diagnostics.Expression_expected)
|
||||
resp := api.NewDiagnosticResponse(diag)
|
||||
|
||||
assert.Equal(t, resp.Pos, 9)
|
||||
assert.Equal(t, resp.End, 10)
|
||||
assert.Equal(t, resp.Pos, file.GetPositionMap().UTF8ToUTF16(pos))
|
||||
assert.Equal(t, resp.End, file.GetPositionMap().UTF8ToUTF16(end))
|
||||
}
|
||||
22
tools/tsgo/internal/api/protocol.go
Normal file
22
tools/tsgo/internal/api/protocol.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/microsoft/typescript-go/internal/jsonrpc"
|
||||
)
|
||||
|
||||
// Message is an alias for jsonrpc.Message for convenience.
|
||||
type Message = jsonrpc.Message
|
||||
|
||||
// Protocol defines the interface for reading and writing API messages.
|
||||
type Protocol interface {
|
||||
// ReadMessage reads the next message from the connection.
|
||||
ReadMessage() (*Message, error)
|
||||
// WriteRequest writes a request message.
|
||||
WriteRequest(id *jsonrpc.ID, method string, params any) error
|
||||
// WriteNotification writes a notification message (no ID).
|
||||
WriteNotification(method string, params any) error
|
||||
// WriteResponse writes a successful response.
|
||||
WriteResponse(id *jsonrpc.ID, result any) error
|
||||
// WriteError writes an error response.
|
||||
WriteError(id *jsonrpc.ID, err *jsonrpc.ResponseError) error
|
||||
}
|
||||
96
tools/tsgo/internal/api/protocol_jsonrpc.go
Normal file
96
tools/tsgo/internal/api/protocol_jsonrpc.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/json"
|
||||
"github.com/microsoft/typescript-go/internal/jsonrpc"
|
||||
)
|
||||
|
||||
// JSONRPCProtocol implements the Protocol interface using JSON-RPC 2.0
|
||||
// with the LSP base protocol framing (Content-Length headers).
|
||||
type JSONRPCProtocol struct {
|
||||
reader *jsonrpc.Reader
|
||||
writer *jsonrpc.Writer
|
||||
}
|
||||
|
||||
var _ Protocol = (*JSONRPCProtocol)(nil)
|
||||
|
||||
// NewJSONRPCProtocol creates a new JSON-RPC protocol handler.
|
||||
func NewJSONRPCProtocol(rw io.ReadWriter) *JSONRPCProtocol {
|
||||
return &JSONRPCProtocol{
|
||||
reader: jsonrpc.NewReader(rw),
|
||||
writer: jsonrpc.NewWriter(rw),
|
||||
}
|
||||
}
|
||||
|
||||
// ReadMessage implements Protocol.
|
||||
func (p *JSONRPCProtocol) ReadMessage() (*Message, error) {
|
||||
data, err := p.reader.Read()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
if err := json.Unmarshal(data, &msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &msg, nil
|
||||
}
|
||||
|
||||
// WriteRequest implements Protocol.
|
||||
func (p *JSONRPCProtocol) WriteRequest(id *jsonrpc.ID, method string, params any) error {
|
||||
msg := jsonrpc.RequestMessage{
|
||||
ID: id,
|
||||
Method: method,
|
||||
Params: params,
|
||||
}
|
||||
data, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.writer.Write(data)
|
||||
}
|
||||
|
||||
// WriteNotification implements Protocol.
|
||||
func (p *JSONRPCProtocol) WriteNotification(method string, params any) error {
|
||||
msg := jsonrpc.RequestMessage{
|
||||
Method: method,
|
||||
Params: params,
|
||||
}
|
||||
data, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.writer.Write(data)
|
||||
}
|
||||
|
||||
// WriteResponse implements Protocol.
|
||||
func (p *JSONRPCProtocol) WriteResponse(id *jsonrpc.ID, result any) error {
|
||||
if result == nil {
|
||||
result = json.Value("null")
|
||||
}
|
||||
msg := jsonrpc.ResponseMessage{
|
||||
ID: id,
|
||||
Result: result,
|
||||
}
|
||||
data, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.writer.Write(data)
|
||||
}
|
||||
|
||||
// WriteError implements Protocol.
|
||||
func (p *JSONRPCProtocol) WriteError(id *jsonrpc.ID, respErr *jsonrpc.ResponseError) error {
|
||||
msg := jsonrpc.ResponseMessage{
|
||||
ID: id,
|
||||
Error: respErr,
|
||||
}
|
||||
data, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.writer.Write(data)
|
||||
}
|
||||
280
tools/tsgo/internal/api/protocol_msgpack.go
Normal file
280
tools/tsgo/internal/api/protocol_msgpack.go
Normal file
@@ -0,0 +1,280 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/json"
|
||||
"github.com/microsoft/typescript-go/internal/jsonrpc"
|
||||
)
|
||||
|
||||
// MessageType represents the type of message in the msgpack protocol.
|
||||
type MessageType uint8
|
||||
|
||||
const (
|
||||
MessageTypeUnknown MessageType = iota
|
||||
MessageTypeRequest
|
||||
MessageTypeCallResponse
|
||||
MessageTypeCallError
|
||||
MessageTypeResponse
|
||||
MessageTypeError
|
||||
MessageTypeCall
|
||||
)
|
||||
|
||||
func (m MessageType) IsValid() bool {
|
||||
return m >= MessageTypeRequest && m <= MessageTypeCall
|
||||
}
|
||||
|
||||
// MessagePack format constants
|
||||
const (
|
||||
msgpackFixedArray3 byte = 0x93
|
||||
msgpackBin8 byte = 0xC4
|
||||
msgpackBin16 byte = 0xC5
|
||||
msgpackBin32 byte = 0xC6
|
||||
msgpackU8 byte = 0xCC
|
||||
)
|
||||
|
||||
// MessagePackProtocol implements the Protocol interface using a custom
|
||||
// msgpack-based tuple format: [MessageType, method, payload].
|
||||
type MessagePackProtocol struct {
|
||||
r *bufio.Reader
|
||||
w *bufio.Writer
|
||||
}
|
||||
|
||||
var _ Protocol = (*MessagePackProtocol)(nil)
|
||||
|
||||
// NewMessagePackProtocol creates a new msgpack protocol handler.
|
||||
func NewMessagePackProtocol(rw io.ReadWriter) *MessagePackProtocol {
|
||||
return &MessagePackProtocol{
|
||||
r: bufio.NewReader(rw),
|
||||
w: bufio.NewWriter(rw),
|
||||
}
|
||||
}
|
||||
|
||||
// ReadMessage implements Protocol.
|
||||
func (p *MessagePackProtocol) ReadMessage() (*Message, error) {
|
||||
msgType, method, payload, err := p.readTuple()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Convert msgpack message type to JSON-RPC message
|
||||
msg := &Message{}
|
||||
|
||||
switch msgType {
|
||||
case MessageTypeRequest:
|
||||
// Client request - needs an ID for response
|
||||
// We use the method as a pseudo-ID since this protocol doesn't have explicit IDs
|
||||
id := jsonrpc.NewIDString(method)
|
||||
msg.ID = id
|
||||
msg.Method = method
|
||||
msg.Params = payload
|
||||
case MessageTypeCallResponse:
|
||||
// Response to our Call - use method as ID
|
||||
// Note: Method must be empty for IsResponse() to return true
|
||||
id := jsonrpc.NewIDString(method)
|
||||
msg.ID = id
|
||||
msg.Result = payload
|
||||
case MessageTypeCallError:
|
||||
// Error response to our Call
|
||||
// Note: Method must be empty for IsResponse() to return true
|
||||
id := jsonrpc.NewIDString(method)
|
||||
msg.ID = id
|
||||
msg.Error = &jsonrpc.ResponseError{
|
||||
Code: jsonrpc.CodeInternalError,
|
||||
Message: string(payload),
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected message type: %d", msgType)
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func (p *MessagePackProtocol) readTuple() (MessageType, string, []byte, error) {
|
||||
// Read fixed array marker (0x93 = 3-element array)
|
||||
t, err := p.r.ReadByte()
|
||||
if err != nil {
|
||||
return 0, "", nil, err
|
||||
}
|
||||
if t != msgpackFixedArray3 {
|
||||
return 0, "", nil, fmt.Errorf("%w: expected fixed 3-element array (0x93), received: 0x%02x", ErrInvalidRequest, t)
|
||||
}
|
||||
|
||||
// Read message type - can be positive fixint (0x00-0x7F) or uint8 (0xCC + value)
|
||||
t, err = p.r.ReadByte()
|
||||
if err != nil {
|
||||
return 0, "", nil, err
|
||||
}
|
||||
var rawType byte
|
||||
if t <= 0x7F {
|
||||
// Positive fixint - the byte IS the value
|
||||
rawType = t
|
||||
} else if t == msgpackU8 {
|
||||
// uint8 marker - next byte is the value
|
||||
rawType, err = p.r.ReadByte()
|
||||
if err != nil {
|
||||
return 0, "", nil, err
|
||||
}
|
||||
} else {
|
||||
return 0, "", nil, fmt.Errorf("%w: expected positive fixint or uint8 marker, received: 0x%02x", ErrInvalidRequest, t)
|
||||
}
|
||||
msgType := MessageType(rawType)
|
||||
if !msgType.IsValid() {
|
||||
return 0, "", nil, fmt.Errorf("%w: unknown message type: %d", ErrInvalidRequest, msgType)
|
||||
}
|
||||
|
||||
// Read method (binary)
|
||||
methodBytes, err := p.readBin()
|
||||
if err != nil {
|
||||
return 0, "", nil, err
|
||||
}
|
||||
method := string(methodBytes)
|
||||
|
||||
// Read payload (binary)
|
||||
payload, err := p.readBin()
|
||||
if err != nil {
|
||||
return 0, "", nil, err
|
||||
}
|
||||
|
||||
return msgType, method, payload, nil
|
||||
}
|
||||
|
||||
func (p *MessagePackProtocol) readBin() ([]byte, error) {
|
||||
t, err := p.r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var size uint
|
||||
switch t {
|
||||
case msgpackBin8:
|
||||
var size8 uint8
|
||||
if err = binary.Read(p.r, binary.BigEndian, &size8); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
size = uint(size8)
|
||||
case msgpackBin16:
|
||||
var size16 uint16
|
||||
if err = binary.Read(p.r, binary.BigEndian, &size16); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
size = uint(size16)
|
||||
case msgpackBin32:
|
||||
var size32 uint32
|
||||
if err = binary.Read(p.r, binary.BigEndian, &size32); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
size = uint(size32)
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: expected binary data (0xc4-0xc6), received: 0x%02x", ErrInvalidRequest, t)
|
||||
}
|
||||
|
||||
payload := make([]byte, size)
|
||||
if _, err := io.ReadFull(p.r, payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
// WriteRequest implements Protocol.
|
||||
func (p *MessagePackProtocol) WriteRequest(id *jsonrpc.ID, method string, params any) error {
|
||||
// For msgpack protocol, requests from server are "Call" type
|
||||
payload, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.writeTuple(MessageTypeCall, method, payload)
|
||||
}
|
||||
|
||||
// WriteNotification implements Protocol.
|
||||
func (p *MessagePackProtocol) WriteNotification(method string, params any) error {
|
||||
// Msgpack protocol doesn't distinguish notifications from calls
|
||||
return p.WriteRequest(nil, method, params)
|
||||
}
|
||||
|
||||
// WriteResponse implements Protocol.
|
||||
func (p *MessagePackProtocol) WriteResponse(id *jsonrpc.ID, result any) error {
|
||||
method := ""
|
||||
if id != nil {
|
||||
method = id.String()
|
||||
}
|
||||
|
||||
var payload []byte
|
||||
var err error
|
||||
|
||||
// Check if result is raw binary (for efficient binary transport)
|
||||
if raw, ok := result.(RawBinary); ok {
|
||||
payload = []byte(raw)
|
||||
} else {
|
||||
payload, err = json.Marshal(result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return p.writeTuple(MessageTypeResponse, method, payload)
|
||||
}
|
||||
|
||||
// WriteError implements Protocol.
|
||||
func (p *MessagePackProtocol) WriteError(id *jsonrpc.ID, respErr *jsonrpc.ResponseError) error {
|
||||
method := ""
|
||||
if id != nil {
|
||||
method = id.String()
|
||||
}
|
||||
return p.writeTuple(MessageTypeError, method, []byte(respErr.Message))
|
||||
}
|
||||
|
||||
func (p *MessagePackProtocol) writeTuple(msgType MessageType, method string, payload []byte) error {
|
||||
// Write fixed array marker
|
||||
if err := p.w.WriteByte(msgpackFixedArray3); err != nil {
|
||||
return err
|
||||
}
|
||||
// Write message type as positive fixint (values 0-127 are written directly)
|
||||
if err := p.w.WriteByte(byte(msgType)); err != nil {
|
||||
return err
|
||||
}
|
||||
// Write method
|
||||
if err := p.writeBin([]byte(method)); err != nil {
|
||||
return err
|
||||
}
|
||||
// Write payload
|
||||
if err := p.writeBin(payload); err != nil {
|
||||
return err
|
||||
}
|
||||
return p.w.Flush()
|
||||
}
|
||||
|
||||
func (p *MessagePackProtocol) writeBin(data []byte) error {
|
||||
length := len(data)
|
||||
if length < 256 {
|
||||
if err := p.w.WriteByte(msgpackBin8); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.w.WriteByte(byte(length)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if length < 1<<16 {
|
||||
if err := p.w.WriteByte(msgpackBin16); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(p.w, binary.BigEndian, uint16(length)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := p.w.WriteByte(msgpackBin32); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(p.w, binary.BigEndian, uint32(length)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err := p.w.Write(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// RawBinary is a marker type for binary data that should be written
|
||||
// directly by MessagePackProtocol instead of being JSON-encoded.
|
||||
type RawBinary []byte
|
||||
124
tools/tsgo/internal/api/server.go
Normal file
124
tools/tsgo/internal/api/server.go
Normal file
@@ -0,0 +1,124 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/bundled"
|
||||
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
|
||||
"github.com/microsoft/typescript-go/internal/project"
|
||||
"github.com/microsoft/typescript-go/internal/vfs/osvfs"
|
||||
)
|
||||
|
||||
// StdioServerOptions configures the STDIO-based API server.
|
||||
type StdioServerOptions struct {
|
||||
In io.ReadCloser
|
||||
Out io.WriteCloser
|
||||
Err io.Writer
|
||||
Cwd string
|
||||
DefaultLibraryPath string
|
||||
// PipePath, if set, listens on a named pipe (Windows) or Unix domain
|
||||
// socket instead of using In/Out for communication.
|
||||
PipePath string
|
||||
// Callbacks specifies which filesystem operations should be delegated
|
||||
// to the client (e.g., "readFile", "fileExists"). Empty means no callbacks.
|
||||
Callbacks []string
|
||||
// Async enables JSON-RPC protocol with async connection handling.
|
||||
// When false (default), uses MessagePack protocol with sync connection.
|
||||
Async bool
|
||||
// CollectTiming enables per-request server processing-time measurement.
|
||||
// When enabled, the server accumulates each request's processing time into
|
||||
// running totals and a recent-request ring buffer. Response messages are
|
||||
// left unchanged; the client folds this data into its own timing snapshot
|
||||
// on demand via getServerTiming / resetServerTiming requests.
|
||||
CollectTiming bool
|
||||
}
|
||||
|
||||
// StdioServer runs an API session over STDIO using MessagePack protocol.
|
||||
// This is the entry point for the synchronous STDIO-based API used by
|
||||
// native TypeScript tooling integration.
|
||||
type StdioServer struct {
|
||||
options *StdioServerOptions
|
||||
}
|
||||
|
||||
// NewStdioServer creates a new STDIO-based API server.
|
||||
func NewStdioServer(options *StdioServerOptions) *StdioServer {
|
||||
if options.Cwd == "" {
|
||||
panic("StdioServerOptions.Cwd is required")
|
||||
}
|
||||
|
||||
return &StdioServer{
|
||||
options: options,
|
||||
}
|
||||
}
|
||||
|
||||
// Run starts the server and blocks until the connection closes.
|
||||
func (s *StdioServer) Run(ctx context.Context) error {
|
||||
var transport Transport
|
||||
if s.options.PipePath != "" {
|
||||
t, err := NewPipeTransport(s.options.PipePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create pipe transport: %w", err)
|
||||
}
|
||||
defer t.Close()
|
||||
transport = t
|
||||
} else {
|
||||
t := NewStdioTransport(s.options.In, s.options.Out)
|
||||
defer t.Close()
|
||||
transport = t
|
||||
}
|
||||
|
||||
fs := bundled.WrapFS(osvfs.FS())
|
||||
|
||||
// Wrap the base FS with callbackFS if callbacks are requested
|
||||
var callbackFS *callbackFS
|
||||
if len(s.options.Callbacks) > 0 {
|
||||
callbackFS = newCallbackFS(fs, s.options.Callbacks)
|
||||
fs = callbackFS
|
||||
}
|
||||
|
||||
projectSession := project.NewSession(&project.SessionInit{
|
||||
BackgroundCtx: ctx,
|
||||
Logger: nil, // TODO: Add logging support
|
||||
FS: fs,
|
||||
Options: &project.SessionOptions{
|
||||
CurrentDirectory: s.options.Cwd,
|
||||
DefaultLibraryPath: s.options.DefaultLibraryPath,
|
||||
PositionEncoding: lsproto.PositionEncodingKindUTF8,
|
||||
LoggingEnabled: false,
|
||||
},
|
||||
})
|
||||
|
||||
session := NewSession(projectSession, &SessionOptions{
|
||||
UseBinaryResponses: !s.options.Async, // Only msgpack uses binary responses
|
||||
})
|
||||
defer session.Close()
|
||||
|
||||
// Accept connection from transport
|
||||
rwc, err := transport.Accept()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to accept connection: %w", err)
|
||||
}
|
||||
|
||||
// Create protocol and connection based on async mode
|
||||
var conn Conn
|
||||
if s.options.Async {
|
||||
protocol := NewJSONRPCProtocol(rwc)
|
||||
asyncConn := NewAsyncConnWithProtocol(rwc, protocol, session)
|
||||
asyncConn.SetCollectTiming(s.options.CollectTiming)
|
||||
conn = asyncConn
|
||||
} else {
|
||||
protocol := NewMessagePackProtocol(rwc)
|
||||
syncConn := NewSyncConn(rwc, protocol, session)
|
||||
syncConn.SetCollectTiming(s.options.CollectTiming)
|
||||
conn = syncConn
|
||||
}
|
||||
|
||||
// If callbacks are enabled, set the connection on the FS
|
||||
if callbackFS != nil {
|
||||
callbackFS.SetConnection(ctx, conn)
|
||||
}
|
||||
|
||||
return conn.Run(ctx)
|
||||
}
|
||||
3210
tools/tsgo/internal/api/session.go
Normal file
3210
tools/tsgo/internal/api/session.go
Normal file
File diff suppressed because it is too large
Load Diff
255
tools/tsgo/internal/api/session_apistate_test.go
Normal file
255
tools/tsgo/internal/api/session_apistate_test.go
Normal file
@@ -0,0 +1,255 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/bundled"
|
||||
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
|
||||
"github.com/microsoft/typescript-go/internal/testutil/projecttestutil"
|
||||
"github.com/microsoft/typescript-go/internal/tspath"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
// TestSessionTracksAndReleasesAPIRefs verifies that an API session holds at most
|
||||
// one ref per opened project/file (opens are idempotent) and releases exactly
|
||||
// those refs when the session is closed, so it never leaks or over-releases refs
|
||||
// in the underlying (potentially shared) project session.
|
||||
func TestSessionTracksAndReleasesAPIRefs(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !bundled.Embedded {
|
||||
t.Skip("bundled files are not embedded")
|
||||
}
|
||||
|
||||
t.Run("project opens are idempotent and released on close", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
const configFileName = "/home/projects/p/tsconfig.json"
|
||||
files := map[string]any{
|
||||
configFileName: `{ "compilerOptions": { "strict": true } }`,
|
||||
"/home/projects/p/src/index.ts": `export const x = 1;`,
|
||||
}
|
||||
projectSession, _ := projecttestutil.Setup(files)
|
||||
defer projectSession.Close()
|
||||
session := NewSession(projectSession, nil)
|
||||
|
||||
_, err := session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{
|
||||
OpenProjects: []DocumentIdentifier{{FileName: configFileName}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, session.openProjects.Len(), 1)
|
||||
|
||||
// Opening the same project again must not take an additional ref.
|
||||
_, err = session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{
|
||||
OpenProjects: []DocumentIdentifier{{FileName: configFileName}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, session.openProjects.Len(), 1)
|
||||
|
||||
assert.Assert(t, projectSession.Snapshot().ProjectCollection.ConfiguredProject(tspath.Path(configFileName)) != nil)
|
||||
|
||||
// Closing the session releases the single API ref, so the project is no
|
||||
// longer kept loaded.
|
||||
session.Close()
|
||||
assert.Equal(t, session.openProjects.Len(), 0)
|
||||
assert.Assert(t, projectSession.Snapshot().ProjectCollection.ConfiguredProject(tspath.Path(configFileName)) == nil)
|
||||
})
|
||||
|
||||
t.Run("explicit close releases the project ref", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
const configFileName = "/home/projects/p/tsconfig.json"
|
||||
files := map[string]any{
|
||||
configFileName: `{ "compilerOptions": { "strict": true } }`,
|
||||
"/home/projects/p/src/index.ts": `export const x = 1;`,
|
||||
}
|
||||
projectSession, _ := projecttestutil.Setup(files)
|
||||
defer projectSession.Close()
|
||||
session := NewSession(projectSession, nil)
|
||||
defer session.Close()
|
||||
|
||||
_, err := session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{
|
||||
OpenProjects: []DocumentIdentifier{{FileName: configFileName}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, session.openProjects.Len(), 1)
|
||||
assert.Assert(t, projectSession.Snapshot().ProjectCollection.ConfiguredProject(tspath.Path(configFileName)) != nil)
|
||||
|
||||
// Closing a project we hold releases the ref and unloads the project.
|
||||
_, err = session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{
|
||||
CloseProjects: []DocumentIdentifier{{FileName: configFileName}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, session.openProjects.Len(), 0)
|
||||
assert.Assert(t, projectSession.Snapshot().ProjectCollection.ConfiguredProject(tspath.Path(configFileName)) == nil)
|
||||
|
||||
// Closing a project we don't hold is a no-op (never over-releases).
|
||||
_, err = session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{
|
||||
CloseProjects: []DocumentIdentifier{{FileName: configFileName}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, session.openProjects.Len(), 0)
|
||||
})
|
||||
|
||||
t.Run("file opens are idempotent and released on close", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
const fileName = "/home/projects/p/src/index.ts"
|
||||
files := map[string]any{
|
||||
"/home/projects/p/tsconfig.json": `{ "compilerOptions": { "strict": true } }`,
|
||||
fileName: `export const x = 1;`,
|
||||
}
|
||||
projectSession, _ := projecttestutil.Setup(files)
|
||||
defer projectSession.Close()
|
||||
session := NewSession(projectSession, nil)
|
||||
|
||||
_, err := session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{
|
||||
OpenFiles: []DocumentIdentifier{{FileName: fileName}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, session.openFiles.Len(), 1)
|
||||
|
||||
// Re-opening the same file must not take an additional ref.
|
||||
_, err = session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{
|
||||
OpenFiles: []DocumentIdentifier{{FileName: fileName}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, session.openFiles.Len(), 1)
|
||||
|
||||
// The file should resolve to the configured project via ancestor search.
|
||||
assert.Assert(t, projectSession.Snapshot().ProjectCollection.ConfiguredProject(tspath.Path("/home/projects/p/tsconfig.json")) != nil)
|
||||
|
||||
// Closing a file we don't hold is a no-op (never over-releases).
|
||||
_, err = session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{
|
||||
CloseFiles: []DocumentIdentifier{{FileName: "/home/projects/p/other.ts"}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, session.openFiles.Len(), 1)
|
||||
|
||||
// Explicitly closing the held file releases the ref.
|
||||
_, err = session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{
|
||||
CloseFiles: []DocumentIdentifier{{FileName: fileName}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, session.openFiles.Len(), 0)
|
||||
|
||||
// Closing the file also tears down the configured project that was
|
||||
// auto-loaded to serve it, instead of leaking it.
|
||||
assert.Assert(t,
|
||||
projectSession.Snapshot().ProjectCollection.ConfiguredProject(tspath.Path("/home/projects/p/tsconfig.json")) == nil,
|
||||
"configured project auto-loaded for the API-opened file should be unloaded after close",
|
||||
)
|
||||
|
||||
session.Close()
|
||||
assert.Equal(t, session.openFiles.Len(), 0)
|
||||
})
|
||||
|
||||
t.Run("relative file paths normalize consistently for open and close", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// The project session's current directory is "/", so a relative path
|
||||
// resolves to the corresponding absolute path.
|
||||
files := map[string]any{
|
||||
"/src/tsconfig.json": `{ "compilerOptions": { "strict": true } }`,
|
||||
"/src/index.ts": `export const x = 1;`,
|
||||
}
|
||||
projectSession, _ := projecttestutil.Setup(files)
|
||||
defer projectSession.Close()
|
||||
session := NewSession(projectSession, nil)
|
||||
defer session.Close()
|
||||
|
||||
// Open via a relative path; it should be tracked under the absolute path
|
||||
// and resolve to the containing configured project.
|
||||
openResp, err := session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{
|
||||
OpenFiles: []DocumentIdentifier{{FileName: "src/index.ts"}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, session.openFiles.Len(), 1)
|
||||
assert.Assert(t, session.openFiles.Has(tspath.Path("/src/index.ts")))
|
||||
assert.Assert(t, projectSession.Snapshot().ProjectCollection.ConfiguredProject(tspath.Path("/src/tsconfig.json")) != nil)
|
||||
|
||||
// getDefaultProjectForFile must also resolve a relative path to the same
|
||||
// configured project (it builds a URI from the identifier internally).
|
||||
proj, err := session.handleGetDefaultProjectForFile(context.Background(), &GetDefaultProjectForFileParams{
|
||||
Snapshot: openResp.Snapshot,
|
||||
File: DocumentIdentifier{FileName: "src/index.ts"},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, proj != nil, "relative path should resolve to a default project")
|
||||
assert.Equal(t, proj.ConfigFileName, "/src/tsconfig.json")
|
||||
|
||||
// Re-opening via the absolute path must match the relative open (no new ref).
|
||||
_, err = session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{
|
||||
OpenFiles: []DocumentIdentifier{{FileName: "/src/index.ts"}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, session.openFiles.Len(), 1)
|
||||
|
||||
// Closing via a relative path must match the path stored when opening.
|
||||
_, err = session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{
|
||||
CloseFiles: []DocumentIdentifier{{FileName: "src/index.ts"}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, session.openFiles.Len(), 0)
|
||||
assert.Assert(t,
|
||||
projectSession.Snapshot().ProjectCollection.ConfiguredProject(tspath.Path("/src/tsconfig.json")) == nil,
|
||||
"configured project should be unloaded after closing the relatively-pathed file",
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// TestUpdateSnapshotResponseSkipsUnloadedAncestorProject verifies that API
|
||||
// updateSnapshot does not report unloaded ancestor project placeholders. This
|
||||
// covers the case where opening a file loads its nearest configured project
|
||||
// while solution search discovers an ancestor tsconfig placeholder whose command
|
||||
// line is still nil.
|
||||
func TestUpdateSnapshotResponseSkipsUnloadedAncestorProject(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !bundled.Embedded {
|
||||
t.Skip("bundled files are not embedded")
|
||||
}
|
||||
|
||||
const (
|
||||
nestedConfigFileName = "/repo/packages/app/tsconfig.json"
|
||||
ancestorConfigFileName = "/repo/packages/tsconfig.json"
|
||||
fileName = "/repo/packages/app/src/index.ts"
|
||||
)
|
||||
files := map[string]any{
|
||||
ancestorConfigFileName: `{ "files": [] }`,
|
||||
nestedConfigFileName: `{
|
||||
"compilerOptions": { "composite": true },
|
||||
"include": ["**/*"]
|
||||
}`,
|
||||
fileName: `let s: string = 1234;`,
|
||||
}
|
||||
projectSession, _ := projecttestutil.Setup(files)
|
||||
defer projectSession.Close()
|
||||
|
||||
projectSession.DidOpenFile(context.Background(), lsproto.DocumentUri("file://"+fileName), 1, files[fileName].(string), lsproto.LanguageKindTypeScript)
|
||||
snapshot := projectSession.Snapshot()
|
||||
nestedProject := snapshot.ProjectCollection.ConfiguredProject(tspath.Path(nestedConfigFileName))
|
||||
assert.Assert(t, nestedProject != nil)
|
||||
assert.Assert(t, nestedProject.CommandLine != nil)
|
||||
ancestorProject := snapshot.ProjectCollection.ConfiguredProject(tspath.Path(ancestorConfigFileName))
|
||||
assert.Assert(t, ancestorProject != nil)
|
||||
assert.Assert(t, ancestorProject.CommandLine == nil)
|
||||
|
||||
session := NewSession(projectSession, nil)
|
||||
defer session.Close()
|
||||
|
||||
response, err := session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{
|
||||
OpenProjects: []DocumentIdentifier{{FileName: nestedConfigFileName}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
var foundNestedProject bool
|
||||
var foundAncestorProject bool
|
||||
for _, project := range response.Projects {
|
||||
switch project.ConfigFileName {
|
||||
case nestedConfigFileName:
|
||||
foundNestedProject = true
|
||||
assert.Assert(t, project.RootFiles != nil)
|
||||
assert.Assert(t, project.CompilerOptions != nil)
|
||||
case ancestorConfigFileName:
|
||||
foundAncestorProject = true
|
||||
}
|
||||
}
|
||||
assert.Assert(t, foundNestedProject)
|
||||
assert.Assert(t, !foundAncestorProject)
|
||||
}
|
||||
141
tools/tsgo/internal/api/session_completion_test.go
Normal file
141
tools/tsgo/internal/api/session_completion_test.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/bundled"
|
||||
"github.com/microsoft/typescript-go/internal/testutil/projecttestutil"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
// TestCompletionSymbolTypeIsResolvable reproduces a crash where requesting the
|
||||
// type of a completion-provided symbol panicked with a nil pointer dereference.
|
||||
//
|
||||
// Completion ran on an ephemeral query checker (default lifetime), so members of
|
||||
// a generic type such as `string[]` (= Array<string>) were returned as
|
||||
// *instantiated* symbols whose per-checker instantiation links live only on that
|
||||
// query checker. GetTypeOfSymbol runs on the persistent API checker — a
|
||||
// different instance — where those links are absent, so getTypeOfInstantiatedSymbol
|
||||
// dereferenced a nil target and brought down the connection.
|
||||
//
|
||||
// The fix pins symbol-producing completion to the API checker, so the returned
|
||||
// handles resolve on the same checker the client re-queries.
|
||||
func TestCompletionSymbolTypeIsResolvable(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !bundled.Embedded {
|
||||
t.Skip("bundled files are not embedded")
|
||||
}
|
||||
|
||||
const fileName = "/home/projects/p/src/index.ts"
|
||||
// The caret sits right after `people.`, requesting members of `string[]`.
|
||||
const content = "declare const people: string[];\npeople."
|
||||
|
||||
files := map[string]any{
|
||||
"/home/projects/p/tsconfig.json": `{ "compilerOptions": { "strict": true } }`,
|
||||
fileName: content,
|
||||
}
|
||||
projectSession, _ := projecttestutil.Setup(files)
|
||||
defer projectSession.Close()
|
||||
session := NewSession(projectSession, nil)
|
||||
defer session.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
snapshotResp, err := session.handleUpdateSnapshot(ctx, &UpdateSnapshotParams{
|
||||
OpenFiles: []DocumentIdentifier{{FileName: fileName}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
proj, err := session.handleGetDefaultProjectForFile(ctx, &GetDefaultProjectForFileParams{
|
||||
Snapshot: snapshotResp.Snapshot,
|
||||
File: DocumentIdentifier{FileName: fileName},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, proj != nil, "file should resolve to a default project")
|
||||
|
||||
// content is pure ASCII, so the UTF-16 caret offset equals the byte length.
|
||||
completions, err := session.handleGetCompletionsAtPosition(ctx, &GetCompletionsAtPositionParams{
|
||||
Snapshot: snapshotResp.Snapshot,
|
||||
Project: proj.Id,
|
||||
File: DocumentIdentifier{FileName: fileName},
|
||||
Position: uint32(len(content)),
|
||||
IncludeSymbol: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, completions != nil, "expected a completion list for array members")
|
||||
|
||||
// Resolving the type of every completion symbol must not panic, and known
|
||||
// members like `push` must produce a concrete type.
|
||||
var sawSymbol, sawPush bool
|
||||
for _, entry := range completions.Entries {
|
||||
if entry.Symbol == nil {
|
||||
continue
|
||||
}
|
||||
sawSymbol = true
|
||||
typeResp, err := session.handleGetTypeOfSymbol(ctx, &GetTypeOfSymbolParams{
|
||||
Snapshot: snapshotResp.Snapshot,
|
||||
Project: proj.Id,
|
||||
Symbol: entry.Symbol.Id,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, typeResp != nil, "type of completion symbol %q should resolve", entry.Name)
|
||||
if entry.Name == "push" {
|
||||
sawPush = true
|
||||
}
|
||||
}
|
||||
assert.Assert(t, sawSymbol, "completion entries should include resolvable symbols")
|
||||
assert.Assert(t, sawPush, "array member completions should include `push`")
|
||||
}
|
||||
|
||||
// TestCompletionOnInferredProject reproduces a crash where requesting completions
|
||||
// for a loose file — one not part of any tsconfig.json, so it resolves to an
|
||||
// inferred project — panicked with "ConfigFilePath called on non-configured
|
||||
// project".
|
||||
//
|
||||
// setupLanguageService called Project.ConfigFilePath(), which is only valid for
|
||||
// configured projects and panics for inferred ones. The fix uses Project.ID(),
|
||||
// which returns the project's path for both configured and inferred projects without panicking.
|
||||
func TestCompletionOnInferredProject(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !bundled.Embedded {
|
||||
t.Skip("bundled files are not embedded")
|
||||
}
|
||||
|
||||
// No tsconfig.json anywhere, so this file belongs to an inferred project.
|
||||
const fileName = "/home/projects/p/src/index.ts"
|
||||
const content = "declare const people: string[];\npeople."
|
||||
|
||||
files := map[string]any{
|
||||
fileName: content,
|
||||
}
|
||||
projectSession, _ := projecttestutil.Setup(files)
|
||||
defer projectSession.Close()
|
||||
session := NewSession(projectSession, nil)
|
||||
defer session.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
snapshotResp, err := session.handleUpdateSnapshot(ctx, &UpdateSnapshotParams{
|
||||
OpenFiles: []DocumentIdentifier{{FileName: fileName}},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
proj, err := session.handleGetDefaultProjectForFile(ctx, &GetDefaultProjectForFileParams{
|
||||
Snapshot: snapshotResp.Snapshot,
|
||||
File: DocumentIdentifier{FileName: fileName},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, proj != nil, "file should resolve to an inferred default project")
|
||||
|
||||
// This request previously panicked in setupLanguageService.
|
||||
// content is pure ASCII, so the UTF-16 caret offset equals the byte length.
|
||||
completions, err := session.handleGetCompletionsAtPosition(ctx, &GetCompletionsAtPositionParams{
|
||||
Snapshot: snapshotResp.Snapshot,
|
||||
Project: proj.Id,
|
||||
File: DocumentIdentifier{FileName: fileName},
|
||||
Position: uint32(len(content)),
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, completions != nil, "expected a completion list for array members")
|
||||
}
|
||||
30
tools/tsgo/internal/api/stringer_generated.go
Normal file
30
tools/tsgo/internal/api/stringer_generated.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Code generated by "stringer -type=MessageType -output=stringer_generated.go"; DO NOT EDIT.
|
||||
|
||||
package api
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[MessageTypeUnknown-0]
|
||||
_ = x[MessageTypeRequest-1]
|
||||
_ = x[MessageTypeCallResponse-2]
|
||||
_ = x[MessageTypeCallError-3]
|
||||
_ = x[MessageTypeResponse-4]
|
||||
_ = x[MessageTypeError-5]
|
||||
_ = x[MessageTypeCall-6]
|
||||
}
|
||||
|
||||
const _MessageType_name = "MessageTypeUnknownMessageTypeRequestMessageTypeCallResponseMessageTypeCallErrorMessageTypeResponseMessageTypeErrorMessageTypeCall"
|
||||
|
||||
var _MessageType_index = [...]uint8{0, 18, 36, 59, 79, 98, 114, 129}
|
||||
|
||||
func (i MessageType) String() string {
|
||||
idx := int(i) - 0
|
||||
if i < 0 || idx >= len(_MessageType_index)-1 {
|
||||
return "MessageType(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _MessageType_name[_MessageType_index[idx]:_MessageType_index[idx+1]]
|
||||
}
|
||||
136
tools/tsgo/internal/api/timing.go
Normal file
136
tools/tsgo/internal/api/timing.go
Normal file
@@ -0,0 +1,136 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// serverRecentRequestCapacity is the number of most-recent requests retained in
|
||||
// the server-side timing ring buffer.
|
||||
const serverRecentRequestCapacity = 5
|
||||
|
||||
// serverRequestTiming is a single server-side request's processing-time sample.
|
||||
type serverRequestTiming struct {
|
||||
// Method is the API method that was handled.
|
||||
Method string `json:"method"`
|
||||
// ProcessingTimeMs is the wall-clock time the server spent handling the
|
||||
// request, in milliseconds.
|
||||
ProcessingTimeMs float64 `json:"processingTimeMs"`
|
||||
// Timestamp is the Unix time in milliseconds when the request completed.
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// serverTimingTotals holds running totals accumulated across every handled request.
|
||||
type serverTimingTotals struct {
|
||||
// RequestCount is the total number of requests measured.
|
||||
RequestCount uint64 `json:"requestCount"`
|
||||
// TotalProcessingTimeMs is the sum of server processing time, in milliseconds.
|
||||
TotalProcessingTimeMs float64 `json:"totalProcessingTimeMs"`
|
||||
}
|
||||
|
||||
// serverTimingInfo is a point-in-time snapshot of collected server timing,
|
||||
// returned to clients in response to a getServerTiming request.
|
||||
type serverTimingInfo struct {
|
||||
// Enabled reports whether server-side timing collection is active.
|
||||
Enabled bool `json:"enabled"`
|
||||
// Totals are the running totals across every handled request.
|
||||
Totals serverTimingTotals `json:"totals"`
|
||||
// RecentRequests are the most recent requests, oldest to newest, up to
|
||||
// serverRecentRequestCapacity.
|
||||
RecentRequests []serverRequestTiming `json:"recentRequests"`
|
||||
}
|
||||
|
||||
// timingCollector accumulates per-request server processing times into running
|
||||
// totals and a fixed-size ring buffer of the most recent requests. It is safe
|
||||
// for concurrent use so the async connection can record from multiple request
|
||||
// goroutines.
|
||||
type timingCollector struct {
|
||||
mu sync.Mutex
|
||||
totals serverTimingTotals
|
||||
// ring holds up to serverRecentRequestCapacity entries; once full, head
|
||||
// marks the oldest entry.
|
||||
ring []serverRequestTiming
|
||||
head int
|
||||
}
|
||||
|
||||
func newTimingCollector() *timingCollector {
|
||||
return &timingCollector{}
|
||||
}
|
||||
|
||||
// record adds a single request's processing time to the totals and ring buffer.
|
||||
func (c *timingCollector) record(method string, d time.Duration) {
|
||||
processingMs := durationToMillis(d)
|
||||
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.totals.RequestCount++
|
||||
c.totals.TotalProcessingTimeMs += processingMs
|
||||
|
||||
entry := serverRequestTiming{
|
||||
Method: method,
|
||||
ProcessingTimeMs: processingMs,
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
}
|
||||
if len(c.ring) < serverRecentRequestCapacity {
|
||||
c.ring = append(c.ring, entry)
|
||||
} else {
|
||||
c.ring[c.head] = entry
|
||||
c.head = (c.head + 1) % serverRecentRequestCapacity
|
||||
}
|
||||
}
|
||||
|
||||
// snapshot returns a copy of the currently collected timing information, with
|
||||
// recent requests ordered from oldest to newest.
|
||||
func (c *timingCollector) snapshot() serverTimingInfo {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
recent := make([]serverRequestTiming, 0, len(c.ring))
|
||||
for i := range c.ring {
|
||||
recent = append(recent, c.ring[(c.head+i)%len(c.ring)])
|
||||
}
|
||||
return serverTimingInfo{
|
||||
Enabled: true,
|
||||
Totals: c.totals,
|
||||
RecentRequests: recent,
|
||||
}
|
||||
}
|
||||
|
||||
// reset clears all accumulated totals and recent-request history.
|
||||
func (c *timingCollector) reset() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.totals = serverTimingTotals{}
|
||||
c.ring = nil
|
||||
c.head = 0
|
||||
}
|
||||
|
||||
// serverTimingSnapshot returns the collector's snapshot, or a disabled snapshot
|
||||
// when timing collection is not enabled (collector is nil).
|
||||
func serverTimingSnapshot(c *timingCollector) serverTimingInfo {
|
||||
if c == nil {
|
||||
return disabledServerTimingInfo()
|
||||
}
|
||||
return c.snapshot()
|
||||
}
|
||||
|
||||
// disabledServerTimingInfo is the snapshot returned when timing collection is
|
||||
// not enabled.
|
||||
func disabledServerTimingInfo() serverTimingInfo {
|
||||
return serverTimingInfo{
|
||||
Enabled: false,
|
||||
RecentRequests: []serverRequestTiming{},
|
||||
}
|
||||
}
|
||||
|
||||
// durationToMillis converts a duration to fractional milliseconds, clamped to be
|
||||
// non-negative. It preserves sub-microsecond precision by converting from the
|
||||
// full nanosecond duration.
|
||||
func durationToMillis(d time.Duration) float64 {
|
||||
if d < 0 {
|
||||
return 0
|
||||
}
|
||||
return float64(d) / float64(time.Millisecond)
|
||||
}
|
||||
95
tools/tsgo/internal/api/timing_test.go
Normal file
95
tools/tsgo/internal/api/timing_test.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestTimingCollector(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("accumulates totals and records recent requests", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := newTimingCollector()
|
||||
c.record("getSourceFile", 2*time.Millisecond)
|
||||
c.record("getSymbolAtPosition", 500*time.Microsecond)
|
||||
|
||||
snap := c.snapshot()
|
||||
assert.Equal(t, snap.Enabled, true)
|
||||
assert.Equal(t, snap.Totals.RequestCount, uint64(2))
|
||||
assert.Equal(t, snap.Totals.TotalProcessingTimeMs, 2.5)
|
||||
assert.Equal(t, len(snap.RecentRequests), 2)
|
||||
assert.Equal(t, snap.RecentRequests[0].Method, "getSourceFile")
|
||||
assert.Equal(t, snap.RecentRequests[0].ProcessingTimeMs, 2.0)
|
||||
assert.Equal(t, snap.RecentRequests[1].Method, "getSymbolAtPosition")
|
||||
assert.Equal(t, snap.RecentRequests[1].ProcessingTimeMs, 0.5)
|
||||
})
|
||||
|
||||
t.Run("ring buffer retains only the most recent requests, oldest to newest", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := newTimingCollector()
|
||||
methods := []string{"a", "b", "c", "d", "e", "f", "g"}
|
||||
for _, m := range methods {
|
||||
c.record(m, time.Millisecond)
|
||||
}
|
||||
|
||||
snap := c.snapshot()
|
||||
assert.Equal(t, snap.Totals.RequestCount, uint64(7))
|
||||
assert.Equal(t, len(snap.RecentRequests), serverRecentRequestCapacity)
|
||||
|
||||
// Expect the last 5 methods, oldest to newest.
|
||||
want := methods[len(methods)-serverRecentRequestCapacity:]
|
||||
for i, w := range want {
|
||||
assert.Equal(t, snap.RecentRequests[i].Method, w)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("negative durations clamp to zero", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := newTimingCollector()
|
||||
c.record("x", -5*time.Second)
|
||||
snap := c.snapshot()
|
||||
assert.Equal(t, snap.Totals.TotalProcessingTimeMs, 0.0)
|
||||
assert.Equal(t, snap.RecentRequests[0].ProcessingTimeMs, 0.0)
|
||||
})
|
||||
}
|
||||
|
||||
func TestServerTimingSnapshotDisabled(t *testing.T) {
|
||||
t.Parallel()
|
||||
snap := serverTimingSnapshot(nil)
|
||||
assert.Equal(t, snap.Enabled, false)
|
||||
assert.Equal(t, snap.Totals.RequestCount, uint64(0))
|
||||
assert.Equal(t, len(snap.RecentRequests), 0)
|
||||
}
|
||||
|
||||
func TestTimingCollectorReset(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := newTimingCollector()
|
||||
c.record("a", time.Millisecond)
|
||||
c.record("b", time.Millisecond)
|
||||
c.reset()
|
||||
|
||||
snap := c.snapshot()
|
||||
assert.Equal(t, snap.Enabled, true)
|
||||
assert.Equal(t, snap.Totals.RequestCount, uint64(0))
|
||||
assert.Equal(t, snap.Totals.TotalProcessingTimeMs, 0.0)
|
||||
assert.Equal(t, len(snap.RecentRequests), 0)
|
||||
|
||||
// The collector remains usable after a reset.
|
||||
c.record("c", 2*time.Millisecond)
|
||||
snap = c.snapshot()
|
||||
assert.Equal(t, snap.Totals.RequestCount, uint64(1))
|
||||
assert.Equal(t, snap.RecentRequests[0].Method, "c")
|
||||
}
|
||||
|
||||
func TestDurationToMillis(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert.Equal(t, durationToMillis(1500*time.Microsecond), 1.5)
|
||||
assert.Equal(t, durationToMillis(0), 0.0)
|
||||
assert.Equal(t, durationToMillis(-5*time.Second), 0.0)
|
||||
// Sub-microsecond durations retain precision rather than truncating to 0.
|
||||
assert.Equal(t, durationToMillis(500*time.Nanosecond), 0.0005)
|
||||
assert.Equal(t, durationToMillis(1234*time.Nanosecond), 0.001234)
|
||||
}
|
||||
95
tools/tsgo/internal/api/transport.go
Normal file
95
tools/tsgo/internal/api/transport.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
)
|
||||
|
||||
// Transport is an interface for accepting connections from API clients.
|
||||
type Transport interface {
|
||||
// Accept waits for and returns the next connection.
|
||||
Accept() (io.ReadWriteCloser, error)
|
||||
// Close stops the transport from accepting new connections.
|
||||
Close() error
|
||||
}
|
||||
|
||||
// PipeTransport accepts connections on a Unix domain socket or Windows named pipe.
|
||||
type PipeTransport struct {
|
||||
listener net.Listener
|
||||
}
|
||||
|
||||
// NewPipeTransport creates a new transport listening on the given path.
|
||||
// On Unix, this creates a Unix domain socket. On Windows, this creates a named pipe.
|
||||
func NewPipeTransport(path string) (*PipeTransport, error) {
|
||||
listener, err := newPipeListener(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PipeTransport{listener: listener}, nil
|
||||
}
|
||||
|
||||
// Accept implements Transport.
|
||||
func (t *PipeTransport) Accept() (io.ReadWriteCloser, error) {
|
||||
return t.listener.Accept()
|
||||
}
|
||||
|
||||
// Close implements Transport.
|
||||
func (t *PipeTransport) Close() error {
|
||||
return t.listener.Close()
|
||||
}
|
||||
|
||||
// Path returns the path of the pipe/socket.
|
||||
func (t *PipeTransport) Path() string {
|
||||
return t.listener.Addr().String()
|
||||
}
|
||||
|
||||
// StdioTransport wraps stdin/stdout as a single connection transport.
|
||||
// It only accepts one connection.
|
||||
type StdioTransport struct {
|
||||
stdin io.ReadCloser
|
||||
stdout io.WriteCloser
|
||||
used bool
|
||||
}
|
||||
|
||||
// NewStdioTransport creates a transport using the given stdin/stdout.
|
||||
func NewStdioTransport(stdin io.ReadCloser, stdout io.WriteCloser) *StdioTransport {
|
||||
return &StdioTransport{
|
||||
stdin: stdin,
|
||||
stdout: stdout,
|
||||
}
|
||||
}
|
||||
|
||||
// Accept implements Transport.
|
||||
func (t *StdioTransport) Accept() (io.ReadWriteCloser, error) {
|
||||
if t.used {
|
||||
return nil, io.EOF
|
||||
}
|
||||
t.used = true
|
||||
return &stdioConn{
|
||||
Reader: t.stdin,
|
||||
Writer: t.stdout,
|
||||
stdin: t.stdin,
|
||||
stdout: t.stdout,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Close implements Transport.
|
||||
func (t *StdioTransport) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type stdioConn struct {
|
||||
io.Reader
|
||||
io.Writer
|
||||
stdin io.ReadCloser
|
||||
stdout io.WriteCloser
|
||||
}
|
||||
|
||||
func (c *stdioConn) Close() error {
|
||||
err1 := c.stdin.Close()
|
||||
err2 := c.stdout.Close()
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
return err2
|
||||
}
|
||||
22
tools/tsgo/internal/api/transport_unix.go
Normal file
22
tools/tsgo/internal/api/transport_unix.go
Normal file
@@ -0,0 +1,22 @@
|
||||
//go:build !windows
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
// newPipeListener creates a Unix domain socket listener.
|
||||
func newPipeListener(path string) (net.Listener, error) {
|
||||
// Remove any existing socket file
|
||||
_ = os.Remove(path) //nolint:forbidigo
|
||||
return net.Listen("unix", path)
|
||||
}
|
||||
|
||||
// GeneratePipePath returns a platform-appropriate pipe path for the given name.
|
||||
func GeneratePipePath(name string) string {
|
||||
//nolint:forbidigo
|
||||
return path.Join(os.TempDir(), name)
|
||||
}
|
||||
19
tools/tsgo/internal/api/transport_windows.go
Normal file
19
tools/tsgo/internal/api/transport_windows.go
Normal file
@@ -0,0 +1,19 @@
|
||||
//go:build windows
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
)
|
||||
|
||||
// newPipeListener creates a Windows named pipe listener.
|
||||
func newPipeListener(path string) (net.Listener, error) {
|
||||
return winio.ListenPipe(path, nil)
|
||||
}
|
||||
|
||||
// GeneratePipePath returns a platform-appropriate pipe path for the given name.
|
||||
func GeneratePipePath(name string) string {
|
||||
return `\\.\pipe\` + name
|
||||
}
|
||||
3059
tools/tsgo/internal/ast/ast.go
Normal file
3059
tools/tsgo/internal/ast/ast.go
Normal file
File diff suppressed because it is too large
Load Diff
10047
tools/tsgo/internal/ast/ast_generated.go
Normal file
10047
tools/tsgo/internal/ast/ast_generated.go
Normal file
File diff suppressed because it is too large
Load Diff
36
tools/tsgo/internal/ast/checkflags.go
Normal file
36
tools/tsgo/internal/ast/checkflags.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package ast
|
||||
|
||||
// CheckFlags
|
||||
|
||||
type CheckFlags uint32
|
||||
|
||||
const (
|
||||
CheckFlagsNone CheckFlags = 0
|
||||
CheckFlagsInstantiated CheckFlags = 1 << 0 // Instantiated symbol
|
||||
CheckFlagsSyntheticProperty CheckFlags = 1 << 1 // Property in union or intersection type
|
||||
CheckFlagsSyntheticMethod CheckFlags = 1 << 2 // Method in union or intersection type
|
||||
CheckFlagsReadonly CheckFlags = 1 << 3 // Readonly transient symbol
|
||||
CheckFlagsReadPartial CheckFlags = 1 << 4 // Synthetic property present in some but not all constituents
|
||||
CheckFlagsWritePartial CheckFlags = 1 << 5 // Synthetic property present in some but only satisfied by an index signature in others
|
||||
CheckFlagsHasNonUniformType CheckFlags = 1 << 6 // Synthetic property with non-uniform type in constituents
|
||||
CheckFlagsHasLiteralType CheckFlags = 1 << 7 // Synthetic property with at least one literal type in constituents
|
||||
CheckFlagsContainsPublic CheckFlags = 1 << 8 // Synthetic property with public constituent(s)
|
||||
CheckFlagsContainsProtected CheckFlags = 1 << 9 // Synthetic property with protected constituent(s)
|
||||
CheckFlagsContainsPrivate CheckFlags = 1 << 10 // Synthetic property with private constituent(s)
|
||||
CheckFlagsContainsStatic CheckFlags = 1 << 11 // Synthetic property with static constituent(s)
|
||||
CheckFlagsLate CheckFlags = 1 << 12 // Late-bound symbol for a computed property with a dynamic name
|
||||
CheckFlagsReverseMapped CheckFlags = 1 << 13 // Property of reverse-inferred homomorphic mapped type
|
||||
CheckFlagsOptionalParameter CheckFlags = 1 << 14 // Optional parameter
|
||||
CheckFlagsRestParameter CheckFlags = 1 << 15 // Rest parameter
|
||||
CheckFlagsDeferredType CheckFlags = 1 << 16 // Calculation of the type of this symbol is deferred due to processing costs, should be fetched with `getTypeOfSymbolWithDeferredType`
|
||||
CheckFlagsHasNeverType CheckFlags = 1 << 17 // Synthetic property with at least one never type in constituents
|
||||
CheckFlagsMapped CheckFlags = 1 << 18 // Property of mapped type
|
||||
CheckFlagsStripOptional CheckFlags = 1 << 19 // Strip optionality in mapped property
|
||||
CheckFlagsUnresolved CheckFlags = 1 << 20 // Unresolved type alias symbol
|
||||
CheckFlagsIsDiscriminantComputed CheckFlags = 1 << 21 // IsDiscriminant flags has been computed
|
||||
CheckFlagsIsDiscriminant CheckFlags = 1 << 22 // Discriminant property
|
||||
CheckFlagsIndexSymbol CheckFlags = 1 << 23 // Synthetic property created from index signature
|
||||
CheckFlagsSynthetic = CheckFlagsSyntheticProperty | CheckFlagsSyntheticMethod
|
||||
CheckFlagsNonUniformAndLiteral = CheckFlagsHasNonUniformType | CheckFlagsHasLiteralType
|
||||
CheckFlagsPartial = CheckFlagsReadPartial | CheckFlagsWritePartial
|
||||
)
|
||||
86
tools/tsgo/internal/ast/deepclone.go
Normal file
86
tools/tsgo/internal/ast/deepclone.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package ast
|
||||
|
||||
import "github.com/microsoft/typescript-go/internal/core"
|
||||
|
||||
// Ideally, this would get cached on the node factory so there's only ever one set of closures made per factory
|
||||
func getDeepCloneVisitor(f *NodeFactory, syntheticLocation bool) *NodeVisitor {
|
||||
var visitor *NodeVisitor
|
||||
visitor = NewNodeVisitor(
|
||||
func(node *Node) *Node {
|
||||
visited := visitor.VisitEachChild(node)
|
||||
if visited != node {
|
||||
if syntheticLocation {
|
||||
visited.Loc = core.NewTextRange(-1, -1)
|
||||
}
|
||||
return visited
|
||||
}
|
||||
c := node.Clone(f) // forcibly clone leaf nodes, which will then cascade new nodes/arrays upwards via `update` calls
|
||||
// In strada, `factory.cloneNode` was dynamic and did _not_ clone positions for any "special cases", meanwhile
|
||||
// Node.Clone in corsa reliably uses `Update` calls for all nodes and so copies locations by default.
|
||||
// Deep clones are done to copy a node across files, so here, we explicitly make the location range synthetic on all cloned nodes
|
||||
if syntheticLocation {
|
||||
c.Loc = core.NewTextRange(-1, -1)
|
||||
}
|
||||
return c
|
||||
},
|
||||
f,
|
||||
NodeVisitorHooks{
|
||||
VisitNodes: func(nodes *NodeList, v *NodeVisitor) *NodeList {
|
||||
if nodes == nil {
|
||||
return nil
|
||||
}
|
||||
visited := v.VisitNodes(nodes)
|
||||
var newList *NodeList
|
||||
if visited != nodes {
|
||||
newList = visited
|
||||
} else {
|
||||
newList = nodes.Clone(v.Factory)
|
||||
}
|
||||
if syntheticLocation {
|
||||
newList.Loc = core.NewTextRange(-1, -1)
|
||||
if nodes.HasTrailingComma() {
|
||||
newList.Nodes[len(newList.Nodes)-1].Loc = core.NewTextRange(-2, -2)
|
||||
}
|
||||
}
|
||||
return newList
|
||||
},
|
||||
VisitModifiers: func(nodes *ModifierList, v *NodeVisitor) *ModifierList {
|
||||
if nodes == nil {
|
||||
return nil
|
||||
}
|
||||
visited := v.VisitModifiers(nodes)
|
||||
var newList *ModifierList
|
||||
if visited != nodes {
|
||||
newList = visited
|
||||
} else {
|
||||
newList = nodes.Clone(v.Factory)
|
||||
}
|
||||
if syntheticLocation {
|
||||
newList.Loc = core.NewTextRange(-1, -1)
|
||||
if nodes.HasTrailingComma() {
|
||||
newList.Nodes[len(newList.Nodes)-1].Loc = core.NewTextRange(-2, -2)
|
||||
}
|
||||
}
|
||||
return newList
|
||||
},
|
||||
},
|
||||
)
|
||||
return visitor
|
||||
}
|
||||
|
||||
func (f *NodeFactory) DeepCloneNode(node *Node) *Node {
|
||||
return getDeepCloneVisitor(f, true /*syntheticLocation*/).VisitNode(node)
|
||||
}
|
||||
|
||||
func (f *NodeFactory) DeepCloneReparse(node *Node) *Node {
|
||||
if node != nil {
|
||||
node = getDeepCloneVisitor(f, false /*syntheticLocation*/).VisitNode(node)
|
||||
SetParentInChildren(node)
|
||||
node.Flags |= NodeFlagsReparsed
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
func (f *NodeFactory) DeepCloneReparseModifiers(modifiers *ModifierList) *ModifierList {
|
||||
return getDeepCloneVisitor(f, false /*syntheticLocation*/).VisitModifiers(modifiers)
|
||||
}
|
||||
599
tools/tsgo/internal/ast/deepclone_test.go
Normal file
599
tools/tsgo/internal/ast/deepclone_test.go
Normal file
@@ -0,0 +1,599 @@
|
||||
package ast_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/testutil/parsetestutil"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
type NodeComparisonWorkItem struct {
|
||||
original *ast.Node
|
||||
copy *ast.Node
|
||||
}
|
||||
|
||||
func getChildren(node *ast.Node) []*ast.Node {
|
||||
children := []*ast.Node{}
|
||||
node.VisitEachChild(ast.NewNodeVisitor(func(node *ast.Node) *ast.Node {
|
||||
children = append(children, node)
|
||||
return node
|
||||
}, nil, ast.NodeVisitorHooks{}))
|
||||
return children
|
||||
}
|
||||
|
||||
func TestDeepCloneNodeSanityCheck(t *testing.T) {
|
||||
t.Parallel()
|
||||
data := []struct {
|
||||
title string
|
||||
input string
|
||||
jsx bool
|
||||
}{
|
||||
{title: "StringLiteral#1", input: `;"test"`},
|
||||
{title: "StringLiteral#2", input: `;'test'`},
|
||||
{title: "NumericLiteral", input: `0`},
|
||||
{title: "BigIntLiteral", input: `0n`},
|
||||
{title: "BooleanLiteral#1", input: `true`},
|
||||
{title: "BooleanLiteral#2", input: `false`},
|
||||
{title: "NoSubstitutionTemplateLiteral", input: "``"},
|
||||
{title: "RegularExpressionLiteral#1", input: `/a/`},
|
||||
{title: "RegularExpressionLiteral#2", input: `/a/g`},
|
||||
{title: "NullLiteral", input: `null`},
|
||||
{title: "ThisExpression", input: `this`},
|
||||
{title: "SuperExpression", input: `super()`},
|
||||
{title: "ImportExpression", input: `import()`},
|
||||
{title: "PropertyAccess#1", input: `a.b`},
|
||||
{title: "PropertyAccess#2", input: `a.#b`},
|
||||
{title: "PropertyAccess#3", input: `a?.b`},
|
||||
{title: "PropertyAccess#4", input: `a?.b.c`},
|
||||
{title: "PropertyAccess#5", input: `1..b`},
|
||||
{title: "PropertyAccess#6", input: `1.0.b`},
|
||||
{title: "PropertyAccess#7", input: `0x1.b`},
|
||||
{title: "PropertyAccess#8", input: `0b1.b`},
|
||||
{title: "PropertyAccess#9", input: `0o1.b`},
|
||||
{title: "PropertyAccess#10", input: `10e1.b`},
|
||||
{title: "PropertyAccess#11", input: `10E1.b`},
|
||||
{title: "ElementAccess#1", input: `a[b]`},
|
||||
{title: "ElementAccess#2", input: `a?.[b]`},
|
||||
{title: "ElementAccess#3", input: `a?.[b].c`},
|
||||
{title: "CallExpression#1", input: `a()`},
|
||||
{title: "CallExpression#2", input: `a<T>()`},
|
||||
{title: "CallExpression#3", input: `a(b)`},
|
||||
{title: "CallExpression#4", input: `a<T>(b)`},
|
||||
{title: "CallExpression#5", input: `a(b).c`},
|
||||
{title: "CallExpression#6", input: `a<T>(b).c`},
|
||||
{title: "CallExpression#7", input: `a?.(b)`},
|
||||
{title: "CallExpression#8", input: `a?.<T>(b)`},
|
||||
{title: "CallExpression#9", input: `a?.(b).c`},
|
||||
{title: "CallExpression#10", input: `a?.<T>(b).c`},
|
||||
{title: "CallExpression#11", input: `a<T, U>()`},
|
||||
{title: "CallExpression#12", input: `a<T,>()`},
|
||||
{title: "NewExpression#1", input: `new a`},
|
||||
{title: "NewExpression#2", input: `new a.b`},
|
||||
{title: "NewExpression#3", input: `new a()`},
|
||||
{title: "NewExpression#4", input: `new a.b()`},
|
||||
{title: "NewExpression#5", input: `new a<T>()`},
|
||||
{title: "NewExpression#6", input: `new a.b<T>()`},
|
||||
{title: "NewExpression#7", input: `new a(b)`},
|
||||
{title: "NewExpression#8", input: `new a.b(c)`},
|
||||
{title: "NewExpression#9", input: `new a<T>(b)`},
|
||||
{title: "NewExpression#10", input: `new a.b<T>(c)`},
|
||||
{title: "NewExpression#11", input: `new a(b).c`},
|
||||
{title: "NewExpression#12", input: `new a<T>(b).c`},
|
||||
{title: "TaggedTemplateExpression#1", input: "tag``"},
|
||||
{title: "TaggedTemplateExpression#2", input: "tag<T>``"},
|
||||
{title: "TypeAssertionExpression#1", input: `<T>a`},
|
||||
{title: "FunctionExpression#1", input: `(function(){})`},
|
||||
{title: "FunctionExpression#2", input: `(function f(){})`},
|
||||
{title: "FunctionExpression#3", input: `(function*f(){})`},
|
||||
{title: "FunctionExpression#4", input: `(async function f(){})`},
|
||||
{title: "FunctionExpression#5", input: `(async function*f(){})`},
|
||||
{title: "FunctionExpression#6", input: `(function<T>(){})`},
|
||||
{title: "FunctionExpression#7", input: `(function(a){})`},
|
||||
{title: "FunctionExpression#8", input: `(function():T{})`},
|
||||
{title: "ArrowFunction#1", input: `a=>{}`},
|
||||
{title: "ArrowFunction#2", input: `()=>{}`},
|
||||
{title: "ArrowFunction#3", input: `(a)=>{}`},
|
||||
{title: "ArrowFunction#4", input: `<T>(a)=>{}`},
|
||||
{title: "ArrowFunction#5", input: `async a=>{}`},
|
||||
{title: "ArrowFunction#6", input: `async()=>{}`},
|
||||
{title: "ArrowFunction#7", input: `async<T>()=>{}`},
|
||||
{title: "ArrowFunction#8", input: `():T=>{}`},
|
||||
{title: "ArrowFunction#9", input: `()=>a`},
|
||||
{title: "DeleteExpression", input: `delete a`},
|
||||
{title: "TypeOfExpression", input: `typeof a`},
|
||||
{title: "VoidExpression", input: `void a`},
|
||||
{title: "AwaitExpression", input: `await a`},
|
||||
{title: "PrefixUnaryExpression#1", input: `+a`},
|
||||
{title: "PrefixUnaryExpression#2", input: `++a`},
|
||||
{title: "PrefixUnaryExpression#3", input: `+ +a`},
|
||||
{title: "PrefixUnaryExpression#4", input: `+ ++a`},
|
||||
{title: "PrefixUnaryExpression#5", input: `-a`},
|
||||
{title: "PrefixUnaryExpression#6", input: `--a`},
|
||||
{title: "PrefixUnaryExpression#7", input: `- -a`},
|
||||
{title: "PrefixUnaryExpression#8", input: `- --a`},
|
||||
{title: "PrefixUnaryExpression#9", input: `+-a`},
|
||||
{title: "PrefixUnaryExpression#10", input: `+--a`},
|
||||
{title: "PrefixUnaryExpression#11", input: `-+a`},
|
||||
{title: "PrefixUnaryExpression#12", input: `-++a`},
|
||||
{title: "PrefixUnaryExpression#13", input: `~a`},
|
||||
{title: "PrefixUnaryExpression#14", input: `!a`},
|
||||
{title: "PostfixUnaryExpression#1", input: `a++`},
|
||||
{title: "PostfixUnaryExpression#2", input: `a--`},
|
||||
{title: "BinaryExpression#1", input: `a,b`},
|
||||
{title: "BinaryExpression#2", input: `a+b`},
|
||||
{title: "BinaryExpression#3", input: `a**b`},
|
||||
{title: "BinaryExpression#4", input: `a instanceof b`},
|
||||
{title: "BinaryExpression#5", input: `a in b`},
|
||||
{title: "ConditionalExpression", input: `a?b:c`},
|
||||
{title: "TemplateExpression#1", input: "`a${b}c`"},
|
||||
{title: "TemplateExpression#2", input: "`a${b}c${d}e`"},
|
||||
{title: "YieldExpression#1", input: `(function*() { yield })`},
|
||||
{title: "YieldExpression#2", input: `(function*() { yield a })`},
|
||||
{title: "YieldExpression#3", input: `(function*() { yield*a })`},
|
||||
{title: "SpreadElement", input: `[...a]`},
|
||||
{title: "ClassExpression#1", input: `(class {})`},
|
||||
{title: "ClassExpression#2", input: `(class a {})`},
|
||||
{title: "ClassExpression#3", input: `(class<T>{})`},
|
||||
{title: "ClassExpression#4", input: `(class a<T>{})`},
|
||||
{title: "ClassExpression#5", input: `(class extends b {})`},
|
||||
{title: "ClassExpression#6", input: `(class a extends b {})`},
|
||||
{title: "ClassExpression#7", input: `(class implements b {})`},
|
||||
{title: "ClassExpression#8", input: `(class a implements b {})`},
|
||||
{title: "ClassExpression#9", input: `(class implements b, c {})`},
|
||||
{title: "ClassExpression#10", input: `(class a implements b, c {})`},
|
||||
{title: "ClassExpression#11", input: `(class extends b implements c, d {})`},
|
||||
{title: "ClassExpression#12", input: `(class a extends b implements c, d {})`},
|
||||
{title: "ClassExpression#13", input: `(@a class {})`},
|
||||
{title: "OmittedExpression", input: `[,]`},
|
||||
{title: "ExpressionWithTypeArguments", input: `a<T>`},
|
||||
{title: "AsExpression", input: `a as T`},
|
||||
{title: "SatisfiesExpression", input: `a satisfies T`},
|
||||
{title: "NonNullExpression", input: `a!`},
|
||||
{title: "MetaProperty#1", input: `new.target`},
|
||||
{title: "MetaProperty#2", input: `import.meta`},
|
||||
{title: "ArrayLiteralExpression#1", input: `[]`},
|
||||
{title: "ArrayLiteralExpression#2", input: `[a]`},
|
||||
{title: "ArrayLiteralExpression#3", input: `[a,]`},
|
||||
{title: "ArrayLiteralExpression#4", input: `[,a]`},
|
||||
{title: "ArrayLiteralExpression#5", input: `[...a]`},
|
||||
{title: "ObjectLiteralExpression#1", input: `({})`},
|
||||
{title: "ObjectLiteralExpression#2", input: `({a,})`},
|
||||
{title: "ShorthandPropertyAssignment", input: `({a})`},
|
||||
{title: "PropertyAssignment", input: `({a:b})`},
|
||||
{title: "SpreadAssignment", input: `({...a})`},
|
||||
{title: "Block", input: `{}`},
|
||||
{title: "VariableStatement#1", input: `var a`},
|
||||
{title: "VariableStatement#2", input: `let a`},
|
||||
{title: "VariableStatement#3", input: `const a = b`},
|
||||
{title: "VariableStatement#4", input: `using a = b`},
|
||||
{title: "VariableStatement#5", input: `await using a = b`},
|
||||
{title: "EmptyStatement", input: `;`},
|
||||
{title: "IfStatement#1", input: `if(a);`},
|
||||
{title: "IfStatement#2", input: `if(a);else;`},
|
||||
{title: "IfStatement#3", input: `if(a);else{}`},
|
||||
{title: "IfStatement#4", input: `if(a);else if(b);`},
|
||||
{title: "IfStatement#5", input: `if(a);else if(b) {}`},
|
||||
{title: "IfStatement#6", input: `if(a) {}`},
|
||||
{title: "IfStatement#7", input: `if(a) {} else;`},
|
||||
{title: "IfStatement#8", input: `if(a) {} else {}`},
|
||||
{title: "IfStatement#9", input: `if(a) {} else if(b);`},
|
||||
{title: "IfStatement#10", input: `if(a) {} else if(b){}`},
|
||||
{title: "DoStatement#1", input: `do;while(a);`},
|
||||
{title: "DoStatement#2", input: `do {} while(a);`},
|
||||
{title: "WhileStatement#1", input: `while(a);`},
|
||||
{title: "WhileStatement#2", input: `while(a) {}`},
|
||||
{title: "ForStatement#1", input: `for(;;);`},
|
||||
{title: "ForStatement#2", input: `for(a;;);`},
|
||||
{title: "ForStatement#3", input: `for(var a;;);`},
|
||||
{title: "ForStatement#4", input: `for(;a;);`},
|
||||
{title: "ForStatement#5", input: `for(;;a);`},
|
||||
{title: "ForStatement#6", input: `for(;;){}`},
|
||||
{title: "ForInStatement#1", input: `for(a in b);`},
|
||||
{title: "ForInStatement#2", input: `for(var a in b);`},
|
||||
{title: "ForInStatement#3", input: `for(a in b){}`},
|
||||
{title: "ForOfStatement#1", input: `for(a of b);`},
|
||||
{title: "ForOfStatement#2", input: `for(var a of b);`},
|
||||
{title: "ForOfStatement#3", input: `for(a of b){}`},
|
||||
{title: "ForOfStatement#4", input: `for await(a of b);`},
|
||||
{title: "ForOfStatement#5", input: `for await(var a of b);`},
|
||||
{title: "ForOfStatement#6", input: `for await(a of b){}`},
|
||||
{title: "ContinueStatement#1", input: `continue`},
|
||||
{title: "ContinueStatement#2", input: `continue a`},
|
||||
{title: "BreakStatement#1", input: `break`},
|
||||
{title: "BreakStatement#2", input: `break a`},
|
||||
{title: "ReturnStatement#1", input: `return`},
|
||||
{title: "ReturnStatement#2", input: `return a`},
|
||||
{title: "WithStatement#1", input: `with(a);`},
|
||||
{title: "WithStatement#2", input: `with(a){}`},
|
||||
{title: "SwitchStatement", input: `switch (a) {}`},
|
||||
{title: "CaseClause#1", input: `switch (a) {case b:}`},
|
||||
{title: "CaseClause#2", input: `switch (a) {case b:;}`},
|
||||
{title: "DefaultClause#1", input: `switch (a) {default:}`},
|
||||
{title: "DefaultClause#2", input: `switch (a) {default:;}`},
|
||||
{title: "LabeledStatement", input: `a:;`},
|
||||
{title: "ThrowStatement", input: `throw a`},
|
||||
{title: "TryStatement#1", input: `try {} catch {}`},
|
||||
{title: "TryStatement#2", input: `try {} finally {}`},
|
||||
{title: "TryStatement#3", input: `try {} catch {} finally {}`},
|
||||
{title: "DebuggerStatement", input: `debugger`},
|
||||
{title: "FunctionDeclaration#1", input: `export default function(){}`},
|
||||
{title: "FunctionDeclaration#2", input: `function f(){}`},
|
||||
{title: "FunctionDeclaration#3", input: `function*f(){}`},
|
||||
{title: "FunctionDeclaration#4", input: `async function f(){}`},
|
||||
{title: "FunctionDeclaration#5", input: `async function*f(){}`},
|
||||
{title: "FunctionDeclaration#6", input: `function f<T>(){}`},
|
||||
{title: "FunctionDeclaration#7", input: `function f(a){}`},
|
||||
{title: "FunctionDeclaration#8", input: `function f():T{}`},
|
||||
{title: "FunctionDeclaration#9", input: `function f();`},
|
||||
{title: "ClassDeclaration#1", input: `class a {}`},
|
||||
{title: "ClassDeclaration#2", input: `class a<T>{}`},
|
||||
{title: "ClassDeclaration#3", input: `class a extends b {}`},
|
||||
{title: "ClassDeclaration#4", input: `class a implements b {}`},
|
||||
{title: "ClassDeclaration#5", input: `class a implements b, c {}`},
|
||||
{title: "ClassDeclaration#6", input: `class a extends b implements c, d {}`},
|
||||
{title: "ClassDeclaration#7", input: `export default class {}`},
|
||||
{title: "ClassDeclaration#8", input: `export default class<T>{}`},
|
||||
{title: "ClassDeclaration#9", input: `export default class extends b {}`},
|
||||
{title: "ClassDeclaration#10", input: `export default class implements b {}`},
|
||||
{title: "ClassDeclaration#11", input: `export default class implements b, c {}`},
|
||||
{title: "ClassDeclaration#12", input: `export default class extends b implements c, d {}`},
|
||||
{title: "ClassDeclaration#13", input: `@a class b {}`},
|
||||
{title: "ClassDeclaration#14", input: `@a export class b {}`},
|
||||
{title: "ClassDeclaration#15", input: `export @a class b {}`},
|
||||
{title: "InterfaceDeclaration#1", input: `interface a {}`},
|
||||
{title: "InterfaceDeclaration#2", input: `interface a<T>{}`},
|
||||
{title: "InterfaceDeclaration#3", input: `interface a extends b {}`},
|
||||
{title: "InterfaceDeclaration#4", input: `interface a extends b, c {}`},
|
||||
{title: "TypeAliasDeclaration#1", input: `type a = b`},
|
||||
{title: "TypeAliasDeclaration#2", input: `type a<T> = b`},
|
||||
{title: "EnumDeclaration#1", input: `enum a{}`},
|
||||
{title: "EnumDeclaration#2", input: `enum a{b}`},
|
||||
{title: "EnumDeclaration#3", input: `enum a{b=c}`},
|
||||
{title: "ModuleDeclaration#1", input: `module a{}`},
|
||||
{title: "ModuleDeclaration#2", input: `module a.b{}`},
|
||||
{title: "ModuleDeclaration#3", input: `module "a";`},
|
||||
{title: "ModuleDeclaration#4", input: `module "a"{}`},
|
||||
{title: "ModuleDeclaration#5", input: `namespace a{}`},
|
||||
{title: "ModuleDeclaration#6", input: `namespace a.b{}`},
|
||||
{title: "ModuleDeclaration#7", input: `global;`},
|
||||
{title: "ModuleDeclaration#8", input: `global{}`},
|
||||
{title: "ImportEqualsDeclaration#1", input: `import a = b`},
|
||||
{title: "ImportEqualsDeclaration#2", input: `import a = b.c`},
|
||||
{title: "ImportEqualsDeclaration#3", input: `import a = require("b")`},
|
||||
{title: "ImportEqualsDeclaration#4", input: `export import a = b`},
|
||||
{title: "ImportEqualsDeclaration#5", input: `export import a = require("b")`},
|
||||
{title: "ImportEqualsDeclaration#6", input: `import type a = b`},
|
||||
{title: "ImportEqualsDeclaration#7", input: `import type a = b.c`},
|
||||
{title: "ImportEqualsDeclaration#8", input: `import type a = require("b")`},
|
||||
{title: "ImportDeclaration#1", input: `import "a"`},
|
||||
{title: "ImportDeclaration#2", input: `import a from "b"`},
|
||||
{title: "ImportDeclaration#3", input: `import type a from "b"`},
|
||||
{title: "ImportDeclaration#4", input: `import * as a from "b"`},
|
||||
{title: "ImportDeclaration#5", input: `import type * as a from "b"`},
|
||||
{title: "ImportDeclaration#6", input: `import {} from "b"`},
|
||||
{title: "ImportDeclaration#7", input: `import type {} from "b"`},
|
||||
{title: "ImportDeclaration#8", input: `import { a } from "b"`},
|
||||
{title: "ImportDeclaration#9", input: `import type { a } from "b"`},
|
||||
{title: "ImportDeclaration#8", input: `import { a as b } from "c"`},
|
||||
{title: "ImportDeclaration#9", input: `import type { a as b } from "c"`},
|
||||
{title: "ImportDeclaration#10", input: `import { "a" as b } from "c"`},
|
||||
{title: "ImportDeclaration#11", input: `import type { "a" as b } from "c"`},
|
||||
{title: "ImportDeclaration#12", input: `import a, {} from "b"`},
|
||||
{title: "ImportDeclaration#13", input: `import a, * as b from "c"`},
|
||||
{title: "ImportDeclaration#14", input: `import {} from "a" with {}`},
|
||||
{title: "ImportDeclaration#15", input: `import {} from "a" with { b: "c" }`},
|
||||
{title: "ImportDeclaration#16", input: `import {} from "a" with { "b": "c" }`},
|
||||
{title: "ExportAssignment#1", input: `export = a`},
|
||||
{title: "ExportAssignment#2", input: `export default a`},
|
||||
{title: "NamespaceExportDeclaration", input: `export as namespace a`},
|
||||
{title: "ExportDeclaration#1", input: `export * from "a"`},
|
||||
{title: "ExportDeclaration#2", input: `export type * from "a"`},
|
||||
{title: "ExportDeclaration#3", input: `export * as a from "b"`},
|
||||
{title: "ExportDeclaration#4", input: `export type * as a from "b"`},
|
||||
{title: "ExportDeclaration#5", input: `export { } from "a"`},
|
||||
{title: "ExportDeclaration#6", input: `export type { } from "a"`},
|
||||
{title: "ExportDeclaration#7", input: `export { a } from "b"`},
|
||||
{title: "ExportDeclaration#8", input: `export { type a } from "b"`},
|
||||
{title: "ExportDeclaration#9", input: `export type { a } from "b"`},
|
||||
{title: "ExportDeclaration#10", input: `export { a as b } from "c"`},
|
||||
{title: "ExportDeclaration#11", input: `export { type a as b } from "c"`},
|
||||
{title: "ExportDeclaration#12", input: `export type { a as b } from "c"`},
|
||||
{title: "ExportDeclaration#13", input: `export { a as "b" } from "c"`},
|
||||
{title: "ExportDeclaration#14", input: `export { type a as "b" } from "c"`},
|
||||
{title: "ExportDeclaration#15", input: `export type { a as "b" } from "c"`},
|
||||
{title: "ExportDeclaration#16", input: `export { "a" } from "b"`},
|
||||
{title: "ExportDeclaration#17", input: `export { type "a" } from "b"`},
|
||||
{title: "ExportDeclaration#18", input: `export type { "a" } from "b"`},
|
||||
{title: "ExportDeclaration#19", input: `export { "a" as b } from "c"`},
|
||||
{title: "ExportDeclaration#20", input: `export { type "a" as b } from "c"`},
|
||||
{title: "ExportDeclaration#21", input: `export type { "a" as b } from "c"`},
|
||||
{title: "ExportDeclaration#22", input: `export { "a" as "b" } from "c"`},
|
||||
{title: "ExportDeclaration#23", input: `export { type "a" as "b" } from "c"`},
|
||||
{title: "ExportDeclaration#24", input: `export type { "a" as "b" } from "c"`},
|
||||
{title: "ExportDeclaration#25", input: `export { }`},
|
||||
{title: "ExportDeclaration#26", input: `export type { }`},
|
||||
{title: "ExportDeclaration#27", input: `export { a }`},
|
||||
{title: "ExportDeclaration#28", input: `export { type a }`},
|
||||
{title: "ExportDeclaration#29", input: `export type { a }`},
|
||||
{title: "ExportDeclaration#30", input: `export { a as b }`},
|
||||
{title: "ExportDeclaration#31", input: `export { type a as b }`},
|
||||
{title: "ExportDeclaration#32", input: `export type { a as b }`},
|
||||
{title: "ExportDeclaration#33", input: `export { a as "b" }`},
|
||||
{title: "ExportDeclaration#34", input: `export { type a as "b" }`},
|
||||
{title: "ExportDeclaration#35", input: `export type { a as "b" }`},
|
||||
{title: "ExportDeclaration#36", input: `export {} from "a" with {}`},
|
||||
{title: "ExportDeclaration#37", input: `export {} from "a" with { b: "c" }`},
|
||||
{title: "ExportDeclaration#38", input: `export {} from "a" with { "b": "c" }`},
|
||||
{title: "KeywordTypeNode#1", input: `type T = any`},
|
||||
{title: "KeywordTypeNode#2", input: `type T = unknown`},
|
||||
{title: "KeywordTypeNode#3", input: `type T = never`},
|
||||
{title: "KeywordTypeNode#4", input: `type T = void`},
|
||||
{title: "KeywordTypeNode#5", input: `type T = undefined`},
|
||||
{title: "KeywordTypeNode#6", input: `type T = null`},
|
||||
{title: "KeywordTypeNode#7", input: `type T = object`},
|
||||
{title: "KeywordTypeNode#8", input: `type T = string`},
|
||||
{title: "KeywordTypeNode#9", input: `type T = symbol`},
|
||||
{title: "KeywordTypeNode#10", input: `type T = number`},
|
||||
{title: "KeywordTypeNode#11", input: `type T = bigint`},
|
||||
{title: "KeywordTypeNode#12", input: `type T = boolean`},
|
||||
{title: "KeywordTypeNode#13", input: `type T = intrinsic`},
|
||||
{title: "TypePredicateNode#1", input: `function f(): asserts a`},
|
||||
{title: "TypePredicateNode#2", input: `function f(): asserts a is b`},
|
||||
{title: "TypePredicateNode#3", input: `function f(): asserts this`},
|
||||
{title: "TypePredicateNode#4", input: `function f(): asserts this is b`},
|
||||
{title: "TypeReferenceNode#1", input: `type T = a`},
|
||||
{title: "TypeReferenceNode#2", input: `type T = a.b`},
|
||||
{title: "TypeReferenceNode#3", input: `type T = a<U>`},
|
||||
{title: "TypeReferenceNode#4", input: `type T = a.b<U>`},
|
||||
{title: "FunctionTypeNode#1", input: `type T = () => a`},
|
||||
{title: "FunctionTypeNode#2", input: `type T = <T>() => a`},
|
||||
{title: "FunctionTypeNode#3", input: `type T = (a) => b`},
|
||||
{title: "ConstructorTypeNode#1", input: `type T = new () => a`},
|
||||
{title: "ConstructorTypeNode#2", input: `type T = new <T>() => a`},
|
||||
{title: "ConstructorTypeNode#3", input: `type T = new (a) => b`},
|
||||
{title: "ConstructorTypeNode#4", input: `type T = abstract new () => a`},
|
||||
{title: "TypeQueryNode#1", input: `type T = typeof a`},
|
||||
{title: "TypeQueryNode#2", input: `type T = typeof a.b`},
|
||||
{title: "TypeQueryNode#3", input: `type T = typeof a<U>`},
|
||||
{title: "TypeLiteralNode#1", input: `type T = {}`},
|
||||
{title: "TypeLiteralNode#2", input: `type T = {a}`},
|
||||
{title: "ArrayTypeNode", input: `type T = a[]`},
|
||||
{title: "TupleTypeNode#1", input: `type T = []`},
|
||||
{title: "TupleTypeNode#2", input: `type T = [a]`},
|
||||
{title: "TupleTypeNode#3", input: `type T = [a,]`},
|
||||
{title: "RestTypeNode", input: `type T = [...a]`},
|
||||
{title: "OptionalTypeNode", input: `type T = [a?]`},
|
||||
{title: "NamedTupleMember#1", input: `type T = [a: b]`},
|
||||
{title: "NamedTupleMember#2", input: `type T = [a?: b]`},
|
||||
{title: "NamedTupleMember#3", input: `type T = [...a: b]`},
|
||||
{title: "UnionTypeNode#1", input: `type T = a | b`},
|
||||
{title: "UnionTypeNode#2", input: `type T = a | b | c`},
|
||||
{title: "UnionTypeNode#3", input: `type T = | a | b`},
|
||||
{title: "IntersectionTypeNode#1", input: `type T = a & b`},
|
||||
{title: "IntersectionTypeNode#2", input: `type T = a & b & c`},
|
||||
{title: "IntersectionTypeNode#3", input: `type T = & a & b`},
|
||||
{title: "ConditionalTypeNode", input: `type T = a extends b ? c : d`},
|
||||
{title: "InferTypeNode#1", input: `type T = a extends infer b ? c : d`},
|
||||
{title: "InferTypeNode#2", input: `type T = a extends infer b extends c ? d : e`},
|
||||
{title: "ParenthesizedTypeNode", input: `type T = (U)`},
|
||||
{title: "ThisTypeNode", input: `type T = this`},
|
||||
{title: "TypeOperatorNode#1", input: `type T = keyof U`},
|
||||
{title: "TypeOperatorNode#2", input: `type T = readonly U[]`},
|
||||
{title: "TypeOperatorNode#3", input: `type T = unique symbol`},
|
||||
{title: "IndexedAccessTypeNode", input: `type T = a[b]`},
|
||||
{title: "MappedTypeNode#1", input: `type T = { [a in b]: c }`},
|
||||
{title: "MappedTypeNode#2", input: `type T = { [a in b as c]: d }`},
|
||||
{title: "MappedTypeNode#3", input: `type T = { readonly [a in b]: c }`},
|
||||
{title: "MappedTypeNode#4", input: `type T = { +readonly [a in b]: c }`},
|
||||
{title: "MappedTypeNode#5", input: `type T = { -readonly [a in b]: c }`},
|
||||
{title: "MappedTypeNode#6", input: `type T = { [a in b]?: c }`},
|
||||
{title: "MappedTypeNode#7", input: `type T = { [a in b]+?: c }`},
|
||||
{title: "MappedTypeNode#8", input: `type T = { [a in b]-?: c }`},
|
||||
{title: "MappedTypeNode#9", input: `type T = { [a in b]: c; d }`},
|
||||
{title: "LiteralTypeNode#1", input: `type T = null`},
|
||||
{title: "LiteralTypeNode#2", input: `type T = true`},
|
||||
{title: "LiteralTypeNode#3", input: `type T = false`},
|
||||
{title: "LiteralTypeNode#4", input: `type T = ""`},
|
||||
{title: "LiteralTypeNode#5", input: "type T = ''"},
|
||||
{title: "LiteralTypeNode#6", input: "type T = ``"},
|
||||
{title: "LiteralTypeNode#7", input: `type T = 0`},
|
||||
{title: "LiteralTypeNode#8", input: `type T = 0n`},
|
||||
{title: "LiteralTypeNode#9", input: `type T = -0`},
|
||||
{title: "LiteralTypeNode#10", input: `type T = -0n`},
|
||||
{title: "TemplateTypeNode#1", input: "type T = `a${b}c`"},
|
||||
{title: "TemplateTypeNode#2", input: "type T = `a${b}c${d}e`"},
|
||||
{title: "ImportTypeNode#1", input: `type T = import(a)`},
|
||||
{title: "ImportTypeNode#2", input: `type T = import(a).b`},
|
||||
{title: "ImportTypeNode#3", input: `type T = import(a).b<U>`},
|
||||
{title: "ImportTypeNode#4", input: `type T = typeof import(a)`},
|
||||
{title: "ImportTypeNode#5", input: `type T = typeof import(a).b`},
|
||||
{title: "ImportTypeNode#6", input: `type T = import(a, { with: { } })`},
|
||||
{title: "ImportTypeNode#6", input: `type T = import(a, { with: { b: "c" } })`},
|
||||
{title: "ImportTypeNode#7", input: `type T = import(a, { with: { "b": "c" } })`},
|
||||
{title: "PropertySignature#1", input: "interface I {a}"},
|
||||
{title: "PropertySignature#2", input: "interface I {readonly a}"},
|
||||
{title: "PropertySignature#3", input: "interface I {\"a\"}"},
|
||||
{title: "PropertySignature#4", input: "interface I {'a'}"},
|
||||
{title: "PropertySignature#5", input: "interface I {0}"},
|
||||
{title: "PropertySignature#6", input: "interface I {0n}"},
|
||||
{title: "PropertySignature#7", input: "interface I {[a]}"},
|
||||
{title: "PropertySignature#8", input: "interface I {a?}"},
|
||||
{title: "PropertySignature#9", input: "interface I {a: b}"},
|
||||
{title: "MethodSignature#1", input: "interface I {a()}"},
|
||||
{title: "MethodSignature#2", input: "interface I {\"a\"()}"},
|
||||
{title: "MethodSignature#3", input: "interface I {'a'()}"},
|
||||
{title: "MethodSignature#4", input: "interface I {0()}"},
|
||||
{title: "MethodSignature#5", input: "interface I {0n()}"},
|
||||
{title: "MethodSignature#6", input: "interface I {[a]()}"},
|
||||
{title: "MethodSignature#7", input: "interface I {a?()}"},
|
||||
{title: "MethodSignature#8", input: "interface I {a<T>()}"},
|
||||
{title: "MethodSignature#9", input: "interface I {a(): b}"},
|
||||
{title: "MethodSignature#10", input: "interface I {a(b): c}"},
|
||||
{title: "CallSignature#1", input: "interface I {()}"},
|
||||
{title: "CallSignature#2", input: "interface I {():a}"},
|
||||
{title: "CallSignature#3", input: "interface I {(p)}"},
|
||||
{title: "CallSignature#4", input: "interface I {<T>()}"},
|
||||
{title: "ConstructSignature#1", input: "interface I {new ()}"},
|
||||
{title: "ConstructSignature#2", input: "interface I {new ():a}"},
|
||||
{title: "ConstructSignature#3", input: "interface I {new (p)}"},
|
||||
{title: "ConstructSignature#4", input: "interface I {new <T>()}"},
|
||||
{title: "IndexSignatureDeclaration#1", input: "interface I {[a]}"},
|
||||
{title: "IndexSignatureDeclaration#2", input: "interface I {[a: b]}"},
|
||||
{title: "IndexSignatureDeclaration#3", input: "interface I {[a: b]: c}"},
|
||||
{title: "PropertyDeclaration#1", input: "class C {a}"},
|
||||
{title: "PropertyDeclaration#2", input: "class C {readonly a}"},
|
||||
{title: "PropertyDeclaration#3", input: "class C {static a}"},
|
||||
{title: "PropertyDeclaration#4", input: "class C {accessor a}"},
|
||||
{title: "PropertyDeclaration#5", input: "class C {\"a\"}"},
|
||||
{title: "PropertyDeclaration#6", input: "class C {'a'}"},
|
||||
{title: "PropertyDeclaration#7", input: "class C {0}"},
|
||||
{title: "PropertyDeclaration#8", input: "class C {0n}"},
|
||||
{title: "PropertyDeclaration#9", input: "class C {[a]}"},
|
||||
{title: "PropertyDeclaration#10", input: "class C {#a}"},
|
||||
{title: "PropertyDeclaration#11", input: "class C {a?}"},
|
||||
{title: "PropertyDeclaration#12", input: "class C {a!}"},
|
||||
{title: "PropertyDeclaration#13", input: "class C {a: b}"},
|
||||
{title: "PropertyDeclaration#14", input: "class C {a = b}"},
|
||||
{title: "PropertyDeclaration#15", input: "class C {@a b}"},
|
||||
{title: "MethodDeclaration#1", input: "class C {a()}"},
|
||||
{title: "MethodDeclaration#2", input: "class C {\"a\"()}"},
|
||||
{title: "MethodDeclaration#3", input: "class C {'a'()}"},
|
||||
{title: "MethodDeclaration#4", input: "class C {0()}"},
|
||||
{title: "MethodDeclaration#5", input: "class C {0n()}"},
|
||||
{title: "MethodDeclaration#6", input: "class C {[a]()}"},
|
||||
{title: "MethodDeclaration#7", input: "class C {#a()}"},
|
||||
{title: "MethodDeclaration#8", input: "class C {a?()}"},
|
||||
{title: "MethodDeclaration#9", input: "class C {a<T>()}"},
|
||||
{title: "MethodDeclaration#10", input: "class C {a(): b}"},
|
||||
{title: "MethodDeclaration#11", input: "class C {a(b): c}"},
|
||||
{title: "MethodDeclaration#12", input: "class C {a() {} }"},
|
||||
{title: "MethodDeclaration#13", input: "class C {@a b() {} }"},
|
||||
{title: "MethodDeclaration#14", input: "class C {static a() {} }"},
|
||||
{title: "MethodDeclaration#15", input: "class C {async a() {} }"},
|
||||
{title: "GetAccessorDeclaration#1", input: "class C {get a()}"},
|
||||
{title: "GetAccessorDeclaration#2", input: "class C {get \"a\"()}"},
|
||||
{title: "GetAccessorDeclaration#3", input: "class C {get 'a'()}"},
|
||||
{title: "GetAccessorDeclaration#4", input: "class C {get 0()}"},
|
||||
{title: "GetAccessorDeclaration#5", input: "class C {get 0n()}"},
|
||||
{title: "GetAccessorDeclaration#6", input: "class C {get [a]()}"},
|
||||
{title: "GetAccessorDeclaration#7", input: "class C {get #a()}"},
|
||||
{title: "GetAccessorDeclaration#8", input: "class C {get a(): b}"},
|
||||
{title: "GetAccessorDeclaration#9", input: "class C {get a(b): c}"},
|
||||
{title: "GetAccessorDeclaration#10", input: "class C {get a() {} }"},
|
||||
{title: "GetAccessorDeclaration#11", input: "class C {@a get b() {} }"},
|
||||
{title: "GetAccessorDeclaration#12", input: "class C {static get a() {} }"},
|
||||
{title: "SetAccessorDeclaration#1", input: "class C {set a()}"},
|
||||
{title: "SetAccessorDeclaration#2", input: "class C {set \"a\"()}"},
|
||||
{title: "SetAccessorDeclaration#3", input: "class C {set 'a'()}"},
|
||||
{title: "SetAccessorDeclaration#4", input: "class C {set 0()}"},
|
||||
{title: "SetAccessorDeclaration#5", input: "class C {set 0n()}"},
|
||||
{title: "SetAccessorDeclaration#6", input: "class C {set [a]()}"},
|
||||
{title: "SetAccessorDeclaration#7", input: "class C {set #a()}"},
|
||||
{title: "SetAccessorDeclaration#8", input: "class C {set a(): b}"},
|
||||
{title: "SetAccessorDeclaration#9", input: "class C {set a(b): c}"},
|
||||
{title: "SetAccessorDeclaration#10", input: "class C {set a() {} }"},
|
||||
{title: "SetAccessorDeclaration#11", input: "class C {@a set b() {} }"},
|
||||
{title: "SetAccessorDeclaration#12", input: "class C {static set a() {} }"},
|
||||
{title: "ConstructorDeclaration#1", input: "class C {constructor()}"},
|
||||
{title: "ConstructorDeclaration#2", input: "class C {constructor(): b}"},
|
||||
{title: "ConstructorDeclaration#3", input: "class C {constructor(b): c}"},
|
||||
{title: "ConstructorDeclaration#4", input: "class C {constructor() {} }"},
|
||||
{title: "ConstructorDeclaration#5", input: "class C {@a constructor() {} }"},
|
||||
{title: "ConstructorDeclaration#6", input: "class C {private constructor() {} }"},
|
||||
{title: "ClassStaticBlockDeclaration", input: "class C {static { }}"},
|
||||
{title: "SemicolonClassElement#1", input: "class C {;}"},
|
||||
{title: "ParameterDeclaration#1", input: "function f(a)"},
|
||||
{title: "ParameterDeclaration#2", input: "function f(a: b)"},
|
||||
{title: "ParameterDeclaration#3", input: "function f(a = b)"},
|
||||
{title: "ParameterDeclaration#4", input: "function f(a?)"},
|
||||
{title: "ParameterDeclaration#5", input: "function f(...a)"},
|
||||
{title: "ParameterDeclaration#6", input: "function f(this)"},
|
||||
{title: "ParameterDeclaration#7", input: "function f(a,)"},
|
||||
{title: "ObjectBindingPattern#1", input: "function f({})"},
|
||||
{title: "ObjectBindingPattern#2", input: "function f({a})"},
|
||||
{title: "ObjectBindingPattern#3", input: "function f({a = b})"},
|
||||
{title: "ObjectBindingPattern#4", input: "function f({a: b})"},
|
||||
{title: "ObjectBindingPattern#5", input: "function f({a: b = c})"},
|
||||
{title: "ObjectBindingPattern#6", input: "function f({\"a\": b})"},
|
||||
{title: "ObjectBindingPattern#7", input: "function f({'a': b})"},
|
||||
{title: "ObjectBindingPattern#8", input: "function f({0: b})"},
|
||||
{title: "ObjectBindingPattern#9", input: "function f({[a]: b})"},
|
||||
{title: "ObjectBindingPattern#10", input: "function f({...a})"},
|
||||
{title: "ObjectBindingPattern#11", input: "function f({a: {}})"},
|
||||
{title: "ObjectBindingPattern#12", input: "function f({a: []})"},
|
||||
{title: "ArrayBindingPattern#1", input: "function f([])"},
|
||||
{title: "ArrayBindingPattern#2", input: "function f([,])"},
|
||||
{title: "ArrayBindingPattern#3", input: "function f([a])"},
|
||||
{title: "ArrayBindingPattern#4", input: "function f([a, b])"},
|
||||
{title: "ArrayBindingPattern#5", input: "function f([a, , b])"},
|
||||
{title: "ArrayBindingPattern#6", input: "function f([a = b])"},
|
||||
{title: "ArrayBindingPattern#7", input: "function f([...a])"},
|
||||
{title: "ArrayBindingPattern#8", input: "function f([{}])"},
|
||||
{title: "ArrayBindingPattern#9", input: "function f([[]])"},
|
||||
{title: "TypeParameterDeclaration#1", input: "function f<T>();"},
|
||||
{title: "TypeParameterDeclaration#2", input: "function f<in T>();"},
|
||||
{title: "TypeParameterDeclaration#3", input: "function f<T extends U>();"},
|
||||
{title: "TypeParameterDeclaration#4", input: "function f<T = U>();"},
|
||||
{title: "TypeParameterDeclaration#5", input: "function f<T extends U = V>();"},
|
||||
{title: "TypeParameterDeclaration#6", input: "function f<T, U>();"},
|
||||
{title: "TypeParameterDeclaration#7", input: "function f<T,>();"},
|
||||
{title: "JsxElement1", input: "<a></a>"},
|
||||
{title: "JsxElement2", input: "<this></this>"},
|
||||
{title: "JsxElement3", input: "<a:b></a:b>"},
|
||||
{title: "JsxElement4", input: "<a.b></a.b>"},
|
||||
{title: "JsxElement5", input: "<a<b>></a>"},
|
||||
{title: "JsxElement6", input: "<a b></a>"},
|
||||
{title: "JsxElement7", input: "<a>b</a>"},
|
||||
{title: "JsxElement8", input: "<a>{b}</a>"},
|
||||
{title: "JsxElement9", input: "<a><b></b></a>"},
|
||||
{title: "JsxElement10", input: "<a><b /></a>"},
|
||||
{title: "JsxElement11", input: "<a><></></a>"},
|
||||
{title: "JsxSelfClosingElement1", input: "<a />"},
|
||||
{title: "JsxSelfClosingElement2", input: "<this />"},
|
||||
{title: "JsxSelfClosingElement3", input: "<a:b />"},
|
||||
{title: "JsxSelfClosingElement4", input: "<a.b />"},
|
||||
{title: "JsxSelfClosingElement5", input: "<a<b> />"},
|
||||
{title: "JsxSelfClosingElement6", input: "<a b/>"},
|
||||
{title: "JsxFragment1", input: "<></>"},
|
||||
{title: "JsxFragment2", input: "<>b</>"},
|
||||
{title: "JsxFragment3", input: "<>{b}</>"},
|
||||
{title: "JsxFragment4", input: "<><b></b></>"},
|
||||
{title: "JsxFragment5", input: "<><b /></>"},
|
||||
{title: "JsxFragment6", input: "<><></></>"},
|
||||
{title: "JsxAttribute1", input: "<a b/>"},
|
||||
{title: "JsxAttribute2", input: "<a b:c/>"},
|
||||
{title: "JsxAttribute3", input: "<a b=\"c\"/>"},
|
||||
{title: "JsxAttribute4", input: "<a b='c'/>"},
|
||||
{title: "JsxAttribute5", input: "<a b={c}/>"},
|
||||
{title: "JsxAttribute6", input: "<a b=<c></c>/>"},
|
||||
{title: "JsxAttribute7", input: "<a b=<c />/>"},
|
||||
{title: "JsxAttribute8", input: "<a b=<></>/>"},
|
||||
{title: "JsxSpreadAttribute", input: "<a {...b}/>"},
|
||||
}
|
||||
for _, rec := range data {
|
||||
t.Run("Clone "+rec.title, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
factory := &ast.NodeFactory{}
|
||||
file := parsetestutil.ParseTypeScript(rec.input, false).AsNode()
|
||||
clone := factory.DeepCloneNode(file.AsNode()).AsNode()
|
||||
|
||||
work := []NodeComparisonWorkItem{{file, clone}}
|
||||
|
||||
for len(work) > 0 {
|
||||
nextWork := []NodeComparisonWorkItem{}
|
||||
for _, item := range work {
|
||||
assert.Assert(t, item.original != item.copy)
|
||||
originalChildren := getChildren(item.original)
|
||||
copyChildren := getChildren(item.copy)
|
||||
assert.Equal(t, len(originalChildren), len(copyChildren))
|
||||
for i, child := range originalChildren {
|
||||
nextWork = append(nextWork, NodeComparisonWorkItem{child, copyChildren[i]})
|
||||
}
|
||||
}
|
||||
work = nextWork
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
362
tools/tsgo/internal/ast/diagnostic.go
Normal file
362
tools/tsgo/internal/ast/diagnostic.go
Normal file
@@ -0,0 +1,362 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/collections"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/diagnostics"
|
||||
"github.com/microsoft/typescript-go/internal/locale"
|
||||
)
|
||||
|
||||
// RepopulateDiagnosticKind indicates the kind of repopulation for a diagnostic chain entry.
|
||||
type RepopulateDiagnosticKind int
|
||||
|
||||
const (
|
||||
RepopulateModeMismatch RepopulateDiagnosticKind = 1
|
||||
RepopulateModuleNotFound RepopulateDiagnosticKind = 2
|
||||
)
|
||||
|
||||
// RepopulateDiagnosticInfo stores information needed to recompute a diagnostic chain entry
|
||||
// during incremental builds when the program state may have changed.
|
||||
type RepopulateDiagnosticInfo struct {
|
||||
Kind RepopulateDiagnosticKind
|
||||
ModuleReference string
|
||||
Mode core.ResolutionMode
|
||||
PackageName string
|
||||
}
|
||||
|
||||
// Diagnostic
|
||||
|
||||
type Diagnostic struct {
|
||||
file *SourceFile
|
||||
loc core.TextRange
|
||||
code int32
|
||||
category diagnostics.Category
|
||||
// Original message; may be nil.
|
||||
message *diagnostics.Message
|
||||
messageKey diagnostics.Key
|
||||
messageArgs []string
|
||||
messageChain []*Diagnostic
|
||||
relatedInformation []*Diagnostic
|
||||
reportsUnnecessary bool
|
||||
reportsDeprecated bool
|
||||
skippedOnNoEmit bool
|
||||
repopulateInfo *RepopulateDiagnosticInfo
|
||||
}
|
||||
|
||||
func (d *Diagnostic) File() *SourceFile { return d.file }
|
||||
func (d *Diagnostic) Pos() int { return d.loc.Pos() }
|
||||
func (d *Diagnostic) End() int { return d.loc.End() }
|
||||
func (d *Diagnostic) Len() int { return d.loc.Len() }
|
||||
func (d *Diagnostic) Loc() core.TextRange { return d.loc }
|
||||
func (d *Diagnostic) Code() int32 { return d.code }
|
||||
func (d *Diagnostic) Category() diagnostics.Category { return d.category }
|
||||
func (d *Diagnostic) MessageKey() diagnostics.Key { return d.messageKey }
|
||||
func (d *Diagnostic) MessageArgs() []string { return d.messageArgs }
|
||||
func (d *Diagnostic) MessageChain() []*Diagnostic { return d.messageChain }
|
||||
func (d *Diagnostic) RelatedInformation() []*Diagnostic { return d.relatedInformation }
|
||||
func (d *Diagnostic) ReportsUnnecessary() bool { return d.reportsUnnecessary }
|
||||
func (d *Diagnostic) ReportsDeprecated() bool { return d.reportsDeprecated }
|
||||
func (d *Diagnostic) SkippedOnNoEmit() bool { return d.skippedOnNoEmit }
|
||||
func (d *Diagnostic) RepopulateInfo() *RepopulateDiagnosticInfo { return d.repopulateInfo }
|
||||
|
||||
func (d *Diagnostic) SetFile(file *SourceFile) { d.file = file }
|
||||
func (d *Diagnostic) SetLocation(loc core.TextRange) { d.loc = loc }
|
||||
func (d *Diagnostic) SetCategory(category diagnostics.Category) { d.category = category }
|
||||
func (d *Diagnostic) SetSkippedOnNoEmit() { d.skippedOnNoEmit = true }
|
||||
func (d *Diagnostic) SetRepopulateInfo(info *RepopulateDiagnosticInfo) { d.repopulateInfo = info }
|
||||
|
||||
func (d *Diagnostic) SetMessageChain(messageChain []*Diagnostic) *Diagnostic {
|
||||
d.messageChain = messageChain
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Diagnostic) AddMessageChain(messageChain *Diagnostic) *Diagnostic {
|
||||
if messageChain != nil {
|
||||
d.messageChain = append(d.messageChain, messageChain)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Diagnostic) SetRelatedInfo(relatedInformation []*Diagnostic) *Diagnostic {
|
||||
d.relatedInformation = relatedInformation
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Diagnostic) AddRelatedInfo(relatedInformation *Diagnostic) *Diagnostic {
|
||||
if relatedInformation != nil {
|
||||
d.relatedInformation = append(d.relatedInformation, relatedInformation)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Diagnostic) Clone() *Diagnostic {
|
||||
result := *d
|
||||
return &result
|
||||
}
|
||||
|
||||
func (d *Diagnostic) Localize(locale locale.Locale) string {
|
||||
return diagnostics.Localize(locale, d.message, d.messageKey, d.messageArgs...)
|
||||
}
|
||||
|
||||
// For debugging only.
|
||||
func (d *Diagnostic) String() string {
|
||||
return diagnostics.Localize(locale.Default, d.message, d.messageKey, d.messageArgs...)
|
||||
}
|
||||
|
||||
func NewDiagnosticFromSerialized(
|
||||
file *SourceFile,
|
||||
loc core.TextRange,
|
||||
code int32,
|
||||
category diagnostics.Category,
|
||||
messageKey diagnostics.Key,
|
||||
messageArgs []string,
|
||||
messageChain []*Diagnostic,
|
||||
relatedInformation []*Diagnostic,
|
||||
reportsUnnecessary bool,
|
||||
reportsDeprecated bool,
|
||||
skippedOnNoEmit bool,
|
||||
) *Diagnostic {
|
||||
return &Diagnostic{
|
||||
file: file,
|
||||
loc: loc,
|
||||
code: code,
|
||||
category: category,
|
||||
messageKey: messageKey,
|
||||
messageArgs: messageArgs,
|
||||
messageChain: messageChain,
|
||||
relatedInformation: relatedInformation,
|
||||
reportsUnnecessary: reportsUnnecessary,
|
||||
reportsDeprecated: reportsDeprecated,
|
||||
skippedOnNoEmit: skippedOnNoEmit,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDiagnostic(file *SourceFile, loc core.TextRange, message *diagnostics.Message, args ...any) *Diagnostic {
|
||||
return &Diagnostic{
|
||||
file: file,
|
||||
loc: loc,
|
||||
code: message.Code(),
|
||||
category: message.Category(),
|
||||
message: message,
|
||||
messageKey: message.Key(),
|
||||
messageArgs: diagnostics.StringifyArgs(args),
|
||||
reportsUnnecessary: message.ReportsUnnecessary(),
|
||||
reportsDeprecated: message.ReportsDeprecated(),
|
||||
}
|
||||
}
|
||||
|
||||
func NewDiagnosticChain(chain *Diagnostic, message *diagnostics.Message, args ...any) *Diagnostic {
|
||||
if chain != nil {
|
||||
return NewDiagnostic(chain.file, chain.loc, message, args...).AddMessageChain(chain).SetRelatedInfo(chain.relatedInformation)
|
||||
}
|
||||
return NewDiagnostic(nil, core.TextRange{}, message, args...)
|
||||
}
|
||||
|
||||
func NewCompilerDiagnostic(message *diagnostics.Message, args ...any) *Diagnostic {
|
||||
return NewDiagnostic(nil, core.UndefinedTextRange(), message, args...)
|
||||
}
|
||||
|
||||
type DiagnosticsCollection struct {
|
||||
mu sync.Mutex
|
||||
count int
|
||||
fileDiagnostics map[string][]*Diagnostic
|
||||
fileDiagnosticsSorted collections.Set[string]
|
||||
nonFileDiagnostics []*Diagnostic
|
||||
nonFileDiagnosticsSorted bool
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) Add(diagnostic *Diagnostic) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.count++
|
||||
|
||||
if diagnostic.File() != nil {
|
||||
fileName := diagnostic.File().FileName()
|
||||
if c.fileDiagnostics == nil {
|
||||
c.fileDiagnostics = make(map[string][]*Diagnostic)
|
||||
}
|
||||
c.fileDiagnostics[fileName] = append(c.fileDiagnostics[fileName], diagnostic)
|
||||
c.fileDiagnosticsSorted.Delete(fileName)
|
||||
} else {
|
||||
c.nonFileDiagnostics = append(c.nonFileDiagnostics, diagnostic)
|
||||
c.nonFileDiagnosticsSorted = false
|
||||
}
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) Lookup(diagnostic *Diagnostic) *Diagnostic {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
var diagnostics []*Diagnostic
|
||||
if diagnostic.File() != nil {
|
||||
diagnostics = c.getDiagnosticsForFileLocked(diagnostic.File().FileName())
|
||||
} else {
|
||||
diagnostics = c.getGlobalDiagnosticsLocked()
|
||||
}
|
||||
if i, ok := slices.BinarySearchFunc(diagnostics, diagnostic, CompareDiagnostics); ok {
|
||||
return diagnostics[i]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) GetGlobalDiagnostics() []*Diagnostic {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
return c.getGlobalDiagnosticsLocked()
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) getGlobalDiagnosticsLocked() []*Diagnostic {
|
||||
if !c.nonFileDiagnosticsSorted {
|
||||
slices.SortStableFunc(c.nonFileDiagnostics, CompareDiagnostics)
|
||||
c.nonFileDiagnosticsSorted = true
|
||||
}
|
||||
return slices.Clone(c.nonFileDiagnostics)
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) GetDiagnosticsForFile(fileName string) []*Diagnostic {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
return c.getDiagnosticsForFileLocked(fileName)
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) getDiagnosticsForFileLocked(fileName string) []*Diagnostic {
|
||||
if !c.fileDiagnosticsSorted.Has(fileName) {
|
||||
slices.SortStableFunc(c.fileDiagnostics[fileName], CompareDiagnostics)
|
||||
c.fileDiagnosticsSorted.Add(fileName)
|
||||
}
|
||||
return slices.Clone(c.fileDiagnostics[fileName])
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) GetDiagnostics() []*Diagnostic {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
diagnostics := make([]*Diagnostic, 0, c.count)
|
||||
diagnostics = append(diagnostics, c.nonFileDiagnostics...)
|
||||
for _, diags := range c.fileDiagnostics {
|
||||
diagnostics = append(diagnostics, diags...)
|
||||
}
|
||||
slices.SortFunc(diagnostics, CompareDiagnostics)
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
func getDiagnosticPath(d *Diagnostic) string {
|
||||
if d.File() != nil {
|
||||
return d.File().FileName()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func EqualDiagnostics(d1, d2 *Diagnostic) bool {
|
||||
if d1 == d2 {
|
||||
return true
|
||||
}
|
||||
return EqualDiagnosticsNoRelatedInfo(d1, d2) &&
|
||||
slices.EqualFunc(d1.RelatedInformation(), d2.RelatedInformation(), EqualDiagnostics)
|
||||
}
|
||||
|
||||
func EqualDiagnosticsNoRelatedInfo(d1, d2 *Diagnostic) bool {
|
||||
if d1 == d2 {
|
||||
return true
|
||||
}
|
||||
return getDiagnosticPath(d1) == getDiagnosticPath(d2) &&
|
||||
d1.Loc() == d2.Loc() &&
|
||||
d1.Code() == d2.Code() &&
|
||||
slices.Equal(d1.MessageArgs(), d2.MessageArgs()) &&
|
||||
slices.EqualFunc(d1.MessageChain(), d2.MessageChain(), equalMessageChain)
|
||||
}
|
||||
|
||||
func equalMessageChain(c1, c2 *Diagnostic) bool {
|
||||
if c1 == c2 {
|
||||
return true
|
||||
}
|
||||
return c1.Code() == c2.Code() &&
|
||||
slices.Equal(c1.MessageArgs(), c2.MessageArgs()) &&
|
||||
slices.EqualFunc(c1.MessageChain(), c2.MessageChain(), equalMessageChain)
|
||||
}
|
||||
|
||||
func compareMessageChainSize(c1, c2 []*Diagnostic) int {
|
||||
c := len(c2) - len(c1)
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
for i := range c1 {
|
||||
c = compareMessageChainSize(c1[i].MessageChain(), c2[i].MessageChain())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func compareMessageChainContent(c1, c2 []*Diagnostic) int {
|
||||
for i := range c1 {
|
||||
c := slices.Compare(c1[i].MessageArgs(), c2[i].MessageArgs())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
if c1[i].MessageChain() != nil {
|
||||
c = compareMessageChainContent(c1[i].MessageChain(), c2[i].MessageChain())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func compareRelatedInfo(r1, r2 []*Diagnostic) int {
|
||||
c := len(r2) - len(r1)
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
for i := range r1 {
|
||||
c = CompareDiagnostics(r1[i], r2[i])
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func CompareDiagnostics(d1, d2 *Diagnostic) int {
|
||||
if d1 == d2 {
|
||||
return 0
|
||||
}
|
||||
c := strings.Compare(getDiagnosticPath(d1), getDiagnosticPath(d2))
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
c = d1.Loc().Pos() - d2.Loc().Pos()
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
c = d1.Loc().End() - d2.Loc().End()
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
c = int(d1.Code()) - int(d2.Code())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
c = slices.Compare(d1.MessageArgs(), d2.MessageArgs())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
c = compareMessageChainSize(d1.MessageChain(), d2.MessageChain())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
c = compareMessageChainContent(d1.MessageChain(), d2.MessageChain())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
return compareRelatedInfo(d1.RelatedInformation(), d2.RelatedInformation())
|
||||
}
|
||||
75
tools/tsgo/internal/ast/flow.go
Normal file
75
tools/tsgo/internal/ast/flow.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package ast
|
||||
|
||||
// FlowFlags
|
||||
|
||||
type FlowFlags uint32
|
||||
|
||||
const (
|
||||
FlowFlagsUnreachable FlowFlags = 1 << 0 // Unreachable code
|
||||
FlowFlagsStart FlowFlags = 1 << 1 // Start of flow graph
|
||||
FlowFlagsBranchLabel FlowFlags = 1 << 2 // Non-looping junction
|
||||
FlowFlagsLoopLabel FlowFlags = 1 << 3 // Looping junction
|
||||
FlowFlagsAssignment FlowFlags = 1 << 4 // Assignment
|
||||
FlowFlagsTrueCondition FlowFlags = 1 << 5 // Condition known to be true
|
||||
FlowFlagsFalseCondition FlowFlags = 1 << 6 // Condition known to be false
|
||||
FlowFlagsSwitchClause FlowFlags = 1 << 7 // Switch statement clause
|
||||
FlowFlagsArrayMutation FlowFlags = 1 << 8 // Potential array mutation
|
||||
FlowFlagsCall FlowFlags = 1 << 9 // Potential assertion call
|
||||
FlowFlagsReduceLabel FlowFlags = 1 << 10 // Temporarily reduce antecedents of label
|
||||
FlowFlagsReferenced FlowFlags = 1 << 11 // Referenced as antecedent once
|
||||
FlowFlagsShared FlowFlags = 1 << 12 // Referenced as antecedent more than once
|
||||
FlowFlagsLabel = FlowFlagsBranchLabel | FlowFlagsLoopLabel
|
||||
FlowFlagsCondition = FlowFlagsTrueCondition | FlowFlagsFalseCondition
|
||||
)
|
||||
|
||||
// FlowNode
|
||||
|
||||
type FlowNode struct {
|
||||
Flags FlowFlags
|
||||
Node *Node // Associated AST node
|
||||
Antecedent *FlowNode // Antecedent for all but FlowLabel
|
||||
Antecedents *FlowList // Linked list of antecedents for FlowLabel
|
||||
}
|
||||
|
||||
type FlowList struct {
|
||||
Flow *FlowNode
|
||||
Next *FlowList
|
||||
}
|
||||
|
||||
type FlowLabel = FlowNode
|
||||
|
||||
// FlowSwitchClauseData (synthetic AST node for FlowFlagsSwitchClause)
|
||||
|
||||
type FlowSwitchClauseData struct {
|
||||
NodeBase
|
||||
SwitchStatement *Node
|
||||
ClauseStart int32 // Start index of case/default clause range
|
||||
ClauseEnd int32 // End index of case/default clause range
|
||||
}
|
||||
|
||||
func NewFlowSwitchClauseData(switchStatement *Node, clauseStart int, clauseEnd int) *Node {
|
||||
node := &FlowSwitchClauseData{}
|
||||
node.SwitchStatement = switchStatement
|
||||
node.ClauseStart = int32(clauseStart)
|
||||
node.ClauseEnd = int32(clauseEnd)
|
||||
return newNode(KindUnknown, node, NodeFactoryHooks{})
|
||||
}
|
||||
|
||||
func (node *FlowSwitchClauseData) IsEmpty() bool {
|
||||
return node.ClauseStart == node.ClauseEnd
|
||||
}
|
||||
|
||||
// FlowReduceLabelData (synthetic AST node for FlowFlagsReduceLabel)
|
||||
|
||||
type FlowReduceLabelData struct {
|
||||
NodeBase
|
||||
Target *FlowLabel // Target label
|
||||
Antecedents *FlowList // Temporary antecedent list
|
||||
}
|
||||
|
||||
func NewFlowReduceLabelData(target *FlowLabel, antecedents *FlowList) *Node {
|
||||
node := &FlowReduceLabelData{}
|
||||
node.Target = target
|
||||
node.Antecedents = antecedents
|
||||
return newNode(KindUnknown, node, NodeFactoryHooks{})
|
||||
}
|
||||
37
tools/tsgo/internal/ast/functionflags.go
Normal file
37
tools/tsgo/internal/ast/functionflags.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package ast
|
||||
|
||||
type FunctionFlags uint32
|
||||
|
||||
const (
|
||||
FunctionFlagsNormal FunctionFlags = 0
|
||||
FunctionFlagsGenerator FunctionFlags = 1 << 0
|
||||
FunctionFlagsAsync FunctionFlags = 1 << 1
|
||||
FunctionFlagsInvalid FunctionFlags = 1 << 2
|
||||
FunctionFlagsAsyncGenerator FunctionFlags = FunctionFlagsAsync | FunctionFlagsGenerator
|
||||
)
|
||||
|
||||
func GetFunctionFlags(node *Node) FunctionFlags {
|
||||
if node == nil {
|
||||
return FunctionFlagsInvalid
|
||||
}
|
||||
data := node.BodyData()
|
||||
if data == nil {
|
||||
return FunctionFlagsInvalid
|
||||
}
|
||||
flags := FunctionFlagsNormal
|
||||
switch node.Kind {
|
||||
case KindFunctionDeclaration, KindFunctionExpression, KindMethodDeclaration:
|
||||
if data.AsteriskToken != nil {
|
||||
flags |= FunctionFlagsGenerator
|
||||
}
|
||||
fallthrough
|
||||
case KindArrowFunction:
|
||||
if HasSyntacticModifier(node, ModifierFlagsAsync) {
|
||||
flags |= FunctionFlagsAsync
|
||||
}
|
||||
}
|
||||
if data.Body == nil {
|
||||
flags |= FunctionFlagsInvalid
|
||||
}
|
||||
return flags
|
||||
}
|
||||
6
tools/tsgo/internal/ast/ids.go
Normal file
6
tools/tsgo/internal/ast/ids.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package ast
|
||||
|
||||
type (
|
||||
NodeId uint64
|
||||
SymbolId uint64
|
||||
)
|
||||
463
tools/tsgo/internal/ast/kind_generated.go
Normal file
463
tools/tsgo/internal/ast/kind_generated.go
Normal file
@@ -0,0 +1,463 @@
|
||||
// Code generated by _scripts/generate-go-ast.ts. DO NOT EDIT.
|
||||
|
||||
package ast
|
||||
|
||||
//go:generate go tool golang.org/x/tools/cmd/stringer -type=Kind -output=kind_stringer_generated.go
|
||||
//go:generate npx dprint fmt kind_stringer_generated.go
|
||||
|
||||
type Kind int16
|
||||
|
||||
const (
|
||||
KindUnknown Kind = iota
|
||||
KindEndOfFile
|
||||
KindSingleLineCommentTrivia
|
||||
KindMultiLineCommentTrivia
|
||||
KindNewLineTrivia
|
||||
KindWhitespaceTrivia
|
||||
KindConflictMarkerTrivia
|
||||
KindNonTextFileMarkerTrivia
|
||||
KindNumericLiteral
|
||||
KindBigIntLiteral
|
||||
KindStringLiteral
|
||||
KindJsxText
|
||||
KindJsxTextAllWhiteSpaces
|
||||
KindRegularExpressionLiteral
|
||||
KindNoSubstitutionTemplateLiteral
|
||||
// Pseudo-literals
|
||||
KindTemplateHead
|
||||
KindTemplateMiddle
|
||||
KindTemplateTail
|
||||
// Punctuation
|
||||
KindOpenBraceToken
|
||||
KindCloseBraceToken
|
||||
KindOpenParenToken
|
||||
KindCloseParenToken
|
||||
KindOpenBracketToken
|
||||
KindCloseBracketToken
|
||||
KindDotToken
|
||||
KindDotDotDotToken
|
||||
KindSemicolonToken
|
||||
KindCommaToken
|
||||
KindQuestionDotToken
|
||||
KindLessThanToken
|
||||
KindLessThanSlashToken
|
||||
KindGreaterThanToken
|
||||
KindLessThanEqualsToken
|
||||
KindGreaterThanEqualsToken
|
||||
KindEqualsEqualsToken
|
||||
KindExclamationEqualsToken
|
||||
KindEqualsEqualsEqualsToken
|
||||
KindExclamationEqualsEqualsToken
|
||||
KindEqualsGreaterThanToken
|
||||
KindPlusToken
|
||||
KindMinusToken
|
||||
KindAsteriskToken
|
||||
KindAsteriskAsteriskToken
|
||||
KindSlashToken
|
||||
KindPercentToken
|
||||
KindPlusPlusToken
|
||||
KindMinusMinusToken
|
||||
KindLessThanLessThanToken
|
||||
KindGreaterThanGreaterThanToken
|
||||
KindGreaterThanGreaterThanGreaterThanToken
|
||||
KindAmpersandToken
|
||||
KindBarToken
|
||||
KindCaretToken
|
||||
KindExclamationToken
|
||||
KindTildeToken
|
||||
KindAmpersandAmpersandToken
|
||||
KindBarBarToken
|
||||
KindQuestionToken
|
||||
KindColonToken
|
||||
KindAtToken
|
||||
KindQuestionQuestionToken
|
||||
// Only the JSDoc scanner produces BacktickToken. The normal scanner produces NoSubstitutionTemplateLiteral and related kinds.
|
||||
KindBacktickToken
|
||||
// Only the JSDoc scanner produces HashToken. The normal scanner produces PrivateIdentifier.
|
||||
KindHashToken
|
||||
// Assignments
|
||||
KindEqualsToken
|
||||
KindPlusEqualsToken
|
||||
KindMinusEqualsToken
|
||||
KindAsteriskEqualsToken
|
||||
KindAsteriskAsteriskEqualsToken
|
||||
KindSlashEqualsToken
|
||||
KindPercentEqualsToken
|
||||
KindLessThanLessThanEqualsToken
|
||||
KindGreaterThanGreaterThanEqualsToken
|
||||
KindGreaterThanGreaterThanGreaterThanEqualsToken
|
||||
KindAmpersandEqualsToken
|
||||
KindBarEqualsToken
|
||||
KindBarBarEqualsToken
|
||||
KindAmpersandAmpersandEqualsToken
|
||||
KindQuestionQuestionEqualsToken
|
||||
KindCaretEqualsToken
|
||||
// Identifiers and PrivateIdentifier
|
||||
KindIdentifier
|
||||
KindPrivateIdentifier
|
||||
KindJSDocCommentTextToken
|
||||
// Reserved words
|
||||
KindBreakKeyword
|
||||
KindCaseKeyword
|
||||
KindCatchKeyword
|
||||
KindClassKeyword
|
||||
KindConstKeyword
|
||||
KindContinueKeyword
|
||||
KindDebuggerKeyword
|
||||
KindDefaultKeyword
|
||||
KindDeleteKeyword
|
||||
KindDoKeyword
|
||||
KindElseKeyword
|
||||
KindEnumKeyword
|
||||
KindExportKeyword
|
||||
KindExtendsKeyword
|
||||
KindFalseKeyword
|
||||
KindFinallyKeyword
|
||||
KindForKeyword
|
||||
KindFunctionKeyword
|
||||
KindIfKeyword
|
||||
KindImportKeyword
|
||||
KindInKeyword
|
||||
KindInstanceOfKeyword
|
||||
KindNewKeyword
|
||||
KindNullKeyword
|
||||
KindReturnKeyword
|
||||
KindSuperKeyword
|
||||
KindSwitchKeyword
|
||||
KindThisKeyword
|
||||
KindThrowKeyword
|
||||
KindTrueKeyword
|
||||
KindTryKeyword
|
||||
KindTypeOfKeyword
|
||||
KindVarKeyword
|
||||
KindVoidKeyword
|
||||
KindWhileKeyword
|
||||
KindWithKeyword
|
||||
// Strict mode reserved words
|
||||
KindImplementsKeyword
|
||||
KindInterfaceKeyword
|
||||
KindLetKeyword
|
||||
KindPackageKeyword
|
||||
KindPrivateKeyword
|
||||
KindProtectedKeyword
|
||||
KindPublicKeyword
|
||||
KindStaticKeyword
|
||||
KindYieldKeyword
|
||||
// Contextual keywords
|
||||
KindAbstractKeyword
|
||||
KindAccessorKeyword
|
||||
KindAsKeyword
|
||||
KindAssertsKeyword
|
||||
KindAssertKeyword
|
||||
KindAnyKeyword
|
||||
KindAsyncKeyword
|
||||
KindAwaitKeyword
|
||||
KindBooleanKeyword
|
||||
KindConstructorKeyword
|
||||
KindDeclareKeyword
|
||||
KindGetKeyword
|
||||
KindImmediateKeyword
|
||||
KindInferKeyword
|
||||
KindIntrinsicKeyword
|
||||
KindIsKeyword
|
||||
KindKeyOfKeyword
|
||||
KindModuleKeyword
|
||||
KindNamespaceKeyword
|
||||
KindNeverKeyword
|
||||
KindOutKeyword
|
||||
KindReadonlyKeyword
|
||||
KindRequireKeyword
|
||||
KindNumberKeyword
|
||||
KindObjectKeyword
|
||||
KindSatisfiesKeyword
|
||||
KindSetKeyword
|
||||
KindStringKeyword
|
||||
KindSymbolKeyword
|
||||
KindTypeKeyword
|
||||
KindUndefinedKeyword
|
||||
KindUniqueKeyword
|
||||
KindUnknownKeyword
|
||||
KindUsingKeyword
|
||||
KindFromKeyword
|
||||
KindGlobalKeyword
|
||||
KindBigIntKeyword
|
||||
KindOverrideKeyword
|
||||
KindOfKeyword
|
||||
KindDeferKeyword // LastKeyword and LastToken and LastContextualKeyword
|
||||
// Parse tree nodes
|
||||
// Names
|
||||
KindQualifiedName
|
||||
KindComputedPropertyName
|
||||
// Signature elements
|
||||
KindTypeParameter
|
||||
KindParameter
|
||||
KindDecorator
|
||||
// TypeMember
|
||||
KindPropertySignature
|
||||
KindPropertyDeclaration
|
||||
KindMethodSignature
|
||||
KindMethodDeclaration
|
||||
KindClassStaticBlockDeclaration
|
||||
KindConstructor
|
||||
KindGetAccessor
|
||||
KindSetAccessor
|
||||
KindCallSignature
|
||||
KindConstructSignature
|
||||
KindIndexSignature
|
||||
// Type
|
||||
KindTypePredicate
|
||||
KindTypeReference
|
||||
KindFunctionType
|
||||
KindConstructorType
|
||||
KindTypeQuery
|
||||
KindTypeLiteral
|
||||
KindArrayType
|
||||
KindTupleType
|
||||
KindOptionalType
|
||||
KindRestType
|
||||
KindUnionType
|
||||
KindIntersectionType
|
||||
KindConditionalType
|
||||
KindInferType
|
||||
KindParenthesizedType
|
||||
KindThisType
|
||||
KindTypeOperator
|
||||
KindIndexedAccessType
|
||||
KindMappedType
|
||||
KindLiteralType
|
||||
KindNamedTupleMember
|
||||
KindTemplateLiteralType
|
||||
KindTemplateLiteralTypeSpan
|
||||
KindImportType
|
||||
// Binding patterns
|
||||
KindObjectBindingPattern
|
||||
KindArrayBindingPattern
|
||||
KindBindingElement
|
||||
// Expression
|
||||
KindArrayLiteralExpression
|
||||
KindObjectLiteralExpression
|
||||
KindPropertyAccessExpression
|
||||
KindElementAccessExpression
|
||||
KindCallExpression
|
||||
KindNewExpression
|
||||
KindTaggedTemplateExpression
|
||||
KindTypeAssertionExpression
|
||||
KindParenthesizedExpression
|
||||
KindFunctionExpression
|
||||
KindArrowFunction
|
||||
KindDeleteExpression
|
||||
KindTypeOfExpression
|
||||
KindVoidExpression
|
||||
KindAwaitExpression
|
||||
KindPrefixUnaryExpression
|
||||
KindPostfixUnaryExpression
|
||||
KindBinaryExpression
|
||||
KindConditionalExpression
|
||||
KindTemplateExpression
|
||||
KindYieldExpression
|
||||
KindSpreadElement
|
||||
KindClassExpression
|
||||
KindOmittedExpression
|
||||
KindExpressionWithTypeArguments
|
||||
KindAsExpression
|
||||
KindNonNullExpression
|
||||
KindMetaProperty
|
||||
KindSyntheticExpression
|
||||
KindSatisfiesExpression
|
||||
// Misc
|
||||
KindTemplateSpan
|
||||
KindSemicolonClassElement
|
||||
// Element
|
||||
KindBlock
|
||||
KindEmptyStatement
|
||||
KindVariableStatement
|
||||
KindExpressionStatement
|
||||
KindIfStatement
|
||||
KindDoStatement
|
||||
KindWhileStatement
|
||||
KindForStatement
|
||||
KindForInStatement
|
||||
KindForOfStatement
|
||||
KindContinueStatement
|
||||
KindBreakStatement
|
||||
KindReturnStatement
|
||||
KindWithStatement
|
||||
KindSwitchStatement
|
||||
KindLabeledStatement
|
||||
KindThrowStatement
|
||||
KindTryStatement
|
||||
KindDebuggerStatement
|
||||
KindVariableDeclaration
|
||||
KindVariableDeclarationList
|
||||
KindFunctionDeclaration
|
||||
KindClassDeclaration
|
||||
KindInterfaceDeclaration
|
||||
KindTypeAliasDeclaration
|
||||
KindEnumDeclaration
|
||||
KindModuleDeclaration
|
||||
KindModuleBlock
|
||||
KindCaseBlock
|
||||
KindNamespaceExportDeclaration
|
||||
KindImportEqualsDeclaration
|
||||
KindImportDeclaration
|
||||
KindImportClause
|
||||
KindNamespaceImport
|
||||
KindNamedImports
|
||||
KindImportSpecifier
|
||||
KindExportAssignment
|
||||
KindExportDeclaration
|
||||
KindNamedExports
|
||||
KindNamespaceExport
|
||||
KindExportSpecifier
|
||||
KindMissingDeclaration
|
||||
// Module references
|
||||
KindExternalModuleReference
|
||||
// JSX
|
||||
KindJsxElement
|
||||
KindJsxSelfClosingElement
|
||||
KindJsxOpeningElement
|
||||
KindJsxClosingElement
|
||||
KindJsxFragment
|
||||
KindJsxOpeningFragment
|
||||
KindJsxClosingFragment
|
||||
KindJsxAttribute
|
||||
KindJsxAttributes
|
||||
KindJsxSpreadAttribute
|
||||
KindJsxExpression
|
||||
KindJsxNamespacedName
|
||||
// Clauses
|
||||
KindCaseClause
|
||||
KindDefaultClause
|
||||
KindHeritageClause
|
||||
KindCatchClause
|
||||
// Import attributes
|
||||
KindImportAttributes
|
||||
KindImportAttribute
|
||||
// Property assignments
|
||||
KindPropertyAssignment
|
||||
KindShorthandPropertyAssignment
|
||||
KindSpreadAssignment
|
||||
// Enum
|
||||
KindEnumMember
|
||||
// Top-level nodes
|
||||
KindSourceFile
|
||||
// JSDoc nodes
|
||||
KindJSDocTypeExpression
|
||||
KindJSDocNameReference
|
||||
KindJSDocAllType // The * type
|
||||
KindJSDocNullableType
|
||||
KindJSDocNonNullableType
|
||||
KindJSDocOptionalType
|
||||
KindJSDocVariadicType
|
||||
KindJSDoc
|
||||
KindJSDocText
|
||||
KindJSDocTypeLiteral
|
||||
KindJSDocSignature
|
||||
KindJSDocLink
|
||||
KindJSDocLinkCode
|
||||
KindJSDocLinkPlain
|
||||
KindJSDocUnknownTag
|
||||
KindJSDocAugmentsTag
|
||||
KindJSDocImplementsTag
|
||||
KindJSDocDeprecatedTag
|
||||
KindJSDocPublicTag
|
||||
KindJSDocPrivateTag
|
||||
KindJSDocProtectedTag
|
||||
KindJSDocReadonlyTag
|
||||
KindJSDocOverrideTag
|
||||
KindJSDocCallbackTag
|
||||
KindJSDocOverloadTag
|
||||
KindJSDocParameterTag
|
||||
KindJSDocReturnTag
|
||||
KindJSDocThisTag
|
||||
KindJSDocTypeTag
|
||||
KindJSDocTemplateTag
|
||||
KindJSDocTypedefTag
|
||||
KindJSDocSeeTag
|
||||
KindJSDocPropertyTag
|
||||
KindJSDocThrowsTag
|
||||
KindJSDocSatisfiesTag
|
||||
KindJSDocImportTag
|
||||
// Synthesized list
|
||||
KindSyntaxList
|
||||
// Reparsed JS nodes
|
||||
KindJSTypeAliasDeclaration
|
||||
KindJSImportDeclaration
|
||||
// Transformation nodes
|
||||
KindNotEmittedStatement
|
||||
KindPartiallyEmittedExpression
|
||||
KindSyntheticReferenceExpression
|
||||
KindNotEmittedTypeElement
|
||||
KindCount
|
||||
KindFirstAssignment = KindEqualsToken
|
||||
KindLastAssignment = KindCaretEqualsToken
|
||||
KindFirstCompoundAssignment = KindPlusEqualsToken
|
||||
KindLastCompoundAssignment = KindCaretEqualsToken
|
||||
KindFirstReservedWord = KindBreakKeyword
|
||||
KindLastReservedWord = KindWithKeyword
|
||||
KindFirstKeyword = KindBreakKeyword
|
||||
KindLastKeyword = KindDeferKeyword
|
||||
KindFirstFutureReservedWord = KindImplementsKeyword
|
||||
KindLastFutureReservedWord = KindYieldKeyword
|
||||
KindFirstTypeNode = KindTypePredicate
|
||||
KindLastTypeNode = KindImportType
|
||||
KindFirstPunctuation = KindOpenBraceToken
|
||||
KindLastPunctuation = KindCaretEqualsToken
|
||||
KindFirstToken = KindUnknown
|
||||
KindLastToken = KindLastKeyword
|
||||
KindFirstLiteralToken = KindNumericLiteral
|
||||
KindLastLiteralToken = KindNoSubstitutionTemplateLiteral
|
||||
KindFirstTemplateToken = KindNoSubstitutionTemplateLiteral
|
||||
KindLastTemplateToken = KindTemplateTail
|
||||
KindFirstBinaryOperator = KindLessThanToken
|
||||
KindLastBinaryOperator = KindCaretEqualsToken
|
||||
KindFirstStatement = KindVariableStatement
|
||||
KindLastStatement = KindDebuggerStatement
|
||||
KindFirstNode = KindQualifiedName
|
||||
KindFirstJSDocNode = KindJSDocTypeExpression
|
||||
KindLastJSDocNode = KindJSDocImportTag
|
||||
KindFirstJSDocTagNode = KindJSDocUnknownTag
|
||||
KindLastJSDocTagNode = KindJSDocImportTag
|
||||
KindFirstContextualKeyword = KindAbstractKeyword
|
||||
KindLastContextualKeyword = KindDeferKeyword
|
||||
KindLastUnaryOperator = KindTildeToken
|
||||
KindFirstTriviaToken = KindSingleLineCommentTrivia
|
||||
KindLastTriviaToken = KindConflictMarkerTrivia
|
||||
)
|
||||
|
||||
type (
|
||||
TriviaSyntaxKind = Kind // KindSingleLineCommentTrivia | KindMultiLineCommentTrivia | KindNewLineTrivia | KindWhitespaceTrivia | KindConflictMarkerTrivia
|
||||
LiteralSyntaxKind = Kind // KindNumericLiteral | KindBigIntLiteral | KindStringLiteral | KindJsxText | KindJsxTextAllWhiteSpaces | KindRegularExpressionLiteral | KindNoSubstitutionTemplateLiteral
|
||||
PseudoLiteralSyntaxKind = Kind // KindTemplateHead | KindTemplateMiddle | KindTemplateTail
|
||||
PunctuationSyntaxKind = Kind // KindOpenBraceToken | KindCloseBraceToken | KindOpenParenToken | KindCloseParenToken | KindOpenBracketToken | KindCloseBracketToken | KindDotToken | KindDotDotDotToken | KindSemicolonToken | KindCommaToken | KindQuestionDotToken | KindLessThanToken | KindLessThanSlashToken | KindGreaterThanToken | KindLessThanEqualsToken | KindGreaterThanEqualsToken | KindEqualsEqualsToken | KindExclamationEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindEqualsGreaterThanToken | KindPlusToken | KindMinusToken | KindAsteriskToken | KindAsteriskAsteriskToken | KindSlashToken | KindPercentToken | KindPlusPlusToken | KindMinusMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindAmpersandToken | KindBarToken | KindCaretToken | KindExclamationToken | KindTildeToken | KindAmpersandAmpersandToken | KindBarBarToken | KindQuestionToken | KindColonToken | KindAtToken | KindQuestionQuestionToken | KindBacktickToken | KindHashToken | KindEqualsToken | KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskEqualsToken | KindAsteriskAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken | KindCaretEqualsToken
|
||||
KeywordSyntaxKind = Kind // KindBreakKeyword | KindCaseKeyword | KindCatchKeyword | KindClassKeyword | KindConstKeyword | KindContinueKeyword | KindDebuggerKeyword | KindDefaultKeyword | KindDeleteKeyword | KindDoKeyword | KindElseKeyword | KindEnumKeyword | KindExportKeyword | KindExtendsKeyword | KindFalseKeyword | KindFinallyKeyword | KindForKeyword | KindFunctionKeyword | KindIfKeyword | KindImportKeyword | KindInKeyword | KindInstanceOfKeyword | KindNewKeyword | KindNullKeyword | KindReturnKeyword | KindSuperKeyword | KindSwitchKeyword | KindThisKeyword | KindThrowKeyword | KindTrueKeyword | KindTryKeyword | KindTypeOfKeyword | KindVarKeyword | KindVoidKeyword | KindWhileKeyword | KindWithKeyword | KindImplementsKeyword | KindInterfaceKeyword | KindLetKeyword | KindPackageKeyword | KindPrivateKeyword | KindProtectedKeyword | KindPublicKeyword | KindStaticKeyword | KindYieldKeyword | KindAbstractKeyword | KindAccessorKeyword | KindAsKeyword | KindAssertsKeyword | KindAssertKeyword | KindAnyKeyword | KindAsyncKeyword | KindAwaitKeyword | KindBooleanKeyword | KindConstructorKeyword | KindDeclareKeyword | KindGetKeyword | KindImmediateKeyword | KindInferKeyword | KindIntrinsicKeyword | KindIsKeyword | KindKeyOfKeyword | KindModuleKeyword | KindNamespaceKeyword | KindNeverKeyword | KindOutKeyword | KindReadonlyKeyword | KindRequireKeyword | KindNumberKeyword | KindObjectKeyword | KindSatisfiesKeyword | KindSetKeyword | KindStringKeyword | KindSymbolKeyword | KindTypeKeyword | KindUndefinedKeyword | KindUniqueKeyword | KindUnknownKeyword | KindUsingKeyword | KindFromKeyword | KindGlobalKeyword | KindBigIntKeyword | KindOverrideKeyword | KindOfKeyword | KindDeferKeyword
|
||||
ModifierSyntaxKind = Kind // KindAbstractKeyword | KindAccessorKeyword | KindAsyncKeyword | KindConstKeyword | KindDeclareKeyword | KindDefaultKeyword | KindExportKeyword | KindInKeyword | KindPrivateKeyword | KindProtectedKeyword | KindPublicKeyword | KindReadonlyKeyword | KindOutKeyword | KindOverrideKeyword | KindStaticKeyword
|
||||
KeywordTypeSyntaxKind = Kind // KindAnyKeyword | KindBigIntKeyword | KindBooleanKeyword | KindIntrinsicKeyword | KindNeverKeyword | KindNumberKeyword | KindObjectKeyword | KindStringKeyword | KindSymbolKeyword | KindUndefinedKeyword | KindUnknownKeyword | KindVoidKeyword
|
||||
KeywordExpressionSyntaxKind = Kind // KindNullKeyword | KindTrueKeyword | KindFalseKeyword | KindThisKeyword | KindSuperKeyword | KindImportKeyword
|
||||
TokenSyntaxKind = Kind // KindUnknown | KindEndOfFile | KindSingleLineCommentTrivia | KindMultiLineCommentTrivia | KindNewLineTrivia | KindWhitespaceTrivia | KindConflictMarkerTrivia | KindNonTextFileMarkerTrivia | KindNumericLiteral | KindBigIntLiteral | KindStringLiteral | KindJsxText | KindJsxTextAllWhiteSpaces | KindRegularExpressionLiteral | KindNoSubstitutionTemplateLiteral | KindTemplateHead | KindTemplateMiddle | KindTemplateTail | KindOpenBraceToken | KindCloseBraceToken | KindOpenParenToken | KindCloseParenToken | KindOpenBracketToken | KindCloseBracketToken | KindDotToken | KindDotDotDotToken | KindSemicolonToken | KindCommaToken | KindQuestionDotToken | KindLessThanToken | KindLessThanSlashToken | KindGreaterThanToken | KindLessThanEqualsToken | KindGreaterThanEqualsToken | KindEqualsEqualsToken | KindExclamationEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindEqualsGreaterThanToken | KindPlusToken | KindMinusToken | KindAsteriskToken | KindAsteriskAsteriskToken | KindSlashToken | KindPercentToken | KindPlusPlusToken | KindMinusMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindAmpersandToken | KindBarToken | KindCaretToken | KindExclamationToken | KindTildeToken | KindAmpersandAmpersandToken | KindBarBarToken | KindQuestionToken | KindColonToken | KindAtToken | KindQuestionQuestionToken | KindBacktickToken | KindHashToken | KindEqualsToken | KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskEqualsToken | KindAsteriskAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken | KindCaretEqualsToken | KindIdentifier | KindPrivateIdentifier | KindJSDocCommentTextToken | KindBreakKeyword | KindCaseKeyword | KindCatchKeyword | KindClassKeyword | KindConstKeyword | KindContinueKeyword | KindDebuggerKeyword | KindDefaultKeyword | KindDeleteKeyword | KindDoKeyword | KindElseKeyword | KindEnumKeyword | KindExportKeyword | KindExtendsKeyword | KindFalseKeyword | KindFinallyKeyword | KindForKeyword | KindFunctionKeyword | KindIfKeyword | KindImportKeyword | KindInKeyword | KindInstanceOfKeyword | KindNewKeyword | KindNullKeyword | KindReturnKeyword | KindSuperKeyword | KindSwitchKeyword | KindThisKeyword | KindThrowKeyword | KindTrueKeyword | KindTryKeyword | KindTypeOfKeyword | KindVarKeyword | KindVoidKeyword | KindWhileKeyword | KindWithKeyword | KindImplementsKeyword | KindInterfaceKeyword | KindLetKeyword | KindPackageKeyword | KindPrivateKeyword | KindProtectedKeyword | KindPublicKeyword | KindStaticKeyword | KindYieldKeyword | KindAbstractKeyword | KindAccessorKeyword | KindAsKeyword | KindAssertsKeyword | KindAssertKeyword | KindAnyKeyword | KindAsyncKeyword | KindAwaitKeyword | KindBooleanKeyword | KindConstructorKeyword | KindDeclareKeyword | KindGetKeyword | KindImmediateKeyword | KindInferKeyword | KindIntrinsicKeyword | KindIsKeyword | KindKeyOfKeyword | KindModuleKeyword | KindNamespaceKeyword | KindNeverKeyword | KindOutKeyword | KindReadonlyKeyword | KindRequireKeyword | KindNumberKeyword | KindObjectKeyword | KindSatisfiesKeyword | KindSetKeyword | KindStringKeyword | KindSymbolKeyword | KindTypeKeyword | KindUndefinedKeyword | KindUniqueKeyword | KindUnknownKeyword | KindUsingKeyword | KindFromKeyword | KindGlobalKeyword | KindBigIntKeyword | KindOverrideKeyword | KindOfKeyword | KindDeferKeyword
|
||||
JsxTokenSyntaxKind = Kind // KindLessThanSlashToken | KindEndOfFile | KindConflictMarkerTrivia | KindJsxText | KindJsxTextAllWhiteSpaces | KindOpenBraceToken | KindLessThanToken
|
||||
JSDocNodeSyntaxKind = Kind // KindJSDocTypeExpression | KindJSDocNameReference | KindJSDocAllType | KindJSDocNullableType | KindJSDocNonNullableType | KindJSDocOptionalType | KindJSDocVariadicType | KindJSDoc | KindJSDocText | KindJSDocTypeLiteral | KindJSDocSignature | KindJSDocLink | KindJSDocLinkCode | KindJSDocLinkPlain | KindJSDocUnknownTag | KindJSDocAugmentsTag | KindJSDocImplementsTag | KindJSDocDeprecatedTag | KindJSDocPublicTag | KindJSDocPrivateTag | KindJSDocProtectedTag | KindJSDocReadonlyTag | KindJSDocOverrideTag | KindJSDocCallbackTag | KindJSDocOverloadTag | KindJSDocParameterTag | KindJSDocReturnTag | KindJSDocThisTag | KindJSDocTypeTag | KindJSDocTemplateTag | KindJSDocTypedefTag | KindJSDocSeeTag | KindJSDocPropertyTag | KindJSDocThrowsTag | KindJSDocSatisfiesTag | KindJSDocImportTag
|
||||
ImportPhaseModifierSyntaxKind = Kind // KindTypeKeyword | KindDeferKeyword
|
||||
PostfixUnaryOperator = Kind // KindPlusPlusToken | KindMinusMinusToken
|
||||
PrefixUnaryOperator = Kind // KindPlusToken | KindMinusToken | KindTildeToken | KindExclamationToken | KindPlusPlusToken | KindMinusMinusToken
|
||||
AssignmentOperator = Kind // KindEqualsToken | KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskAsteriskEqualsToken | KindAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindCaretEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken
|
||||
BinaryOperator = Kind // KindQuestionQuestionToken | KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword | KindEqualsEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindExclamationEqualsToken | KindAmpersandToken | KindBarToken | KindCaretToken | KindAmpersandAmpersandToken | KindBarBarToken | KindEqualsToken | KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskAsteriskEqualsToken | KindAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindCaretEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken | KindCommaToken
|
||||
ExponentiationOperator = Kind // KindAsteriskAsteriskToken
|
||||
MultiplicativeOperator = Kind // KindAsteriskToken | KindSlashToken | KindPercentToken
|
||||
MultiplicativeOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken
|
||||
AdditiveOperator = Kind // KindPlusToken | KindMinusToken
|
||||
AdditiveOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken
|
||||
ShiftOperator = Kind // KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken
|
||||
ShiftOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken
|
||||
RelationalOperator = Kind // KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword
|
||||
RelationalOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword
|
||||
EqualityOperator = Kind // KindEqualsEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindExclamationEqualsToken
|
||||
EqualityOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword | KindEqualsEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindExclamationEqualsToken
|
||||
BitwiseOperator = Kind // KindAmpersandToken | KindBarToken | KindCaretToken
|
||||
BitwiseOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword | KindEqualsEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindExclamationEqualsToken | KindAmpersandToken | KindBarToken | KindCaretToken
|
||||
LogicalOperator = Kind // KindAmpersandAmpersandToken | KindBarBarToken
|
||||
LogicalOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword | KindEqualsEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindExclamationEqualsToken | KindAmpersandToken | KindBarToken | KindCaretToken | KindAmpersandAmpersandToken | KindBarBarToken
|
||||
CompoundAssignmentOperator = Kind // KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskAsteriskEqualsToken | KindAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindCaretEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken
|
||||
AssignmentOperatorOrHigher = Kind // KindQuestionQuestionToken | KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword | KindEqualsEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindExclamationEqualsToken | KindAmpersandToken | KindBarToken | KindCaretToken | KindAmpersandAmpersandToken | KindBarBarToken | KindEqualsToken | KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskAsteriskEqualsToken | KindAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindCaretEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken
|
||||
LogicalOrCoalescingAssignmentOperator = Kind // KindAmpersandAmpersandEqualsToken | KindBarBarEqualsToken | KindQuestionQuestionEqualsToken
|
||||
)
|
||||
375
tools/tsgo/internal/ast/kind_stringer_generated.go
Normal file
375
tools/tsgo/internal/ast/kind_stringer_generated.go
Normal file
File diff suppressed because one or more lines are too long
53
tools/tsgo/internal/ast/modifierflags.go
Normal file
53
tools/tsgo/internal/ast/modifierflags.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package ast
|
||||
|
||||
type ModifierFlags uint32
|
||||
|
||||
const (
|
||||
ModifierFlagsNone ModifierFlags = 0
|
||||
// Syntactic/JSDoc modifiers
|
||||
ModifierFlagsPublic ModifierFlags = 1 << 0 // Property/Method
|
||||
ModifierFlagsPrivate ModifierFlags = 1 << 1 // Property/Method
|
||||
ModifierFlagsProtected ModifierFlags = 1 << 2 // Property/Method
|
||||
ModifierFlagsReadonly ModifierFlags = 1 << 3 // Property/Method
|
||||
ModifierFlagsOverride ModifierFlags = 1 << 4 // Override method
|
||||
// Syntactic-only modifiers
|
||||
ModifierFlagsExport ModifierFlags = 1 << 5 // Declarations
|
||||
ModifierFlagsAbstract ModifierFlags = 1 << 6 // Class/Method/ConstructSignature
|
||||
ModifierFlagsAmbient ModifierFlags = 1 << 7 // Declarations (declare keyword)
|
||||
ModifierFlagsStatic ModifierFlags = 1 << 8 // Property/Method
|
||||
ModifierFlagsAccessor ModifierFlags = 1 << 9 // Property
|
||||
ModifierFlagsAsync ModifierFlags = 1 << 10 // Property/Method/Function
|
||||
ModifierFlagsDefault ModifierFlags = 1 << 11 // Function/Class (export default declaration)
|
||||
ModifierFlagsConst ModifierFlags = 1 << 12 // Const enum
|
||||
ModifierFlagsIn ModifierFlags = 1 << 13 // Contravariance modifier
|
||||
ModifierFlagsOut ModifierFlags = 1 << 14 // Covariance modifier
|
||||
ModifierFlagsDecorator ModifierFlags = 1 << 15 // Contains a decorator
|
||||
// JSDoc-only modifiers
|
||||
ModifierFlagsDeprecated ModifierFlags = 1 << 16 // Deprecated tag
|
||||
// Cache-only JSDoc-modifiers. Should match order of Syntactic/JSDoc modifiers, above.
|
||||
ModifierFlagsJSDocPublic ModifierFlags = 1 << 23 // if this value changes, `selectEffectiveModifierFlags` must change accordingly
|
||||
ModifierFlagsJSDocPrivate ModifierFlags = 1 << 24
|
||||
ModifierFlagsJSDocProtected ModifierFlags = 1 << 25
|
||||
ModifierFlagsJSDocReadonly ModifierFlags = 1 << 26
|
||||
ModifierFlagsJSDocOverride ModifierFlags = 1 << 27
|
||||
ModifierFlagsHasComputedJSDocModifiers ModifierFlags = 1 << 28 // Indicates the computed modifier flags include modifiers from JSDoc.
|
||||
ModifierFlagsHasComputedFlags ModifierFlags = 1 << 29 // Modifier flags have been computed
|
||||
|
||||
ModifierFlagsSyntacticOrJSDocModifiers = ModifierFlagsPublic | ModifierFlagsPrivate | ModifierFlagsProtected | ModifierFlagsReadonly | ModifierFlagsOverride
|
||||
ModifierFlagsSyntacticOnlyModifiers = ModifierFlagsExport | ModifierFlagsAmbient | ModifierFlagsAbstract | ModifierFlagsStatic | ModifierFlagsAccessor | ModifierFlagsAsync | ModifierFlagsDefault | ModifierFlagsConst | ModifierFlagsIn | ModifierFlagsOut | ModifierFlagsDecorator
|
||||
ModifierFlagsSyntacticModifiers = ModifierFlagsSyntacticOrJSDocModifiers | ModifierFlagsSyntacticOnlyModifiers
|
||||
ModifierFlagsJSDocCacheOnlyModifiers = ModifierFlagsJSDocPublic | ModifierFlagsJSDocPrivate | ModifierFlagsJSDocProtected | ModifierFlagsJSDocReadonly | ModifierFlagsJSDocOverride
|
||||
ModifierFlagsJSDocOnlyModifiers = ModifierFlagsDeprecated
|
||||
ModifierFlagsNonCacheOnlyModifiers = ModifierFlagsSyntacticOrJSDocModifiers | ModifierFlagsSyntacticOnlyModifiers | ModifierFlagsJSDocOnlyModifiers
|
||||
|
||||
ModifierFlagsAccessibilityModifier = ModifierFlagsPublic | ModifierFlagsPrivate | ModifierFlagsProtected
|
||||
// Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property.
|
||||
ModifierFlagsParameterPropertyModifier = ModifierFlagsAccessibilityModifier | ModifierFlagsReadonly | ModifierFlagsOverride
|
||||
ModifierFlagsNonPublicAccessibilityModifier = ModifierFlagsPrivate | ModifierFlagsProtected
|
||||
|
||||
ModifierFlagsTypeScriptModifier = ModifierFlagsAmbient | ModifierFlagsPublic | ModifierFlagsPrivate | ModifierFlagsProtected | ModifierFlagsReadonly | ModifierFlagsAbstract | ModifierFlagsConst | ModifierFlagsOverride | ModifierFlagsIn | ModifierFlagsOut
|
||||
ModifierFlagsExportDefault = ModifierFlagsExport | ModifierFlagsDefault
|
||||
ModifierFlagsAll = ModifierFlagsExport | ModifierFlagsAmbient | ModifierFlagsPublic | ModifierFlagsPrivate | ModifierFlagsProtected | ModifierFlagsStatic | ModifierFlagsReadonly | ModifierFlagsAbstract | ModifierFlagsAccessor | ModifierFlagsAsync | ModifierFlagsDefault | ModifierFlagsConst | ModifierFlagsDeprecated | ModifierFlagsOverride | ModifierFlagsIn | ModifierFlagsOut | ModifierFlagsDecorator
|
||||
ModifierFlagsModifier = ModifierFlagsAll & ^ModifierFlagsDecorator
|
||||
ModifierFlagsJavaScript = ModifierFlagsExport | ModifierFlagsStatic | ModifierFlagsAccessor | ModifierFlagsAsync | ModifierFlagsDefault
|
||||
)
|
||||
73
tools/tsgo/internal/ast/nodeflags.go
Normal file
73
tools/tsgo/internal/ast/nodeflags.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package ast
|
||||
|
||||
type NodeFlags uint32
|
||||
|
||||
const (
|
||||
NodeFlagsNone NodeFlags = 0
|
||||
NodeFlagsLet NodeFlags = 1 << 0 // Variable declaration
|
||||
NodeFlagsConst NodeFlags = 1 << 1 // Variable declaration
|
||||
NodeFlagsUsing NodeFlags = 1 << 2 // Variable declaration
|
||||
NodeFlagsReparsed NodeFlags = 1 << 3 // Node was synthesized during parsing
|
||||
NodeFlagsSynthesized NodeFlags = 1 << 4 // Node was synthesized during transformation
|
||||
NodeFlagsOptionalChain NodeFlags = 1 << 5 // Chained MemberExpression rooted to a pseudo-OptionalExpression
|
||||
NodeFlagsExportContext NodeFlags = 1 << 6 // Export context (initialized by binding)
|
||||
NodeFlagsContainsThis NodeFlags = 1 << 7 // Interface contains references to "this"
|
||||
NodeFlagsHasImplicitReturn NodeFlags = 1 << 8 // If function implicitly returns on one of codepaths (initialized by binding)
|
||||
NodeFlagsHasExplicitReturn NodeFlags = 1 << 9 // If function has explicit reachable return on one of codepaths (initialized by binding)
|
||||
NodeFlagsDisallowInContext NodeFlags = 1 << 10 // If node was parsed in a context where 'in-expressions' are not allowed
|
||||
NodeFlagsYieldContext NodeFlags = 1 << 11 // If node was parsed in the 'yield' context created when parsing a generator
|
||||
NodeFlagsDecoratorContext NodeFlags = 1 << 12 // If node was parsed as part of a decorator
|
||||
NodeFlagsAwaitContext NodeFlags = 1 << 13 // If node was parsed in the 'await' context created when parsing an async function
|
||||
NodeFlagsDisallowConditionalTypesContext NodeFlags = 1 << 14 // If node was parsed in a context where conditional types are not allowed
|
||||
NodeFlagsThisNodeHasError NodeFlags = 1 << 15 // If the parser encountered an error when parsing the code that created this node
|
||||
NodeFlagsJavaScriptFile NodeFlags = 1 << 16 // If node was parsed in a JavaScript
|
||||
NodeFlagsThisNodeOrAnySubNodesHasError NodeFlags = 1 << 17 // If this node or any of its children had an error
|
||||
NodeFlagsHasAsyncFunctions NodeFlags = 1 << 18 // If the file has async functions (initialized by binding)
|
||||
// NodeFlagsHasAggregatedChildData is deprecated. Use `subtreeFacts` instead.
|
||||
|
||||
// These flags will be set when the parser encounters a dynamic import expression or 'import.meta' to avoid
|
||||
// walking the tree if the flags are not set. However, these flags are just a approximation
|
||||
// (hence why it's named "PossiblyContainsDynamicImport") because once set, the flags never get cleared.
|
||||
// During editing, if a dynamic import is removed, incremental parsing will *NOT* clear this flag.
|
||||
// This means that the tree will always be traversed during module resolution, or when looking for external module indicators.
|
||||
// However, the removal operation should not occur often and in the case of the
|
||||
// removal, it is likely that users will add the import anyway.
|
||||
// The advantage of this approach is its simplicity. For the case of batch compilation,
|
||||
// we guarantee that users won't have to pay the price of walking the tree if a dynamic import isn't used.
|
||||
NodeFlagsPossiblyContainsDynamicImport NodeFlags = 1 << 19
|
||||
NodeFlagsPossiblyContainsImportMeta NodeFlags = 1 << 20
|
||||
|
||||
NodeFlagsHasJSDoc NodeFlags = 1 << 21 // If node has preceding JSDoc comment(s)
|
||||
NodeFlagsJSDoc NodeFlags = 1 << 22 // If node was parsed inside jsdoc
|
||||
NodeFlagsAmbient NodeFlags = 1 << 23 // If node was inside an ambient context -- a declaration file, or inside something with the `declare` modifier.
|
||||
NodeFlagsInWithStatement NodeFlags = 1 << 24 // If any ancestor of node was the `statement` of a WithStatement (not the `expression`)
|
||||
NodeFlagsJsonFile NodeFlags = 1 << 25 // If node was parsed in a Json
|
||||
NodeFlagsPossiblyContainsDeprecatedTag NodeFlags = 1 << 26 // Set during parse if comment text contains '@deprecated'; must confirm via JSDoc lookup
|
||||
NodeFlagsUnreachable NodeFlags = 1 << 27 // If node is unreachable according to the binder
|
||||
NodeFlagsReparserTransformedLiteral NodeFlags = 1 << 28 // If node was transformed during parsing, making its' naive text source not match the AST
|
||||
|
||||
NodeFlagsBlockScoped = NodeFlagsLet | NodeFlagsConst | NodeFlagsUsing
|
||||
NodeFlagsConstant = NodeFlagsConst | NodeFlagsUsing
|
||||
NodeFlagsAwaitUsing = NodeFlagsConst | NodeFlagsUsing // Variable declaration (NOTE: on a single node these flags would otherwise be mutually exclusive)
|
||||
|
||||
NodeFlagsReachabilityCheckFlags = NodeFlagsHasImplicitReturn | NodeFlagsHasExplicitReturn
|
||||
NodeFlagsReachabilityAndEmitFlags = NodeFlagsReachabilityCheckFlags | NodeFlagsHasAsyncFunctions
|
||||
|
||||
// Parsing context flags
|
||||
NodeFlagsContextFlags NodeFlags = NodeFlagsDisallowInContext | NodeFlagsDisallowConditionalTypesContext | NodeFlagsYieldContext | NodeFlagsDecoratorContext | NodeFlagsAwaitContext | NodeFlagsJavaScriptFile | NodeFlagsInWithStatement | NodeFlagsAmbient
|
||||
|
||||
// Exclude these flags when parsing a Type
|
||||
NodeFlagsTypeExcludesFlags NodeFlags = NodeFlagsYieldContext | NodeFlagsAwaitContext
|
||||
|
||||
// Represents all flags that are potentially set once and
|
||||
// never cleared on SourceFiles which get re-used in between incremental parses.
|
||||
// See the comment above on `PossiblyContainsDynamicImport` and `PossiblyContainsImportMeta`.
|
||||
NodeFlagsPermanentlySetIncrementalFlags NodeFlags = NodeFlagsPossiblyContainsDynamicImport | NodeFlagsPossiblyContainsImportMeta
|
||||
|
||||
// The following flags repurpose other NodeFlags as different meanings for Identifier nodes
|
||||
NodeFlagsIdentifierHasExtendedUnicodeEscape NodeFlags = NodeFlagsContainsThis // Indicates whether the identifier contains an extended unicode escape sequence
|
||||
NodeFlagsIdentifierIsInJSDocNamespace NodeFlags = NodeFlagsHasAsyncFunctions // Indicates the identifier is the innermost name of a JSDoc namespace declaration
|
||||
|
||||
// The following flag repurposes other NodeFlags for ModuleDeclaration nodes
|
||||
NodeFlagsNestedNamespace NodeFlags = NodeFlagsOptionalChain // If ModuleDeclaration is a nested namespace (e.g. inner part of A.B.C)
|
||||
)
|
||||
149
tools/tsgo/internal/ast/parseoptions.go
Normal file
149
tools/tsgo/internal/ast/parseoptions.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/tspath"
|
||||
)
|
||||
|
||||
type SourceFileParseOptions struct {
|
||||
FileName string
|
||||
Path tspath.Path
|
||||
ExternalModuleIndicatorOptions ExternalModuleIndicatorOptions
|
||||
}
|
||||
|
||||
type ExternalModuleIndicatorOptions struct {
|
||||
JSX bool
|
||||
Force bool
|
||||
}
|
||||
|
||||
func GetExternalModuleIndicatorOptions(fileName string, options *core.CompilerOptions, metadata SourceFileMetaData) ExternalModuleIndicatorOptions {
|
||||
if tspath.IsDeclarationFileName(fileName) {
|
||||
return ExternalModuleIndicatorOptions{}
|
||||
}
|
||||
|
||||
switch options.GetEmitModuleDetectionKind() {
|
||||
case core.ModuleDetectionKindForce:
|
||||
// All non-declaration files are modules, declaration files still do the usual isFileProbablyExternalModule
|
||||
return ExternalModuleIndicatorOptions{Force: true}
|
||||
case core.ModuleDetectionKindLegacy:
|
||||
// Files are modules if they have imports, exports, or import.meta
|
||||
return ExternalModuleIndicatorOptions{}
|
||||
case core.ModuleDetectionKindAuto:
|
||||
// If module is nodenext or node16, all esm format files are modules
|
||||
// If jsx is react-jsx or react-jsxdev then jsx tags force module-ness
|
||||
// otherwise, the presence of import or export statments (or import.meta) implies module-ness
|
||||
return ExternalModuleIndicatorOptions{
|
||||
JSX: options.Jsx == core.JsxEmitReactJSX || options.Jsx == core.JsxEmitReactJSXDev,
|
||||
Force: isFileForcedToBeModuleByFormat(fileName, options, metadata),
|
||||
}
|
||||
default:
|
||||
return ExternalModuleIndicatorOptions{}
|
||||
}
|
||||
}
|
||||
|
||||
var isFileForcedToBeModuleByFormatExtensions = []string{tspath.ExtensionCjs, tspath.ExtensionCts, tspath.ExtensionMjs, tspath.ExtensionMts}
|
||||
|
||||
func isFileForcedToBeModuleByFormat(fileName string, options *core.CompilerOptions, metadata SourceFileMetaData) bool {
|
||||
// Excludes declaration files - they still require an explicit `export {}` or the like
|
||||
// for back compat purposes. The only non-declaration files _not_ forced to be a module are `.js` files
|
||||
// that aren't esm-mode (meaning not in a `type: module` scope).
|
||||
if GetImpliedNodeFormatForEmitWorker(fileName, options.GetEmitModuleKind(), metadata) == core.ModuleKindESNext || tspath.FileExtensionIsOneOf(fileName, isFileForcedToBeModuleByFormatExtensions) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func SetExternalModuleIndicator(file *SourceFile, opts ExternalModuleIndicatorOptions) {
|
||||
file.ExternalModuleIndicator = getExternalModuleIndicator(file, opts)
|
||||
}
|
||||
|
||||
func getExternalModuleIndicator(file *SourceFile, opts ExternalModuleIndicatorOptions) *Node {
|
||||
if file.ScriptKind == core.ScriptKindJSON {
|
||||
return nil
|
||||
}
|
||||
|
||||
if node := isFileProbablyExternalModule(file); node != nil {
|
||||
return node
|
||||
}
|
||||
|
||||
if file.IsDeclarationFile {
|
||||
return nil
|
||||
}
|
||||
|
||||
if opts.JSX {
|
||||
if node := isFileModuleFromUsingJSXTag(file); node != nil {
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
if opts.Force {
|
||||
return file.AsNode()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func isFileProbablyExternalModule(sourceFile *SourceFile) *Node {
|
||||
for _, statement := range sourceFile.Statements.Nodes {
|
||||
if isAnExternalModuleIndicatorNode(statement) {
|
||||
return statement
|
||||
}
|
||||
}
|
||||
return getImportMetaIfNecessary(sourceFile)
|
||||
}
|
||||
|
||||
func isAnExternalModuleIndicatorNode(node *Node) bool {
|
||||
return HasSyntacticModifier(node, ModifierFlagsExport) ||
|
||||
IsImportEqualsDeclaration(node) && IsExternalModuleReference(node.AsImportEqualsDeclaration().ModuleReference) ||
|
||||
IsImportDeclaration(node) || IsExportAssignment(node) || IsExportDeclaration(node)
|
||||
}
|
||||
|
||||
func getImportMetaIfNecessary(sourceFile *SourceFile) *Node {
|
||||
if sourceFile.AsNode().Flags&NodeFlagsPossiblyContainsImportMeta != 0 {
|
||||
return findChildNode(sourceFile.AsNode(), IsImportMeta)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func findChildNode(root *Node, check func(*Node) bool) *Node {
|
||||
var result *Node
|
||||
var visit func(*Node) bool
|
||||
visit = func(node *Node) bool {
|
||||
if check(node) {
|
||||
result = node
|
||||
return true
|
||||
}
|
||||
return node.ForEachChild(visit)
|
||||
}
|
||||
visit(root)
|
||||
return result
|
||||
}
|
||||
|
||||
func isFileModuleFromUsingJSXTag(file *SourceFile) *Node {
|
||||
return walkTreeForJSXTags(file.AsNode())
|
||||
}
|
||||
|
||||
// This is a somewhat unavoidable full tree walk to locate a JSX tag - `import.meta` requires the same,
|
||||
// but we avoid that walk (or parts of it) if at all possible using the `PossiblyContainsImportMeta` node flag.
|
||||
// Unfortunately, there's no `NodeFlag` space to do the same for JSX.
|
||||
func walkTreeForJSXTags(node *Node) *Node {
|
||||
var found *Node
|
||||
|
||||
var visitor func(node *Node) bool
|
||||
visitor = func(node *Node) bool {
|
||||
if found != nil {
|
||||
return true
|
||||
}
|
||||
if node.SubtreeFacts()&SubtreeContainsJsx == 0 {
|
||||
return false
|
||||
}
|
||||
if IsJsxOpeningLikeElement(node) || IsJsxFragment(node) {
|
||||
found = node
|
||||
return true
|
||||
}
|
||||
return node.ForEachChild(visitor)
|
||||
}
|
||||
visitor(node)
|
||||
|
||||
return found
|
||||
}
|
||||
111
tools/tsgo/internal/ast/positionmap.go
Normal file
111
tools/tsgo/internal/ast/positionmap.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/stringutil"
|
||||
)
|
||||
|
||||
// PositionMap provides bidirectional mapping between UTF-8 byte offsets (used by Go)
|
||||
// and UTF-16 code unit offsets (used by JavaScript/TypeScript).
|
||||
//
|
||||
// For ASCII-only text, the two are identical. For text containing non-ASCII characters,
|
||||
// the offsets diverge because multi-byte UTF-8 sequences map to different numbers of
|
||||
// UTF-16 code units:
|
||||
// - U+0000..U+007F: 1 byte in UTF-8, 1 code unit in UTF-16
|
||||
// - U+0080..U+07FF: 2 bytes in UTF-8, 1 code unit in UTF-16
|
||||
// - U+0800..U+FFFF: 3 bytes in UTF-8, 1 code unit in UTF-16
|
||||
// - U+10000..U+10FFFF: 4 bytes in UTF-8, 2 code units in UTF-16 (surrogate pair)
|
||||
type PositionMap struct {
|
||||
// asciiOnly is true if the text contains only ASCII characters,
|
||||
// meaning UTF-8 byte offsets and UTF-16 code unit offsets are identical.
|
||||
asciiOnly bool
|
||||
// For each multi-byte character, we store:
|
||||
// - the UTF-8 byte offset of the character
|
||||
// - the cumulative delta (utf8Offset - utf16Offset) at that character
|
||||
// This allows O(log n) conversion in either direction.
|
||||
//
|
||||
// entries[i].utf8Pos is the byte offset of the i-th multi-byte character.
|
||||
// entries[i].delta is the total (utf8 - utf16) difference accumulated
|
||||
// through and including the i-th multi-byte character.
|
||||
entries []positionMapEntry
|
||||
}
|
||||
|
||||
type positionMapEntry struct {
|
||||
utf8Pos int // UTF-8 byte offset AFTER this multi-byte character
|
||||
delta int // cumulative (utf8 - utf16) offset difference after this character
|
||||
}
|
||||
|
||||
// ComputePositionMap builds a PositionMap for the given text.
|
||||
func ComputePositionMap(text string) *PositionMap {
|
||||
pm := &PositionMap{}
|
||||
delta := 0
|
||||
for i := 0; i < len(text); {
|
||||
b := text[i]
|
||||
if b < utf8.RuneSelf {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
r, size := stringutil.DecodeJSStringRune(text[i:])
|
||||
utf16Size := 1
|
||||
if r >= 0x10000 {
|
||||
utf16Size = 2
|
||||
}
|
||||
delta += size - utf16Size
|
||||
pm.entries = append(pm.entries, positionMapEntry{utf8Pos: i + size, delta: delta})
|
||||
i += size
|
||||
}
|
||||
pm.asciiOnly = len(pm.entries) == 0
|
||||
return pm
|
||||
}
|
||||
|
||||
// IsAsciiOnly returns true if the text is ASCII-only,
|
||||
// meaning UTF-8 and UTF-16 offsets are identical.
|
||||
func (pm *PositionMap) IsAsciiOnly() bool {
|
||||
return pm.asciiOnly
|
||||
}
|
||||
|
||||
// UTF8ToUTF16 converts a UTF-8 byte offset to a UTF-16 code unit offset.
|
||||
func (pm *PositionMap) UTF8ToUTF16(utf8Offset int) int {
|
||||
if pm.asciiOnly {
|
||||
return utf8Offset
|
||||
}
|
||||
// Binary search: find the last entry where utf8Pos <= utf8Offset
|
||||
lo, hi := 0, len(pm.entries)
|
||||
for lo < hi {
|
||||
mid := lo + (hi-lo)/2
|
||||
if pm.entries[mid].utf8Pos <= utf8Offset {
|
||||
lo = mid + 1
|
||||
} else {
|
||||
hi = mid
|
||||
}
|
||||
}
|
||||
if lo == 0 {
|
||||
// Before any multi-byte character
|
||||
return utf8Offset
|
||||
}
|
||||
return utf8Offset - pm.entries[lo-1].delta
|
||||
}
|
||||
|
||||
// UTF16ToUTF8 converts a UTF-16 code unit offset to a UTF-8 byte offset.
|
||||
func (pm *PositionMap) UTF16ToUTF8(utf16Offset int) int {
|
||||
if pm.asciiOnly {
|
||||
return utf16Offset
|
||||
}
|
||||
// We need the last entry where (utf8Pos - delta) <= utf16Offset.
|
||||
// (utf8Pos - delta) is the UTF-16 offset of that entry's character.
|
||||
lo, hi := 0, len(pm.entries)
|
||||
for lo < hi {
|
||||
mid := lo + (hi-lo)/2
|
||||
utf16Pos := pm.entries[mid].utf8Pos - pm.entries[mid].delta
|
||||
if utf16Pos <= utf16Offset {
|
||||
lo = mid + 1
|
||||
} else {
|
||||
hi = mid
|
||||
}
|
||||
}
|
||||
if lo == 0 {
|
||||
return utf16Offset
|
||||
}
|
||||
return utf16Offset + pm.entries[lo-1].delta
|
||||
}
|
||||
225
tools/tsgo/internal/ast/positionmap_test.go
Normal file
225
tools/tsgo/internal/ast/positionmap_test.go
Normal file
@@ -0,0 +1,225 @@
|
||||
package ast_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/stringutil"
|
||||
)
|
||||
|
||||
func TestPositionMapASCII(t *testing.T) {
|
||||
t.Parallel()
|
||||
text := "const x = 1;"
|
||||
pm := ast.ComputePositionMap(text)
|
||||
if !pm.IsAsciiOnly() {
|
||||
t.Fatal("expected ASCII-only")
|
||||
}
|
||||
for i := 0; i <= len(text); i++ {
|
||||
if got := pm.UTF8ToUTF16(i); got != i {
|
||||
t.Errorf("UTF8ToUTF16(%d) = %d, want %d", i, got, i)
|
||||
}
|
||||
if got := pm.UTF16ToUTF8(i); got != i {
|
||||
t.Errorf("UTF16ToUTF8(%d) = %d, want %d", i, got, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPositionMapTwoByte(t *testing.T) {
|
||||
t.Parallel()
|
||||
// "café" — é (U+00E9) is 2 bytes UTF-8, 1 code unit UTF-16
|
||||
text := "const café = 1;\nconst x = 2;"
|
||||
pm := ast.ComputePositionMap(text)
|
||||
if pm.IsAsciiOnly() {
|
||||
t.Fatal("expected non-ASCII")
|
||||
}
|
||||
|
||||
// Everything before é (byte offset 9) should be identity
|
||||
for i := range 10 {
|
||||
if got := pm.UTF8ToUTF16(i); got != i {
|
||||
t.Errorf("before é: UTF8ToUTF16(%d) = %d, want %d", i, got, i)
|
||||
}
|
||||
}
|
||||
|
||||
// é starts at UTF-8 byte 9, UTF-16 offset 9: same
|
||||
if got := pm.UTF8ToUTF16(9); got != 9 {
|
||||
t.Errorf("at é: UTF8ToUTF16(9) = %d, want 9", got)
|
||||
}
|
||||
|
||||
// After é (byte 11 in UTF-8 = code unit 10 in UTF-16), delta is 1
|
||||
// ' ' after café: UTF-8 byte 11, UTF-16 offset 10
|
||||
if got := pm.UTF8ToUTF16(11); got != 10 {
|
||||
t.Errorf("after é: UTF8ToUTF16(11) = %d, want 10", got)
|
||||
}
|
||||
|
||||
// 'x' on second line: UTF-8 byte 23, UTF-16 offset 22
|
||||
xUTF8 := strings.LastIndex(text, "x")
|
||||
if got := pm.UTF8ToUTF16(xUTF8); got != xUTF8-1 {
|
||||
t.Errorf("at x: UTF8ToUTF16(%d) = %d, want %d", xUTF8, got, xUTF8-1)
|
||||
}
|
||||
|
||||
// Reverse: UTF-16 offset 22 should map to UTF-8 byte 23
|
||||
xUTF16 := xUTF8 - 1
|
||||
if got := pm.UTF16ToUTF8(xUTF16); got != xUTF8 {
|
||||
t.Errorf("reverse at x: UTF16ToUTF8(%d) = %d, want %d", xUTF16, got, xUTF8)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPositionMapFourByte(t *testing.T) {
|
||||
t.Parallel()
|
||||
// 🎉 (U+1F389) is 4 bytes UTF-8, 2 code units UTF-16
|
||||
text := `const a = "🎉";` + "\nconst b = 2;"
|
||||
pm := ast.ComputePositionMap(text)
|
||||
if pm.IsAsciiOnly() {
|
||||
t.Fatal("expected non-ASCII")
|
||||
}
|
||||
|
||||
// 🎉 starts at byte 11 (after `const a = "`)
|
||||
// UTF-8: bytes 11-14 (4 bytes), UTF-16: units 11-12 (2 code units)
|
||||
// After 🎉: UTF-8 byte 15, UTF-16 offset 13. Delta = 2.
|
||||
|
||||
// 'b' on second line
|
||||
bUTF8 := strings.LastIndex(text, "b")
|
||||
bUTF16 := bUTF8 - 2 // delta of 2 from emoji
|
||||
if got := pm.UTF8ToUTF16(bUTF8); got != bUTF16 {
|
||||
t.Errorf("at b: UTF8ToUTF16(%d) = %d, want %d", bUTF8, got, bUTF16)
|
||||
}
|
||||
if got := pm.UTF16ToUTF8(bUTF16); got != bUTF8 {
|
||||
t.Errorf("reverse at b: UTF16ToUTF8(%d) = %d, want %d", bUTF16, got, bUTF8)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPositionMapMultipleNonASCII(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Mix of 2-byte and 4-byte characters
|
||||
// "à" (U+00E0) = 2 bytes UTF-8, 1 code unit UTF-16 (delta +1)
|
||||
// "🎉" (U+1F389) = 4 bytes UTF-8, 2 code units UTF-16 (delta +2)
|
||||
text := "à🎉x"
|
||||
pm := ast.ComputePositionMap(text)
|
||||
|
||||
// à: UTF-8 [0,2), UTF-16 [0,1)
|
||||
// 🎉: UTF-8 [2,6), UTF-16 [1,3)
|
||||
// x: UTF-8 [6,7), UTF-16 [3,4)
|
||||
tests := []struct {
|
||||
utf8 int
|
||||
utf16 int
|
||||
}{
|
||||
{0, 0},
|
||||
{2, 1}, // start of 🎉
|
||||
{6, 3}, // x
|
||||
{7, 4}, // end
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if got := pm.UTF8ToUTF16(tt.utf8); got != tt.utf16 {
|
||||
t.Errorf("UTF8ToUTF16(%d) = %d, want %d", tt.utf8, got, tt.utf16)
|
||||
}
|
||||
if got := pm.UTF16ToUTF8(tt.utf16); got != tt.utf8 {
|
||||
t.Errorf("UTF16ToUTF8(%d) = %d, want %d", tt.utf16, got, tt.utf8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPositionMapLoneSurrogateSentinel(t *testing.T) {
|
||||
t.Parallel()
|
||||
text := "a" + stringutil.EncodeJSStringRune(0xD800) + "b"
|
||||
pm := ast.ComputePositionMap(text)
|
||||
if pm.IsAsciiOnly() {
|
||||
t.Fatal("expected non-ASCII")
|
||||
}
|
||||
|
||||
if got := pm.UTF8ToUTF16(len(text)); got != 3 {
|
||||
t.Errorf("UTF8ToUTF16(%d) = %d, want 3", len(text), got)
|
||||
}
|
||||
if got := pm.UTF16ToUTF8(2); got != len(text)-1 {
|
||||
t.Errorf("UTF16ToUTF8(2) = %d, want %d", got, len(text)-1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPositionMapRoundtrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
text := "let café = \"🎉\"; // naïve"
|
||||
pm := ast.ComputePositionMap(text)
|
||||
|
||||
// Convert every valid UTF-16 position to UTF-8 and back
|
||||
utf16Len := pm.UTF8ToUTF16(len(text))
|
||||
for i := 0; i <= utf16Len; i++ {
|
||||
utf8Pos := pm.UTF16ToUTF8(i)
|
||||
back := pm.UTF8ToUTF16(utf8Pos)
|
||||
if back != i {
|
||||
t.Errorf("roundtrip UTF16->UTF8->UTF16: %d -> %d -> %d", i, utf8Pos, back)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkComputePositionMap_ASCII(b *testing.B) {
|
||||
// ~10KB of ASCII TypeScript-like code
|
||||
line := "const variable = someFunction(argument1, argument2);\n"
|
||||
text := strings.Repeat(line, 200)
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
ast.ComputePositionMap(text)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkComputePositionMap_NonASCII(b *testing.B) {
|
||||
// Mix of ASCII and non-ASCII (comments with unicode)
|
||||
line := "const café = \"héllo wörld 🎉\";\n"
|
||||
text := strings.Repeat(line, 200)
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
ast.ComputePositionMap(text)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUTF8ToUTF16_ASCII(b *testing.B) {
|
||||
line := "const variable = someFunction(argument1, argument2);\n"
|
||||
text := strings.Repeat(line, 200)
|
||||
pm := ast.ComputePositionMap(text)
|
||||
positions := []int{0, 100, 500, 1000, 5000, len(text) - 1}
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
for _, p := range positions {
|
||||
pm.UTF8ToUTF16(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUTF8ToUTF16_NonASCII(b *testing.B) {
|
||||
line := "const café = \"héllo wörld 🎉\";\n"
|
||||
text := strings.Repeat(line, 200)
|
||||
pm := ast.ComputePositionMap(text)
|
||||
positions := []int{0, 100, 500, 1000, 5000, len(text) - 1}
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
for _, p := range positions {
|
||||
pm.UTF8ToUTF16(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUTF16ToUTF8_NonASCII(b *testing.B) {
|
||||
line := "const café = \"héllo wörld 🎉\";\n"
|
||||
text := strings.Repeat(line, 200)
|
||||
pm := ast.ComputePositionMap(text)
|
||||
utf16Len := pm.UTF8ToUTF16(len(text))
|
||||
positions := []int{0, 100, 500, 1000, 3000, utf16Len - 1}
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
for _, p := range positions {
|
||||
pm.UTF16ToUTF8(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkComputePositionMap_CheckerTS(b *testing.B) {
|
||||
data, err := os.ReadFile("../../_submodules/TypeScript/src/compiler/checker.ts")
|
||||
if err != nil {
|
||||
b.Skip("checker.ts not available:", err)
|
||||
}
|
||||
text := string(data)
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
ast.ComputePositionMap(text)
|
||||
}
|
||||
}
|
||||
717
tools/tsgo/internal/ast/precedence.go
Normal file
717
tools/tsgo/internal/ast/precedence.go
Normal file
@@ -0,0 +1,717 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type OperatorPrecedence int
|
||||
|
||||
const (
|
||||
// Expression:
|
||||
// AssignmentExpression
|
||||
// Expression `,` AssignmentExpression
|
||||
OperatorPrecedenceComma OperatorPrecedence = iota
|
||||
// NOTE: `Spread` is higher than `Comma` due to how it is parsed in |ElementList|
|
||||
// SpreadElement:
|
||||
// `...` AssignmentExpression
|
||||
OperatorPrecedenceSpread
|
||||
// AssignmentExpression:
|
||||
// ConditionalExpression
|
||||
// YieldExpression
|
||||
// ArrowFunction
|
||||
// AsyncArrowFunction
|
||||
// LeftHandSideExpression `=` AssignmentExpression
|
||||
// LeftHandSideExpression AssignmentOperator AssignmentExpression
|
||||
//
|
||||
// NOTE: AssignmentExpression is broken down into several precedences due to the requirements
|
||||
// of the parenthesizer rules.
|
||||
// AssignmentExpression: YieldExpression
|
||||
// YieldExpression:
|
||||
// `yield`
|
||||
// `yield` AssignmentExpression
|
||||
// `yield` `*` AssignmentExpression
|
||||
OperatorPrecedenceYield
|
||||
// AssignmentExpression: LeftHandSideExpression `=` AssignmentExpression
|
||||
// AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression
|
||||
// AssignmentOperator: one of
|
||||
// `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `>>>=` `&=` `^=` `|=` `**=`
|
||||
OperatorPrecedenceAssignment
|
||||
// NOTE: `Conditional` is considered higher than `Assignment` here, but in reality they have
|
||||
// the same precedence.
|
||||
// AssignmentExpression: ConditionalExpression
|
||||
// ConditionalExpression:
|
||||
// ShortCircuitExpression
|
||||
// ShortCircuitExpression `?` AssignmentExpression `:` AssignmentExpression
|
||||
OperatorPrecedenceConditional
|
||||
// LogicalORExpression:
|
||||
// LogicalANDExpression
|
||||
// LogicalORExpression `||` LogicalANDExpression
|
||||
OperatorPrecedenceLogicalOR
|
||||
// LogicalANDExpression:
|
||||
// BitwiseORExpression
|
||||
// LogicalANDExprerssion `&&` BitwiseORExpression
|
||||
OperatorPrecedenceLogicalAND
|
||||
// BitwiseORExpression:
|
||||
// BitwiseXORExpression
|
||||
// BitwiseORExpression `|` BitwiseXORExpression
|
||||
OperatorPrecedenceBitwiseOR
|
||||
// BitwiseXORExpression:
|
||||
// BitwiseANDExpression
|
||||
// BitwiseXORExpression `^` BitwiseANDExpression
|
||||
OperatorPrecedenceBitwiseXOR
|
||||
// BitwiseANDExpression:
|
||||
// EqualityExpression
|
||||
// BitwiseANDExpression `&` EqualityExpression
|
||||
OperatorPrecedenceBitwiseAND
|
||||
// EqualityExpression:
|
||||
// RelationalExpression
|
||||
// EqualityExpression `==` RelationalExpression
|
||||
// EqualityExpression `!=` RelationalExpression
|
||||
// EqualityExpression `===` RelationalExpression
|
||||
// EqualityExpression `!==` RelationalExpression
|
||||
OperatorPrecedenceEquality
|
||||
// RelationalExpression:
|
||||
// ShiftExpression
|
||||
// RelationalExpression `<` ShiftExpression
|
||||
// RelationalExpression `>` ShiftExpression
|
||||
// RelationalExpression `<=` ShiftExpression
|
||||
// RelationalExpression `>=` ShiftExpression
|
||||
// RelationalExpression `instanceof` ShiftExpression
|
||||
// RelationalExpression `in` ShiftExpression
|
||||
// [+TypeScript] RelationalExpression `as` Type
|
||||
OperatorPrecedenceRelational
|
||||
// ShiftExpression:
|
||||
// AdditiveExpression
|
||||
// ShiftExpression `<<` AdditiveExpression
|
||||
// ShiftExpression `>>` AdditiveExpression
|
||||
// ShiftExpression `>>>` AdditiveExpression
|
||||
OperatorPrecedenceShift
|
||||
// AdditiveExpression:
|
||||
// MultiplicativeExpression
|
||||
// AdditiveExpression `+` MultiplicativeExpression
|
||||
// AdditiveExpression `-` MultiplicativeExpression
|
||||
OperatorPrecedenceAdditive
|
||||
// MultiplicativeExpression:
|
||||
// ExponentiationExpression
|
||||
// MultiplicativeExpression MultiplicativeOperator ExponentiationExpression
|
||||
// MultiplicativeOperator: one of `*`, `/`, `%`
|
||||
OperatorPrecedenceMultiplicative
|
||||
// ExponentiationExpression:
|
||||
// UnaryExpression
|
||||
// UpdateExpression `**` ExponentiationExpression
|
||||
OperatorPrecedenceExponentiation
|
||||
// UnaryExpression:
|
||||
// UpdateExpression
|
||||
// `delete` UnaryExpression
|
||||
// `void` UnaryExpression
|
||||
// `typeof` UnaryExpression
|
||||
// `+` UnaryExpression
|
||||
// `-` UnaryExpression
|
||||
// `~` UnaryExpression
|
||||
// `!` UnaryExpression
|
||||
// AwaitExpression
|
||||
// UpdateExpression: // TODO: Do we need to investigate the precedence here?
|
||||
// `++` UnaryExpression
|
||||
// `--` UnaryExpression
|
||||
OperatorPrecedenceUnary
|
||||
// UpdateExpression:
|
||||
// LeftHandSideExpression
|
||||
// LeftHandSideExpression `++`
|
||||
// LeftHandSideExpression `--`
|
||||
OperatorPrecedenceUpdate
|
||||
// LeftHandSideExpression:
|
||||
// NewExpression
|
||||
// NewExpression:
|
||||
// MemberExpression
|
||||
// `new` NewExpression
|
||||
OperatorPrecedenceLeftHandSide
|
||||
// LeftHandSideExpression:
|
||||
// OptionalExpression
|
||||
// OptionalExpression:
|
||||
// MemberExpression OptionalChain
|
||||
// CallExpression OptionalChain
|
||||
// OptionalExpression OptionalChain
|
||||
OperatorPrecedenceOptionalChain
|
||||
// LeftHandSideExpression:
|
||||
// CallExpression
|
||||
// CallExpression:
|
||||
// CoverCallExpressionAndAsyncArrowHead
|
||||
// SuperCall
|
||||
// ImportCall
|
||||
// CallExpression Arguments
|
||||
// CallExpression `[` Expression `]`
|
||||
// CallExpression `.` IdentifierName
|
||||
// CallExpression TemplateLiteral
|
||||
// MemberExpression:
|
||||
// PrimaryExpression
|
||||
// MemberExpression `[` Expression `]`
|
||||
// MemberExpression `.` IdentifierName
|
||||
// MemberExpression TemplateLiteral
|
||||
// SuperProperty
|
||||
// MetaProperty
|
||||
// `new` MemberExpression Arguments
|
||||
OperatorPrecedenceMember
|
||||
// TODO: JSXElement?
|
||||
// PrimaryExpression:
|
||||
// `this`
|
||||
// IdentifierReference
|
||||
// Literal
|
||||
// ArrayLiteral
|
||||
// ObjectLiteral
|
||||
// FunctionExpression
|
||||
// ClassExpression
|
||||
// GeneratorExpression
|
||||
// AsyncFunctionExpression
|
||||
// AsyncGeneratorExpression
|
||||
// RegularExpressionLiteral
|
||||
// TemplateLiteral
|
||||
OperatorPrecedencePrimary
|
||||
// PrimaryExpression:
|
||||
// CoverParenthesizedExpressionAndArrowParameterList
|
||||
OperatorPrecedenceParentheses
|
||||
OperatorPrecedenceLowest = OperatorPrecedenceComma
|
||||
OperatorPrecedenceHighest = OperatorPrecedenceParentheses
|
||||
OperatorPrecedenceDisallowComma = OperatorPrecedenceYield
|
||||
// ShortCircuitExpression:
|
||||
// LogicalORExpression
|
||||
// CoalesceExpression
|
||||
// CoalesceExpression:
|
||||
// CoalesceExpressionHead `??` BitwiseORExpression
|
||||
// CoalesceExpressionHead:
|
||||
// CoalesceExpression
|
||||
// BitwiseORExpression
|
||||
OperatorPrecedenceCoalesce = OperatorPrecedenceLogicalOR
|
||||
// -1 is lower than all other precedences. Returning it will cause binary expression
|
||||
// parsing to stop.
|
||||
OperatorPrecedenceInvalid OperatorPrecedence = -1
|
||||
)
|
||||
|
||||
func getOperator(expression *Expression) Kind {
|
||||
switch expression.Kind {
|
||||
case KindBinaryExpression:
|
||||
return expression.AsBinaryExpression().OperatorToken.Kind
|
||||
case KindPrefixUnaryExpression:
|
||||
return expression.AsPrefixUnaryExpression().Operator
|
||||
case KindPostfixUnaryExpression:
|
||||
return expression.AsPostfixUnaryExpression().Operator
|
||||
default:
|
||||
return expression.Kind
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the precedence of an expression
|
||||
func GetExpressionPrecedence(expression *Expression) OperatorPrecedence {
|
||||
operator := getOperator(expression)
|
||||
var flags OperatorPrecedenceFlags
|
||||
if expression.Kind == KindNewExpression && expression.ArgumentList() == nil {
|
||||
flags = OperatorPrecedenceFlagsNewWithoutArguments
|
||||
} else if IsOptionalChain(expression) {
|
||||
flags = OperatorPrecedenceFlagsOptionalChain
|
||||
}
|
||||
return GetOperatorPrecedence(expression.Kind, operator, flags)
|
||||
}
|
||||
|
||||
type OperatorPrecedenceFlags int
|
||||
|
||||
const (
|
||||
OperatorPrecedenceFlagsNone OperatorPrecedenceFlags = 0
|
||||
OperatorPrecedenceFlagsNewWithoutArguments OperatorPrecedenceFlags = 1 << 0
|
||||
OperatorPrecedenceFlagsOptionalChain OperatorPrecedenceFlags = 1 << 1
|
||||
)
|
||||
|
||||
// Gets the precedence of an operator
|
||||
func GetOperatorPrecedence(nodeKind Kind, operatorKind Kind, flags OperatorPrecedenceFlags) OperatorPrecedence {
|
||||
switch nodeKind {
|
||||
case KindSpreadElement:
|
||||
return OperatorPrecedenceSpread
|
||||
case KindYieldExpression:
|
||||
return OperatorPrecedenceYield
|
||||
// !!! By necessity, this differs from the old compiler to better align with ParenthesizerRules. consider backporting
|
||||
case KindArrowFunction:
|
||||
return OperatorPrecedenceAssignment
|
||||
case KindConditionalExpression:
|
||||
return OperatorPrecedenceConditional
|
||||
case KindBinaryExpression:
|
||||
switch operatorKind {
|
||||
case KindCommaToken:
|
||||
return OperatorPrecedenceComma
|
||||
|
||||
case KindEqualsToken,
|
||||
KindPlusEqualsToken,
|
||||
KindMinusEqualsToken,
|
||||
KindAsteriskAsteriskEqualsToken,
|
||||
KindAsteriskEqualsToken,
|
||||
KindSlashEqualsToken,
|
||||
KindPercentEqualsToken,
|
||||
KindLessThanLessThanEqualsToken,
|
||||
KindGreaterThanGreaterThanEqualsToken,
|
||||
KindGreaterThanGreaterThanGreaterThanEqualsToken,
|
||||
KindAmpersandEqualsToken,
|
||||
KindCaretEqualsToken,
|
||||
KindBarEqualsToken,
|
||||
KindBarBarEqualsToken,
|
||||
KindAmpersandAmpersandEqualsToken,
|
||||
KindQuestionQuestionEqualsToken:
|
||||
return OperatorPrecedenceAssignment
|
||||
|
||||
default:
|
||||
return GetBinaryOperatorPrecedence(operatorKind)
|
||||
}
|
||||
// TODO: Should prefix `++` and `--` be moved to the `Update` precedence?
|
||||
case KindTypeAssertionExpression,
|
||||
KindNonNullExpression,
|
||||
KindPrefixUnaryExpression,
|
||||
KindTypeOfExpression,
|
||||
KindVoidExpression,
|
||||
KindDeleteExpression,
|
||||
KindAwaitExpression:
|
||||
return OperatorPrecedenceUnary
|
||||
|
||||
case KindPostfixUnaryExpression:
|
||||
return OperatorPrecedenceUpdate
|
||||
|
||||
// !!! By necessity, this differs from the old compiler to better align with ParenthesizerRules. consider backporting
|
||||
case KindPropertyAccessExpression, KindElementAccessExpression:
|
||||
if flags&OperatorPrecedenceFlagsOptionalChain != 0 {
|
||||
return OperatorPrecedenceOptionalChain
|
||||
}
|
||||
return OperatorPrecedenceMember
|
||||
|
||||
case KindCallExpression:
|
||||
if flags&OperatorPrecedenceFlagsOptionalChain != 0 {
|
||||
return OperatorPrecedenceOptionalChain
|
||||
}
|
||||
return OperatorPrecedenceMember
|
||||
|
||||
// !!! By necessity, this differs from the old compiler to better align with ParenthesizerRules. consider backporting
|
||||
case KindNewExpression:
|
||||
if flags&OperatorPrecedenceFlagsNewWithoutArguments != 0 {
|
||||
return OperatorPrecedenceLeftHandSide
|
||||
}
|
||||
return OperatorPrecedenceMember
|
||||
|
||||
// !!! By necessity, this differs from the old compiler to better align with ParenthesizerRules. consider backporting
|
||||
case KindTaggedTemplateExpression, KindMetaProperty, KindExpressionWithTypeArguments:
|
||||
return OperatorPrecedenceMember
|
||||
|
||||
case KindAsExpression,
|
||||
KindSatisfiesExpression:
|
||||
return OperatorPrecedenceRelational
|
||||
|
||||
case KindThisKeyword,
|
||||
KindSuperKeyword,
|
||||
KindImportKeyword,
|
||||
KindIdentifier,
|
||||
KindPrivateIdentifier,
|
||||
KindNullKeyword,
|
||||
KindTrueKeyword,
|
||||
KindFalseKeyword,
|
||||
KindNumericLiteral,
|
||||
KindBigIntLiteral,
|
||||
KindStringLiteral,
|
||||
KindArrayLiteralExpression,
|
||||
KindObjectLiteralExpression,
|
||||
KindFunctionExpression,
|
||||
KindClassExpression,
|
||||
KindRegularExpressionLiteral,
|
||||
KindNoSubstitutionTemplateLiteral,
|
||||
KindTemplateExpression,
|
||||
KindOmittedExpression,
|
||||
KindJsxElement,
|
||||
KindJsxSelfClosingElement,
|
||||
KindJsxFragment,
|
||||
KindMissingDeclaration:
|
||||
return OperatorPrecedencePrimary
|
||||
|
||||
// !!! By necessity, this differs from the old compiler to support emit. consider backporting
|
||||
case KindParenthesizedExpression:
|
||||
return OperatorPrecedenceParentheses
|
||||
|
||||
default:
|
||||
return OperatorPrecedenceInvalid
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the precedence of a binary operator
|
||||
func GetBinaryOperatorPrecedence(operatorKind Kind) OperatorPrecedence {
|
||||
switch operatorKind {
|
||||
case KindQuestionQuestionToken:
|
||||
return OperatorPrecedenceCoalesce
|
||||
case KindBarBarToken:
|
||||
return OperatorPrecedenceLogicalOR
|
||||
case KindAmpersandAmpersandToken:
|
||||
return OperatorPrecedenceLogicalAND
|
||||
case KindBarToken:
|
||||
return OperatorPrecedenceBitwiseOR
|
||||
case KindCaretToken:
|
||||
return OperatorPrecedenceBitwiseXOR
|
||||
case KindAmpersandToken:
|
||||
return OperatorPrecedenceBitwiseAND
|
||||
case KindEqualsEqualsToken, KindExclamationEqualsToken, KindEqualsEqualsEqualsToken, KindExclamationEqualsEqualsToken:
|
||||
return OperatorPrecedenceEquality
|
||||
case KindLessThanToken, KindGreaterThanToken, KindLessThanEqualsToken, KindGreaterThanEqualsToken,
|
||||
KindInstanceOfKeyword, KindInKeyword, KindAsKeyword, KindSatisfiesKeyword:
|
||||
return OperatorPrecedenceRelational
|
||||
case KindLessThanLessThanToken, KindGreaterThanGreaterThanToken, KindGreaterThanGreaterThanGreaterThanToken:
|
||||
return OperatorPrecedenceShift
|
||||
case KindPlusToken, KindMinusToken:
|
||||
return OperatorPrecedenceAdditive
|
||||
case KindAsteriskToken, KindSlashToken, KindPercentToken:
|
||||
return OperatorPrecedenceMultiplicative
|
||||
case KindAsteriskAsteriskToken:
|
||||
return OperatorPrecedenceExponentiation
|
||||
}
|
||||
// -1 is lower than all other precedences. Returning it will cause binary expression
|
||||
// parsing to stop.
|
||||
return OperatorPrecedenceInvalid
|
||||
}
|
||||
|
||||
// Gets the leftmost expression of an expression, e.g. `a` in `a.b`, `a[b]`, `a++`, `a+b`, `a?b:c`, `a as B`, etc.
|
||||
func GetLeftmostExpression(node *Expression, stopAtCallExpressions bool) *Expression {
|
||||
for {
|
||||
switch node.Kind {
|
||||
case KindPostfixUnaryExpression:
|
||||
node = node.AsPostfixUnaryExpression().Operand
|
||||
continue
|
||||
case KindBinaryExpression:
|
||||
node = node.AsBinaryExpression().Left
|
||||
continue
|
||||
case KindConditionalExpression:
|
||||
node = node.AsConditionalExpression().Condition
|
||||
continue
|
||||
case KindTaggedTemplateExpression:
|
||||
node = node.AsTaggedTemplateExpression().Tag
|
||||
continue
|
||||
case KindCallExpression:
|
||||
if stopAtCallExpressions {
|
||||
return node
|
||||
}
|
||||
fallthrough
|
||||
case KindAsExpression,
|
||||
KindElementAccessExpression,
|
||||
KindPropertyAccessExpression,
|
||||
KindNonNullExpression,
|
||||
KindPartiallyEmittedExpression,
|
||||
KindSatisfiesExpression:
|
||||
node = node.Expression()
|
||||
continue
|
||||
}
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
type TypePrecedence int32
|
||||
|
||||
const (
|
||||
// Conditional precedence (lowest)
|
||||
//
|
||||
// Type[Extends]:
|
||||
// ConditionalTypeNode[?Extends]
|
||||
//
|
||||
// ConditionalTypeNode[Extends]:
|
||||
// [~Extends] UnionTypeNode `extends` Type[+Extends] `?` Type[~Extends] `:` Type[~Extends]
|
||||
//
|
||||
TypePrecedenceConditional TypePrecedence = iota
|
||||
|
||||
// JSDoc precedence (optional and variadic types)
|
||||
//
|
||||
// JSDocType:
|
||||
// `...`? Type `=`?
|
||||
TypePrecedenceJSDoc
|
||||
|
||||
// Function precedence
|
||||
//
|
||||
// Type[Extends]:
|
||||
// ConditionalTypeNode[?Extends]
|
||||
// FunctionTypeNode[?Extends]
|
||||
// ConstructorTypeNode[?Extends]
|
||||
//
|
||||
// ConditionalTypeNode[Extends]:
|
||||
// UnionTypeNode
|
||||
//
|
||||
// FunctionTypeNode[Extends]:
|
||||
// TypeParameters? ArrowParameters `=>` Type[?Extends]
|
||||
//
|
||||
// ConstructorTypeNode[Extends]:
|
||||
// `abstract`? TypeParameters? ArrowParameters `=>` Type[?Extends]
|
||||
//
|
||||
TypePrecedenceFunction
|
||||
|
||||
// Union precedence
|
||||
//
|
||||
// UnionTypeNode:
|
||||
// `|`? UnionTypeNoBar
|
||||
//
|
||||
// UnionTypeNoBar:
|
||||
// IntersectionTypeNode
|
||||
// UnionTypeNoBar `|` IntersectionTypeNode
|
||||
//
|
||||
TypePrecedenceUnion
|
||||
|
||||
// Intersection precedence
|
||||
//
|
||||
// IntersectionTypeNode:
|
||||
// `&`? IntersectionTypeNoAmpersand
|
||||
//
|
||||
// IntersectionTypeNoAmpersand:
|
||||
// TypeOperatorNode
|
||||
// IntersectionTypeNoAmpersand `&` TypeOperatorNode
|
||||
//
|
||||
TypePrecedenceIntersection
|
||||
|
||||
// TypeOperatorNode precedence
|
||||
//
|
||||
// TypeOperatorNode:
|
||||
// PostfixType
|
||||
// InferTypeNode
|
||||
// `keyof` TypeOperatorNode
|
||||
// `unique` TypeOperatorNode
|
||||
// `readonly` PostfixType
|
||||
//
|
||||
// InferTypeNode:
|
||||
// `infer` BindingIdentifier
|
||||
// `infer` BindingIdentifier `extends` Type[+Extends]
|
||||
//
|
||||
TypePrecedenceTypeOperator
|
||||
|
||||
// Postfix precedence
|
||||
//
|
||||
// PostfixType:
|
||||
// NonArrayType
|
||||
// OptionalTypeNode
|
||||
// ArrayTypeNode
|
||||
// IndexedAccessTypeNode
|
||||
//
|
||||
// OptionalTypeNode:
|
||||
// PostfixType `?`
|
||||
//
|
||||
// ArrayTypeNode:
|
||||
// PostfixType `[` `]`
|
||||
//
|
||||
// IndexedAccessTypeNode:
|
||||
// PostfixType `[` Type[~Extends] `]`
|
||||
//
|
||||
TypePrecedencePostfix
|
||||
|
||||
// NonArray precedence (highest)
|
||||
//
|
||||
// NonArrayType:
|
||||
// KeywordType
|
||||
// LiteralTypeNode
|
||||
// ThisTypeNode
|
||||
// ImportType
|
||||
// TypeQueryNode
|
||||
// MappedTypeNode
|
||||
// TypeLiteralNode
|
||||
// TupleTypeNode
|
||||
// ParenthesizedTypeNode
|
||||
// TypePredicateNode
|
||||
// TypeReferenceNode
|
||||
// TemplateType
|
||||
//
|
||||
// KeywordType: one of
|
||||
// `any` `unknown` `string` `number` `bigint`
|
||||
// `symbol` `boolean` `undefined` `never` `object`
|
||||
// `intrinsic` `void`
|
||||
//
|
||||
// LiteralTypeNode:
|
||||
// StringLiteral
|
||||
// NoSubstitutionTemplateLiteral
|
||||
// NumericLiteral
|
||||
// BigIntLiteral
|
||||
// `-` NumericLiteral
|
||||
// `-` BigIntLiteral
|
||||
// `true`
|
||||
// `false`
|
||||
// `null`
|
||||
//
|
||||
// ThisTypeNode:
|
||||
// `this`
|
||||
//
|
||||
// ImportType:
|
||||
// `typeof`? `import` `(` Type[~Extends] `,`? `)` ImportTypeQualifier? TypeArguments?
|
||||
// `typeof`? `import` `(` Type[~Extends] `,` ImportTypeAttributes `,`? `)` ImportTypeQualifier? TypeArguments?
|
||||
//
|
||||
// ImportTypeQualifier:
|
||||
// `.` EntityName
|
||||
//
|
||||
// ImportTypeAttributes:
|
||||
// `{` `with` `:` ImportAttributes `,`? `}`
|
||||
//
|
||||
// TypeQueryNode:
|
||||
//
|
||||
// MappedTypeNode:
|
||||
// `{` MappedTypePrefix? MappedTypePropertyName MappedTypeSuffix? `:` Type[~Extends] `;` `}`
|
||||
//
|
||||
// MappedTypePrefix:
|
||||
// `readonly`
|
||||
// `+` `readonly`
|
||||
// `-` `readonly`
|
||||
//
|
||||
// MappedTypePropertyName:
|
||||
// `[` BindingIdentifier `in` Type[~Extends] `]`
|
||||
// `[` BindingIdentifier `in` Type[~Extends] `as` Type[~Extends] `]`
|
||||
//
|
||||
// MappedTypeSuffix:
|
||||
// `?`
|
||||
// `+` `?`
|
||||
// `-` `?`
|
||||
//
|
||||
// TypeLiteralNode:
|
||||
// `{` TypeElementList `}`
|
||||
//
|
||||
// TypeElementList:
|
||||
// [empty]
|
||||
// TypeElementList TypeElement
|
||||
//
|
||||
// TypeElement:
|
||||
// PropertySignatureDeclaration
|
||||
// MethodSignatureDeclaration
|
||||
// IndexSignatureDeclaration
|
||||
// CallSignatureDeclaration
|
||||
// ConstructSignatureDeclaration
|
||||
//
|
||||
// PropertySignatureDeclaration:
|
||||
// PropertyName `?`? TypeAnnotation? `;`
|
||||
//
|
||||
// MethodSignatureDeclaration:
|
||||
// PropertyName `?`? TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;`
|
||||
// `get` PropertyName TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;` // GetAccessorDeclaration
|
||||
// `set` PropertyName TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;` // SetAccessorDeclaration
|
||||
//
|
||||
// IndexSignatureDeclaration:
|
||||
// `[` IdentifierName`]` TypeAnnotation `;`
|
||||
//
|
||||
// CallSignatureDeclaration:
|
||||
// TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;`
|
||||
//
|
||||
// ConstructSignatureDeclaration:
|
||||
// `new` TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;`
|
||||
//
|
||||
// TupleTypeNode:
|
||||
// `[` `]`
|
||||
// `[` NamedTupleElementTypes `,`? `]`
|
||||
// `[` TupleElementTypes `,`? `]`
|
||||
//
|
||||
// NamedTupleElementTypes:
|
||||
// NamedTupleMember
|
||||
// NamedTupleElementTypes `,` NamedTupleMember
|
||||
//
|
||||
// NamedTupleMember:
|
||||
// IdentifierName `?`? `:` Type[~Extends]
|
||||
// `...` IdentifierName `:` Type[~Extends]
|
||||
//
|
||||
// TupleElementTypes:
|
||||
// TupleElementType
|
||||
// TupleElementTypes `,` TupleElementType
|
||||
//
|
||||
// TupleElementType:
|
||||
// Type[~Extends]
|
||||
// OptionalTypeNode
|
||||
// RestTypeNode
|
||||
//
|
||||
// RestTypeNode:
|
||||
// `...` Type[~Extends]
|
||||
//
|
||||
// ParenthesizedTypeNode:
|
||||
// `(` Type[~Extends] `)`
|
||||
//
|
||||
// TypePredicateNode:
|
||||
// `asserts`? TypePredicateParameterName
|
||||
// `asserts`? TypePredicateParameterName `is` Type[~Extends]
|
||||
//
|
||||
// TypePredicateParameterName:
|
||||
// `this`
|
||||
// IdentifierReference
|
||||
//
|
||||
// TypeReferenceNode:
|
||||
// EntityName TypeArguments?
|
||||
//
|
||||
// TemplateType:
|
||||
// TemplateHead Type[~Extends] TemplateTypeSpans
|
||||
//
|
||||
// TemplateTypeSpans:
|
||||
// TemplateTail
|
||||
// TemplateTypeMiddleList TemplateTail
|
||||
//
|
||||
// TemplateTypeMiddleList:
|
||||
// TemplateMiddle Type[~Extends]
|
||||
// TemplateTypeMiddleList TemplateMiddle Type[~Extends]
|
||||
//
|
||||
// TypeArguments:
|
||||
// `<` TypeArgumentList `,`? `>`
|
||||
//
|
||||
// TypeArgumentList:
|
||||
// Type[~Extends]
|
||||
// TypeArgumentList `,` Type[~Extends]
|
||||
//
|
||||
TypePrecedenceNonArray
|
||||
|
||||
TypePrecedenceLowest = TypePrecedenceConditional
|
||||
TypePrecedenceHighest = TypePrecedenceNonArray
|
||||
)
|
||||
|
||||
// Gets the precedence of a TypeNode
|
||||
func GetTypeNodePrecedence(n *TypeNode) TypePrecedence {
|
||||
switch n.Kind {
|
||||
case KindConditionalType:
|
||||
return TypePrecedenceConditional
|
||||
case KindJSDocOptionalType, KindJSDocVariadicType:
|
||||
return TypePrecedenceJSDoc
|
||||
case KindFunctionType, KindConstructorType:
|
||||
return TypePrecedenceFunction
|
||||
case KindUnionType:
|
||||
return TypePrecedenceUnion
|
||||
case KindIntersectionType:
|
||||
return TypePrecedenceIntersection
|
||||
case KindTypeOperator:
|
||||
return TypePrecedenceTypeOperator
|
||||
case KindInferType:
|
||||
if n.AsInferTypeNode().TypeParameter.AsTypeParameterDeclaration().Constraint != nil {
|
||||
// `infer T extends U` must be treated as FunctionTypeNode precedence as the `extends` clause eagerly consumes
|
||||
// TypeNode
|
||||
return TypePrecedenceFunction
|
||||
}
|
||||
return TypePrecedenceTypeOperator
|
||||
case KindIndexedAccessType, KindArrayType, KindOptionalType:
|
||||
return TypePrecedencePostfix
|
||||
case KindTypeQuery:
|
||||
// TypeQueryNode is actually a NonArrayType, but we treat it as TypeOperatorNode
|
||||
// precedence so that it is parenthesized when used in a PostfixType
|
||||
// context (e.g., `(typeof C)[]` instead of `typeof C[]`)
|
||||
return TypePrecedenceTypeOperator
|
||||
case KindAnyKeyword,
|
||||
KindUnknownKeyword,
|
||||
KindStringKeyword,
|
||||
KindNumberKeyword,
|
||||
KindBigIntKeyword,
|
||||
KindSymbolKeyword,
|
||||
KindBooleanKeyword,
|
||||
KindUndefinedKeyword,
|
||||
KindNeverKeyword,
|
||||
KindObjectKeyword,
|
||||
KindIntrinsicKeyword,
|
||||
KindVoidKeyword,
|
||||
KindJSDocAllType,
|
||||
KindJSDocNullableType,
|
||||
KindJSDocNonNullableType,
|
||||
KindLiteralType,
|
||||
KindTypePredicate,
|
||||
KindTypeReference,
|
||||
KindTypeLiteral,
|
||||
KindTupleType,
|
||||
KindRestType,
|
||||
KindParenthesizedType,
|
||||
KindThisType,
|
||||
KindMappedType,
|
||||
KindNamedTupleMember,
|
||||
KindTemplateLiteralType,
|
||||
KindImportType,
|
||||
// These occur in pseudo-types like `f<T>.C`, where `f` is a generic function and `C` is a local type
|
||||
KindPropertyAccessExpression,
|
||||
KindExpressionWithTypeArguments:
|
||||
return TypePrecedenceNonArray
|
||||
default:
|
||||
panic(fmt.Sprintf("unhandled TypeNode: %v", n.Kind))
|
||||
}
|
||||
}
|
||||
133
tools/tsgo/internal/ast/subtreefacts.go
Normal file
133
tools/tsgo/internal/ast/subtreefacts.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
)
|
||||
|
||||
type SubtreeFacts uint32
|
||||
|
||||
const (
|
||||
// Facts
|
||||
// - Flags used to indicate that a node or subtree contains syntax relevant to a specific transform
|
||||
|
||||
SubtreeContainsTypeScript SubtreeFacts = 1 << iota
|
||||
SubtreeContainsJsx
|
||||
SubtreeContainsESDecorators
|
||||
SubtreeContainsUsing
|
||||
SubtreeContainsClassStaticBlocks
|
||||
SubtreeContainsESClassFields
|
||||
SubtreeContainsLogicalAssignments
|
||||
SubtreeContainsNullishCoalescing
|
||||
SubtreeContainsOptionalChaining
|
||||
SubtreeContainsMissingCatchClauseVariable
|
||||
SubtreeContainsESObjectRestOrSpread // subtree has a `...` somewhere inside it, never cleared
|
||||
SubtreeContainsForAwaitOrAsyncGenerator
|
||||
SubtreeContainsAnyAwait
|
||||
SubtreeContainsExponentiationOperator
|
||||
|
||||
// Markers
|
||||
// - Flags used to indicate that a node or subtree contains a particular kind of syntax.
|
||||
|
||||
SubtreeContainsLexicalThis
|
||||
SubtreeContainsLexicalSuper
|
||||
SubtreeContainsRestOrSpread // marker on any `...` - cleared on binding pattern exit
|
||||
SubtreeContainsObjectRestOrSpread // marker on any `{...x}` - cleared on most scope exits
|
||||
SubtreeContainsAwait
|
||||
SubtreeContainsDynamicImport
|
||||
SubtreeContainsClassFields
|
||||
SubtreeContainsDecorators
|
||||
SubtreeContainsIdentifier
|
||||
SubtreeContainsPrivateIdentifierInExpression
|
||||
SubtreeContainsInvalidTemplateEscape
|
||||
|
||||
SubtreeFactsComputed // NOTE: This should always be last
|
||||
SubtreeFactsNone SubtreeFacts = 0
|
||||
|
||||
// Aliases (unused, for documentation purposes only - correspond to combinations in transformers/estransforms/definitions.go)
|
||||
|
||||
SubtreeContainsESNext = SubtreeContainsESDecorators | SubtreeContainsUsing
|
||||
SubtreeContainsES2022 = SubtreeContainsClassStaticBlocks | SubtreeContainsESClassFields
|
||||
SubtreeContainsES2021 = SubtreeContainsLogicalAssignments
|
||||
SubtreeContainsES2020 = SubtreeContainsNullishCoalescing | SubtreeContainsOptionalChaining
|
||||
SubtreeContainsES2019 = SubtreeContainsMissingCatchClauseVariable
|
||||
SubtreeContainsES2018 = SubtreeContainsESObjectRestOrSpread | SubtreeContainsForAwaitOrAsyncGenerator | SubtreeContainsInvalidTemplateEscape
|
||||
SubtreeContainsES2017 = SubtreeContainsAnyAwait
|
||||
SubtreeContainsES2016 = SubtreeContainsExponentiationOperator
|
||||
|
||||
// Scope Exclusions
|
||||
// - Bitmasks that exclude flags from propagating out of a specific context
|
||||
// into the subtree flags of their container.
|
||||
|
||||
SubtreeExclusionsNode = SubtreeFactsComputed
|
||||
SubtreeExclusionsEraseable = ^SubtreeContainsTypeScript
|
||||
SubtreeExclusionsOuterExpression = SubtreeExclusionsNode
|
||||
SubtreeExclusionsPropertyAccess = SubtreeExclusionsNode
|
||||
SubtreeExclusionsElementAccess = SubtreeExclusionsNode
|
||||
SubtreeExclusionsArrowFunction = SubtreeExclusionsNode | SubtreeContainsAwait | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsFunction = SubtreeExclusionsNode | SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper | SubtreeContainsAwait | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsConstructor = SubtreeExclusionsNode | SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper | SubtreeContainsAwait | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsMethod = SubtreeExclusionsNode | SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper | SubtreeContainsAwait | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsAccessor = SubtreeExclusionsNode | SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper | SubtreeContainsAwait | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsProperty = SubtreeExclusionsNode | SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper
|
||||
SubtreeExclusionsClass = SubtreeExclusionsNode
|
||||
SubtreeExclusionsModule = SubtreeExclusionsNode | SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper
|
||||
SubtreeExclusionsObjectLiteral = SubtreeExclusionsNode | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsArrayLiteral = SubtreeExclusionsNode
|
||||
SubtreeExclusionsCall = SubtreeExclusionsNode
|
||||
SubtreeExclusionsNew = SubtreeExclusionsNode
|
||||
SubtreeExclusionsVariableDeclarationList = SubtreeExclusionsNode | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsParameter = SubtreeExclusionsNode
|
||||
SubtreeExclusionsCatchClause = SubtreeExclusionsNode | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsBindingPattern = SubtreeExclusionsNode | SubtreeContainsRestOrSpread
|
||||
|
||||
// Masks
|
||||
// - Additional bitmasks
|
||||
|
||||
SubtreeContainsLexicalThisOrSuper = SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper
|
||||
)
|
||||
|
||||
func propagateEraseableSyntaxListSubtreeFacts(children *TypeArgumentList) SubtreeFacts {
|
||||
return core.IfElse(children != nil, SubtreeContainsTypeScript, SubtreeFactsNone)
|
||||
}
|
||||
|
||||
func propagateEraseableSyntaxSubtreeFacts(child *TypeNode) SubtreeFacts {
|
||||
return core.IfElse(child != nil, SubtreeContainsTypeScript, SubtreeFactsNone)
|
||||
}
|
||||
|
||||
func propagateObjectBindingElementSubtreeFacts(child *BindingElementNode) SubtreeFacts {
|
||||
facts := propagateSubtreeFacts(child)
|
||||
if facts&SubtreeContainsRestOrSpread != 0 {
|
||||
facts &^= SubtreeContainsRestOrSpread
|
||||
facts |= SubtreeContainsObjectRestOrSpread | SubtreeContainsESObjectRestOrSpread
|
||||
}
|
||||
return facts
|
||||
}
|
||||
|
||||
func propagateBindingElementSubtreeFacts(child *BindingElementNode) SubtreeFacts {
|
||||
return propagateSubtreeFacts(child) & ^SubtreeContainsRestOrSpread
|
||||
}
|
||||
|
||||
func propagateSubtreeFacts(child *Node) SubtreeFacts {
|
||||
if child == nil {
|
||||
return SubtreeFactsNone
|
||||
}
|
||||
return child.propagateSubtreeFacts()
|
||||
}
|
||||
|
||||
func propagateNodeListSubtreeFacts(children *NodeList, propagate func(*Node) SubtreeFacts) SubtreeFacts {
|
||||
if children == nil {
|
||||
return SubtreeFactsNone
|
||||
}
|
||||
facts := SubtreeFactsNone
|
||||
for _, child := range children.Nodes {
|
||||
facts |= propagate(child)
|
||||
}
|
||||
return facts
|
||||
}
|
||||
|
||||
func propagateModifierListSubtreeFacts(children *ModifierList) SubtreeFacts {
|
||||
if children == nil {
|
||||
return SubtreeFactsNone
|
||||
}
|
||||
return propagateNodeListSubtreeFacts(&children.NodeList, propagateSubtreeFacts)
|
||||
}
|
||||
103
tools/tsgo/internal/ast/symbol.go
Normal file
103
tools/tsgo/internal/ast/symbol.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Symbol
|
||||
|
||||
type Symbol struct {
|
||||
Flags SymbolFlags
|
||||
CheckFlags CheckFlags // Non-zero only in transient symbols created by Checker
|
||||
Name string
|
||||
Declarations []*Node
|
||||
ValueDeclaration *Node
|
||||
Members SymbolTable
|
||||
Exports SymbolTable
|
||||
id atomic.Uint64
|
||||
Parent *Symbol
|
||||
ExportSymbol *Symbol
|
||||
}
|
||||
|
||||
func (s *Symbol) IsExternalModule() bool {
|
||||
return s.Flags&SymbolFlagsModule != 0 && len(s.Name) > 0 && s.Name[0] == '"'
|
||||
}
|
||||
|
||||
func (s *Symbol) IsStatic() bool {
|
||||
if s.ValueDeclaration == nil {
|
||||
return false
|
||||
}
|
||||
modifierFlags := s.ValueDeclaration.ModifierFlags()
|
||||
return modifierFlags&ModifierFlagsStatic != 0
|
||||
}
|
||||
|
||||
// See comment on `declareModuleMember` in `binder.go`.
|
||||
func (s *Symbol) CombinedLocalAndExportSymbolFlags() SymbolFlags {
|
||||
if s.ExportSymbol != nil {
|
||||
return s.Flags | s.ExportSymbol.Flags
|
||||
}
|
||||
return s.Flags
|
||||
}
|
||||
|
||||
// SymbolTable
|
||||
|
||||
type SymbolTable map[string]*Symbol
|
||||
|
||||
const InternalSymbolNamePrefix = "\xFE" // Invalid UTF8 sequence, will never occur as IdentifierName
|
||||
|
||||
const (
|
||||
InternalSymbolNameCall = InternalSymbolNamePrefix + "call" // Call signatures
|
||||
InternalSymbolNameConstructor = InternalSymbolNamePrefix + "constructor" // Constructor implementations
|
||||
InternalSymbolNameNew = InternalSymbolNamePrefix + "new" // Constructor signatures
|
||||
InternalSymbolNameIndex = InternalSymbolNamePrefix + "index" // Index signatures
|
||||
InternalSymbolNameExportStar = InternalSymbolNamePrefix + "export" // Module export * declarations
|
||||
InternalSymbolNameGlobal = InternalSymbolNamePrefix + "global" // Global self-reference
|
||||
InternalSymbolNameMissing = InternalSymbolNamePrefix + "missing" // Indicates missing symbol
|
||||
InternalSymbolNameType = InternalSymbolNamePrefix + "type" // Anonymous type literal symbol
|
||||
InternalSymbolNameObject = InternalSymbolNamePrefix + "object" // Anonymous object literal declaration
|
||||
InternalSymbolNameJSXAttributes = InternalSymbolNamePrefix + "jsxAttributes" // Anonymous JSX attributes object literal declaration
|
||||
InternalSymbolNameClass = InternalSymbolNamePrefix + "class" // Unnamed class expression
|
||||
InternalSymbolNameFunction = InternalSymbolNamePrefix + "function" // Unnamed function expression
|
||||
InternalSymbolNameComputed = InternalSymbolNamePrefix + "computed" // Computed property name declaration with dynamic name
|
||||
InternalSymbolNameAssignmentDeclaration = InternalSymbolNamePrefix + "assignment" // Assignment declarations
|
||||
InternalSymbolNameInstantiationExpression = InternalSymbolNamePrefix + "instantiationExpression" // Instantiation expressions
|
||||
InternalSymbolNameImportAttributes = InternalSymbolNamePrefix + "importAttributes"
|
||||
InternalSymbolNameExportEquals = "export=" // Export assignment symbol
|
||||
InternalSymbolNameDefault = "default" // Default export symbol (technically not wholly internal, but included here for usability)
|
||||
InternalSymbolNameThis = "this"
|
||||
InternalSymbolNameModuleExports = "module.exports"
|
||||
)
|
||||
|
||||
func SymbolName(symbol *Symbol) string {
|
||||
if symbol.ValueDeclaration != nil && IsPrivateIdentifierClassElementDeclaration(symbol.ValueDeclaration) {
|
||||
return symbol.ValueDeclaration.Name().Text()
|
||||
}
|
||||
return symbol.Name
|
||||
}
|
||||
|
||||
// EscapeAllInternalSymbolNames replaces internal symbol name markers ("\xFE") with "__".
|
||||
func EscapeAllInternalSymbolNames(name string) string {
|
||||
return strings.ReplaceAll(name, InternalSymbolNamePrefix, "__")
|
||||
}
|
||||
|
||||
func EscapeInternalSymbolName(name string) string {
|
||||
if rest, ok := strings.CutPrefix(name, InternalSymbolNamePrefix); ok {
|
||||
return "__" + rest
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// EscapeSymbolName converts a binder symbol name into its escaped "__String"
|
||||
// form. Internal names (prefixed with the "\xFE" sentinel) become "__"-prefixed,
|
||||
// and user names that already begin with "__" gain an extra leading underscore
|
||||
// so they can be distinguished from internal names.
|
||||
func EscapeSymbolName(name string) string {
|
||||
if rest, ok := strings.CutPrefix(name, InternalSymbolNamePrefix); ok {
|
||||
return "__" + rest
|
||||
}
|
||||
if len(name) >= 2 && name[0] == '_' && name[1] == '_' {
|
||||
return "_" + name
|
||||
}
|
||||
return name
|
||||
}
|
||||
86
tools/tsgo/internal/ast/symbolflags.go
Normal file
86
tools/tsgo/internal/ast/symbolflags.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package ast
|
||||
|
||||
// SymbolFlags
|
||||
|
||||
type SymbolFlags uint32
|
||||
|
||||
const (
|
||||
SymbolFlagsNone SymbolFlags = 0
|
||||
SymbolFlagsFunctionScopedVariable SymbolFlags = 1 << 0 // Variable (var) or parameter
|
||||
SymbolFlagsBlockScopedVariable SymbolFlags = 1 << 1 // A block-scoped variable (let or const)
|
||||
SymbolFlagsProperty SymbolFlags = 1 << 2 // Property or enum member
|
||||
SymbolFlagsEnumMember SymbolFlags = 1 << 3 // Enum member
|
||||
SymbolFlagsFunction SymbolFlags = 1 << 4 // Function
|
||||
SymbolFlagsClass SymbolFlags = 1 << 5 // Class
|
||||
SymbolFlagsInterface SymbolFlags = 1 << 6 // Interface
|
||||
SymbolFlagsConstEnum SymbolFlags = 1 << 7 // Const enum
|
||||
SymbolFlagsRegularEnum SymbolFlags = 1 << 8 // Enum
|
||||
SymbolFlagsValueModule SymbolFlags = 1 << 9 // Instantiated module
|
||||
SymbolFlagsNamespaceModule SymbolFlags = 1 << 10 // Uninstantiated module
|
||||
SymbolFlagsTypeLiteral SymbolFlags = 1 << 11 // Type Literal or mapped type
|
||||
SymbolFlagsObjectLiteral SymbolFlags = 1 << 12 // Object Literal
|
||||
SymbolFlagsMethod SymbolFlags = 1 << 13 // Method
|
||||
SymbolFlagsConstructor SymbolFlags = 1 << 14 // Constructor
|
||||
SymbolFlagsGetAccessor SymbolFlags = 1 << 15 // Get accessor
|
||||
SymbolFlagsSetAccessor SymbolFlags = 1 << 16 // Set accessor
|
||||
SymbolFlagsSignature SymbolFlags = 1 << 17 // Call, construct, or index signature
|
||||
SymbolFlagsTypeParameter SymbolFlags = 1 << 18 // Type parameter
|
||||
SymbolFlagsTypeAlias SymbolFlags = 1 << 19 // Type alias
|
||||
SymbolFlagsExportValue SymbolFlags = 1 << 20 // Exported value marker (see comment in declareModuleMember in binder)
|
||||
SymbolFlagsAlias SymbolFlags = 1 << 21 // An alias for another symbol (see comment in isAliasSymbolDeclaration in checker)
|
||||
SymbolFlagsPrototype SymbolFlags = 1 << 22 // Prototype property (no source representation)
|
||||
SymbolFlagsExportStar SymbolFlags = 1 << 23 // Export * declaration
|
||||
SymbolFlagsOptional SymbolFlags = 1 << 24 // Optional property
|
||||
SymbolFlagsTransient SymbolFlags = 1 << 25 // Transient symbol (created during type check)
|
||||
SymbolFlagsAssignment SymbolFlags = 1 << 26 // Assignment to property on function acting as declaration (eg `func.prop = 1`)
|
||||
SymbolFlagsModuleExports SymbolFlags = 1 << 27 // Symbol for CommonJS `module` of `module.exports`
|
||||
SymbolFlagsConstEnumOnlyModule SymbolFlags = 1 << 28 // Module contains only const enums or other modules with only const enums
|
||||
SymbolFlagsReplaceableByMethod SymbolFlags = 1 << 29
|
||||
SymbolFlagsGlobalLookup SymbolFlags = 1 << 30 // Flag to signal this is a global lookup
|
||||
SymbolFlagsAll SymbolFlags = 1<<30 - 1 // All flags except SymbolFlagsGlobalLookup
|
||||
|
||||
SymbolFlagsEnum = SymbolFlagsRegularEnum | SymbolFlagsConstEnum
|
||||
SymbolFlagsVariable = SymbolFlagsFunctionScopedVariable | SymbolFlagsBlockScopedVariable
|
||||
SymbolFlagsValue = SymbolFlagsVariable | SymbolFlagsProperty | SymbolFlagsEnumMember | SymbolFlagsObjectLiteral | SymbolFlagsFunction | SymbolFlagsClass | SymbolFlagsEnum | SymbolFlagsValueModule | SymbolFlagsMethod | SymbolFlagsGetAccessor | SymbolFlagsSetAccessor
|
||||
SymbolFlagsType = SymbolFlagsClass | SymbolFlagsInterface | SymbolFlagsEnum | SymbolFlagsEnumMember | SymbolFlagsTypeLiteral | SymbolFlagsTypeParameter | SymbolFlagsTypeAlias
|
||||
SymbolFlagsNamespace = SymbolFlagsValueModule | SymbolFlagsNamespaceModule | SymbolFlagsEnum
|
||||
SymbolFlagsModule = SymbolFlagsValueModule | SymbolFlagsNamespaceModule
|
||||
SymbolFlagsAccessor = SymbolFlagsGetAccessor | SymbolFlagsSetAccessor
|
||||
|
||||
// Variables can be redeclared, but can not redeclare a block-scoped declaration with the
|
||||
// same name, or any other value that is not a variable, e.g. ValueModule or Class
|
||||
SymbolFlagsFunctionScopedVariableExcludes = SymbolFlagsValue & ^SymbolFlagsFunctionScopedVariable
|
||||
|
||||
// Block-scoped declarations are not allowed to be re-declared
|
||||
// they can not merge with anything in the value space
|
||||
SymbolFlagsBlockScopedVariableExcludes = SymbolFlagsValue
|
||||
|
||||
SymbolFlagsParameterExcludes = SymbolFlagsValue
|
||||
SymbolFlagsPropertyExcludes = SymbolFlagsValue & ^(SymbolFlagsProperty | SymbolFlagsAccessor)
|
||||
SymbolFlagsEnumMemberExcludes = SymbolFlagsValue | SymbolFlagsType
|
||||
SymbolFlagsFunctionExcludes = SymbolFlagsValue & ^(SymbolFlagsFunction | SymbolFlagsValueModule | SymbolFlagsClass)
|
||||
SymbolFlagsClassExcludes = (SymbolFlagsValue | SymbolFlagsType) & ^(SymbolFlagsValueModule | SymbolFlagsInterface | SymbolFlagsFunction) // class-interface mergability done in checker.ts
|
||||
SymbolFlagsInterfaceExcludes = SymbolFlagsType & ^(SymbolFlagsInterface | SymbolFlagsClass)
|
||||
SymbolFlagsRegularEnumExcludes = (SymbolFlagsValue | SymbolFlagsType) & ^(SymbolFlagsRegularEnum | SymbolFlagsValueModule) // regular enums merge only with regular enums and modules
|
||||
SymbolFlagsConstEnumExcludes = (SymbolFlagsValue | SymbolFlagsType) & ^SymbolFlagsConstEnum // const enums merge only with const enums
|
||||
SymbolFlagsValueModuleExcludes = SymbolFlagsValue & ^(SymbolFlagsFunction | SymbolFlagsClass | SymbolFlagsRegularEnum | SymbolFlagsValueModule)
|
||||
SymbolFlagsNamespaceModuleExcludes = SymbolFlagsNone
|
||||
SymbolFlagsMethodExcludes = SymbolFlagsValue & ^SymbolFlagsMethod
|
||||
SymbolFlagsGetAccessorExcludes = SymbolFlagsValue & ^(SymbolFlagsSetAccessor | SymbolFlagsProperty)
|
||||
SymbolFlagsSetAccessorExcludes = SymbolFlagsValue & ^(SymbolFlagsGetAccessor | SymbolFlagsProperty)
|
||||
SymbolFlagsAccessorExcludes = SymbolFlagsValue & ^SymbolFlagsProperty
|
||||
SymbolFlagsTypeParameterExcludes = SymbolFlagsType & ^SymbolFlagsTypeParameter
|
||||
SymbolFlagsTypeAliasExcludes = SymbolFlagsType
|
||||
SymbolFlagsAliasExcludes = SymbolFlagsAlias
|
||||
SymbolFlagsModuleMember = SymbolFlagsVariable | SymbolFlagsFunction | SymbolFlagsClass | SymbolFlagsInterface | SymbolFlagsEnum | SymbolFlagsModule | SymbolFlagsTypeAlias | SymbolFlagsAlias
|
||||
SymbolFlagsExportHasLocal = SymbolFlagsFunction | SymbolFlagsClass | SymbolFlagsEnum | SymbolFlagsValueModule
|
||||
SymbolFlagsBlockScoped = SymbolFlagsBlockScopedVariable | SymbolFlagsClass | SymbolFlagsEnum
|
||||
SymbolFlagsPropertyOrAccessor = SymbolFlagsProperty | SymbolFlagsAccessor
|
||||
SymbolFlagsClassMember = SymbolFlagsMethod | SymbolFlagsAccessor | SymbolFlagsProperty
|
||||
SymbolFlagsExportSupportsDefaultModifier = SymbolFlagsClass | SymbolFlagsFunction | SymbolFlagsInterface
|
||||
SymbolFlagsExportDoesNotSupportDefaultModifier = ^SymbolFlagsExportSupportsDefaultModifier
|
||||
// The set of things we consider semantically classifiable. Used to speed up the LS during
|
||||
// classification.
|
||||
SymbolFlagsClassifiable = SymbolFlagsClass | SymbolFlagsEnum | SymbolFlagsTypeAlias | SymbolFlagsInterface | SymbolFlagsTypeParameter | SymbolFlagsModule | SymbolFlagsAlias
|
||||
SymbolFlagsLateBindingContainer = SymbolFlagsClass | SymbolFlagsInterface | SymbolFlagsTypeLiteral | SymbolFlagsObjectLiteral | SymbolFlagsFunction
|
||||
)
|
||||
33
tools/tsgo/internal/ast/tokenflags.go
Normal file
33
tools/tsgo/internal/ast/tokenflags.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package ast
|
||||
|
||||
type TokenFlags int32
|
||||
|
||||
const (
|
||||
TokenFlagsNone TokenFlags = 0
|
||||
TokenFlagsPrecedingLineBreak TokenFlags = 1 << 0
|
||||
TokenFlagsPrecedingJSDocComment TokenFlags = 1 << 1
|
||||
TokenFlagsUnterminated TokenFlags = 1 << 2
|
||||
TokenFlagsExtendedUnicodeEscape TokenFlags = 1 << 3 // e.g. `\u{10ffff}`
|
||||
TokenFlagsScientific TokenFlags = 1 << 4 // e.g. `10e2`
|
||||
TokenFlagsOctal TokenFlags = 1 << 5 // e.g. `0777`
|
||||
TokenFlagsHexSpecifier TokenFlags = 1 << 6 // e.g. `0x00000000`
|
||||
TokenFlagsBinarySpecifier TokenFlags = 1 << 7 // e.g. `0b0110010000000000`
|
||||
TokenFlagsOctalSpecifier TokenFlags = 1 << 8 // e.g. `0o777`
|
||||
TokenFlagsContainsSeparator TokenFlags = 1 << 9 // e.g. `0b1100_0101`
|
||||
TokenFlagsUnicodeEscape TokenFlags = 1 << 10 // e.g. `\u00a0`
|
||||
TokenFlagsContainsInvalidEscape TokenFlags = 1 << 11 // e.g. `\uhello`
|
||||
TokenFlagsHexEscape TokenFlags = 1 << 12 // e.g. `\xa0`
|
||||
TokenFlagsContainsLeadingZero TokenFlags = 1 << 13 // e.g. `0888`
|
||||
TokenFlagsContainsInvalidSeparator TokenFlags = 1 << 14 // e.g. `0_1`
|
||||
TokenFlagsPrecedingJSDocLeadingAsterisks TokenFlags = 1 << 15
|
||||
TokenFlagsSingleQuote TokenFlags = 1 << 16 // e.g. `'abc'`
|
||||
TokenFlagsPrecedingJSDocWithDeprecated TokenFlags = 1 << 17 // Preceding JSDoc comment contains @deprecated
|
||||
TokenFlagsPrecedingJSDocWithSeeOrLink TokenFlags = 1 << 18 // Preceding JSDoc comment contains @see or @link
|
||||
TokenFlagsBinaryOrOctalSpecifier TokenFlags = TokenFlagsBinarySpecifier | TokenFlagsOctalSpecifier
|
||||
TokenFlagsWithSpecifier TokenFlags = TokenFlagsHexSpecifier | TokenFlagsBinaryOrOctalSpecifier
|
||||
TokenFlagsStringLiteralFlags TokenFlags = TokenFlagsUnterminated | TokenFlagsHexEscape | TokenFlagsUnicodeEscape | TokenFlagsExtendedUnicodeEscape | TokenFlagsContainsInvalidEscape | TokenFlagsSingleQuote
|
||||
TokenFlagsNumericLiteralFlags TokenFlags = TokenFlagsScientific | TokenFlagsOctal | TokenFlagsContainsLeadingZero | TokenFlagsWithSpecifier | TokenFlagsContainsSeparator | TokenFlagsContainsInvalidSeparator
|
||||
TokenFlagsTemplateLiteralLikeFlags TokenFlags = TokenFlagsUnterminated | TokenFlagsHexEscape | TokenFlagsUnicodeEscape | TokenFlagsExtendedUnicodeEscape | TokenFlagsContainsInvalidEscape
|
||||
TokenFlagsRegularExpressionLiteralFlags TokenFlags = TokenFlagsUnterminated
|
||||
TokenFlagsIsInvalid TokenFlags = TokenFlagsOctal | TokenFlagsContainsLeadingZero | TokenFlagsContainsInvalidSeparator | TokenFlagsContainsInvalidEscape
|
||||
)
|
||||
4565
tools/tsgo/internal/ast/utilities.go
Normal file
4565
tools/tsgo/internal/ast/utilities.go
Normal file
File diff suppressed because it is too large
Load Diff
278
tools/tsgo/internal/ast/visitor.go
Normal file
278
tools/tsgo/internal/ast/visitor.go
Normal file
@@ -0,0 +1,278 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"slices"
|
||||
)
|
||||
|
||||
// NodeVisitor
|
||||
|
||||
type NodeVisitor struct {
|
||||
Visit func(node *Node) *Node // Required. The callback used to visit a node
|
||||
Factory *NodeFactory // Required. The NodeFactory used to produce new nodes when passed to VisitEachChild
|
||||
Hooks NodeVisitorHooks // Hooks to be invoked when visiting a node
|
||||
}
|
||||
|
||||
// These hooks are used to intercept the default behavior of the visitor
|
||||
type NodeVisitorHooks struct {
|
||||
VisitNode func(node *Node, v *NodeVisitor) *Node // Overrides visiting a Node. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitToken func(node *TokenNode, v *NodeVisitor) *Node // Overrides visiting a TokenNode. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitNodes func(nodes *NodeList, v *NodeVisitor) *NodeList // Overrides visiting a NodeList. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitModifiers func(nodes *ModifierList, v *NodeVisitor) *ModifierList // Overrides visiting a ModifierList. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitEmbeddedStatement func(node *Statement, v *NodeVisitor) *Statement // Overrides visiting a Node when it is the embedded statement body of an iteration statement, `if` statement, or `with` statement. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitIterationBody func(node *Statement, v *NodeVisitor) *Statement // Overrides visiting a Node when it is the embedded statement body of an iteration statement. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitParameters func(nodes *ParameterList, v *NodeVisitor) *ParameterList // Overrides visiting a ParameterList. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitFunctionBody func(node *BlockOrExpression, v *NodeVisitor) *BlockOrExpression // Overrides visiting a function body. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitTopLevelStatements func(nodes *StatementList, v *NodeVisitor) *StatementList // Overrides visiting a variable environment. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
}
|
||||
|
||||
func NewNodeVisitor(visit func(node *Node) *Node, factory *NodeFactory, hooks NodeVisitorHooks) *NodeVisitor {
|
||||
if factory == nil {
|
||||
factory = &NodeFactory{}
|
||||
}
|
||||
return &NodeVisitor{Visit: visit, Factory: factory, Hooks: hooks}
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) VisitSourceFile(node *SourceFile) *SourceFile {
|
||||
return v.VisitNode(node.AsNode()).AsSourceFile()
|
||||
}
|
||||
|
||||
// Visits a Node, possibly returning a new Node in its place.
|
||||
//
|
||||
// - If the input node is nil, then the output is nil.
|
||||
// - If v.Visit is nil, then the output is the input.
|
||||
// - If v.Visit returns nil, then the output is nil.
|
||||
// - If v.Visit returns a SyntaxList Node, then the output is the only child of the SyntaxList Node.
|
||||
func (v *NodeVisitor) VisitNode(node *Node) *Node {
|
||||
if node == nil || v.Visit == nil {
|
||||
return node
|
||||
}
|
||||
|
||||
if v.Visit != nil {
|
||||
visited := v.Visit(node)
|
||||
if visited != nil && visited.Kind == KindSyntaxList {
|
||||
nodes := visited.AsSyntaxList().Children
|
||||
if len(nodes) != 1 {
|
||||
panic("Expected only a single node to be written to output")
|
||||
}
|
||||
visited = nodes[0]
|
||||
if visited != nil && visited.Kind == KindSyntaxList {
|
||||
panic("The result of visiting and lifting a Node may not be SyntaxList")
|
||||
}
|
||||
}
|
||||
return visited
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
// Visits an embedded Statement (i.e., the single statement body of a loop, `if..else` branch, etc.), possibly returning a new Statement in its place.
|
||||
//
|
||||
// - If the input node is nil, then the output is nil.
|
||||
// - If v.Visit is nil, then the output is the input.
|
||||
// - If v.Visit returns nil, then the output is nil.
|
||||
// - If v.Visit returns a SyntaxList Node, then the output is either the only child of the SyntaxList Node, or a Block containing the nodes in the list.
|
||||
func (v *NodeVisitor) VisitEmbeddedStatement(node *Statement) *Statement {
|
||||
if node == nil || v.Visit == nil {
|
||||
return node
|
||||
}
|
||||
|
||||
visited := v.Visit(node)
|
||||
if visited == nil {
|
||||
return nil
|
||||
}
|
||||
return v.liftToBlock(visited)
|
||||
}
|
||||
|
||||
// Visits a NodeList, possibly returning a new NodeList in its place.
|
||||
//
|
||||
// - If the input NodeList is nil, the output is nil.
|
||||
// - If v.Visit is nil, then the output is the input.
|
||||
// - If v.Visit returns nil, the visited Node will be absent in the output.
|
||||
// - If v.Visit returns a different Node than the input, a new NodeList will be generated and returned.
|
||||
// - If v.Visit returns a SyntaxList Node, then the children of that node will be merged into the output and a new NodeList will be returned.
|
||||
// - If this method returns a new NodeList for any reason, it will have the same Loc as the input NodeList.
|
||||
func (v *NodeVisitor) VisitNodes(nodes *NodeList) *NodeList {
|
||||
if nodes == nil || v.Visit == nil {
|
||||
return nodes
|
||||
}
|
||||
|
||||
if result, changed := v.VisitSlice(nodes.Nodes); changed {
|
||||
list := v.Factory.NewNodeList(result)
|
||||
list.Loc = nodes.Loc
|
||||
return list
|
||||
}
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
// Visits a ModifierList, possibly returning a new ModifierList in its place.
|
||||
//
|
||||
// - If the input ModifierList is nil, the output is nil.
|
||||
// - If v.Visit is nil, then the output is the input.
|
||||
// - If v.Visit returns nil, the visited Node will be absent in the output.
|
||||
// - If v.Visit returns a different Node than the input, a new ModifierList will be generated and returned.
|
||||
// - If v.Visit returns a SyntaxList Node, then the children of that node will be merged into the output and a new NodeList will be returned.
|
||||
// - If this method returns a new NodeList for any reason, it will have the same Loc as the input NodeList.
|
||||
func (v *NodeVisitor) VisitModifiers(nodes *ModifierList) *ModifierList {
|
||||
if nodes == nil || v.Visit == nil {
|
||||
return nodes
|
||||
}
|
||||
|
||||
if result, changed := v.VisitSlice(nodes.Nodes); changed {
|
||||
list := v.Factory.NewModifierList(result)
|
||||
list.Loc = nodes.Loc
|
||||
return list
|
||||
}
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
// Visits a slice of Nodes, returning the resulting slice and a value indicating whether the slice was changed.
|
||||
//
|
||||
// - If the input slice is nil, the output is nil.
|
||||
// - If v.Visit is nil, then the output is the input.
|
||||
// - If v.Visit returns nil, the visited Node will be absent in the output.
|
||||
// - If v.Visit returns a different Node than the input, a new slice will be generated and returned.
|
||||
// - If v.Visit returns a SyntaxList Node, then the children of that node will be merged into the output and a new slice will be returned.
|
||||
func (v *NodeVisitor) VisitSlice(nodes []*Node) (result []*Node, changed bool) {
|
||||
if nodes == nil || v.Visit == nil {
|
||||
return nodes, false
|
||||
}
|
||||
|
||||
for i := 0; i < len(nodes); i++ {
|
||||
node := nodes[i]
|
||||
if v.Visit == nil {
|
||||
break
|
||||
}
|
||||
|
||||
visited := v.Visit(node)
|
||||
if visited == nil || visited != node {
|
||||
updated := slices.Clone(nodes[:i])
|
||||
|
||||
for {
|
||||
// finish prior loop
|
||||
switch {
|
||||
case visited == nil: // do nothing
|
||||
case visited.Kind == KindSyntaxList:
|
||||
updated = append(updated, visited.AsSyntaxList().Children...)
|
||||
default:
|
||||
updated = append(updated, visited)
|
||||
}
|
||||
|
||||
i++
|
||||
|
||||
// loop over remaining elements
|
||||
if i >= len(nodes) {
|
||||
break
|
||||
}
|
||||
|
||||
if v.Visit != nil {
|
||||
node = nodes[i]
|
||||
visited = v.Visit(node)
|
||||
} else {
|
||||
updated = append(updated, nodes[i:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return updated, true
|
||||
}
|
||||
}
|
||||
|
||||
return nodes, false
|
||||
}
|
||||
|
||||
// Visits each child of a Node, possibly returning a new Node of the same kind in its place.
|
||||
func (v *NodeVisitor) VisitEachChild(node *Node) *Node {
|
||||
if node == nil || v.Visit == nil {
|
||||
return node
|
||||
}
|
||||
|
||||
return node.VisitEachChild(v)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitNode(node *Node) *Node {
|
||||
if v.Hooks.VisitNode != nil {
|
||||
return v.Hooks.VisitNode(node, v)
|
||||
}
|
||||
return v.VisitNode(node)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitEmbeddedStatement(node *Node) *Node {
|
||||
if v.Hooks.VisitEmbeddedStatement != nil {
|
||||
return v.Hooks.VisitEmbeddedStatement(node, v)
|
||||
}
|
||||
if v.Hooks.VisitNode != nil {
|
||||
return v.liftToBlock(v.Hooks.VisitNode(node, v))
|
||||
}
|
||||
return v.VisitEmbeddedStatement(node)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitIterationBody(node *Statement) *Statement {
|
||||
if v.Hooks.VisitIterationBody != nil {
|
||||
return v.Hooks.VisitIterationBody(node, v)
|
||||
}
|
||||
return v.visitEmbeddedStatement(node)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitFunctionBody(node *BlockOrExpression) *BlockOrExpression {
|
||||
if v.Hooks.VisitFunctionBody != nil {
|
||||
return v.Hooks.VisitFunctionBody(node, v)
|
||||
}
|
||||
return v.visitNode(node)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitToken(node *Node) *Node {
|
||||
if v.Hooks.VisitToken != nil {
|
||||
return v.Hooks.VisitToken(node, v)
|
||||
}
|
||||
return v.VisitNode(node)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitNodes(nodes *NodeList) *NodeList {
|
||||
if v.Hooks.VisitNodes != nil {
|
||||
return v.Hooks.VisitNodes(nodes, v)
|
||||
}
|
||||
return v.VisitNodes(nodes)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitModifiers(nodes *ModifierList) *ModifierList {
|
||||
if v.Hooks.VisitModifiers != nil {
|
||||
return v.Hooks.VisitModifiers(nodes, v)
|
||||
}
|
||||
return v.VisitModifiers(nodes)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitParameters(nodes *ParameterList) *ParameterList {
|
||||
if v.Hooks.VisitParameters != nil {
|
||||
return v.Hooks.VisitParameters(nodes, v)
|
||||
}
|
||||
return v.visitNodes(nodes)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitTopLevelStatements(nodes *StatementList) *StatementList {
|
||||
if v.Hooks.VisitTopLevelStatements != nil {
|
||||
return v.Hooks.VisitTopLevelStatements(nodes, v)
|
||||
}
|
||||
return v.visitNodes(nodes)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) liftToBlock(node *Statement) *Statement {
|
||||
var nodes []*Node
|
||||
if node != nil {
|
||||
if node.Kind == KindSyntaxList {
|
||||
nodes = node.AsSyntaxList().Children
|
||||
} else {
|
||||
nodes = []*Node{node}
|
||||
}
|
||||
}
|
||||
if len(nodes) == 1 {
|
||||
node = nodes[0]
|
||||
} else {
|
||||
node = v.Factory.NewBlock(v.Factory.NewNodeList(nodes), true /*multiLine*/)
|
||||
}
|
||||
if node.Kind == KindSyntaxList {
|
||||
panic("The result of visiting and lifting a Node may not be SyntaxList")
|
||||
}
|
||||
return node
|
||||
}
|
||||
14
tools/tsgo/internal/astnav/testmain_test.go
Normal file
14
tools/tsgo/internal/astnav/testmain_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package astnav_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/testutil/baseline"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
core.ApplyDebugStackLimit()
|
||||
defer baseline.Track()()
|
||||
m.Run()
|
||||
}
|
||||
783
tools/tsgo/internal/astnav/tokens.go
Normal file
783
tools/tsgo/internal/astnav/tokens.go
Normal file
@@ -0,0 +1,783 @@
|
||||
package astnav
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/scanner"
|
||||
)
|
||||
|
||||
func shouldRescanLessThanLessThanToken(s *scanner.Scanner, containingNode *ast.Node, token ast.Kind) bool {
|
||||
return token == ast.KindLessThanLessThanToken && ast.IsJsxChild(containingNode)
|
||||
}
|
||||
|
||||
func scanNavigationToken(s *scanner.Scanner, containingNode *ast.Node) ast.Kind {
|
||||
token := s.Token()
|
||||
if shouldRescanLessThanLessThanToken(s, containingNode, token) {
|
||||
return s.ReScanJsxToken(true /*allowMultilineJsxText*/)
|
||||
}
|
||||
return token
|
||||
}
|
||||
|
||||
func GetTouchingPropertyName(sourceFile *ast.SourceFile, position int) *ast.Node {
|
||||
return getTokenAtPosition(sourceFile, position, false /*allowPositionInLeadingTrivia*/, func(node *ast.Node) bool {
|
||||
return ast.IsPropertyNameLiteral(node) || ast.IsKeywordKind(node.Kind) || ast.IsPrivateIdentifier(node)
|
||||
})
|
||||
}
|
||||
|
||||
func GetTouchingToken(sourceFile *ast.SourceFile, position int) *ast.Node {
|
||||
return getTokenAtPosition(sourceFile, position, false /*allowPositionInLeadingTrivia*/, nil)
|
||||
}
|
||||
|
||||
func GetTokenAtPosition(sourceFile *ast.SourceFile, position int) *ast.Node {
|
||||
return getTokenAtPosition(sourceFile, position, true /*allowPositionInLeadingTrivia*/, nil)
|
||||
}
|
||||
|
||||
func getTokenAtPosition(
|
||||
sourceFile *ast.SourceFile,
|
||||
position int,
|
||||
allowPositionInLeadingTrivia bool,
|
||||
includePrecedingTokenAtEndPosition func(node *ast.Node) bool,
|
||||
) *ast.Node {
|
||||
// getTokenAtPosition returns a token at the given position in the source file.
|
||||
// The token can be a real node in the AST, or a synthesized token constructed
|
||||
// with information from the scanner. Synthesized tokens are only created when
|
||||
// needed, and they are stored in the source file's token cache such that multiple
|
||||
// calls to getTokenAtPosition with the same position will return the same object
|
||||
// in memory. If there is no token at the given position (possible when
|
||||
// `allowPositionInLeadingTrivia` is false), the lowest node that encloses the
|
||||
// position is returned.
|
||||
|
||||
// `next` tracks the node whose children will be visited on the next iteration.
|
||||
// `prevSubtree` is a node whose end position is equal to the target position,
|
||||
// only if `includePrecedingTokenAtEndPosition` is provided. Once set, the next
|
||||
// iteration of the loop will test the rightmost token of `prevSubtree` to see
|
||||
// if it should be returned.
|
||||
var next, prevSubtree *ast.Node
|
||||
current := sourceFile.AsNode()
|
||||
// `left` tracks the lower boundary of the node/token that could be returned,
|
||||
// and is eventually the scanner's start position, if the scanner is used.
|
||||
left := 0
|
||||
// `nodeAfterLeft` tracks the first node we visit after visiting the node that advances `left`.
|
||||
// When scanning in between nodes for token, we should only scan up to the start of `nodeAfterLeft`.
|
||||
var nodeAfterLeft *ast.Node
|
||||
|
||||
testNode := func(node *ast.Node) int {
|
||||
if node.Kind != ast.KindEndOfFile && node.End() == position &&
|
||||
includePrecedingTokenAtEndPosition != nil && node.Flags&ast.NodeFlagsReparsed == 0 {
|
||||
prevSubtree = node
|
||||
}
|
||||
|
||||
// A node "contains" the position if position < end, except nodes at the file end
|
||||
// treat end as inclusive (there's nowhere else to look). This applies to the EOF
|
||||
// token itself, and to JSDoc nodes reaching EOF (e.g. unterminated JSDoc comments).
|
||||
if node.End() < position || node.End() == position &&
|
||||
node.Kind != ast.KindEndOfFile &&
|
||||
(!ast.IsJSDocKind(node.Kind) || node.End() != sourceFile.EndOfFileToken.End()) {
|
||||
return -1
|
||||
}
|
||||
nodePos := getPosition(node, sourceFile, allowPositionInLeadingTrivia)
|
||||
if nodePos > position {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// We zero in on the node that contains the target position by visiting each
|
||||
// child and JSDoc comment of the current node. Node children are walked in
|
||||
// order, while node lists are binary searched.
|
||||
visitNode := func(node *ast.Node, _ *ast.NodeVisitor) *ast.Node {
|
||||
// We can't abort visiting children, so once a match is found, we set `next`
|
||||
// and do nothing on subsequent visits.
|
||||
if node == nil || node.Flags&ast.NodeFlagsReparsed != 0 {
|
||||
return nil
|
||||
}
|
||||
if nodeAfterLeft == nil {
|
||||
nodeAfterLeft = node
|
||||
}
|
||||
if next == nil {
|
||||
result := testNode(node)
|
||||
switch result {
|
||||
case -1:
|
||||
if !ast.IsJSDocKind(node.Kind) {
|
||||
// We can't move the left boundary into or beyond JSDoc,
|
||||
// because we may end up returning the token after this JSDoc,
|
||||
// constructing it with the scanner, and we need to include
|
||||
// all its leading trivia in its position.
|
||||
left = node.End()
|
||||
}
|
||||
nodeAfterLeft = nil
|
||||
case 0:
|
||||
next = node
|
||||
}
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
visitNodeList := func(nodeList *ast.NodeList, _ *ast.NodeVisitor) *ast.NodeList {
|
||||
if nodeList == nil || len(nodeList.Nodes) == 0 {
|
||||
return nodeList
|
||||
}
|
||||
if nodeAfterLeft == nil {
|
||||
for _, node := range nodeList.Nodes {
|
||||
if node.Flags&ast.NodeFlagsReparsed == 0 {
|
||||
nodeAfterLeft = node
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if next == nil {
|
||||
if nodeList.End() == position && includePrecedingTokenAtEndPosition != nil {
|
||||
left = nodeList.End()
|
||||
nodeAfterLeft = nil
|
||||
for i := len(nodeList.Nodes) - 1; i >= 0; i-- {
|
||||
if nodeList.Nodes[i].Flags&ast.NodeFlagsReparsed == 0 {
|
||||
prevSubtree = nodeList.Nodes[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
} else if nodeList.End() <= position {
|
||||
left = nodeList.End()
|
||||
nodeAfterLeft = nil
|
||||
} else if nodeList.Pos() <= position {
|
||||
nodes := nodeList.Nodes
|
||||
index, match := core.BinarySearchUniqueFunc(nodes, func(middle int, node *ast.Node) int {
|
||||
if node.Flags&ast.NodeFlagsReparsed != 0 {
|
||||
return 0
|
||||
}
|
||||
cmp := testNode(node)
|
||||
if cmp < 0 {
|
||||
left = node.End()
|
||||
nodeAfterLeft = nil
|
||||
for i := middle + 1; i < len(nodes); i++ {
|
||||
if nodes[i].Flags&ast.NodeFlagsReparsed == 0 {
|
||||
nodeAfterLeft = nodes[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return cmp
|
||||
})
|
||||
if match && nodes[index].Flags&ast.NodeFlagsReparsed != 0 {
|
||||
// filter and search again
|
||||
nodes = core.Filter(nodes, func(node *ast.Node) bool {
|
||||
return node.Flags&ast.NodeFlagsReparsed == 0
|
||||
})
|
||||
index, match = core.BinarySearchUniqueFunc(nodes, func(middle int, node *ast.Node) int {
|
||||
cmp := testNode(node)
|
||||
if cmp < 0 {
|
||||
left = node.End()
|
||||
if middle+1 < len(nodes) {
|
||||
nodeAfterLeft = nodes[middle+1]
|
||||
} else {
|
||||
nodeAfterLeft = nil
|
||||
}
|
||||
}
|
||||
return cmp
|
||||
})
|
||||
}
|
||||
if match {
|
||||
next = nodes[index]
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodeList
|
||||
}
|
||||
|
||||
for {
|
||||
VisitEachChildAndJSDoc(current, sourceFile, visitNode, visitNodeList)
|
||||
// If prevSubtree was set on the last iteration, it ends at the target position.
|
||||
// Check if the rightmost token of prevSubtree should be returned based on the
|
||||
// `includePrecedingTokenAtEndPosition` callback.
|
||||
if prevSubtree != nil {
|
||||
child := FindPrecedingTokenEx(sourceFile, position, prevSubtree, false /*excludeJSDoc*/)
|
||||
if child != nil && child.End() == position && includePrecedingTokenAtEndPosition(child) {
|
||||
// Optimization: includePrecedingTokenAtEndPosition only ever returns true
|
||||
// for real AST nodes, so we don't run the scanner here.
|
||||
return child
|
||||
}
|
||||
prevSubtree = nil
|
||||
}
|
||||
|
||||
// No node was found that contains the target position, so we've gone as deep as
|
||||
// we can in the AST. We've either found a token, or we need to run the scanner
|
||||
// to construct one that isn't stored in the AST.
|
||||
if next == nil {
|
||||
if ast.IsTokenKind(current.Kind) || shouldSkipChild(current) {
|
||||
return current
|
||||
}
|
||||
scanner := scanner.GetScannerForSourceFile(sourceFile, left)
|
||||
end := current.End()
|
||||
// We should only scan up to the start of the next node in the AST after the node ending at position `left`.
|
||||
// It is necessary to enforce this invariant in cases where `position` occurs in between two node/tokens,
|
||||
// such that we would not find a token in the loop below before we reach the next node.
|
||||
// We can fall into this case when `allowPositionInLeadingTrivia` is false and `position` is in a leading trivia,
|
||||
// or when `position` would be in the leading trivia of a node but this node is inside JSDoc:
|
||||
// ```
|
||||
// /**
|
||||
// * @type {{
|
||||
// */*$*/ identifier: boolean;
|
||||
// * }}
|
||||
// */
|
||||
// ```
|
||||
// The position of marker '$' falls in between the asterisk token and the identifier token, but is not
|
||||
// part of the leading trivia for `identifier`.
|
||||
if nodeAfterLeft != nil {
|
||||
end = nodeAfterLeft.Pos()
|
||||
}
|
||||
for left < end {
|
||||
token := scanNavigationToken(scanner, current)
|
||||
tokenFullStart := scanner.TokenFullStart()
|
||||
tokenStart := core.IfElse(allowPositionInLeadingTrivia, tokenFullStart, scanner.TokenStart())
|
||||
tokenEnd := scanner.TokenEnd()
|
||||
flags := scanner.TokenFlags()
|
||||
if tokenEnd > end {
|
||||
break
|
||||
}
|
||||
if tokenStart <= position && (position < tokenEnd) {
|
||||
if token == ast.KindIdentifier || !ast.IsTokenKind(token) {
|
||||
if ast.IsJSDocKind(current.Kind) {
|
||||
return current
|
||||
}
|
||||
panic(fmt.Sprintf("did not expect %s to have %s in its trivia", current.Kind.String(), token.String()))
|
||||
}
|
||||
return sourceFile.GetOrCreateToken(token, tokenFullStart, tokenEnd, current, flags)
|
||||
}
|
||||
if includePrecedingTokenAtEndPosition != nil && tokenEnd == position {
|
||||
prevToken := sourceFile.GetOrCreateToken(token, tokenFullStart, tokenEnd, current, flags)
|
||||
if includePrecedingTokenAtEndPosition(prevToken) {
|
||||
return prevToken
|
||||
}
|
||||
}
|
||||
left = tokenEnd
|
||||
scanner.Scan()
|
||||
}
|
||||
return current
|
||||
}
|
||||
current = next
|
||||
left = current.Pos()
|
||||
nodeAfterLeft = nil
|
||||
next = nil
|
||||
}
|
||||
}
|
||||
|
||||
func getPosition(node *ast.Node, sourceFile *ast.SourceFile, allowPositionInLeadingTrivia bool) int {
|
||||
if allowPositionInLeadingTrivia {
|
||||
return node.Pos()
|
||||
}
|
||||
return scanner.GetTokenPosOfNode(node, sourceFile, true /*includeJSDoc*/)
|
||||
}
|
||||
|
||||
func findRightmostNode(node *ast.Node) *ast.Node {
|
||||
var next *ast.Node
|
||||
current := node
|
||||
visitNode := func(node *ast.Node, _ *ast.NodeVisitor) *ast.Node {
|
||||
if node != nil {
|
||||
next = node
|
||||
}
|
||||
return node
|
||||
}
|
||||
visitNodes := func(nodeList *ast.NodeList, visitor *ast.NodeVisitor) *ast.NodeList {
|
||||
if nodeList != nil {
|
||||
if rightmost := ast.FindLastVisibleNode(nodeList.Nodes); rightmost != nil {
|
||||
next = rightmost
|
||||
}
|
||||
}
|
||||
return nodeList
|
||||
}
|
||||
visitor := getNodeVisitor(visitNode, visitNodes)
|
||||
|
||||
for {
|
||||
current.VisitEachChild(visitor)
|
||||
if next == nil {
|
||||
return current
|
||||
}
|
||||
current = next
|
||||
next = nil
|
||||
}
|
||||
}
|
||||
|
||||
func VisitEachChildAndJSDoc(
|
||||
node *ast.Node,
|
||||
sourceFile *ast.SourceFile,
|
||||
visitNode func(*ast.Node, *ast.NodeVisitor) *ast.Node,
|
||||
visitNodes func(*ast.NodeList, *ast.NodeVisitor) *ast.NodeList,
|
||||
) {
|
||||
visitor := getNodeVisitor(visitNode, visitNodes)
|
||||
for _, jsdoc := range node.JSDoc(sourceFile) {
|
||||
if visitor.Hooks.VisitNode != nil {
|
||||
visitor.Hooks.VisitNode(jsdoc, visitor)
|
||||
} else {
|
||||
visitor.VisitNode(jsdoc)
|
||||
}
|
||||
}
|
||||
node.VisitEachChild(visitor)
|
||||
}
|
||||
|
||||
const (
|
||||
comparisonLessThan = -1
|
||||
comparisonEqualTo = 0
|
||||
comparisonGreaterThan = 1
|
||||
)
|
||||
|
||||
// Finds the leftmost token satisfying `position < token.End()`.
|
||||
// If the leftmost token satisfying `position < token.End()` is invalid, or if position
|
||||
// is in the trivia of that leftmost token,
|
||||
// we will find the rightmost valid token with `token.End() <= position`.
|
||||
func FindPrecedingToken(sourceFile *ast.SourceFile, position int) *ast.Node {
|
||||
return FindPrecedingTokenEx(sourceFile, position, nil, false)
|
||||
}
|
||||
|
||||
func FindPrecedingTokenEx(sourceFile *ast.SourceFile, position int, startNode *ast.Node, excludeJSDoc bool) *ast.Node {
|
||||
var find func(node *ast.Node) *ast.Node
|
||||
find = func(n *ast.Node) *ast.Node {
|
||||
if ast.IsNonWhitespaceToken(n) && n.Kind != ast.KindEndOfFile {
|
||||
return n
|
||||
}
|
||||
|
||||
// `foundChild` is the leftmost node that contains the target position.
|
||||
// `prevChild` is the last visited child of the current node.
|
||||
var foundChild, prevChild *ast.Node
|
||||
visitNode := func(node *ast.Node, _ *ast.NodeVisitor) *ast.Node {
|
||||
// skip synthesized nodes (that will exist now because of jsdoc handling)
|
||||
if node == nil || node.Flags&ast.NodeFlagsReparsed != 0 {
|
||||
return node
|
||||
}
|
||||
if foundChild != nil { // We cannot abort visiting children, so once the desired child is found, we do nothing.
|
||||
return node
|
||||
}
|
||||
if position < node.End() && (prevChild == nil || prevChild.End() <= position) {
|
||||
foundChild = node
|
||||
} else {
|
||||
prevChild = node
|
||||
}
|
||||
return node
|
||||
}
|
||||
visitNodes := func(nodeList *ast.NodeList, _ *ast.NodeVisitor) *ast.NodeList {
|
||||
if foundChild != nil {
|
||||
return nodeList
|
||||
}
|
||||
if nodeList != nil && len(nodeList.Nodes) > 0 {
|
||||
nodes := nodeList.Nodes
|
||||
index, match := core.BinarySearchUniqueFunc(nodes, func(middle int, _ *ast.Node) int {
|
||||
// synthetic jsdoc nodes should have jsdocNode.End() <= n.Pos()
|
||||
if nodes[middle].Flags&ast.NodeFlagsReparsed != 0 {
|
||||
return comparisonLessThan
|
||||
}
|
||||
if position < nodes[middle].End() {
|
||||
if middle == 0 || position >= nodes[middle-1].End() {
|
||||
return comparisonEqualTo
|
||||
}
|
||||
return comparisonGreaterThan
|
||||
}
|
||||
return comparisonLessThan
|
||||
})
|
||||
|
||||
if match {
|
||||
foundChild = nodes[index]
|
||||
}
|
||||
|
||||
validLookupIndex := core.IfElse(match, index-1, len(nodes)-1)
|
||||
for i := validLookupIndex; i >= 0; i-- {
|
||||
if nodes[i].Flags&ast.NodeFlagsReparsed != 0 {
|
||||
continue
|
||||
}
|
||||
if prevChild == nil {
|
||||
prevChild = nodes[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodeList
|
||||
}
|
||||
VisitEachChildAndJSDoc(n, sourceFile, visitNode, visitNodes)
|
||||
|
||||
if foundChild != nil {
|
||||
// Note that the span of a node's tokens is [getStartOfNode(node, ...), node.end).
|
||||
// Given that `position < child.end` and child has constituent tokens, we distinguish these cases:
|
||||
// 1) `position` precedes `child`'s tokens or `child` has no tokens (ie: in a comment or whitespace preceding `child`):
|
||||
// we need to find the last token in a previous child node or child tokens.
|
||||
// 2) `position` is within the same span: we recurse on `child`.
|
||||
start := GetStartOfNode(foundChild, sourceFile, !excludeJSDoc /*includeJSDoc*/)
|
||||
lookInPreviousChild := start >= position || // cursor in the leading trivia or preceding tokens
|
||||
!isValidPrecedingNode(foundChild, sourceFile)
|
||||
if lookInPreviousChild {
|
||||
if position >= foundChild.Pos() {
|
||||
// Find jsdoc preceding the foundChild.
|
||||
var jsDoc *ast.Node
|
||||
nodeJSDoc := n.JSDoc(sourceFile)
|
||||
for i := len(nodeJSDoc) - 1; i >= 0; i-- {
|
||||
if nodeJSDoc[i].Pos() >= foundChild.Pos() {
|
||||
jsDoc = nodeJSDoc[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if jsDoc != nil {
|
||||
if !excludeJSDoc && position < jsDoc.End() {
|
||||
return find(jsDoc)
|
||||
} else {
|
||||
return findRightmostValidToken(jsDoc.End(), sourceFile, n, position, excludeJSDoc)
|
||||
}
|
||||
}
|
||||
return findRightmostValidToken(foundChild.Pos(), sourceFile, n, -1 /*position*/, excludeJSDoc)
|
||||
} else { // Answer is in tokens between two visited children.
|
||||
return findRightmostValidToken(foundChild.Pos(), sourceFile, n, position, excludeJSDoc)
|
||||
}
|
||||
} else {
|
||||
// position is in [foundChild.getStart(), foundChild.End): recur.
|
||||
return find(foundChild)
|
||||
}
|
||||
}
|
||||
|
||||
// We have two cases here: either the position is at the end of the file,
|
||||
// or the desired token is in the unvisited trailing tokens of the current node.
|
||||
if position >= n.End() {
|
||||
return findRightmostValidToken(n.End(), sourceFile, n, -1 /*position*/, excludeJSDoc)
|
||||
} else {
|
||||
return findRightmostValidToken(n.End(), sourceFile, n, position, excludeJSDoc)
|
||||
}
|
||||
}
|
||||
|
||||
var node *ast.Node
|
||||
if startNode != nil {
|
||||
node = startNode
|
||||
} else {
|
||||
node = sourceFile.AsNode()
|
||||
}
|
||||
result := find(node)
|
||||
if result != nil && ast.IsWhitespaceOnlyJsxText(result) {
|
||||
panic("Expected result to be a non-whitespace token.")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func isValidPrecedingNode(node *ast.Node, sourceFile *ast.SourceFile) bool {
|
||||
if node.Kind == ast.KindEndOfFile {
|
||||
return len(node.JSDoc(sourceFile)) > 0
|
||||
}
|
||||
start := GetStartOfNode(node, sourceFile, false /*includeJSDoc*/)
|
||||
width := node.End() - start
|
||||
return !(ast.IsWhitespaceOnlyJsxText(node) || width == 0)
|
||||
}
|
||||
|
||||
func GetStartOfNode(node *ast.Node, file *ast.SourceFile, includeJSDoc bool) int {
|
||||
return scanner.GetTokenPosOfNode(node, file, includeJSDoc)
|
||||
}
|
||||
|
||||
// Looks for rightmost valid token in the range [startPos, endPos).
|
||||
// If position is >= 0, looks for rightmost valid token that precedes or touches that position.
|
||||
func findRightmostValidToken(endPos int, sourceFile *ast.SourceFile, containingNode *ast.Node, position int, excludeJSDoc bool) *ast.Node {
|
||||
if position == -1 {
|
||||
position = containingNode.End()
|
||||
}
|
||||
var find func(n *ast.Node, endPos int) *ast.Node
|
||||
find = func(n *ast.Node, endPos int) *ast.Node {
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
if ast.IsNonWhitespaceToken(n) {
|
||||
return n
|
||||
}
|
||||
|
||||
var rightmostValidNode *ast.Node
|
||||
rightmostVisitedNodes := make([]*ast.Node, 0, 1) // Nodes after the last valid node.
|
||||
hasChildren := false
|
||||
shouldVisitNode := func(node *ast.Node) bool {
|
||||
// Node is synthetic or out of the desired range: don't visit it.
|
||||
return !(node.Flags&ast.NodeFlagsReparsed != 0 ||
|
||||
node.End() > endPos || GetStartOfNode(node, sourceFile, !excludeJSDoc /*includeJSDoc*/) >= position)
|
||||
}
|
||||
visitNode := func(node *ast.Node, _ *ast.NodeVisitor) *ast.Node {
|
||||
if node == nil || node.Flags&ast.NodeFlagsReparsed != 0 {
|
||||
return node
|
||||
}
|
||||
hasChildren = true
|
||||
if !shouldVisitNode(node) {
|
||||
return node
|
||||
}
|
||||
rightmostVisitedNodes = append(rightmostVisitedNodes, node)
|
||||
if isValidPrecedingNode(node, sourceFile) {
|
||||
rightmostValidNode = node
|
||||
rightmostVisitedNodes = rightmostVisitedNodes[:0]
|
||||
}
|
||||
return node
|
||||
}
|
||||
visitNodes := func(nodeList *ast.NodeList, _ *ast.NodeVisitor) *ast.NodeList {
|
||||
if nodeList != nil && len(nodeList.Nodes) > 0 {
|
||||
hasChildren = true
|
||||
index, _ := core.BinarySearchUniqueFunc(nodeList.Nodes, func(middle int, node *ast.Node) int {
|
||||
if node.End() > endPos {
|
||||
return comparisonGreaterThan
|
||||
}
|
||||
return comparisonLessThan
|
||||
})
|
||||
validIndex := -1
|
||||
for i := index - 1; i >= 0; i-- {
|
||||
if !shouldVisitNode(nodeList.Nodes[i]) {
|
||||
continue
|
||||
}
|
||||
if isValidPrecedingNode(nodeList.Nodes[i], sourceFile) {
|
||||
validIndex = i
|
||||
rightmostValidNode = nodeList.Nodes[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
for i := validIndex + 1; i < index; i++ {
|
||||
if !shouldVisitNode(nodeList.Nodes[i]) {
|
||||
continue
|
||||
}
|
||||
rightmostVisitedNodes = append(rightmostVisitedNodes, nodeList.Nodes[i])
|
||||
}
|
||||
}
|
||||
return nodeList
|
||||
}
|
||||
VisitEachChildAndJSDoc(n, sourceFile, visitNode, visitNodes)
|
||||
|
||||
// Three cases:
|
||||
// 1. The answer is a token of `rightmostValidNode`.
|
||||
// 2. The answer is one of the unvisited tokens that occur after the rightmost valid node.
|
||||
// 3. The current node is a childless, token-less node. The answer is the current node.
|
||||
|
||||
// Case 2: Look at unvisited trailing tokens that occur in between the rightmost visited nodes.
|
||||
if !shouldSkipChild(n) { // JSDoc nodes don't include trivia tokens as children.
|
||||
var startPos int
|
||||
if rightmostValidNode != nil {
|
||||
startPos = rightmostValidNode.End()
|
||||
} else {
|
||||
startPos = n.Pos()
|
||||
}
|
||||
scanner := scanner.GetScannerForSourceFile(sourceFile, startPos)
|
||||
var tokens []*ast.Node
|
||||
for _, visitedNode := range rightmostVisitedNodes {
|
||||
// Trailing tokens that occur before this node.
|
||||
for startPos < min(visitedNode.Pos(), position) {
|
||||
token := scanNavigationToken(scanner, n)
|
||||
tokenStart := scanner.TokenStart()
|
||||
if tokenStart >= position {
|
||||
break
|
||||
}
|
||||
tokenFullStart := scanner.TokenFullStart()
|
||||
tokenEnd := scanner.TokenEnd()
|
||||
startPos = tokenEnd
|
||||
flags := scanner.TokenFlags()
|
||||
tokens = append(tokens, sourceFile.GetOrCreateToken(token, tokenFullStart, tokenEnd, n, flags))
|
||||
scanner.Scan()
|
||||
}
|
||||
startPos = visitedNode.End()
|
||||
scanner.ResetPos(startPos)
|
||||
scanner.Scan()
|
||||
}
|
||||
// Trailing tokens after last visited node.
|
||||
for startPos < min(endPos, position) {
|
||||
token := scanNavigationToken(scanner, n)
|
||||
tokenStart := scanner.TokenStart()
|
||||
if tokenStart >= position {
|
||||
break
|
||||
}
|
||||
tokenFullStart := scanner.TokenFullStart()
|
||||
tokenEnd := scanner.TokenEnd()
|
||||
startPos = tokenEnd
|
||||
flags := scanner.TokenFlags()
|
||||
tokens = append(tokens, sourceFile.GetOrCreateToken(token, tokenFullStart, tokenEnd, n, flags))
|
||||
scanner.Scan()
|
||||
}
|
||||
|
||||
lastToken := len(tokens) - 1
|
||||
// Find preceding valid token.
|
||||
for i := lastToken; i >= 0; i-- {
|
||||
if !ast.IsWhitespaceOnlyJsxText(tokens[i]) {
|
||||
return tokens[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Case 3: childless node.
|
||||
if !hasChildren {
|
||||
if n != containingNode {
|
||||
return n
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// Case 1: recur on rightmostValidNode.
|
||||
if rightmostValidNode != nil {
|
||||
endPos = rightmostValidNode.End()
|
||||
}
|
||||
return find(rightmostValidNode, endPos)
|
||||
}
|
||||
|
||||
return find(containingNode, endPos)
|
||||
}
|
||||
|
||||
func FindNextToken(previousToken *ast.Node, parent *ast.Node, file *ast.SourceFile) *ast.Node {
|
||||
var find func(n *ast.Node) *ast.Node
|
||||
find = func(n *ast.Node) *ast.Node {
|
||||
if ast.IsTokenKind(n.Kind) && n.Pos() == previousToken.End() {
|
||||
// this is token that starts at the end of previous token - return it
|
||||
return n
|
||||
}
|
||||
// Node that contains `previousToken` or occurs immediately after it.
|
||||
var foundNode *ast.Node
|
||||
visitNode := func(node *ast.Node, _ *ast.NodeVisitor) *ast.Node {
|
||||
if node != nil && node.Flags&ast.NodeFlagsReparsed == 0 &&
|
||||
node.Pos() <= previousToken.End() && node.End() > previousToken.End() {
|
||||
foundNode = node
|
||||
}
|
||||
return node
|
||||
}
|
||||
visitNodes := func(nodeList *ast.NodeList, _ *ast.NodeVisitor) *ast.NodeList {
|
||||
if nodeList != nil && len(nodeList.Nodes) > 0 && foundNode == nil {
|
||||
nodes := nodeList.Nodes
|
||||
index, match := core.BinarySearchUniqueFunc(nodes, func(_ int, node *ast.Node) int {
|
||||
if node.Flags&ast.NodeFlagsReparsed != 0 {
|
||||
return comparisonLessThan
|
||||
}
|
||||
if node.Pos() > previousToken.End() {
|
||||
return comparisonGreaterThan
|
||||
}
|
||||
if node.End() <= previousToken.Pos() {
|
||||
return comparisonLessThan
|
||||
}
|
||||
return comparisonEqualTo
|
||||
})
|
||||
if match {
|
||||
foundNode = nodes[index]
|
||||
}
|
||||
}
|
||||
return nodeList
|
||||
}
|
||||
VisitEachChildAndJSDoc(n, file, visitNode, visitNodes)
|
||||
// Cases:
|
||||
// 1. no answer exists
|
||||
// 2. answer is an unvisited token
|
||||
// 3. answer is in the visited found node
|
||||
|
||||
// Case 3: look for the next token inside the found node.
|
||||
if foundNode != nil {
|
||||
return find(foundNode)
|
||||
}
|
||||
startPos := previousToken.End()
|
||||
// Case 2: look for the next token directly.
|
||||
if startPos >= n.Pos() && startPos < n.End() {
|
||||
scanner := scanner.GetScannerForSourceFile(file, startPos)
|
||||
token := scanner.Token()
|
||||
tokenFullStart := scanner.TokenFullStart()
|
||||
tokenEnd := scanner.TokenEnd()
|
||||
flags := scanner.TokenFlags()
|
||||
// Use tokenFullStart (which includes leading trivia) to match TS's
|
||||
// findNextToken behavior where `n.pos === previousToken.end` is checked
|
||||
// (TS's pos includes trivia, same as Go's Pos()/tokenFullStart).
|
||||
if tokenFullStart == previousToken.End() {
|
||||
return file.GetOrCreateToken(token, tokenFullStart, tokenEnd, n, flags)
|
||||
}
|
||||
panic(fmt.Sprintf("Expected to find next token at %d, got token %s at %d", previousToken.End(), token, tokenFullStart))
|
||||
}
|
||||
// Case 3: no answer.
|
||||
return nil
|
||||
}
|
||||
return find(parent)
|
||||
}
|
||||
|
||||
func getNodeVisitor(
|
||||
visitNode func(*ast.Node, *ast.NodeVisitor) *ast.Node,
|
||||
visitNodes func(*ast.NodeList, *ast.NodeVisitor) *ast.NodeList,
|
||||
) *ast.NodeVisitor {
|
||||
var wrappedVisitNode func(*ast.Node, *ast.NodeVisitor) *ast.Node
|
||||
var wrappedVisitNodes func(*ast.NodeList, *ast.NodeVisitor) *ast.NodeList
|
||||
if visitNode != nil {
|
||||
wrappedVisitNode = func(n *ast.Node, v *ast.NodeVisitor) *ast.Node {
|
||||
if ast.IsJSDocSingleCommentNodeComment(n) {
|
||||
return n
|
||||
}
|
||||
return visitNode(n, v)
|
||||
}
|
||||
}
|
||||
|
||||
if visitNodes != nil {
|
||||
wrappedVisitNodes = func(n *ast.NodeList, v *ast.NodeVisitor) *ast.NodeList {
|
||||
if ast.IsJSDocSingleCommentNodeList(n) {
|
||||
return n
|
||||
}
|
||||
return visitNodes(n, v)
|
||||
}
|
||||
}
|
||||
|
||||
return ast.NewNodeVisitor(core.Identity, nil, ast.NodeVisitorHooks{
|
||||
VisitNode: wrappedVisitNode,
|
||||
VisitToken: wrappedVisitNode,
|
||||
VisitNodes: wrappedVisitNodes,
|
||||
VisitModifiers: func(modifiers *ast.ModifierList, visitor *ast.NodeVisitor) *ast.ModifierList {
|
||||
if modifiers != nil {
|
||||
wrappedVisitNodes(&modifiers.NodeList, visitor)
|
||||
}
|
||||
return modifiers
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func shouldSkipChild(node *ast.Node) bool {
|
||||
return node.Kind == ast.KindJSDoc ||
|
||||
node.Kind == ast.KindJSDocText ||
|
||||
node.Kind == ast.KindJSDocTypeLiteral ||
|
||||
node.Kind == ast.KindJSDocSignature ||
|
||||
ast.IsJSDocLinkLike(node) ||
|
||||
ast.IsJSDocTag(node)
|
||||
}
|
||||
|
||||
// FindChildOfKind searches for a child node or token of the specified kind within a containing node.
|
||||
// This function scans through both AST nodes and intervening tokens to find the first match.
|
||||
func FindChildOfKind(containingNode *ast.Node, kind ast.Kind, sourceFile *ast.SourceFile) *ast.Node {
|
||||
lastNodePos := containingNode.Pos()
|
||||
scan := scanner.GetScannerForSourceFile(sourceFile, lastNodePos)
|
||||
|
||||
var foundChild *ast.Node
|
||||
visitNode := func(node *ast.Node) bool {
|
||||
if node == nil || node.Flags&ast.NodeFlagsReparsed != 0 {
|
||||
return false
|
||||
}
|
||||
// Look for child in preceding tokens.
|
||||
startPos := lastNodePos
|
||||
for startPos < node.Pos() {
|
||||
tokenKind := scan.Token()
|
||||
tokenEnd := scan.TokenEnd()
|
||||
if tokenKind == kind {
|
||||
tokenFullStart := scan.TokenFullStart()
|
||||
flags := scan.TokenFlags()
|
||||
foundChild = sourceFile.GetOrCreateToken(tokenKind, tokenFullStart, tokenEnd, containingNode, flags)
|
||||
return true
|
||||
}
|
||||
startPos = tokenEnd
|
||||
scan.Scan()
|
||||
}
|
||||
|
||||
if node.Kind == kind {
|
||||
foundChild = node
|
||||
return true
|
||||
}
|
||||
|
||||
lastNodePos = node.End()
|
||||
scan.ResetPos(lastNodePos)
|
||||
return false
|
||||
}
|
||||
|
||||
ast.ForEachChildAndJSDoc(containingNode, sourceFile, visitNode)
|
||||
|
||||
if foundChild != nil {
|
||||
return foundChild
|
||||
}
|
||||
|
||||
// Look for child in trailing tokens.
|
||||
startPos := lastNodePos
|
||||
for startPos < containingNode.End() {
|
||||
tokenKind := scan.Token()
|
||||
tokenEnd := scan.TokenEnd()
|
||||
if tokenKind == kind {
|
||||
tokenFullStart := scan.TokenFullStart()
|
||||
flags := scan.TokenFlags()
|
||||
token := sourceFile.GetOrCreateToken(tokenKind, tokenFullStart, tokenEnd, containingNode, flags)
|
||||
return token
|
||||
}
|
||||
startPos = tokenEnd
|
||||
scan.Scan()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
626
tools/tsgo/internal/astnav/tokens_test.go
Normal file
626
tools/tsgo/internal/astnav/tokens_test.go
Normal file
@@ -0,0 +1,626 @@
|
||||
package astnav_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/astnav"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/parser"
|
||||
"github.com/microsoft/typescript-go/internal/repo"
|
||||
"github.com/microsoft/typescript-go/internal/testutil/baseline"
|
||||
"github.com/microsoft/typescript-go/internal/testutil/jstest"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
var testFiles = []string{
|
||||
filepath.Join(repo.TypeScriptSubmodulePath(), "src/services/mapCode.ts"),
|
||||
}
|
||||
|
||||
func TestGetTokenAtPosition(t *testing.T) {
|
||||
t.Parallel()
|
||||
repo.SkipIfNoTypeScriptSubmodule(t)
|
||||
jstest.SkipIfNoNodeJS(t)
|
||||
|
||||
t.Run("baseline", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
baselineTokens(
|
||||
t,
|
||||
"GetTokenAtPosition",
|
||||
false, /*includeEOF*/
|
||||
func(fileText string, positions []int) []*tokenInfo {
|
||||
return tsGetTokensAtPositions(t, fileText, positions)
|
||||
},
|
||||
func(file *ast.SourceFile, pos int) *tokenInfo {
|
||||
return toTokenInfo(astnav.GetTokenAtPosition(file, pos))
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("go baseline json", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
baselineGoTokensJSON(t, "GetTokenAtPosition", func(file *ast.SourceFile, pos int) *tokenInfo {
|
||||
return toTokenInfo(astnav.GetTokenAtPosition(file, pos))
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("JSDoc type assertion", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
fileText := `function foo(x) {
|
||||
const s = /**@type {string}*/(x)
|
||||
}`
|
||||
file := parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/test.js",
|
||||
Path: "/test.js",
|
||||
}, fileText, core.ScriptKindJS)
|
||||
|
||||
// Position of 'x' inside the parenthesized expression (position 52)
|
||||
position := 52
|
||||
|
||||
// This should not panic - it previously panicked with:
|
||||
// "did not expect KindParenthesizedExpression to have KindIdentifier in its trivia"
|
||||
token := astnav.GetTouchingPropertyName(file, position)
|
||||
if token == nil {
|
||||
t.Fatal("Expected to get a token, got nil")
|
||||
}
|
||||
|
||||
// The function may return either the identifier itself or the containing
|
||||
// parenthesized expression, depending on how the AST is structured
|
||||
if token.Kind != ast.KindIdentifier && token.Kind != ast.KindParenthesizedExpression {
|
||||
t.Errorf("Expected identifier or parenthesized expression, got %s", token.Kind)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("JSDoc type assertion with comment", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Exact code from the issue report
|
||||
fileText := `function foo(x) {
|
||||
const s = /**@type {string}*/(x) // Go-to-definition on x causes panic
|
||||
}`
|
||||
file := parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/test.js",
|
||||
Path: "/test.js",
|
||||
}, fileText, core.ScriptKindJS)
|
||||
|
||||
// Find position of 'x' in the type assertion
|
||||
xPos := 52 // Position of 'x' in (x)
|
||||
|
||||
// This should not panic
|
||||
token := astnav.GetTouchingPropertyName(file, xPos)
|
||||
assert.Assert(t, token != nil, "Expected to get a token")
|
||||
})
|
||||
|
||||
t.Run("pointer equality", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
fileText := `
|
||||
function foo() {
|
||||
return 0;
|
||||
}
|
||||
`
|
||||
file := parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/file.ts",
|
||||
Path: "/file.ts",
|
||||
}, fileText, core.ScriptKindTS)
|
||||
assert.Equal(t, astnav.GetTokenAtPosition(file, 0), astnav.GetTokenAtPosition(file, 0))
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetTouchingPropertyName(t *testing.T) {
|
||||
t.Parallel()
|
||||
jstest.SkipIfNoNodeJS(t)
|
||||
repo.SkipIfNoTypeScriptSubmodule(t)
|
||||
|
||||
baselineTokens(
|
||||
t,
|
||||
"GetTouchingPropertyName",
|
||||
false, /*includeEOF*/
|
||||
func(fileText string, positions []int) []*tokenInfo {
|
||||
return tsGetTouchingPropertyName(t, fileText, positions)
|
||||
},
|
||||
func(file *ast.SourceFile, pos int) *tokenInfo {
|
||||
return toTokenInfo(astnav.GetTouchingPropertyName(file, pos))
|
||||
},
|
||||
)
|
||||
|
||||
t.Run("go baseline json", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
baselineGoTokensJSON(t, "GetTouchingPropertyName", func(file *ast.SourceFile, pos int) *tokenInfo {
|
||||
return toTokenInfo(astnav.GetTouchingPropertyName(file, pos))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func baselineTokens(t *testing.T, testName string, includeEOF bool, getTSTokens func(fileText string, positions []int) []*tokenInfo, getGoToken func(file *ast.SourceFile, pos int) *tokenInfo) {
|
||||
for _, fileName := range testFiles {
|
||||
t.Run(filepath.Base(fileName), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
fileText, err := os.ReadFile(fileName)
|
||||
assert.NilError(t, err)
|
||||
|
||||
positions := make([]int, len(fileText)+core.IfElse(includeEOF, 1, 0))
|
||||
for i := range positions {
|
||||
positions[i] = i
|
||||
}
|
||||
tsTokens := getTSTokens(string(fileText), positions)
|
||||
file := parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/file.ts",
|
||||
Path: "/file.ts",
|
||||
}, string(fileText), core.ScriptKindTS)
|
||||
|
||||
var output strings.Builder
|
||||
currentRange := core.NewTextRange(0, 0)
|
||||
currentDiff := tokenDiff{}
|
||||
|
||||
for pos, tsToken := range tsTokens {
|
||||
goToken := getGoToken(file, pos)
|
||||
diff := tokenDiff{goToken: goToken, tsToken: tsToken}
|
||||
|
||||
if !diffEqual(currentDiff, diff) {
|
||||
if !tokensEqual(currentDiff.goToken, currentDiff.tsToken) {
|
||||
writeRangeDiff(&output, file, currentDiff, currentRange, pos)
|
||||
}
|
||||
currentDiff = diff
|
||||
currentRange = core.NewTextRange(pos, pos)
|
||||
}
|
||||
currentRange = currentRange.WithEnd(pos)
|
||||
}
|
||||
|
||||
if !tokensEqual(currentDiff.goToken, currentDiff.tsToken) {
|
||||
writeRangeDiff(&output, file, currentDiff, currentRange, len(tsTokens)-1)
|
||||
}
|
||||
|
||||
baseline.Run(
|
||||
t,
|
||||
fmt.Sprintf("%s.%s.baseline.txt", testName, filepath.Base(fileName)),
|
||||
core.IfElse(output.Len() > 0, output.String(), baseline.NoContent),
|
||||
baseline.Options{
|
||||
Subfolder: "astnav",
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type tokenRun struct {
|
||||
StartPos int `json:"startPos"`
|
||||
EndPos int `json:"endPos"`
|
||||
Kind string `json:"kind"`
|
||||
NodePos int `json:"nodePos"`
|
||||
NodeEnd int `json:"nodeEnd"`
|
||||
}
|
||||
|
||||
func baselineGoTokensJSON(t *testing.T, testName string, getGoToken func(file *ast.SourceFile, pos int) *tokenInfo) {
|
||||
for _, fileName := range testFiles {
|
||||
t.Run(filepath.Base(fileName), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
fileText, err := os.ReadFile(fileName)
|
||||
assert.NilError(t, err)
|
||||
|
||||
file := parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/file.ts",
|
||||
Path: "/file.ts",
|
||||
}, string(fileText), core.ScriptKindTS)
|
||||
|
||||
maxPos := len(fileText)
|
||||
var runs []tokenRun
|
||||
var current *tokenRun
|
||||
|
||||
for pos := range maxPos {
|
||||
token := getGoToken(file, pos)
|
||||
if current != nil && token != nil && current.Kind == token.Kind && current.NodePos == token.Pos && current.NodeEnd == token.End {
|
||||
current.EndPos = pos
|
||||
} else {
|
||||
if current != nil {
|
||||
runs = append(runs, *current)
|
||||
}
|
||||
if token != nil {
|
||||
current = &tokenRun{
|
||||
StartPos: pos,
|
||||
EndPos: pos,
|
||||
Kind: token.Kind,
|
||||
NodePos: token.Pos,
|
||||
NodeEnd: token.End,
|
||||
}
|
||||
} else {
|
||||
current = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if current != nil {
|
||||
runs = append(runs, *current)
|
||||
}
|
||||
|
||||
output := core.Must(core.StringifyJson(runs, "", " "))
|
||||
|
||||
baseline.Run(
|
||||
t,
|
||||
fmt.Sprintf("%s.%s.baseline.json", testName, filepath.Base(fileName)),
|
||||
output,
|
||||
baseline.Options{
|
||||
Subfolder: "astnav",
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type tokenDiff struct {
|
||||
goToken *tokenInfo
|
||||
tsToken *tokenInfo
|
||||
}
|
||||
|
||||
type tokenInfo struct {
|
||||
Kind string `json:"kind"`
|
||||
Pos int `json:"pos"`
|
||||
End int `json:"end"`
|
||||
}
|
||||
|
||||
func toTokenInfo(node *ast.Node) *tokenInfo {
|
||||
if node == nil {
|
||||
return nil
|
||||
}
|
||||
kind := strings.Replace(node.Kind.String(), "Kind", "", 1)
|
||||
switch kind {
|
||||
case "EndOfFile":
|
||||
kind = "EndOfFileToken"
|
||||
}
|
||||
return &tokenInfo{
|
||||
Kind: kind,
|
||||
Pos: node.Pos(),
|
||||
End: node.End(),
|
||||
}
|
||||
}
|
||||
|
||||
func diffEqual(a, b tokenDiff) bool {
|
||||
return tokensEqual(a.goToken, b.goToken) && tokensEqual(a.tsToken, b.tsToken)
|
||||
}
|
||||
|
||||
func tokensEqual(t1, t2 *tokenInfo) bool {
|
||||
if t1 == nil || t2 == nil {
|
||||
return t1 == t2
|
||||
}
|
||||
return *t1 == *t2
|
||||
}
|
||||
|
||||
func tsGetTokensAtPositions(t testing.TB, fileText string, positions []int) []*tokenInfo {
|
||||
dir := t.TempDir()
|
||||
err := os.WriteFile(filepath.Join(dir, "file.ts"), []byte(fileText), 0o644)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = os.WriteFile(filepath.Join(dir, "positions.json"), []byte(core.Must(core.StringifyJson(positions, "", ""))), 0o644)
|
||||
assert.NilError(t, err)
|
||||
|
||||
script := `
|
||||
import fs from "fs";
|
||||
export default (ts) => {
|
||||
const positions = JSON.parse(fs.readFileSync("positions.json", "utf8"));
|
||||
const fileText = fs.readFileSync("file.ts", "utf8");
|
||||
const file = ts.createSourceFile(
|
||||
"file.ts",
|
||||
fileText,
|
||||
{ languageVersion: ts.ScriptTarget.Latest, jsDocParsingMode: ts.JSDocParsingMode.ParseAll },
|
||||
/*setParentNodes*/ true
|
||||
);
|
||||
return positions.map(position => {
|
||||
let token = ts.getTokenAtPosition(file, position);
|
||||
if (token.kind === ts.SyntaxKind.SyntaxList) {
|
||||
token = token.parent;
|
||||
}
|
||||
return {
|
||||
kind: ts.Debug.formatSyntaxKind(token.kind),
|
||||
pos: token.pos,
|
||||
end: token.end,
|
||||
};
|
||||
});
|
||||
};`
|
||||
|
||||
info, err := jstest.EvalNodeScriptWithTS[[]*tokenInfo](t, script, dir, "")
|
||||
assert.NilError(t, err)
|
||||
return info
|
||||
}
|
||||
|
||||
func tsGetTouchingPropertyName(t testing.TB, fileText string, positions []int) []*tokenInfo {
|
||||
dir := t.TempDir()
|
||||
err := os.WriteFile(filepath.Join(dir, "file.ts"), []byte(fileText), 0o644)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = os.WriteFile(filepath.Join(dir, "positions.json"), []byte(core.Must(core.StringifyJson(positions, "", ""))), 0o644)
|
||||
assert.NilError(t, err)
|
||||
|
||||
script := `
|
||||
import fs from "fs";
|
||||
export default (ts) => {
|
||||
const positions = JSON.parse(fs.readFileSync("positions.json", "utf8"));
|
||||
const fileText = fs.readFileSync("file.ts", "utf8");
|
||||
const file = ts.createSourceFile(
|
||||
"file.ts",
|
||||
fileText,
|
||||
{ languageVersion: ts.ScriptTarget.Latest, jsDocParsingMode: ts.JSDocParsingMode.ParseAll },
|
||||
/*setParentNodes*/ true
|
||||
);
|
||||
return positions.map(position => {
|
||||
let token = ts.getTouchingPropertyName(file, position);
|
||||
if (token.kind === ts.SyntaxKind.SyntaxList) {
|
||||
token = token.parent;
|
||||
}
|
||||
return {
|
||||
kind: ts.Debug.formatSyntaxKind(token.kind),
|
||||
pos: token.pos,
|
||||
end: token.end,
|
||||
};
|
||||
});
|
||||
};`
|
||||
|
||||
info, err := jstest.EvalNodeScriptWithTS[[]*tokenInfo](t, script, dir, "")
|
||||
assert.NilError(t, err)
|
||||
return info
|
||||
}
|
||||
|
||||
func writeRangeDiff(output *strings.Builder, file *ast.SourceFile, diff tokenDiff, rng core.TextRange, position int) {
|
||||
lines := file.ECMALineMap()
|
||||
|
||||
tsTokenPos := position
|
||||
goTokenPos := position
|
||||
tsTokenEnd := position
|
||||
goTokenEnd := position
|
||||
if diff.tsToken != nil {
|
||||
tsTokenPos = diff.tsToken.Pos
|
||||
tsTokenEnd = diff.tsToken.End
|
||||
}
|
||||
if diff.goToken != nil {
|
||||
goTokenPos = diff.goToken.Pos
|
||||
goTokenEnd = diff.goToken.End
|
||||
}
|
||||
tsStartLine, _ := core.PositionToLineAndByteOffset(tsTokenPos, lines)
|
||||
tsEndLine, _ := core.PositionToLineAndByteOffset(tsTokenEnd, lines)
|
||||
goStartLine, _ := core.PositionToLineAndByteOffset(goTokenPos, lines)
|
||||
goEndLine, _ := core.PositionToLineAndByteOffset(goTokenEnd, lines)
|
||||
|
||||
contextLines := 2
|
||||
startLine := min(tsStartLine, goStartLine)
|
||||
endLine := max(tsEndLine, goEndLine)
|
||||
markerLines := []int{tsStartLine, tsEndLine, goStartLine, goEndLine}
|
||||
slices.Sort(markerLines)
|
||||
contextStart := max(0, startLine-contextLines)
|
||||
contextEnd := min(len(lines)-1, endLine+contextLines)
|
||||
digits := len(strconv.Itoa(contextEnd))
|
||||
|
||||
shouldTruncate := func(line int) (result bool, skipTo int) {
|
||||
index, _ := slices.BinarySearch(markerLines, line)
|
||||
if index == 0 || index == len(markerLines) {
|
||||
return false, 0
|
||||
}
|
||||
low := markerLines[index-1]
|
||||
high := markerLines[index]
|
||||
if line-low > 5 && high-line > 5 {
|
||||
return true, high - 5
|
||||
}
|
||||
return false, 0
|
||||
}
|
||||
|
||||
if output.Len() > 0 {
|
||||
output.WriteString("\n\n")
|
||||
}
|
||||
|
||||
output.WriteString(fmt.Sprintf("〚Positions: [%d, %d]〛\n", rng.Pos(), rng.End()))
|
||||
if diff.tsToken != nil {
|
||||
output.WriteString(fmt.Sprintf("【TS: %s [%d, %d)】\n", diff.tsToken.Kind, tsTokenPos, tsTokenEnd))
|
||||
} else {
|
||||
output.WriteString("【TS: nil】\n")
|
||||
}
|
||||
if diff.goToken != nil {
|
||||
output.WriteString(fmt.Sprintf("《Go: %s [%d, %d)》\n", diff.goToken.Kind, goTokenPos, goTokenEnd))
|
||||
} else {
|
||||
output.WriteString("《Go: nil》\n")
|
||||
}
|
||||
for line := contextStart; line <= contextEnd; line++ {
|
||||
if truncate, skipTo := shouldTruncate(line); truncate {
|
||||
output.WriteString(fmt.Sprintf("%s │........ %d lines omitted ........\n", strings.Repeat(" ", digits), skipTo-line+1))
|
||||
line = skipTo
|
||||
}
|
||||
output.WriteString(fmt.Sprintf("%*d │", digits, line+1))
|
||||
end := len(file.Text()) + 1
|
||||
if line < len(lines)-1 {
|
||||
end = int(lines[line+1])
|
||||
}
|
||||
for pos := int(lines[line]); pos < end; pos++ {
|
||||
if pos == rng.End()+1 {
|
||||
output.WriteString("〛")
|
||||
}
|
||||
if diff.tsToken != nil && pos == tsTokenEnd {
|
||||
output.WriteString("】")
|
||||
}
|
||||
if diff.goToken != nil && pos == goTokenEnd {
|
||||
output.WriteString("》")
|
||||
}
|
||||
|
||||
if diff.goToken != nil && pos == goTokenPos {
|
||||
output.WriteString("《")
|
||||
}
|
||||
if diff.tsToken != nil && pos == tsTokenPos {
|
||||
output.WriteString("【")
|
||||
}
|
||||
if pos == rng.Pos() {
|
||||
output.WriteString("〚")
|
||||
}
|
||||
|
||||
if pos < len(file.Text()) {
|
||||
output.WriteByte(file.Text()[pos])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindPrecedingToken(t *testing.T) {
|
||||
t.Parallel()
|
||||
repo.SkipIfNoTypeScriptSubmodule(t)
|
||||
jstest.SkipIfNoNodeJS(t)
|
||||
|
||||
t.Run("baseline", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
baselineTokens(
|
||||
t,
|
||||
"FindPrecedingToken",
|
||||
true, /*includeEOF*/
|
||||
func(fileText string, positions []int) []*tokenInfo {
|
||||
return tsFindPrecedingTokens(t, fileText, positions)
|
||||
},
|
||||
func(file *ast.SourceFile, pos int) *tokenInfo {
|
||||
return toTokenInfo(astnav.FindPrecedingToken(file, pos))
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("go baseline json", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
baselineGoTokensJSON(t, "FindPrecedingToken", func(file *ast.SourceFile, pos int) *tokenInfo {
|
||||
return toTokenInfo(astnav.FindPrecedingToken(file, pos))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestFindNextToken(t *testing.T) {
|
||||
t.Parallel()
|
||||
repo.SkipIfNoTypeScriptSubmodule(t)
|
||||
|
||||
t.Run("go baseline json", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
baselineGoTokensJSON(t, "FindNextToken", func(file *ast.SourceFile, pos int) (result *tokenInfo) {
|
||||
// FindNextToken panics (like Go's assert) when the scanner finds trivia between
|
||||
// previousToken.End() and the next syntactic token. Catch those to avoid crashing
|
||||
// the baseline generator; those positions will be absent from the baseline.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
result = nil
|
||||
}
|
||||
}()
|
||||
token := astnav.GetTokenAtPosition(file, pos)
|
||||
next := astnav.FindNextToken(token, file.AsNode(), file)
|
||||
return toTokenInfo(next)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestUnitFindPrecedingToken(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCases := []struct {
|
||||
name string
|
||||
fileContent string
|
||||
position int
|
||||
expectedKind ast.Kind
|
||||
}{
|
||||
{
|
||||
name: "after dot in jsdoc",
|
||||
fileContent: `import {
|
||||
CharacterCodes,
|
||||
compareStringsCaseInsensitive,
|
||||
compareStringsCaseSensitive,
|
||||
compareValues,
|
||||
Comparison,
|
||||
Debug,
|
||||
endsWith,
|
||||
equateStringsCaseInsensitive,
|
||||
equateStringsCaseSensitive,
|
||||
GetCanonicalFileName,
|
||||
getDeclarationFileExtension,
|
||||
getStringComparer,
|
||||
identity,
|
||||
lastOrUndefined,
|
||||
Path,
|
||||
some,
|
||||
startsWith,
|
||||
} from "./_namespaces/ts.js";
|
||||
|
||||
/**
|
||||
* Internally, we represent paths as strings with '/' as the directory separator.
|
||||
* When we make system calls (eg: LanguageServiceHost.getDirectory()),
|
||||
* we expect the host to correctly handle paths in our specified format.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export const directorySeparator = "/";
|
||||
/** @internal */
|
||||
export const altDirectorySeparator = "\\";
|
||||
const urlSchemeSeparator = "://";
|
||||
const backslashRegExp = /\\/g;
|
||||
|
||||
|
||||
backslashRegExp.
|
||||
|
||||
//Path Tests
|
||||
|
||||
/**
|
||||
* Determines whether a charCode corresponds to '/' or '\'.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function isAnyDirectorySeparator(charCode: number): boolean {
|
||||
return charCode === CharacterCodes.slash || charCode === CharacterCodes.backslash;
|
||||
}`,
|
||||
position: 839,
|
||||
expectedKind: ast.KindDotToken,
|
||||
},
|
||||
{
|
||||
name: "after comma in parameter list",
|
||||
fileContent: `takesCb((n, s, ))`,
|
||||
position: 15,
|
||||
expectedKind: ast.KindCommaToken,
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
file := parser.ParseSourceFile(ast.SourceFileParseOptions{
|
||||
FileName: "/file.ts",
|
||||
Path: "/file.ts",
|
||||
}, testCase.fileContent, core.ScriptKindTS)
|
||||
token := astnav.FindPrecedingToken(file, testCase.position)
|
||||
assert.Equal(t, token.Kind, testCase.expectedKind)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func tsFindPrecedingTokens(t *testing.T, fileText string, positions []int) []*tokenInfo {
|
||||
dir := t.TempDir()
|
||||
err := os.WriteFile(filepath.Join(dir, "file.ts"), []byte(fileText), 0o644)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = os.WriteFile(filepath.Join(dir, "positions.json"), []byte(core.Must(core.StringifyJson(positions, "", ""))), 0o644)
|
||||
assert.NilError(t, err)
|
||||
|
||||
script := `
|
||||
import fs from "fs";
|
||||
export default (ts) => {
|
||||
const positions = JSON.parse(fs.readFileSync("positions.json", "utf8"));
|
||||
const fileText = fs.readFileSync("file.ts", "utf8");
|
||||
const file = ts.createSourceFile(
|
||||
"file.ts",
|
||||
fileText,
|
||||
{ languageVersion: ts.ScriptTarget.Latest, jsDocParsingMode: ts.JSDocParsingMode.ParseAll },
|
||||
/*setParentNodes*/ true
|
||||
);
|
||||
return positions.map(position => {
|
||||
let token = ts.findPrecedingToken(position, file);
|
||||
if (token === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (token.kind === ts.SyntaxKind.SyntaxList) {
|
||||
token = token.parent;
|
||||
}
|
||||
return {
|
||||
kind: ts.Debug.formatSyntaxKind(token.kind),
|
||||
pos: token.pos,
|
||||
end: token.end,
|
||||
};
|
||||
});
|
||||
};`
|
||||
info, err := jstest.EvalNodeScriptWithTS[[]*tokenInfo](t, script, dir, "")
|
||||
assert.NilError(t, err)
|
||||
return info
|
||||
}
|
||||
2795
tools/tsgo/internal/binder/binder.go
Normal file
2795
tools/tsgo/internal/binder/binder.go
Normal file
File diff suppressed because it is too large
Load Diff
46
tools/tsgo/internal/binder/binder_test.go
Normal file
46
tools/tsgo/internal/binder/binder_test.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package binder
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/parser"
|
||||
"github.com/microsoft/typescript-go/internal/testutil/fixtures"
|
||||
"github.com/microsoft/typescript-go/internal/tspath"
|
||||
"github.com/microsoft/typescript-go/internal/vfs/osvfs"
|
||||
)
|
||||
|
||||
func BenchmarkBind(b *testing.B) {
|
||||
for _, f := range fixtures.BenchFixtures {
|
||||
b.Run(f.Name(), func(b *testing.B) {
|
||||
f.SkipIfNotExist(b)
|
||||
|
||||
fileName := tspath.GetNormalizedAbsolutePath(f.Path(), "/")
|
||||
path := tspath.ToPath(fileName, "/", osvfs.FS().UseCaseSensitiveFileNames())
|
||||
sourceText := f.ReadFile(b)
|
||||
|
||||
parseOptions := ast.SourceFileParseOptions{
|
||||
FileName: fileName,
|
||||
Path: path,
|
||||
}
|
||||
scriptKind := core.GetScriptKindFromFileName(fileName)
|
||||
|
||||
sourceFiles := make([]*ast.SourceFile, b.N)
|
||||
for i := range b.N {
|
||||
sourceFiles[i] = parser.ParseSourceFile(parseOptions, sourceText, scriptKind)
|
||||
}
|
||||
|
||||
// The above parses do a lot of work; ensure GC is finished before we start collecting performance data.
|
||||
// GC must be called twice to allow things to settle.
|
||||
runtime.GC()
|
||||
runtime.GC()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := range b.N {
|
||||
BindSourceFile(sourceFiles[i])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
498
tools/tsgo/internal/binder/nameresolver.go
Normal file
498
tools/tsgo/internal/binder/nameresolver.go
Normal file
@@ -0,0 +1,498 @@
|
||||
package binder
|
||||
|
||||
import (
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/diagnostics"
|
||||
)
|
||||
|
||||
type NameResolver struct {
|
||||
CompilerOptions *core.CompilerOptions
|
||||
GetSymbolOfDeclaration func(node *ast.Node) *ast.Symbol
|
||||
Error func(location *ast.Node, message *diagnostics.Message, args ...any) *ast.Diagnostic
|
||||
Globals ast.SymbolTable
|
||||
ArgumentsSymbol *ast.Symbol
|
||||
RequireSymbol *ast.Symbol
|
||||
Lookup func(symbols ast.SymbolTable, name string, meaning ast.SymbolFlags) *ast.Symbol
|
||||
SymbolReferenced func(symbol *ast.Symbol, meaning ast.SymbolFlags)
|
||||
SetRequiresScopeChangeCache func(node *ast.Node, value core.Tristate)
|
||||
GetRequiresScopeChangeCache func(node *ast.Node) core.Tristate
|
||||
OnPropertyWithInvalidInitializer func(location *ast.Node, name string, declaration *ast.Node, result *ast.Symbol) bool
|
||||
OnFailedToResolveSymbol func(location *ast.Node, name string, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message)
|
||||
OnSuccessfullyResolvedSymbol func(location *ast.Node, result *ast.Symbol, meaning ast.SymbolFlags, lastLocation *ast.Node, associatedDeclarationForContainingInitializerOrBindingName *ast.Node, withinDeferredContext bool)
|
||||
}
|
||||
|
||||
func (r *NameResolver) Resolve(location *ast.Node, name string, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message, isUse bool, excludeGlobals bool) *ast.Symbol {
|
||||
var result *ast.Symbol
|
||||
var lastLocation *ast.Node
|
||||
var lastSelfReferenceLocation *ast.Node
|
||||
var propertyWithInvalidInitializer *ast.Node
|
||||
var associatedDeclarationForContainingInitializerOrBindingName *ast.Node
|
||||
var withinDeferredContext bool
|
||||
var grandparent *ast.Node
|
||||
originalLocation := location // needed for did-you-mean error reporting, which gathers candidates starting from the original location
|
||||
nameIsConst := name == "const"
|
||||
loop:
|
||||
for location != nil {
|
||||
if nameIsConst && ast.IsConstAssertion(location) {
|
||||
// `const` in an `as const` has no symbol, but issues no error because there is no *actual* lookup of the type
|
||||
// (it refers to the constant type of the expression instead)
|
||||
return nil
|
||||
}
|
||||
if ast.IsModuleOrEnumDeclaration(location) && lastLocation != nil && location.Name() == lastLocation {
|
||||
// If lastLocation is the name of a namespace or enum, skip the parent since it will have is own locals that could
|
||||
// conflict.
|
||||
lastLocation = location
|
||||
location = location.Parent
|
||||
}
|
||||
locals := location.Locals()
|
||||
// Locals of a source file are not in scope (because they get merged into the global symbol table)
|
||||
if locals != nil && !ast.IsGlobalSourceFile(location) {
|
||||
result = r.lookup(locals, name, meaning)
|
||||
if result != nil {
|
||||
useResult := true
|
||||
if ast.IsFunctionLike(location) && lastLocation != nil && lastLocation != location.Body() {
|
||||
// symbol lookup restrictions for function-like declarations
|
||||
// - Type parameters of a function are in scope in the entire function declaration, including the parameter
|
||||
// list and return type. However, local types are only in scope in the function body.
|
||||
// - parameters are only in the scope of function body
|
||||
// This restriction does not apply to JSDoc comment types because they are parented
|
||||
// at a higher level than type parameters would normally be
|
||||
if meaning&result.Flags&ast.SymbolFlagsType != 0 && lastLocation.Kind != ast.KindJSDoc {
|
||||
// type parameters are visible in parameter list, return type and type parameter list.
|
||||
// Synthetic fake scopes are added for signatures so type parameters are accessible from them.
|
||||
useResult = result.Flags&ast.SymbolFlagsTypeParameter != 0 &&
|
||||
(lastLocation.Flags&ast.NodeFlagsSynthesized != 0 ||
|
||||
lastLocation == location.Type() ||
|
||||
lastLocation.Kind == ast.KindParameter ||
|
||||
lastLocation.Kind == ast.KindJSDocParameterTag ||
|
||||
lastLocation.Kind == ast.KindJSDocReturnTag ||
|
||||
lastLocation.Kind == ast.KindTypeParameter)
|
||||
}
|
||||
if meaning&result.Flags&ast.SymbolFlagsVariable != 0 {
|
||||
// expression inside parameter will lookup as normal variable scope when targeting es2015+
|
||||
if r.useOuterVariableScopeInParameter(result, location, lastLocation) {
|
||||
useResult = false
|
||||
} else if result.Flags&ast.SymbolFlagsFunctionScopedVariable != 0 {
|
||||
// parameters are visible only inside function body, parameter list and return type
|
||||
// technically for parameter list case here we might mix parameters and variables declared in function,
|
||||
// however it is detected separately when checking initializers of parameters
|
||||
// to make sure that they reference no variables declared after them.
|
||||
useResult = lastLocation.Kind == ast.KindParameter ||
|
||||
lastLocation.Flags&ast.NodeFlagsSynthesized != 0 ||
|
||||
lastLocation == location.Type() && ast.FindAncestor(result.ValueDeclaration, ast.IsParameterDeclaration) != nil
|
||||
}
|
||||
}
|
||||
} else if location.Kind == ast.KindConditionalType {
|
||||
// A type parameter declared using 'infer T' in a conditional type is visible only in
|
||||
// the true branch of the conditional type.
|
||||
useResult = lastLocation == location.AsConditionalTypeNode().TrueType
|
||||
}
|
||||
if useResult {
|
||||
break loop
|
||||
}
|
||||
result = nil
|
||||
}
|
||||
}
|
||||
withinDeferredContext = withinDeferredContext || getIsDeferredContext(location, lastLocation)
|
||||
switch location.Kind {
|
||||
case ast.KindSourceFile:
|
||||
if !ast.IsExternalOrCommonJSModule(location.AsSourceFile()) {
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case ast.KindModuleDeclaration:
|
||||
moduleSymbol := r.getSymbolOfDeclaration(location)
|
||||
if moduleSymbol == nil {
|
||||
break
|
||||
}
|
||||
moduleExports := moduleSymbol.Exports
|
||||
if ast.IsSourceFile(location) || (ast.IsModuleDeclaration(location) && location.Flags&ast.NodeFlagsAmbient != 0 && !ast.IsGlobalScopeAugmentation(location)) {
|
||||
// It's an external module. First see if the module has an export default and if the local
|
||||
// name of that export default matches.
|
||||
result = moduleExports[ast.InternalSymbolNameDefault]
|
||||
if result != nil {
|
||||
localSymbol := GetLocalSymbolForExportDefault(result)
|
||||
if localSymbol != nil && result.Flags&meaning != 0 && localSymbol.Name == name {
|
||||
break loop
|
||||
}
|
||||
result = nil
|
||||
}
|
||||
// Because of module/namespace merging, a module's exports are in scope,
|
||||
// yet we never want to treat an export specifier as putting a member in scope.
|
||||
// Therefore, if the name we find is purely an export specifier, it is not actually considered in scope.
|
||||
// Two things to note about this:
|
||||
// 1. We have to check this without calling getSymbol. The problem with calling getSymbol
|
||||
// on an export specifier is that it might find the export specifier itself, and try to
|
||||
// resolve it as an alias. This will cause the checker to consider the export specifier
|
||||
// a circular alias reference when it might not be.
|
||||
// 2. We check === SymbolFlags.Alias in order to check that the symbol is *purely*
|
||||
// an alias. If we used &, we'd be throwing out symbols that have non alias aspects,
|
||||
// which is not the desired behavior.
|
||||
moduleExport := moduleExports[name]
|
||||
if moduleExport != nil && moduleExport.Flags == ast.SymbolFlagsAlias && (ast.GetDeclarationOfKind(moduleExport, ast.KindExportSpecifier) != nil || ast.GetDeclarationOfKind(moduleExport, ast.KindNamespaceExport) != nil) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if name != ast.InternalSymbolNameDefault {
|
||||
if result = r.lookup(moduleExports, name, meaning&ast.SymbolFlagsModuleMember); result != nil {
|
||||
if ast.IsSourceFile(location) && location.AsSourceFile().CommonJSModuleIndicator != nil && result.Flags&ast.SymbolFlagsType == 0 {
|
||||
result = nil
|
||||
} else {
|
||||
break loop
|
||||
}
|
||||
}
|
||||
}
|
||||
case ast.KindEnumDeclaration:
|
||||
enumSymbol := r.getSymbolOfDeclaration(location)
|
||||
if enumSymbol == nil {
|
||||
break
|
||||
}
|
||||
result = r.lookup(enumSymbol.Exports, name, meaning&ast.SymbolFlagsEnumMember)
|
||||
if result != nil {
|
||||
if nameNotFoundMessage != nil && r.CompilerOptions.GetIsolatedModules() && location.Flags&ast.NodeFlagsAmbient == 0 && ast.GetSourceFileOfNode(location) != ast.GetSourceFileOfNode(result.ValueDeclaration) {
|
||||
isolatedModulesLikeFlagName := core.IfElse(r.CompilerOptions.VerbatimModuleSyntax == core.TSTrue, "verbatimModuleSyntax", "isolatedModules")
|
||||
r.error(originalLocation, diagnostics.Cannot_access_0_from_another_file_without_qualification_when_1_is_enabled_Use_2_instead,
|
||||
name, isolatedModulesLikeFlagName, enumSymbol.Name+"."+name)
|
||||
}
|
||||
break loop
|
||||
}
|
||||
case ast.KindPropertyDeclaration:
|
||||
if !ast.IsStatic(location) {
|
||||
ctor := ast.FindConstructorDeclaration(location.Parent)
|
||||
if ctor != nil && ctor.Locals() != nil {
|
||||
if r.lookup(ctor.Locals(), name, meaning&ast.SymbolFlagsValue) != nil {
|
||||
// Remember the property node, it will be used later to report appropriate error
|
||||
propertyWithInvalidInitializer = location
|
||||
}
|
||||
}
|
||||
}
|
||||
case ast.KindClassDeclaration, ast.KindClassExpression, ast.KindInterfaceDeclaration:
|
||||
result = r.lookup(r.getSymbolOfDeclaration(location).Members, name, meaning&ast.SymbolFlagsType)
|
||||
if result != nil {
|
||||
if !isTypeParameterSymbolDeclaredInContainer(result, location) {
|
||||
// ignore type parameters not declared in this container
|
||||
result = nil
|
||||
break
|
||||
}
|
||||
if lastLocation != nil && ast.IsStatic(lastLocation) {
|
||||
// TypeScript 1.0 spec (April 2014): 3.4.1
|
||||
// The scope of a type parameter extends over the entire declaration with which the type
|
||||
// parameter list is associated, with the exception of static member declarations in classes.
|
||||
if nameNotFoundMessage != nil {
|
||||
r.error(originalLocation, diagnostics.Static_members_cannot_reference_class_type_parameters)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
break loop
|
||||
}
|
||||
if ast.IsClassExpression(location) && meaning&ast.SymbolFlagsClass != 0 {
|
||||
className := location.Name()
|
||||
if className != nil && name == className.Text() {
|
||||
result = location.Symbol()
|
||||
break loop
|
||||
}
|
||||
}
|
||||
case ast.KindExpressionWithTypeArguments:
|
||||
if lastLocation == location.Expression() && ast.IsHeritageClause(location.Parent) && location.Parent.AsHeritageClause().Token == ast.KindExtendsKeyword {
|
||||
container := location.Parent.Parent
|
||||
if ast.IsClassLike(container) {
|
||||
result = r.lookup(r.getSymbolOfDeclaration(container).Members, name, meaning&ast.SymbolFlagsType)
|
||||
if result != nil {
|
||||
if nameNotFoundMessage != nil {
|
||||
r.error(originalLocation, diagnostics.Base_class_expressions_cannot_reference_class_type_parameters)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
// It is not legal to reference a class's own type parameters from a computed property name that
|
||||
// belongs to the class. For example:
|
||||
//
|
||||
// function foo<T>() { return '' }
|
||||
// class C<T> { // <-- Class's own type parameter T
|
||||
// [foo<T>()]() { } // <-- Reference to T from class's own computed property
|
||||
// }
|
||||
case ast.KindComputedPropertyName:
|
||||
grandparent = location.Parent.Parent
|
||||
if ast.IsClassLike(grandparent) || ast.IsInterfaceDeclaration(grandparent) {
|
||||
// A reference to this grandparent's type parameters would be an error
|
||||
result = r.lookup(r.getSymbolOfDeclaration(grandparent).Members, name, meaning&ast.SymbolFlagsType)
|
||||
if result != nil {
|
||||
if nameNotFoundMessage != nil {
|
||||
r.error(originalLocation, diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
case ast.KindMethodDeclaration, ast.KindConstructor, ast.KindGetAccessor, ast.KindSetAccessor, ast.KindFunctionDeclaration:
|
||||
if meaning&ast.SymbolFlagsVariable != 0 && name == "arguments" {
|
||||
result = r.argumentsSymbol()
|
||||
break loop
|
||||
}
|
||||
case ast.KindFunctionExpression:
|
||||
if meaning&ast.SymbolFlagsVariable != 0 && name == "arguments" {
|
||||
result = r.argumentsSymbol()
|
||||
break loop
|
||||
}
|
||||
if meaning&ast.SymbolFlagsFunction != 0 {
|
||||
functionName := location.AsFunctionExpression().Name()
|
||||
if functionName != nil && name == functionName.Text() {
|
||||
result = location.Symbol()
|
||||
break loop
|
||||
}
|
||||
}
|
||||
case ast.KindDecorator:
|
||||
// Decorators are resolved at the class declaration. Resolving at the parameter
|
||||
// or member would result in looking up locals in the method.
|
||||
//
|
||||
// function y() {}
|
||||
// class C {
|
||||
// method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter.
|
||||
// }
|
||||
//
|
||||
if location.Parent != nil && location.Parent.Kind == ast.KindParameter {
|
||||
location = location.Parent
|
||||
}
|
||||
// function y() {}
|
||||
// class C {
|
||||
// @y method(x, y) {} // <-- decorator y should be resolved at the class declaration, not the method.
|
||||
// }
|
||||
//
|
||||
// class Decorators are resolved outside of the class to avoid referencing type parameters of that class.
|
||||
//
|
||||
// type T = number;
|
||||
// declare function y(x: T): any;
|
||||
// @param(1 as T) // <-- T should resolve to the type alias outside of class C
|
||||
// class C<T> {}
|
||||
if location.Parent != nil && (ast.IsClassElement(location.Parent) || location.Parent.Kind == ast.KindClassDeclaration) {
|
||||
location = location.Parent
|
||||
}
|
||||
case ast.KindParameter:
|
||||
parameterDeclaration := location.AsParameterDeclaration()
|
||||
if lastLocation != nil && (lastLocation == parameterDeclaration.Initializer ||
|
||||
lastLocation == parameterDeclaration.Name() && ast.IsBindingPattern(lastLocation)) {
|
||||
if associatedDeclarationForContainingInitializerOrBindingName == nil {
|
||||
associatedDeclarationForContainingInitializerOrBindingName = location
|
||||
}
|
||||
}
|
||||
case ast.KindBindingElement:
|
||||
bindingElement := location.AsBindingElement()
|
||||
if lastLocation != nil && (lastLocation == bindingElement.Initializer ||
|
||||
lastLocation == bindingElement.Name() && ast.IsBindingPattern(lastLocation)) {
|
||||
if ast.IsPartOfParameterDeclaration(location) && associatedDeclarationForContainingInitializerOrBindingName == nil {
|
||||
associatedDeclarationForContainingInitializerOrBindingName = location
|
||||
}
|
||||
}
|
||||
case ast.KindInferType:
|
||||
if meaning&ast.SymbolFlagsTypeParameter != 0 {
|
||||
parameterName := location.AsInferTypeNode().TypeParameter.AsTypeParameterDeclaration().Name()
|
||||
if parameterName != nil && name == parameterName.Text() {
|
||||
result = location.AsInferTypeNode().TypeParameter.Symbol()
|
||||
break loop
|
||||
}
|
||||
}
|
||||
case ast.KindExportSpecifier:
|
||||
exportSpecifier := location.AsExportSpecifier()
|
||||
if lastLocation != nil && lastLocation == exportSpecifier.PropertyName && location.Parent.Parent.ModuleSpecifier() != nil {
|
||||
location = location.Parent.Parent.Parent
|
||||
}
|
||||
}
|
||||
if isSelfReferenceLocation(location, lastLocation) {
|
||||
lastSelfReferenceLocation = location
|
||||
}
|
||||
lastLocation = location
|
||||
// !!! In Strada, JSDocTemplateTag/JSDocParameterTag/JSDocReturnTag locations skip to
|
||||
// getEffectiveContainerForJSDocTemplateTag/getHostSignatureFromJSDoc instead of location.parent.
|
||||
// This is a no-op currently because JSDoc nodes have no locals and getEffectiveJSDocHost is not
|
||||
// fully ported for JS assignment patterns.
|
||||
location = location.Parent
|
||||
}
|
||||
// We just climbed up parents looking for the name, meaning that we started in a descendant node of `lastLocation`.
|
||||
// If `result === lastSelfReferenceLocation.symbol`, that means that we are somewhere inside `lastSelfReferenceLocation` looking up a name, and resolving to `lastLocation` itself.
|
||||
// That means that this is a self-reference of `lastLocation`, and shouldn't count this when considering whether `lastLocation` is used.
|
||||
if isUse && result != nil && (lastSelfReferenceLocation == nil || result != lastSelfReferenceLocation.Symbol()) {
|
||||
if r.SymbolReferenced != nil {
|
||||
r.SymbolReferenced(result, meaning)
|
||||
}
|
||||
}
|
||||
if result == nil && !excludeGlobals {
|
||||
result = r.lookup(r.Globals, name, meaning|ast.SymbolFlagsGlobalLookup)
|
||||
}
|
||||
if result == nil {
|
||||
if originalLocation != nil && ast.IsInJSFile(originalLocation) && originalLocation.Parent != nil {
|
||||
if ast.IsRequireCall(originalLocation.Parent, false /*requireStringLiteralLikeArgument*/) {
|
||||
return r.RequireSymbol
|
||||
}
|
||||
}
|
||||
}
|
||||
if nameNotFoundMessage != nil {
|
||||
if propertyWithInvalidInitializer != nil && r.OnPropertyWithInvalidInitializer != nil && r.OnPropertyWithInvalidInitializer(originalLocation, name, propertyWithInvalidInitializer, result) {
|
||||
return nil
|
||||
}
|
||||
if result == nil {
|
||||
if r.OnFailedToResolveSymbol != nil {
|
||||
r.OnFailedToResolveSymbol(originalLocation, name, meaning, nameNotFoundMessage)
|
||||
}
|
||||
} else {
|
||||
if r.OnSuccessfullyResolvedSymbol != nil {
|
||||
r.OnSuccessfullyResolvedSymbol(originalLocation, result, meaning, lastLocation, associatedDeclarationForContainingInitializerOrBindingName, withinDeferredContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (r *NameResolver) useOuterVariableScopeInParameter(result *ast.Symbol, location *ast.Node, lastLocation *ast.Node) bool {
|
||||
if ast.IsParameterDeclaration(lastLocation) {
|
||||
body := location.Body()
|
||||
if body != nil && result.ValueDeclaration != nil && result.ValueDeclaration.Pos() >= body.Pos() && result.ValueDeclaration.End() <= body.End() {
|
||||
// check for several cases where we introduce temporaries that require moving the name/initializer of the parameter to the body
|
||||
// - static field in a class expression
|
||||
// - optional chaining pre-es2020
|
||||
// - nullish coalesce pre-es2020
|
||||
// - spread assignment in binding pattern pre-es2017
|
||||
functionLocation := location
|
||||
declarationRequiresScopeChange := core.TSUnknown
|
||||
if r.GetRequiresScopeChangeCache != nil {
|
||||
declarationRequiresScopeChange = r.GetRequiresScopeChangeCache(functionLocation)
|
||||
}
|
||||
if declarationRequiresScopeChange == core.TSUnknown {
|
||||
declarationRequiresScopeChange = core.IfElse(core.Some(functionLocation.Parameters(), r.requiresScopeChange), core.TSTrue, core.TSFalse)
|
||||
if r.SetRequiresScopeChangeCache != nil {
|
||||
r.SetRequiresScopeChangeCache(functionLocation, declarationRequiresScopeChange)
|
||||
}
|
||||
}
|
||||
return declarationRequiresScopeChange != core.TSTrue
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *NameResolver) requiresScopeChange(node *ast.Node) bool {
|
||||
d := node.AsParameterDeclaration()
|
||||
return r.requiresScopeChangeWorker(d.Name()) || d.Initializer != nil && r.requiresScopeChangeWorker(d.Initializer)
|
||||
}
|
||||
|
||||
func (r *NameResolver) requiresScopeChangeWorker(node *ast.Node) bool {
|
||||
switch node.Kind {
|
||||
case ast.KindArrowFunction, ast.KindFunctionExpression, ast.KindFunctionDeclaration, ast.KindConstructor:
|
||||
return false
|
||||
case ast.KindMethodDeclaration, ast.KindGetAccessor, ast.KindSetAccessor, ast.KindPropertyAssignment:
|
||||
return r.requiresScopeChangeWorker(node.Name())
|
||||
case ast.KindPropertyDeclaration:
|
||||
if ast.HasStaticModifier(node) {
|
||||
return !r.CompilerOptions.GetEmitStandardClassFields()
|
||||
}
|
||||
return r.requiresScopeChangeWorker(node.AsPropertyDeclaration().Name())
|
||||
default:
|
||||
if ast.IsNullishCoalesce(node) || ast.IsOptionalChain(node) {
|
||||
return r.CompilerOptions.GetEmitScriptTarget() < core.ScriptTargetES2020
|
||||
}
|
||||
if ast.IsBindingElement(node) && node.AsBindingElement().DotDotDotToken != nil && ast.IsObjectBindingPattern(node.Parent) {
|
||||
return r.CompilerOptions.GetEmitScriptTarget() < core.ScriptTargetES2017
|
||||
}
|
||||
if ast.IsTypeNode(node) {
|
||||
return false
|
||||
}
|
||||
return node.ForEachChild(r.requiresScopeChangeWorker)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *NameResolver) error(location *ast.Node, message *diagnostics.Message, args ...any) {
|
||||
if r.Error != nil {
|
||||
r.Error(location, message, args...)
|
||||
}
|
||||
// Default implementation does not report errors
|
||||
}
|
||||
|
||||
func (r *NameResolver) getSymbolOfDeclaration(node *ast.Node) *ast.Symbol {
|
||||
if r.GetSymbolOfDeclaration != nil {
|
||||
return r.GetSymbolOfDeclaration(node)
|
||||
}
|
||||
|
||||
// Default implementation does not support merged symbols
|
||||
return node.Symbol()
|
||||
}
|
||||
|
||||
func (r *NameResolver) lookup(symbols ast.SymbolTable, name string, meaning ast.SymbolFlags) *ast.Symbol {
|
||||
if r.Lookup != nil {
|
||||
return r.Lookup(symbols, name, meaning)
|
||||
}
|
||||
// Default implementation does not support following aliases or merged symbols
|
||||
if meaning != 0 {
|
||||
symbol := symbols[name]
|
||||
if symbol != nil {
|
||||
if symbol.Flags&meaning != 0 {
|
||||
return symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *NameResolver) argumentsSymbol() *ast.Symbol {
|
||||
if r.ArgumentsSymbol == nil {
|
||||
// Default implementation synthesizes a transient symbol for `arguments`
|
||||
r.ArgumentsSymbol = &ast.Symbol{Name: "arguments", Flags: ast.SymbolFlagsProperty | ast.SymbolFlagsTransient}
|
||||
}
|
||||
return r.ArgumentsSymbol
|
||||
}
|
||||
|
||||
func GetLocalSymbolForExportDefault(symbol *ast.Symbol) *ast.Symbol {
|
||||
if !isExportDefaultSymbol(symbol) || len(symbol.Declarations) == 0 {
|
||||
return nil
|
||||
}
|
||||
for _, decl := range symbol.Declarations {
|
||||
localSymbol := decl.LocalSymbol()
|
||||
if localSymbol != nil {
|
||||
return localSymbol
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isExportDefaultSymbol(symbol *ast.Symbol) bool {
|
||||
return symbol != nil && len(symbol.Declarations) > 0 && ast.HasSyntacticModifier(symbol.Declarations[0], ast.ModifierFlagsDefault)
|
||||
}
|
||||
|
||||
func getIsDeferredContext(location *ast.Node, lastLocation *ast.Node) bool {
|
||||
if location.Kind != ast.KindArrowFunction && location.Kind != ast.KindFunctionExpression {
|
||||
// initializers in instance property declaration of class like entities are executed in constructor and thus deferred
|
||||
// A name is evaluated within the enclosing scope - so it shouldn't count as deferred
|
||||
return ast.IsTypeQueryNode(location) ||
|
||||
(ast.IsFunctionLikeDeclaration(location) || location.Kind == ast.KindPropertyDeclaration && !ast.IsStatic(location)) &&
|
||||
(lastLocation == nil || lastLocation != location.Name())
|
||||
}
|
||||
if lastLocation != nil && lastLocation == location.Name() {
|
||||
return false
|
||||
}
|
||||
// generator functions and async functions are not inlined in control flow when immediately invoked
|
||||
if location.BodyData().AsteriskToken != nil || ast.HasSyntacticModifier(location, ast.ModifierFlagsAsync) {
|
||||
return true
|
||||
}
|
||||
return ast.GetImmediatelyInvokedFunctionExpression(location) == nil
|
||||
}
|
||||
|
||||
func isTypeParameterSymbolDeclaredInContainer(symbol *ast.Symbol, container *ast.Node) bool {
|
||||
for _, decl := range symbol.Declarations {
|
||||
if decl.Kind == ast.KindTypeParameter {
|
||||
parent := decl.Parent
|
||||
if parent == container {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isSelfReferenceLocation(node *ast.Node, lastLocation *ast.Node) bool {
|
||||
switch node.Kind {
|
||||
case ast.KindParameter:
|
||||
return lastLocation != nil && lastLocation == node.Name()
|
||||
case ast.KindFunctionDeclaration, ast.KindClassDeclaration, ast.KindInterfaceDeclaration, ast.KindEnumDeclaration,
|
||||
ast.KindTypeAliasDeclaration, ast.KindJSTypeAliasDeclaration, ast.KindModuleDeclaration: // For `namespace N { N; }`
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
262
tools/tsgo/internal/binder/referenceresolver.go
Normal file
262
tools/tsgo/internal/binder/referenceresolver.go
Normal file
@@ -0,0 +1,262 @@
|
||||
package binder
|
||||
|
||||
import (
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/diagnostics"
|
||||
)
|
||||
|
||||
type ReferenceResolver interface {
|
||||
GetReferencedExportContainer(node *ast.IdentifierNode, prefixLocals bool) *ast.Node
|
||||
GetReferencedImportDeclaration(node *ast.IdentifierNode) *ast.Declaration
|
||||
GetReferencedValueDeclaration(node *ast.IdentifierNode) *ast.Declaration
|
||||
GetReferencedValueDeclarations(node *ast.IdentifierNode) []*ast.Declaration
|
||||
GetElementAccessExpressionName(expression *ast.ElementAccessExpression) string
|
||||
GetReferencedMemberValueDeclaration(node *ast.Node) *ast.Declaration
|
||||
}
|
||||
|
||||
type ReferenceResolverHooks struct {
|
||||
ResolveName func(location *ast.Node, name string, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message, isUse bool, excludeGlobals bool) *ast.Symbol
|
||||
GetResolvedSymbol func(*ast.Node) *ast.Symbol
|
||||
GetMergedSymbol func(*ast.Symbol) *ast.Symbol
|
||||
GetParentOfSymbol func(*ast.Symbol) *ast.Symbol
|
||||
GetSymbolOfDeclaration func(*ast.Declaration) *ast.Symbol
|
||||
GetTypeOnlyAliasDeclaration func(symbol *ast.Symbol, include ast.SymbolFlags) *ast.Declaration
|
||||
GetExportSymbolOfValueSymbolIfExported func(*ast.Symbol) *ast.Symbol
|
||||
GetElementAccessExpressionName func(*ast.ElementAccessExpression) (string, bool)
|
||||
}
|
||||
|
||||
var _ ReferenceResolver = &referenceResolver{}
|
||||
|
||||
type referenceResolver struct {
|
||||
resolver *NameResolver
|
||||
options *core.CompilerOptions
|
||||
hooks ReferenceResolverHooks
|
||||
}
|
||||
|
||||
func NewReferenceResolver(options *core.CompilerOptions, hooks ReferenceResolverHooks) ReferenceResolver {
|
||||
return &referenceResolver{
|
||||
options: options,
|
||||
hooks: hooks,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *referenceResolver) getResolvedSymbol(node *ast.Node) *ast.Symbol {
|
||||
if node != nil {
|
||||
if r.hooks.GetResolvedSymbol != nil {
|
||||
return r.hooks.GetResolvedSymbol(node)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *referenceResolver) getMergedSymbol(symbol *ast.Symbol) *ast.Symbol {
|
||||
if symbol != nil {
|
||||
if r.hooks.GetMergedSymbol != nil {
|
||||
return r.hooks.GetMergedSymbol(symbol)
|
||||
}
|
||||
return symbol
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *referenceResolver) getParentOfSymbol(symbol *ast.Symbol) *ast.Symbol {
|
||||
if symbol != nil {
|
||||
if r.hooks.GetParentOfSymbol != nil {
|
||||
return r.hooks.GetParentOfSymbol(symbol)
|
||||
}
|
||||
return symbol.Parent
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *referenceResolver) getSymbolOfDeclaration(declaration *ast.Declaration) *ast.Symbol {
|
||||
if declaration != nil {
|
||||
if r.hooks.GetSymbolOfDeclaration != nil {
|
||||
return r.hooks.GetSymbolOfDeclaration(declaration)
|
||||
}
|
||||
return declaration.Symbol()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *referenceResolver) getReferencedValueSymbol(reference *ast.IdentifierNode, startInDeclarationContainer bool) *ast.Symbol {
|
||||
resolvedSymbol := r.getResolvedSymbol(reference)
|
||||
if resolvedSymbol != nil {
|
||||
return resolvedSymbol
|
||||
}
|
||||
|
||||
location := reference
|
||||
if startInDeclarationContainer && reference.Parent != nil && ast.IsDeclaration(reference.Parent) && reference.Parent.Name() == reference {
|
||||
location = ast.GetDeclarationContainer(reference.Parent)
|
||||
}
|
||||
|
||||
if r.hooks.ResolveName != nil {
|
||||
return r.hooks.ResolveName(location, reference.Text(), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/)
|
||||
}
|
||||
|
||||
if r.resolver == nil {
|
||||
r.resolver = &NameResolver{
|
||||
CompilerOptions: r.options,
|
||||
}
|
||||
}
|
||||
|
||||
return r.resolver.Resolve(location, reference.Text(), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/)
|
||||
}
|
||||
|
||||
func (r *referenceResolver) isTypeOnlyAliasDeclaration(symbol *ast.Symbol) bool {
|
||||
if symbol != nil {
|
||||
if r.hooks.GetTypeOnlyAliasDeclaration != nil {
|
||||
return r.hooks.GetTypeOnlyAliasDeclaration(symbol, ast.SymbolFlagsValue) != nil
|
||||
}
|
||||
|
||||
node := r.getDeclarationOfAliasSymbol(symbol)
|
||||
for node != nil {
|
||||
switch node.Kind {
|
||||
case ast.KindImportEqualsDeclaration, ast.KindExportDeclaration:
|
||||
return node.IsTypeOnly()
|
||||
case ast.KindImportClause, ast.KindImportSpecifier, ast.KindExportSpecifier:
|
||||
if node.IsTypeOnly() {
|
||||
return true
|
||||
}
|
||||
node = node.Parent
|
||||
continue
|
||||
case ast.KindNamedImports, ast.KindNamedExports:
|
||||
node = node.Parent
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *referenceResolver) getDeclarationOfAliasSymbol(symbol *ast.Symbol) *ast.Declaration {
|
||||
return core.FindLast(symbol.Declarations, ast.IsAliasSymbolDeclaration)
|
||||
}
|
||||
|
||||
func (r *referenceResolver) getExportSymbolOfValueSymbolIfExported(symbol *ast.Symbol) *ast.Symbol {
|
||||
if symbol != nil {
|
||||
if r.hooks.GetExportSymbolOfValueSymbolIfExported != nil {
|
||||
return r.hooks.GetExportSymbolOfValueSymbolIfExported(symbol)
|
||||
}
|
||||
if symbol.Flags&ast.SymbolFlagsExportValue != 0 && symbol.ExportSymbol != nil {
|
||||
symbol = symbol.ExportSymbol
|
||||
}
|
||||
return r.getMergedSymbol(symbol)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *referenceResolver) GetReferencedExportContainer(node *ast.IdentifierNode, prefixLocals bool) *ast.Node /*SourceFile|ModuleDeclaration|EnumDeclaration*/ {
|
||||
// When resolving the export for the name of a module or enum
|
||||
// declaration, we need to start resolution at the declaration's container.
|
||||
// Otherwise, we could incorrectly resolve the export as the
|
||||
// declaration if it contains an exported member with the same name.
|
||||
startInDeclarationContainer := node.Parent != nil && (node.Parent.Kind == ast.KindModuleDeclaration || node.Parent.Kind == ast.KindEnumDeclaration) && node == node.Parent.Name()
|
||||
if symbol := r.getReferencedValueSymbol(node, startInDeclarationContainer); symbol != nil {
|
||||
if symbol.Flags&ast.SymbolFlagsExportValue != 0 {
|
||||
// If we reference an exported entity within the same module declaration, then whether
|
||||
// we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the
|
||||
// kinds that we do NOT prefix.
|
||||
exportSymbol := r.getMergedSymbol(symbol.ExportSymbol)
|
||||
if !prefixLocals && exportSymbol.Flags&ast.SymbolFlagsExportHasLocal != 0 && exportSymbol.Flags&ast.SymbolFlagsVariable == 0 {
|
||||
return nil
|
||||
}
|
||||
symbol = exportSymbol
|
||||
}
|
||||
parentSymbol := r.getParentOfSymbol(symbol)
|
||||
if parentSymbol != nil {
|
||||
if parentSymbol.Flags&ast.SymbolFlagsValueModule != 0 && parentSymbol.ValueDeclaration != nil && parentSymbol.ValueDeclaration.Kind == ast.KindSourceFile {
|
||||
symbolFile := parentSymbol.ValueDeclaration.AsSourceFile()
|
||||
referenceFile := ast.GetSourceFileOfNode(node)
|
||||
// If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return nil.
|
||||
symbolIsUmdExport := symbolFile != referenceFile
|
||||
if symbolIsUmdExport {
|
||||
return nil
|
||||
}
|
||||
return symbolFile.AsNode()
|
||||
}
|
||||
isMatchingContainer := func(n *ast.Node) bool {
|
||||
return (n.Kind == ast.KindModuleDeclaration || n.Kind == ast.KindEnumDeclaration) && r.getSymbolOfDeclaration(n) == parentSymbol
|
||||
}
|
||||
return ast.FindAncestor(node.Parent, isMatchingContainer)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *referenceResolver) GetReferencedImportDeclaration(node *ast.IdentifierNode) *ast.Declaration {
|
||||
if symbol := r.getReferencedValueSymbol(node, false /*startInDeclarationContainer*/); symbol != nil {
|
||||
// We should only get the declaration of an alias if there isn't a local value
|
||||
// declaration for the symbol
|
||||
if ast.IsNonLocalAlias(symbol, ast.SymbolFlagsValue /*excludes*/) && !r.isTypeOnlyAliasDeclaration(symbol) {
|
||||
return r.getDeclarationOfAliasSymbol(symbol)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *referenceResolver) GetReferencedValueDeclaration(node *ast.IdentifierNode) *ast.Declaration {
|
||||
if symbol := r.getReferencedValueSymbol(node, false /*startInDeclarationContainer*/); symbol != nil {
|
||||
return r.getExportSymbolOfValueSymbolIfExported(symbol).ValueDeclaration
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *referenceResolver) GetReferencedValueDeclarations(node *ast.IdentifierNode) []*ast.Declaration {
|
||||
var declarations []*ast.Declaration
|
||||
if symbol := r.getReferencedValueSymbol(node, false /*startInDeclarationContainer*/); symbol != nil {
|
||||
symbol = r.getExportSymbolOfValueSymbolIfExported(symbol)
|
||||
for _, declaration := range symbol.Declarations {
|
||||
switch declaration.Kind {
|
||||
case ast.KindVariableDeclaration,
|
||||
ast.KindParameter,
|
||||
ast.KindBindingElement,
|
||||
ast.KindPropertyDeclaration,
|
||||
ast.KindPropertyAssignment,
|
||||
ast.KindShorthandPropertyAssignment,
|
||||
ast.KindEnumMember,
|
||||
ast.KindObjectLiteralExpression,
|
||||
ast.KindFunctionDeclaration,
|
||||
ast.KindFunctionExpression,
|
||||
ast.KindArrowFunction,
|
||||
ast.KindClassDeclaration,
|
||||
ast.KindClassExpression,
|
||||
ast.KindEnumDeclaration,
|
||||
ast.KindMethodDeclaration,
|
||||
ast.KindGetAccessor,
|
||||
ast.KindSetAccessor,
|
||||
ast.KindModuleDeclaration:
|
||||
declarations = append(declarations, declaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
return declarations
|
||||
}
|
||||
|
||||
func (r *referenceResolver) GetElementAccessExpressionName(expression *ast.ElementAccessExpression) string {
|
||||
if expression != nil {
|
||||
if r.hooks.GetElementAccessExpressionName != nil {
|
||||
if name, ok := r.hooks.GetElementAccessExpressionName(expression); ok {
|
||||
return name
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *referenceResolver) GetReferencedMemberValueDeclaration(node *ast.Node) *ast.Declaration {
|
||||
// member references are `this.something` or `this[something]`, so should always simply have a resolved symbol
|
||||
s := r.getResolvedSymbol(node)
|
||||
if s == nil && node.Symbol() != nil {
|
||||
// might be a declaration instead of a ref, get the merged declaration symbol
|
||||
s = r.getMergedSymbol(node.Symbol())
|
||||
}
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
return r.getExportSymbolOfValueSymbolIfExported(s).ValueDeclaration
|
||||
}
|
||||
53
tools/tsgo/internal/bundled/bundled.go
Normal file
53
tools/tsgo/internal/bundled/bundled.go
Normal file
@@ -0,0 +1,53 @@
|
||||
// Package bundled provides access to files bundled with TypeScript.
|
||||
package bundled
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/tspath"
|
||||
"github.com/microsoft/typescript-go/internal/vfs"
|
||||
)
|
||||
|
||||
//go:generate go run generate.go
|
||||
|
||||
// Define the below here to consolidate documentation.
|
||||
|
||||
// Embedded is true if the bundled files are implemented through an embedded FS.
|
||||
const Embedded = embedded
|
||||
|
||||
// WrapFS returns an FS which redirects embedded paths to the embedded file system.
|
||||
// If the embedded file system is not available, it returns the original FS.
|
||||
func WrapFS(fs vfs.FS) vfs.FS {
|
||||
return wrapFS(fs)
|
||||
}
|
||||
|
||||
// LibPath returns the path to the directory containing the bundled lib.d.ts files.
|
||||
// If embedding is not enabled, this is a path on disk, and must be accessed through
|
||||
// a real OS filesystem.
|
||||
func LibPath() string {
|
||||
return libPath()
|
||||
}
|
||||
|
||||
var bundledSourceDir = sync.OnceValue(func() string {
|
||||
_, filename, _, ok := runtime.Caller(0)
|
||||
if !ok {
|
||||
panic("bundled: could not get current filename")
|
||||
}
|
||||
return filepath.Dir(filepath.FromSlash(filename))
|
||||
})
|
||||
|
||||
var testingLibPath = sync.OnceValue(func() string {
|
||||
if !testing.Testing() {
|
||||
panic("bundled: TestingLibPath should only be called during tests")
|
||||
}
|
||||
return tspath.NormalizeSlashes(filepath.Join(bundledSourceDir(), "libs"))
|
||||
})
|
||||
|
||||
// TestingLibPath returns the path to the source bundled libs directory.
|
||||
// It's only valid to use in tests where the source code is available.
|
||||
func TestingLibPath() string {
|
||||
return testingLibPath()
|
||||
}
|
||||
48
tools/tsgo/internal/bundled/bundled_test.go
Normal file
48
tools/tsgo/internal/bundled/bundled_test.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package bundled_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/bundled"
|
||||
"github.com/microsoft/typescript-go/internal/tspath"
|
||||
"github.com/microsoft/typescript-go/internal/vfs"
|
||||
"github.com/microsoft/typescript-go/internal/vfs/osvfs"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestTestingLibPath(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
p := bundled.TestingLibPath()
|
||||
|
||||
_, err := os.Stat(p)
|
||||
assert.NilError(t, err)
|
||||
|
||||
libdts := filepath.Join(p, "lib.d.ts")
|
||||
|
||||
_, err = os.Stat(libdts)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestEmbeddedLibs(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := bundled.WrapFS(osvfs.FS())
|
||||
|
||||
var files []string
|
||||
|
||||
err := fs.WalkDir(bundled.LibPath(), func(path string, d vfs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !d.IsDir() {
|
||||
files = append(files, tspath.GetBaseFileName(path))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.DeepEqual(t, files, bundled.LibNames)
|
||||
}
|
||||
224
tools/tsgo/internal/bundled/embed.go
Normal file
224
tools/tsgo/internal/bundled/embed.go
Normal file
@@ -0,0 +1,224 @@
|
||||
//go:build !noembed
|
||||
|
||||
package bundled
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/vfs"
|
||||
)
|
||||
|
||||
const embedded = true
|
||||
|
||||
const scheme = "bundled:///"
|
||||
|
||||
func splitPath(path string) (rest string, ok bool) {
|
||||
return strings.CutPrefix(path, scheme)
|
||||
}
|
||||
|
||||
func libPath() string {
|
||||
return scheme + "libs"
|
||||
}
|
||||
|
||||
func IsBundled(path string) bool {
|
||||
_, ok := splitPath(path)
|
||||
return ok
|
||||
}
|
||||
|
||||
// wrappedFS is implemented directly rather than going through [io/fs.FS].
|
||||
// Our vfs.FS works with file contents in terms of strings, and that's
|
||||
// what go:embed does under the hood, but going through fs.FS will cause
|
||||
// copying to []byte and back.
|
||||
|
||||
type wrappedFS struct {
|
||||
fs vfs.FS
|
||||
}
|
||||
|
||||
var _ vfs.FS = (*wrappedFS)(nil)
|
||||
|
||||
func wrapFS(fs vfs.FS) vfs.FS {
|
||||
return &wrappedFS{fs: fs}
|
||||
}
|
||||
|
||||
func (vfs *wrappedFS) UseCaseSensitiveFileNames() bool {
|
||||
return vfs.fs.UseCaseSensitiveFileNames()
|
||||
}
|
||||
|
||||
func (vfs *wrappedFS) FileExists(path string) bool {
|
||||
if rest, ok := splitPath(path); ok {
|
||||
_, ok := embeddedContents[rest]
|
||||
return ok
|
||||
}
|
||||
return vfs.fs.FileExists(path)
|
||||
}
|
||||
|
||||
func (vfs *wrappedFS) ReadFile(path string) (contents string, ok bool) {
|
||||
if rest, ok := splitPath(path); ok {
|
||||
contents, ok = embeddedContents[rest]
|
||||
return contents, ok
|
||||
}
|
||||
return vfs.fs.ReadFile(path)
|
||||
}
|
||||
|
||||
func (vfs *wrappedFS) DirectoryExists(path string) bool {
|
||||
if rest, ok := splitPath(path); ok {
|
||||
return rest == "libs"
|
||||
}
|
||||
return vfs.fs.DirectoryExists(path)
|
||||
}
|
||||
|
||||
func (vfs *wrappedFS) GetAccessibleEntries(path string) (result vfs.Entries) {
|
||||
if rest, ok := splitPath(path); ok {
|
||||
if rest == "" {
|
||||
result.Directories = []string{"libs"}
|
||||
} else if rest == "libs" {
|
||||
result.Files = LibNames
|
||||
}
|
||||
return result
|
||||
}
|
||||
return vfs.fs.GetAccessibleEntries(path)
|
||||
}
|
||||
|
||||
var rootEntries = []fs.DirEntry{
|
||||
fs.FileInfoToDirEntry(&fileInfo{name: "libs", mode: fs.ModeDir}),
|
||||
}
|
||||
|
||||
func (vfs *wrappedFS) Stat(path string) vfs.FileInfo {
|
||||
if rest, ok := splitPath(path); ok {
|
||||
if rest == "" || rest == "libs" {
|
||||
return &fileInfo{name: rest, mode: fs.ModeDir}
|
||||
}
|
||||
if lib, ok := embeddedContents[rest]; ok {
|
||||
libName, _ := strings.CutPrefix(rest, "libs/")
|
||||
return &fileInfo{name: libName, size: int64(len(lib))}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return vfs.fs.Stat(path)
|
||||
}
|
||||
|
||||
func (vfs *wrappedFS) WalkDir(root string, walkFn vfs.WalkDirFunc) error {
|
||||
if rest, ok := splitPath(root); ok {
|
||||
if err := vfs.walkDir(rest, walkFn); err != nil {
|
||||
if err == fs.SkipAll { //nolint:errorlint
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return vfs.fs.WalkDir(root, walkFn)
|
||||
}
|
||||
|
||||
func (vfs *wrappedFS) walkDir(rest string, walkFn vfs.WalkDirFunc) error {
|
||||
var entries []fs.DirEntry
|
||||
switch rest {
|
||||
case "":
|
||||
entries = rootEntries
|
||||
case "libs":
|
||||
entries = libsEntries
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
name := rest + "/" + entry.Name()
|
||||
|
||||
if err := walkFn(scheme+name, entry, nil); err != nil {
|
||||
if err == fs.SkipAll { //nolint:errorlint
|
||||
return fs.SkipAll
|
||||
}
|
||||
if err == fs.SkipDir { //nolint:errorlint
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
if entry.IsDir() {
|
||||
if err := vfs.walkDir(strings.TrimPrefix(name, "/"), walkFn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vfs *wrappedFS) Realpath(path string) string {
|
||||
if _, ok := splitPath(path); ok {
|
||||
return path
|
||||
}
|
||||
return vfs.fs.Realpath(path)
|
||||
}
|
||||
|
||||
func (vfs *wrappedFS) WriteFile(path string, data string) error {
|
||||
if _, ok := splitPath(path); ok {
|
||||
panic("cannot write to embedded file system")
|
||||
}
|
||||
return vfs.fs.WriteFile(path, data)
|
||||
}
|
||||
|
||||
func (vfs *wrappedFS) AppendFile(path string, data string) error {
|
||||
if _, ok := splitPath(path); ok {
|
||||
panic("cannot write to embedded file system")
|
||||
}
|
||||
return vfs.fs.AppendFile(path, data)
|
||||
}
|
||||
|
||||
func (vfs *wrappedFS) Remove(path string) error {
|
||||
if _, ok := splitPath(path); ok {
|
||||
panic("cannot remove from embedded file system")
|
||||
}
|
||||
return vfs.fs.Remove(path)
|
||||
}
|
||||
|
||||
func (vfs *wrappedFS) Chtimes(path string, aTime time.Time, mTime time.Time) error {
|
||||
if _, ok := splitPath(path); ok {
|
||||
panic("cannot change times on embedded file system")
|
||||
}
|
||||
return vfs.fs.Chtimes(path, aTime, mTime)
|
||||
}
|
||||
|
||||
type fileInfo struct {
|
||||
mode fs.FileMode
|
||||
name string
|
||||
size int64
|
||||
}
|
||||
|
||||
var (
|
||||
_ fs.FileInfo = (*fileInfo)(nil)
|
||||
_ fs.DirEntry = (*fileInfo)(nil)
|
||||
)
|
||||
|
||||
func (fi *fileInfo) IsDir() bool {
|
||||
return fi.mode.IsDir()
|
||||
}
|
||||
|
||||
func (fi *fileInfo) ModTime() time.Time {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (fi *fileInfo) Mode() fs.FileMode {
|
||||
return fi.mode
|
||||
}
|
||||
|
||||
func (fi *fileInfo) Name() string {
|
||||
return fi.name
|
||||
}
|
||||
|
||||
func (fi *fileInfo) Size() int64 {
|
||||
return fi.size
|
||||
}
|
||||
|
||||
func (fi *fileInfo) Sys() any {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fi *fileInfo) Info() (fs.FileInfo, error) {
|
||||
return fi, nil
|
||||
}
|
||||
|
||||
func (fi *fileInfo) Type() fs.FileMode {
|
||||
return fi.mode.Type()
|
||||
}
|
||||
452
tools/tsgo/internal/bundled/embed_generated.go
Normal file
452
tools/tsgo/internal/bundled/embed_generated.go
Normal file
@@ -0,0 +1,452 @@
|
||||
//go:build !noembed
|
||||
|
||||
// Code generated by generate.go; DO NOT EDIT.
|
||||
|
||||
package bundled
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
|
||||
_ "embed"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed libs/lib.d.ts
|
||||
libs_lib_d_ts string
|
||||
//go:embed libs/lib.decorators.d.ts
|
||||
libs_lib_decorators_d_ts string
|
||||
//go:embed libs/lib.decorators.legacy.d.ts
|
||||
libs_lib_decorators_legacy_d_ts string
|
||||
//go:embed libs/lib.dom.asynciterable.d.ts
|
||||
libs_lib_dom_asynciterable_d_ts string
|
||||
//go:embed libs/lib.dom.d.ts
|
||||
libs_lib_dom_d_ts string
|
||||
//go:embed libs/lib.dom.iterable.d.ts
|
||||
libs_lib_dom_iterable_d_ts string
|
||||
//go:embed libs/lib.es2015.collection.d.ts
|
||||
libs_lib_es2015_collection_d_ts string
|
||||
//go:embed libs/lib.es2015.core.d.ts
|
||||
libs_lib_es2015_core_d_ts string
|
||||
//go:embed libs/lib.es2015.d.ts
|
||||
libs_lib_es2015_d_ts string
|
||||
//go:embed libs/lib.es2015.generator.d.ts
|
||||
libs_lib_es2015_generator_d_ts string
|
||||
//go:embed libs/lib.es2015.iterable.d.ts
|
||||
libs_lib_es2015_iterable_d_ts string
|
||||
//go:embed libs/lib.es2015.promise.d.ts
|
||||
libs_lib_es2015_promise_d_ts string
|
||||
//go:embed libs/lib.es2015.proxy.d.ts
|
||||
libs_lib_es2015_proxy_d_ts string
|
||||
//go:embed libs/lib.es2015.reflect.d.ts
|
||||
libs_lib_es2015_reflect_d_ts string
|
||||
//go:embed libs/lib.es2015.symbol.d.ts
|
||||
libs_lib_es2015_symbol_d_ts string
|
||||
//go:embed libs/lib.es2015.symbol.wellknown.d.ts
|
||||
libs_lib_es2015_symbol_wellknown_d_ts string
|
||||
//go:embed libs/lib.es2016.array.include.d.ts
|
||||
libs_lib_es2016_array_include_d_ts string
|
||||
//go:embed libs/lib.es2016.d.ts
|
||||
libs_lib_es2016_d_ts string
|
||||
//go:embed libs/lib.es2016.full.d.ts
|
||||
libs_lib_es2016_full_d_ts string
|
||||
//go:embed libs/lib.es2016.intl.d.ts
|
||||
libs_lib_es2016_intl_d_ts string
|
||||
//go:embed libs/lib.es2017.arraybuffer.d.ts
|
||||
libs_lib_es2017_arraybuffer_d_ts string
|
||||
//go:embed libs/lib.es2017.d.ts
|
||||
libs_lib_es2017_d_ts string
|
||||
//go:embed libs/lib.es2017.date.d.ts
|
||||
libs_lib_es2017_date_d_ts string
|
||||
//go:embed libs/lib.es2017.full.d.ts
|
||||
libs_lib_es2017_full_d_ts string
|
||||
//go:embed libs/lib.es2017.intl.d.ts
|
||||
libs_lib_es2017_intl_d_ts string
|
||||
//go:embed libs/lib.es2017.object.d.ts
|
||||
libs_lib_es2017_object_d_ts string
|
||||
//go:embed libs/lib.es2017.sharedmemory.d.ts
|
||||
libs_lib_es2017_sharedmemory_d_ts string
|
||||
//go:embed libs/lib.es2017.string.d.ts
|
||||
libs_lib_es2017_string_d_ts string
|
||||
//go:embed libs/lib.es2017.typedarrays.d.ts
|
||||
libs_lib_es2017_typedarrays_d_ts string
|
||||
//go:embed libs/lib.es2018.asyncgenerator.d.ts
|
||||
libs_lib_es2018_asyncgenerator_d_ts string
|
||||
//go:embed libs/lib.es2018.asynciterable.d.ts
|
||||
libs_lib_es2018_asynciterable_d_ts string
|
||||
//go:embed libs/lib.es2018.d.ts
|
||||
libs_lib_es2018_d_ts string
|
||||
//go:embed libs/lib.es2018.full.d.ts
|
||||
libs_lib_es2018_full_d_ts string
|
||||
//go:embed libs/lib.es2018.intl.d.ts
|
||||
libs_lib_es2018_intl_d_ts string
|
||||
//go:embed libs/lib.es2018.promise.d.ts
|
||||
libs_lib_es2018_promise_d_ts string
|
||||
//go:embed libs/lib.es2018.regexp.d.ts
|
||||
libs_lib_es2018_regexp_d_ts string
|
||||
//go:embed libs/lib.es2019.array.d.ts
|
||||
libs_lib_es2019_array_d_ts string
|
||||
//go:embed libs/lib.es2019.d.ts
|
||||
libs_lib_es2019_d_ts string
|
||||
//go:embed libs/lib.es2019.full.d.ts
|
||||
libs_lib_es2019_full_d_ts string
|
||||
//go:embed libs/lib.es2019.intl.d.ts
|
||||
libs_lib_es2019_intl_d_ts string
|
||||
//go:embed libs/lib.es2019.object.d.ts
|
||||
libs_lib_es2019_object_d_ts string
|
||||
//go:embed libs/lib.es2019.string.d.ts
|
||||
libs_lib_es2019_string_d_ts string
|
||||
//go:embed libs/lib.es2019.symbol.d.ts
|
||||
libs_lib_es2019_symbol_d_ts string
|
||||
//go:embed libs/lib.es2020.bigint.d.ts
|
||||
libs_lib_es2020_bigint_d_ts string
|
||||
//go:embed libs/lib.es2020.d.ts
|
||||
libs_lib_es2020_d_ts string
|
||||
//go:embed libs/lib.es2020.date.d.ts
|
||||
libs_lib_es2020_date_d_ts string
|
||||
//go:embed libs/lib.es2020.full.d.ts
|
||||
libs_lib_es2020_full_d_ts string
|
||||
//go:embed libs/lib.es2020.intl.d.ts
|
||||
libs_lib_es2020_intl_d_ts string
|
||||
//go:embed libs/lib.es2020.number.d.ts
|
||||
libs_lib_es2020_number_d_ts string
|
||||
//go:embed libs/lib.es2020.promise.d.ts
|
||||
libs_lib_es2020_promise_d_ts string
|
||||
//go:embed libs/lib.es2020.sharedmemory.d.ts
|
||||
libs_lib_es2020_sharedmemory_d_ts string
|
||||
//go:embed libs/lib.es2020.string.d.ts
|
||||
libs_lib_es2020_string_d_ts string
|
||||
//go:embed libs/lib.es2020.symbol.wellknown.d.ts
|
||||
libs_lib_es2020_symbol_wellknown_d_ts string
|
||||
//go:embed libs/lib.es2021.d.ts
|
||||
libs_lib_es2021_d_ts string
|
||||
//go:embed libs/lib.es2021.full.d.ts
|
||||
libs_lib_es2021_full_d_ts string
|
||||
//go:embed libs/lib.es2021.intl.d.ts
|
||||
libs_lib_es2021_intl_d_ts string
|
||||
//go:embed libs/lib.es2021.promise.d.ts
|
||||
libs_lib_es2021_promise_d_ts string
|
||||
//go:embed libs/lib.es2021.string.d.ts
|
||||
libs_lib_es2021_string_d_ts string
|
||||
//go:embed libs/lib.es2021.weakref.d.ts
|
||||
libs_lib_es2021_weakref_d_ts string
|
||||
//go:embed libs/lib.es2022.array.d.ts
|
||||
libs_lib_es2022_array_d_ts string
|
||||
//go:embed libs/lib.es2022.d.ts
|
||||
libs_lib_es2022_d_ts string
|
||||
//go:embed libs/lib.es2022.error.d.ts
|
||||
libs_lib_es2022_error_d_ts string
|
||||
//go:embed libs/lib.es2022.full.d.ts
|
||||
libs_lib_es2022_full_d_ts string
|
||||
//go:embed libs/lib.es2022.intl.d.ts
|
||||
libs_lib_es2022_intl_d_ts string
|
||||
//go:embed libs/lib.es2022.object.d.ts
|
||||
libs_lib_es2022_object_d_ts string
|
||||
//go:embed libs/lib.es2022.regexp.d.ts
|
||||
libs_lib_es2022_regexp_d_ts string
|
||||
//go:embed libs/lib.es2022.string.d.ts
|
||||
libs_lib_es2022_string_d_ts string
|
||||
//go:embed libs/lib.es2023.array.d.ts
|
||||
libs_lib_es2023_array_d_ts string
|
||||
//go:embed libs/lib.es2023.collection.d.ts
|
||||
libs_lib_es2023_collection_d_ts string
|
||||
//go:embed libs/lib.es2023.d.ts
|
||||
libs_lib_es2023_d_ts string
|
||||
//go:embed libs/lib.es2023.full.d.ts
|
||||
libs_lib_es2023_full_d_ts string
|
||||
//go:embed libs/lib.es2023.intl.d.ts
|
||||
libs_lib_es2023_intl_d_ts string
|
||||
//go:embed libs/lib.es2024.arraybuffer.d.ts
|
||||
libs_lib_es2024_arraybuffer_d_ts string
|
||||
//go:embed libs/lib.es2024.collection.d.ts
|
||||
libs_lib_es2024_collection_d_ts string
|
||||
//go:embed libs/lib.es2024.d.ts
|
||||
libs_lib_es2024_d_ts string
|
||||
//go:embed libs/lib.es2024.full.d.ts
|
||||
libs_lib_es2024_full_d_ts string
|
||||
//go:embed libs/lib.es2024.object.d.ts
|
||||
libs_lib_es2024_object_d_ts string
|
||||
//go:embed libs/lib.es2024.promise.d.ts
|
||||
libs_lib_es2024_promise_d_ts string
|
||||
//go:embed libs/lib.es2024.regexp.d.ts
|
||||
libs_lib_es2024_regexp_d_ts string
|
||||
//go:embed libs/lib.es2024.sharedmemory.d.ts
|
||||
libs_lib_es2024_sharedmemory_d_ts string
|
||||
//go:embed libs/lib.es2024.string.d.ts
|
||||
libs_lib_es2024_string_d_ts string
|
||||
//go:embed libs/lib.es2025.collection.d.ts
|
||||
libs_lib_es2025_collection_d_ts string
|
||||
//go:embed libs/lib.es2025.d.ts
|
||||
libs_lib_es2025_d_ts string
|
||||
//go:embed libs/lib.es2025.float16.d.ts
|
||||
libs_lib_es2025_float16_d_ts string
|
||||
//go:embed libs/lib.es2025.full.d.ts
|
||||
libs_lib_es2025_full_d_ts string
|
||||
//go:embed libs/lib.es2025.intl.d.ts
|
||||
libs_lib_es2025_intl_d_ts string
|
||||
//go:embed libs/lib.es2025.iterator.d.ts
|
||||
libs_lib_es2025_iterator_d_ts string
|
||||
//go:embed libs/lib.es2025.promise.d.ts
|
||||
libs_lib_es2025_promise_d_ts string
|
||||
//go:embed libs/lib.es2025.regexp.d.ts
|
||||
libs_lib_es2025_regexp_d_ts string
|
||||
//go:embed libs/lib.es5.d.ts
|
||||
libs_lib_es5_d_ts string
|
||||
//go:embed libs/lib.es6.d.ts
|
||||
libs_lib_es6_d_ts string
|
||||
//go:embed libs/lib.esnext.array.d.ts
|
||||
libs_lib_esnext_array_d_ts string
|
||||
//go:embed libs/lib.esnext.collection.d.ts
|
||||
libs_lib_esnext_collection_d_ts string
|
||||
//go:embed libs/lib.esnext.d.ts
|
||||
libs_lib_esnext_d_ts string
|
||||
//go:embed libs/lib.esnext.date.d.ts
|
||||
libs_lib_esnext_date_d_ts string
|
||||
//go:embed libs/lib.esnext.decorators.d.ts
|
||||
libs_lib_esnext_decorators_d_ts string
|
||||
//go:embed libs/lib.esnext.disposable.d.ts
|
||||
libs_lib_esnext_disposable_d_ts string
|
||||
//go:embed libs/lib.esnext.error.d.ts
|
||||
libs_lib_esnext_error_d_ts string
|
||||
//go:embed libs/lib.esnext.full.d.ts
|
||||
libs_lib_esnext_full_d_ts string
|
||||
//go:embed libs/lib.esnext.intl.d.ts
|
||||
libs_lib_esnext_intl_d_ts string
|
||||
//go:embed libs/lib.esnext.sharedmemory.d.ts
|
||||
libs_lib_esnext_sharedmemory_d_ts string
|
||||
//go:embed libs/lib.esnext.temporal.d.ts
|
||||
libs_lib_esnext_temporal_d_ts string
|
||||
//go:embed libs/lib.esnext.typedarrays.d.ts
|
||||
libs_lib_esnext_typedarrays_d_ts string
|
||||
//go:embed libs/lib.scripthost.d.ts
|
||||
libs_lib_scripthost_d_ts string
|
||||
//go:embed libs/lib.webworker.asynciterable.d.ts
|
||||
libs_lib_webworker_asynciterable_d_ts string
|
||||
//go:embed libs/lib.webworker.d.ts
|
||||
libs_lib_webworker_d_ts string
|
||||
//go:embed libs/lib.webworker.importscripts.d.ts
|
||||
libs_lib_webworker_importscripts_d_ts string
|
||||
//go:embed libs/lib.webworker.iterable.d.ts
|
||||
libs_lib_webworker_iterable_d_ts string
|
||||
)
|
||||
|
||||
var embeddedContents = map[string]string{
|
||||
"libs/lib.d.ts": libs_lib_d_ts,
|
||||
"libs/lib.decorators.d.ts": libs_lib_decorators_d_ts,
|
||||
"libs/lib.decorators.legacy.d.ts": libs_lib_decorators_legacy_d_ts,
|
||||
"libs/lib.dom.asynciterable.d.ts": libs_lib_dom_asynciterable_d_ts,
|
||||
"libs/lib.dom.d.ts": libs_lib_dom_d_ts,
|
||||
"libs/lib.dom.iterable.d.ts": libs_lib_dom_iterable_d_ts,
|
||||
"libs/lib.es2015.collection.d.ts": libs_lib_es2015_collection_d_ts,
|
||||
"libs/lib.es2015.core.d.ts": libs_lib_es2015_core_d_ts,
|
||||
"libs/lib.es2015.d.ts": libs_lib_es2015_d_ts,
|
||||
"libs/lib.es2015.generator.d.ts": libs_lib_es2015_generator_d_ts,
|
||||
"libs/lib.es2015.iterable.d.ts": libs_lib_es2015_iterable_d_ts,
|
||||
"libs/lib.es2015.promise.d.ts": libs_lib_es2015_promise_d_ts,
|
||||
"libs/lib.es2015.proxy.d.ts": libs_lib_es2015_proxy_d_ts,
|
||||
"libs/lib.es2015.reflect.d.ts": libs_lib_es2015_reflect_d_ts,
|
||||
"libs/lib.es2015.symbol.d.ts": libs_lib_es2015_symbol_d_ts,
|
||||
"libs/lib.es2015.symbol.wellknown.d.ts": libs_lib_es2015_symbol_wellknown_d_ts,
|
||||
"libs/lib.es2016.array.include.d.ts": libs_lib_es2016_array_include_d_ts,
|
||||
"libs/lib.es2016.d.ts": libs_lib_es2016_d_ts,
|
||||
"libs/lib.es2016.full.d.ts": libs_lib_es2016_full_d_ts,
|
||||
"libs/lib.es2016.intl.d.ts": libs_lib_es2016_intl_d_ts,
|
||||
"libs/lib.es2017.arraybuffer.d.ts": libs_lib_es2017_arraybuffer_d_ts,
|
||||
"libs/lib.es2017.d.ts": libs_lib_es2017_d_ts,
|
||||
"libs/lib.es2017.date.d.ts": libs_lib_es2017_date_d_ts,
|
||||
"libs/lib.es2017.full.d.ts": libs_lib_es2017_full_d_ts,
|
||||
"libs/lib.es2017.intl.d.ts": libs_lib_es2017_intl_d_ts,
|
||||
"libs/lib.es2017.object.d.ts": libs_lib_es2017_object_d_ts,
|
||||
"libs/lib.es2017.sharedmemory.d.ts": libs_lib_es2017_sharedmemory_d_ts,
|
||||
"libs/lib.es2017.string.d.ts": libs_lib_es2017_string_d_ts,
|
||||
"libs/lib.es2017.typedarrays.d.ts": libs_lib_es2017_typedarrays_d_ts,
|
||||
"libs/lib.es2018.asyncgenerator.d.ts": libs_lib_es2018_asyncgenerator_d_ts,
|
||||
"libs/lib.es2018.asynciterable.d.ts": libs_lib_es2018_asynciterable_d_ts,
|
||||
"libs/lib.es2018.d.ts": libs_lib_es2018_d_ts,
|
||||
"libs/lib.es2018.full.d.ts": libs_lib_es2018_full_d_ts,
|
||||
"libs/lib.es2018.intl.d.ts": libs_lib_es2018_intl_d_ts,
|
||||
"libs/lib.es2018.promise.d.ts": libs_lib_es2018_promise_d_ts,
|
||||
"libs/lib.es2018.regexp.d.ts": libs_lib_es2018_regexp_d_ts,
|
||||
"libs/lib.es2019.array.d.ts": libs_lib_es2019_array_d_ts,
|
||||
"libs/lib.es2019.d.ts": libs_lib_es2019_d_ts,
|
||||
"libs/lib.es2019.full.d.ts": libs_lib_es2019_full_d_ts,
|
||||
"libs/lib.es2019.intl.d.ts": libs_lib_es2019_intl_d_ts,
|
||||
"libs/lib.es2019.object.d.ts": libs_lib_es2019_object_d_ts,
|
||||
"libs/lib.es2019.string.d.ts": libs_lib_es2019_string_d_ts,
|
||||
"libs/lib.es2019.symbol.d.ts": libs_lib_es2019_symbol_d_ts,
|
||||
"libs/lib.es2020.bigint.d.ts": libs_lib_es2020_bigint_d_ts,
|
||||
"libs/lib.es2020.d.ts": libs_lib_es2020_d_ts,
|
||||
"libs/lib.es2020.date.d.ts": libs_lib_es2020_date_d_ts,
|
||||
"libs/lib.es2020.full.d.ts": libs_lib_es2020_full_d_ts,
|
||||
"libs/lib.es2020.intl.d.ts": libs_lib_es2020_intl_d_ts,
|
||||
"libs/lib.es2020.number.d.ts": libs_lib_es2020_number_d_ts,
|
||||
"libs/lib.es2020.promise.d.ts": libs_lib_es2020_promise_d_ts,
|
||||
"libs/lib.es2020.sharedmemory.d.ts": libs_lib_es2020_sharedmemory_d_ts,
|
||||
"libs/lib.es2020.string.d.ts": libs_lib_es2020_string_d_ts,
|
||||
"libs/lib.es2020.symbol.wellknown.d.ts": libs_lib_es2020_symbol_wellknown_d_ts,
|
||||
"libs/lib.es2021.d.ts": libs_lib_es2021_d_ts,
|
||||
"libs/lib.es2021.full.d.ts": libs_lib_es2021_full_d_ts,
|
||||
"libs/lib.es2021.intl.d.ts": libs_lib_es2021_intl_d_ts,
|
||||
"libs/lib.es2021.promise.d.ts": libs_lib_es2021_promise_d_ts,
|
||||
"libs/lib.es2021.string.d.ts": libs_lib_es2021_string_d_ts,
|
||||
"libs/lib.es2021.weakref.d.ts": libs_lib_es2021_weakref_d_ts,
|
||||
"libs/lib.es2022.array.d.ts": libs_lib_es2022_array_d_ts,
|
||||
"libs/lib.es2022.d.ts": libs_lib_es2022_d_ts,
|
||||
"libs/lib.es2022.error.d.ts": libs_lib_es2022_error_d_ts,
|
||||
"libs/lib.es2022.full.d.ts": libs_lib_es2022_full_d_ts,
|
||||
"libs/lib.es2022.intl.d.ts": libs_lib_es2022_intl_d_ts,
|
||||
"libs/lib.es2022.object.d.ts": libs_lib_es2022_object_d_ts,
|
||||
"libs/lib.es2022.regexp.d.ts": libs_lib_es2022_regexp_d_ts,
|
||||
"libs/lib.es2022.string.d.ts": libs_lib_es2022_string_d_ts,
|
||||
"libs/lib.es2023.array.d.ts": libs_lib_es2023_array_d_ts,
|
||||
"libs/lib.es2023.collection.d.ts": libs_lib_es2023_collection_d_ts,
|
||||
"libs/lib.es2023.d.ts": libs_lib_es2023_d_ts,
|
||||
"libs/lib.es2023.full.d.ts": libs_lib_es2023_full_d_ts,
|
||||
"libs/lib.es2023.intl.d.ts": libs_lib_es2023_intl_d_ts,
|
||||
"libs/lib.es2024.arraybuffer.d.ts": libs_lib_es2024_arraybuffer_d_ts,
|
||||
"libs/lib.es2024.collection.d.ts": libs_lib_es2024_collection_d_ts,
|
||||
"libs/lib.es2024.d.ts": libs_lib_es2024_d_ts,
|
||||
"libs/lib.es2024.full.d.ts": libs_lib_es2024_full_d_ts,
|
||||
"libs/lib.es2024.object.d.ts": libs_lib_es2024_object_d_ts,
|
||||
"libs/lib.es2024.promise.d.ts": libs_lib_es2024_promise_d_ts,
|
||||
"libs/lib.es2024.regexp.d.ts": libs_lib_es2024_regexp_d_ts,
|
||||
"libs/lib.es2024.sharedmemory.d.ts": libs_lib_es2024_sharedmemory_d_ts,
|
||||
"libs/lib.es2024.string.d.ts": libs_lib_es2024_string_d_ts,
|
||||
"libs/lib.es2025.collection.d.ts": libs_lib_es2025_collection_d_ts,
|
||||
"libs/lib.es2025.d.ts": libs_lib_es2025_d_ts,
|
||||
"libs/lib.es2025.float16.d.ts": libs_lib_es2025_float16_d_ts,
|
||||
"libs/lib.es2025.full.d.ts": libs_lib_es2025_full_d_ts,
|
||||
"libs/lib.es2025.intl.d.ts": libs_lib_es2025_intl_d_ts,
|
||||
"libs/lib.es2025.iterator.d.ts": libs_lib_es2025_iterator_d_ts,
|
||||
"libs/lib.es2025.promise.d.ts": libs_lib_es2025_promise_d_ts,
|
||||
"libs/lib.es2025.regexp.d.ts": libs_lib_es2025_regexp_d_ts,
|
||||
"libs/lib.es5.d.ts": libs_lib_es5_d_ts,
|
||||
"libs/lib.es6.d.ts": libs_lib_es6_d_ts,
|
||||
"libs/lib.esnext.array.d.ts": libs_lib_esnext_array_d_ts,
|
||||
"libs/lib.esnext.collection.d.ts": libs_lib_esnext_collection_d_ts,
|
||||
"libs/lib.esnext.d.ts": libs_lib_esnext_d_ts,
|
||||
"libs/lib.esnext.date.d.ts": libs_lib_esnext_date_d_ts,
|
||||
"libs/lib.esnext.decorators.d.ts": libs_lib_esnext_decorators_d_ts,
|
||||
"libs/lib.esnext.disposable.d.ts": libs_lib_esnext_disposable_d_ts,
|
||||
"libs/lib.esnext.error.d.ts": libs_lib_esnext_error_d_ts,
|
||||
"libs/lib.esnext.full.d.ts": libs_lib_esnext_full_d_ts,
|
||||
"libs/lib.esnext.intl.d.ts": libs_lib_esnext_intl_d_ts,
|
||||
"libs/lib.esnext.sharedmemory.d.ts": libs_lib_esnext_sharedmemory_d_ts,
|
||||
"libs/lib.esnext.temporal.d.ts": libs_lib_esnext_temporal_d_ts,
|
||||
"libs/lib.esnext.typedarrays.d.ts": libs_lib_esnext_typedarrays_d_ts,
|
||||
"libs/lib.scripthost.d.ts": libs_lib_scripthost_d_ts,
|
||||
"libs/lib.webworker.asynciterable.d.ts": libs_lib_webworker_asynciterable_d_ts,
|
||||
"libs/lib.webworker.d.ts": libs_lib_webworker_d_ts,
|
||||
"libs/lib.webworker.importscripts.d.ts": libs_lib_webworker_importscripts_d_ts,
|
||||
"libs/lib.webworker.iterable.d.ts": libs_lib_webworker_iterable_d_ts,
|
||||
}
|
||||
|
||||
var libsEntries = []fs.DirEntry{
|
||||
&fileInfo{name: "lib.d.ts", size: int64(len(libs_lib_d_ts))},
|
||||
&fileInfo{name: "lib.decorators.d.ts", size: int64(len(libs_lib_decorators_d_ts))},
|
||||
&fileInfo{name: "lib.decorators.legacy.d.ts", size: int64(len(libs_lib_decorators_legacy_d_ts))},
|
||||
&fileInfo{name: "lib.dom.asynciterable.d.ts", size: int64(len(libs_lib_dom_asynciterable_d_ts))},
|
||||
&fileInfo{name: "lib.dom.d.ts", size: int64(len(libs_lib_dom_d_ts))},
|
||||
&fileInfo{name: "lib.dom.iterable.d.ts", size: int64(len(libs_lib_dom_iterable_d_ts))},
|
||||
&fileInfo{name: "lib.es2015.collection.d.ts", size: int64(len(libs_lib_es2015_collection_d_ts))},
|
||||
&fileInfo{name: "lib.es2015.core.d.ts", size: int64(len(libs_lib_es2015_core_d_ts))},
|
||||
&fileInfo{name: "lib.es2015.d.ts", size: int64(len(libs_lib_es2015_d_ts))},
|
||||
&fileInfo{name: "lib.es2015.generator.d.ts", size: int64(len(libs_lib_es2015_generator_d_ts))},
|
||||
&fileInfo{name: "lib.es2015.iterable.d.ts", size: int64(len(libs_lib_es2015_iterable_d_ts))},
|
||||
&fileInfo{name: "lib.es2015.promise.d.ts", size: int64(len(libs_lib_es2015_promise_d_ts))},
|
||||
&fileInfo{name: "lib.es2015.proxy.d.ts", size: int64(len(libs_lib_es2015_proxy_d_ts))},
|
||||
&fileInfo{name: "lib.es2015.reflect.d.ts", size: int64(len(libs_lib_es2015_reflect_d_ts))},
|
||||
&fileInfo{name: "lib.es2015.symbol.d.ts", size: int64(len(libs_lib_es2015_symbol_d_ts))},
|
||||
&fileInfo{name: "lib.es2015.symbol.wellknown.d.ts", size: int64(len(libs_lib_es2015_symbol_wellknown_d_ts))},
|
||||
&fileInfo{name: "lib.es2016.array.include.d.ts", size: int64(len(libs_lib_es2016_array_include_d_ts))},
|
||||
&fileInfo{name: "lib.es2016.d.ts", size: int64(len(libs_lib_es2016_d_ts))},
|
||||
&fileInfo{name: "lib.es2016.full.d.ts", size: int64(len(libs_lib_es2016_full_d_ts))},
|
||||
&fileInfo{name: "lib.es2016.intl.d.ts", size: int64(len(libs_lib_es2016_intl_d_ts))},
|
||||
&fileInfo{name: "lib.es2017.arraybuffer.d.ts", size: int64(len(libs_lib_es2017_arraybuffer_d_ts))},
|
||||
&fileInfo{name: "lib.es2017.d.ts", size: int64(len(libs_lib_es2017_d_ts))},
|
||||
&fileInfo{name: "lib.es2017.date.d.ts", size: int64(len(libs_lib_es2017_date_d_ts))},
|
||||
&fileInfo{name: "lib.es2017.full.d.ts", size: int64(len(libs_lib_es2017_full_d_ts))},
|
||||
&fileInfo{name: "lib.es2017.intl.d.ts", size: int64(len(libs_lib_es2017_intl_d_ts))},
|
||||
&fileInfo{name: "lib.es2017.object.d.ts", size: int64(len(libs_lib_es2017_object_d_ts))},
|
||||
&fileInfo{name: "lib.es2017.sharedmemory.d.ts", size: int64(len(libs_lib_es2017_sharedmemory_d_ts))},
|
||||
&fileInfo{name: "lib.es2017.string.d.ts", size: int64(len(libs_lib_es2017_string_d_ts))},
|
||||
&fileInfo{name: "lib.es2017.typedarrays.d.ts", size: int64(len(libs_lib_es2017_typedarrays_d_ts))},
|
||||
&fileInfo{name: "lib.es2018.asyncgenerator.d.ts", size: int64(len(libs_lib_es2018_asyncgenerator_d_ts))},
|
||||
&fileInfo{name: "lib.es2018.asynciterable.d.ts", size: int64(len(libs_lib_es2018_asynciterable_d_ts))},
|
||||
&fileInfo{name: "lib.es2018.d.ts", size: int64(len(libs_lib_es2018_d_ts))},
|
||||
&fileInfo{name: "lib.es2018.full.d.ts", size: int64(len(libs_lib_es2018_full_d_ts))},
|
||||
&fileInfo{name: "lib.es2018.intl.d.ts", size: int64(len(libs_lib_es2018_intl_d_ts))},
|
||||
&fileInfo{name: "lib.es2018.promise.d.ts", size: int64(len(libs_lib_es2018_promise_d_ts))},
|
||||
&fileInfo{name: "lib.es2018.regexp.d.ts", size: int64(len(libs_lib_es2018_regexp_d_ts))},
|
||||
&fileInfo{name: "lib.es2019.array.d.ts", size: int64(len(libs_lib_es2019_array_d_ts))},
|
||||
&fileInfo{name: "lib.es2019.d.ts", size: int64(len(libs_lib_es2019_d_ts))},
|
||||
&fileInfo{name: "lib.es2019.full.d.ts", size: int64(len(libs_lib_es2019_full_d_ts))},
|
||||
&fileInfo{name: "lib.es2019.intl.d.ts", size: int64(len(libs_lib_es2019_intl_d_ts))},
|
||||
&fileInfo{name: "lib.es2019.object.d.ts", size: int64(len(libs_lib_es2019_object_d_ts))},
|
||||
&fileInfo{name: "lib.es2019.string.d.ts", size: int64(len(libs_lib_es2019_string_d_ts))},
|
||||
&fileInfo{name: "lib.es2019.symbol.d.ts", size: int64(len(libs_lib_es2019_symbol_d_ts))},
|
||||
&fileInfo{name: "lib.es2020.bigint.d.ts", size: int64(len(libs_lib_es2020_bigint_d_ts))},
|
||||
&fileInfo{name: "lib.es2020.d.ts", size: int64(len(libs_lib_es2020_d_ts))},
|
||||
&fileInfo{name: "lib.es2020.date.d.ts", size: int64(len(libs_lib_es2020_date_d_ts))},
|
||||
&fileInfo{name: "lib.es2020.full.d.ts", size: int64(len(libs_lib_es2020_full_d_ts))},
|
||||
&fileInfo{name: "lib.es2020.intl.d.ts", size: int64(len(libs_lib_es2020_intl_d_ts))},
|
||||
&fileInfo{name: "lib.es2020.number.d.ts", size: int64(len(libs_lib_es2020_number_d_ts))},
|
||||
&fileInfo{name: "lib.es2020.promise.d.ts", size: int64(len(libs_lib_es2020_promise_d_ts))},
|
||||
&fileInfo{name: "lib.es2020.sharedmemory.d.ts", size: int64(len(libs_lib_es2020_sharedmemory_d_ts))},
|
||||
&fileInfo{name: "lib.es2020.string.d.ts", size: int64(len(libs_lib_es2020_string_d_ts))},
|
||||
&fileInfo{name: "lib.es2020.symbol.wellknown.d.ts", size: int64(len(libs_lib_es2020_symbol_wellknown_d_ts))},
|
||||
&fileInfo{name: "lib.es2021.d.ts", size: int64(len(libs_lib_es2021_d_ts))},
|
||||
&fileInfo{name: "lib.es2021.full.d.ts", size: int64(len(libs_lib_es2021_full_d_ts))},
|
||||
&fileInfo{name: "lib.es2021.intl.d.ts", size: int64(len(libs_lib_es2021_intl_d_ts))},
|
||||
&fileInfo{name: "lib.es2021.promise.d.ts", size: int64(len(libs_lib_es2021_promise_d_ts))},
|
||||
&fileInfo{name: "lib.es2021.string.d.ts", size: int64(len(libs_lib_es2021_string_d_ts))},
|
||||
&fileInfo{name: "lib.es2021.weakref.d.ts", size: int64(len(libs_lib_es2021_weakref_d_ts))},
|
||||
&fileInfo{name: "lib.es2022.array.d.ts", size: int64(len(libs_lib_es2022_array_d_ts))},
|
||||
&fileInfo{name: "lib.es2022.d.ts", size: int64(len(libs_lib_es2022_d_ts))},
|
||||
&fileInfo{name: "lib.es2022.error.d.ts", size: int64(len(libs_lib_es2022_error_d_ts))},
|
||||
&fileInfo{name: "lib.es2022.full.d.ts", size: int64(len(libs_lib_es2022_full_d_ts))},
|
||||
&fileInfo{name: "lib.es2022.intl.d.ts", size: int64(len(libs_lib_es2022_intl_d_ts))},
|
||||
&fileInfo{name: "lib.es2022.object.d.ts", size: int64(len(libs_lib_es2022_object_d_ts))},
|
||||
&fileInfo{name: "lib.es2022.regexp.d.ts", size: int64(len(libs_lib_es2022_regexp_d_ts))},
|
||||
&fileInfo{name: "lib.es2022.string.d.ts", size: int64(len(libs_lib_es2022_string_d_ts))},
|
||||
&fileInfo{name: "lib.es2023.array.d.ts", size: int64(len(libs_lib_es2023_array_d_ts))},
|
||||
&fileInfo{name: "lib.es2023.collection.d.ts", size: int64(len(libs_lib_es2023_collection_d_ts))},
|
||||
&fileInfo{name: "lib.es2023.d.ts", size: int64(len(libs_lib_es2023_d_ts))},
|
||||
&fileInfo{name: "lib.es2023.full.d.ts", size: int64(len(libs_lib_es2023_full_d_ts))},
|
||||
&fileInfo{name: "lib.es2023.intl.d.ts", size: int64(len(libs_lib_es2023_intl_d_ts))},
|
||||
&fileInfo{name: "lib.es2024.arraybuffer.d.ts", size: int64(len(libs_lib_es2024_arraybuffer_d_ts))},
|
||||
&fileInfo{name: "lib.es2024.collection.d.ts", size: int64(len(libs_lib_es2024_collection_d_ts))},
|
||||
&fileInfo{name: "lib.es2024.d.ts", size: int64(len(libs_lib_es2024_d_ts))},
|
||||
&fileInfo{name: "lib.es2024.full.d.ts", size: int64(len(libs_lib_es2024_full_d_ts))},
|
||||
&fileInfo{name: "lib.es2024.object.d.ts", size: int64(len(libs_lib_es2024_object_d_ts))},
|
||||
&fileInfo{name: "lib.es2024.promise.d.ts", size: int64(len(libs_lib_es2024_promise_d_ts))},
|
||||
&fileInfo{name: "lib.es2024.regexp.d.ts", size: int64(len(libs_lib_es2024_regexp_d_ts))},
|
||||
&fileInfo{name: "lib.es2024.sharedmemory.d.ts", size: int64(len(libs_lib_es2024_sharedmemory_d_ts))},
|
||||
&fileInfo{name: "lib.es2024.string.d.ts", size: int64(len(libs_lib_es2024_string_d_ts))},
|
||||
&fileInfo{name: "lib.es2025.collection.d.ts", size: int64(len(libs_lib_es2025_collection_d_ts))},
|
||||
&fileInfo{name: "lib.es2025.d.ts", size: int64(len(libs_lib_es2025_d_ts))},
|
||||
&fileInfo{name: "lib.es2025.float16.d.ts", size: int64(len(libs_lib_es2025_float16_d_ts))},
|
||||
&fileInfo{name: "lib.es2025.full.d.ts", size: int64(len(libs_lib_es2025_full_d_ts))},
|
||||
&fileInfo{name: "lib.es2025.intl.d.ts", size: int64(len(libs_lib_es2025_intl_d_ts))},
|
||||
&fileInfo{name: "lib.es2025.iterator.d.ts", size: int64(len(libs_lib_es2025_iterator_d_ts))},
|
||||
&fileInfo{name: "lib.es2025.promise.d.ts", size: int64(len(libs_lib_es2025_promise_d_ts))},
|
||||
&fileInfo{name: "lib.es2025.regexp.d.ts", size: int64(len(libs_lib_es2025_regexp_d_ts))},
|
||||
&fileInfo{name: "lib.es5.d.ts", size: int64(len(libs_lib_es5_d_ts))},
|
||||
&fileInfo{name: "lib.es6.d.ts", size: int64(len(libs_lib_es6_d_ts))},
|
||||
&fileInfo{name: "lib.esnext.array.d.ts", size: int64(len(libs_lib_esnext_array_d_ts))},
|
||||
&fileInfo{name: "lib.esnext.collection.d.ts", size: int64(len(libs_lib_esnext_collection_d_ts))},
|
||||
&fileInfo{name: "lib.esnext.d.ts", size: int64(len(libs_lib_esnext_d_ts))},
|
||||
&fileInfo{name: "lib.esnext.date.d.ts", size: int64(len(libs_lib_esnext_date_d_ts))},
|
||||
&fileInfo{name: "lib.esnext.decorators.d.ts", size: int64(len(libs_lib_esnext_decorators_d_ts))},
|
||||
&fileInfo{name: "lib.esnext.disposable.d.ts", size: int64(len(libs_lib_esnext_disposable_d_ts))},
|
||||
&fileInfo{name: "lib.esnext.error.d.ts", size: int64(len(libs_lib_esnext_error_d_ts))},
|
||||
&fileInfo{name: "lib.esnext.full.d.ts", size: int64(len(libs_lib_esnext_full_d_ts))},
|
||||
&fileInfo{name: "lib.esnext.intl.d.ts", size: int64(len(libs_lib_esnext_intl_d_ts))},
|
||||
&fileInfo{name: "lib.esnext.sharedmemory.d.ts", size: int64(len(libs_lib_esnext_sharedmemory_d_ts))},
|
||||
&fileInfo{name: "lib.esnext.temporal.d.ts", size: int64(len(libs_lib_esnext_temporal_d_ts))},
|
||||
&fileInfo{name: "lib.esnext.typedarrays.d.ts", size: int64(len(libs_lib_esnext_typedarrays_d_ts))},
|
||||
&fileInfo{name: "lib.scripthost.d.ts", size: int64(len(libs_lib_scripthost_d_ts))},
|
||||
&fileInfo{name: "lib.webworker.asynciterable.d.ts", size: int64(len(libs_lib_webworker_asynciterable_d_ts))},
|
||||
&fileInfo{name: "lib.webworker.d.ts", size: int64(len(libs_lib_webworker_d_ts))},
|
||||
&fileInfo{name: "lib.webworker.importscripts.d.ts", size: int64(len(libs_lib_webworker_importscripts_d_ts))},
|
||||
&fileInfo{name: "lib.webworker.iterable.d.ts", size: int64(len(libs_lib_webworker_iterable_d_ts))},
|
||||
}
|
||||
217
tools/tsgo/internal/bundled/generate.go
Normal file
217
tools/tsgo/internal/bundled/generate.go
Normal file
@@ -0,0 +1,217 @@
|
||||
//go:build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/repo"
|
||||
)
|
||||
|
||||
var (
|
||||
libInputDir = filepath.Join(repo.TypeScriptSubmodulePath(), "src", "lib")
|
||||
copyrightNotice = filepath.Join(repo.TypeScriptSubmodulePath(), "scripts", "CopyrightNotice.txt")
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||
|
||||
libs := readLibs()
|
||||
generateLibs(libs)
|
||||
generateLibList(libs)
|
||||
generateEmbedded(libs)
|
||||
}
|
||||
|
||||
type lib struct {
|
||||
target string // target relative to libs dir
|
||||
sources []string // sources relative to src/lib dir
|
||||
}
|
||||
|
||||
func generateLibs(libs []lib) {
|
||||
const outputDir = "libs"
|
||||
|
||||
copyright := readCopyright()
|
||||
|
||||
if err := os.RemoveAll(outputDir); err != nil {
|
||||
log.Fatalf("failed to remove libs directory: %v", err)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(outputDir, 0o755); err != nil {
|
||||
log.Fatalf("failed to create libs directory: %v", err)
|
||||
}
|
||||
|
||||
for _, lib := range libs {
|
||||
var output bytes.Buffer
|
||||
output.Write(copyright)
|
||||
|
||||
for _, source := range lib.sources {
|
||||
sourcePath := filepath.Join(libInputDir, source)
|
||||
b, err := os.ReadFile(sourcePath)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to read %s: %v", sourcePath, err)
|
||||
}
|
||||
|
||||
output.WriteByte('\n')
|
||||
output.Write(removeCRLF(b))
|
||||
}
|
||||
|
||||
outputPath := filepath.Join(outputDir, lib.target)
|
||||
if err := os.WriteFile(outputPath, output.Bytes(), 0o644); err != nil {
|
||||
log.Fatalf("failed to write %s: %v", outputPath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func generateLibList(libs []lib) {
|
||||
var code bytes.Buffer
|
||||
code.WriteString("// Code generated by generate.go; DO NOT EDIT.\n\n")
|
||||
code.WriteString("package bundled\n\n")
|
||||
|
||||
code.WriteString("// LibNames is the list of all bundled lib files, sorted by name.\n")
|
||||
code.WriteString("// For the list of libs sorted by load order, use [tsoptions.Libs].\n")
|
||||
code.WriteString("var LibNames = []string{\n")
|
||||
for _, lib := range libs {
|
||||
code.WriteString("\t\"" + lib.target + "\",\n")
|
||||
}
|
||||
code.WriteString("}\n")
|
||||
|
||||
writeCode("libs_generated.go", code.Bytes())
|
||||
}
|
||||
|
||||
func generateEmbedded(libs []lib) {
|
||||
libVarNames := make([]string, len(libs))
|
||||
for i, lib := range libs {
|
||||
libVarNames[i] = "libs_" + strings.ReplaceAll(lib.target, ".", "_")
|
||||
}
|
||||
|
||||
var code bytes.Buffer
|
||||
code.WriteString("//go:build !noembed\n\n")
|
||||
code.WriteString("// Code generated by generate.go; DO NOT EDIT.\n\n")
|
||||
code.WriteString("package bundled\n\n")
|
||||
code.WriteString("import (\n")
|
||||
code.WriteString("\"io/fs\"\n\n")
|
||||
code.WriteString("_ \"embed\"\n")
|
||||
code.WriteString(")\n\n")
|
||||
|
||||
code.WriteString("var (\n")
|
||||
for i, lib := range libs {
|
||||
varName := libVarNames[i]
|
||||
code.WriteString("//go:embed libs/" + lib.target + "\n")
|
||||
code.WriteString("" + varName + " string\n")
|
||||
}
|
||||
code.WriteString(")\n\n")
|
||||
|
||||
code.WriteString("var embeddedContents = map[string]string{\n")
|
||||
for i, lib := range libs {
|
||||
varName := libVarNames[i]
|
||||
code.WriteString("\t\"libs/" + lib.target + "\": " + varName + ",\n")
|
||||
}
|
||||
code.WriteString("}\n\n")
|
||||
|
||||
code.WriteString("var libsEntries = []fs.DirEntry{\n")
|
||||
for i, lib := range libs {
|
||||
varName := libVarNames[i]
|
||||
fmt.Fprintf(&code, "\t&fileInfo{name: %q, size: int64(len(%s))},\n", lib.target, varName)
|
||||
}
|
||||
code.WriteString("}\n")
|
||||
|
||||
writeCode("embed_generated.go", code.Bytes())
|
||||
}
|
||||
|
||||
var (
|
||||
// Match escaped characters, double-quoted strings, single-line comments, and multi-line comments.
|
||||
reJSONComments = regexp.MustCompile(`\\.|"(?:\\.|[^"])*"|//.*|/\*[\s\S]*?\*/`)
|
||||
// Match double-quoted strings (to skip) or trailing commas before ] or }.
|
||||
reTrailingComma = regexp.MustCompile(`"(?:\\.|[^"])*"|,\s*([}\]])`)
|
||||
)
|
||||
|
||||
// stripJSONC replaces comments and trailing commas with spaces in JSONC content,
|
||||
// producing valid JSON. The input slice is mutated in place.
|
||||
func stripJSONC(b []byte) {
|
||||
for _, loc := range reJSONComments.FindAllIndex(b, -1) {
|
||||
if b[loc[0]] == '/' {
|
||||
for i := loc[0]; i < loc[1]; i++ {
|
||||
if b[i] != '\n' {
|
||||
b[i] = ' '
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, loc := range reTrailingComma.FindAllSubmatchIndex(b, -1) {
|
||||
// loc[2]:loc[3] is the capture group; -1 means this matched a string, not a comma.
|
||||
if loc[2] < 0 {
|
||||
continue
|
||||
}
|
||||
// Blank the comma (at loc[0]), keep whitespace and closing bracket.
|
||||
b[loc[0]] = ' '
|
||||
}
|
||||
}
|
||||
|
||||
func readLibs() []lib {
|
||||
libsFile := filepath.Join(libInputDir, "libs.json")
|
||||
|
||||
b, err := os.ReadFile(libsFile)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open libs.json: %v", err)
|
||||
}
|
||||
stripJSONC(b)
|
||||
|
||||
var meta struct {
|
||||
Libs []string `json:"libs"`
|
||||
Paths map[string]string `json:"paths"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(b, &meta); err != nil {
|
||||
log.Fatalf("failed to parse libs.json: %v", err)
|
||||
}
|
||||
|
||||
var libs []lib
|
||||
for _, libName := range meta.Libs {
|
||||
sources := []string{libName + ".d.ts"}
|
||||
var target string
|
||||
if path, ok := meta.Paths[libName]; ok {
|
||||
target = path
|
||||
} else {
|
||||
target = "lib." + libName + ".d.ts"
|
||||
}
|
||||
libs = append(libs, lib{target: target, sources: sources})
|
||||
}
|
||||
|
||||
slices.SortFunc(libs, func(a lib, b lib) int {
|
||||
return strings.Compare(a.target, b.target)
|
||||
})
|
||||
|
||||
return libs
|
||||
}
|
||||
|
||||
func readCopyright() []byte {
|
||||
b, err := os.ReadFile(copyrightNotice)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to read copyright notice: %v", err)
|
||||
}
|
||||
return removeCRLF(b)
|
||||
}
|
||||
|
||||
func removeCRLF(b []byte) []byte {
|
||||
return bytes.ReplaceAll(b, []byte("\r\n"), []byte("\n"))
|
||||
}
|
||||
|
||||
func writeCode(filename string, code []byte) {
|
||||
formatted, err := format.Source(code)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to format source: %v", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filename, formatted, 0o644); err != nil {
|
||||
log.Fatalf("failed to write %s: %v", filename, err)
|
||||
}
|
||||
}
|
||||
20
tools/tsgo/internal/bundled/libs/lib.d.ts
vendored
Normal file
20
tools/tsgo/internal/bundled/libs/lib.d.ts
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es5" />
|
||||
/// <reference lib="dom" />
|
||||
/// <reference lib="webworker.importscripts" />
|
||||
/// <reference lib="scripthost" />
|
||||
382
tools/tsgo/internal/bundled/libs/lib.decorators.d.ts
vendored
Normal file
382
tools/tsgo/internal/bundled/libs/lib.decorators.d.ts
vendored
Normal file
@@ -0,0 +1,382 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/**
|
||||
* The decorator context types provided to class element decorators.
|
||||
*/
|
||||
type ClassMemberDecoratorContext =
|
||||
| ClassMethodDecoratorContext
|
||||
| ClassGetterDecoratorContext
|
||||
| ClassSetterDecoratorContext
|
||||
| ClassFieldDecoratorContext
|
||||
| ClassAccessorDecoratorContext;
|
||||
|
||||
/**
|
||||
* The decorator context types provided to any decorator.
|
||||
*/
|
||||
type DecoratorContext =
|
||||
| ClassDecoratorContext
|
||||
| ClassMemberDecoratorContext;
|
||||
|
||||
type DecoratorMetadataObject = Record<PropertyKey, unknown> & object;
|
||||
|
||||
type DecoratorMetadata = typeof globalThis extends { Symbol: { readonly metadata: symbol; }; } ? DecoratorMetadataObject : DecoratorMetadataObject | undefined;
|
||||
|
||||
/**
|
||||
* Context provided to a class decorator.
|
||||
* @template Class The type of the decorated class associated with this context.
|
||||
*/
|
||||
interface ClassDecoratorContext<
|
||||
Class extends abstract new (...args: any) => any = abstract new (...args: any) => any,
|
||||
> {
|
||||
/** The kind of element that was decorated. */
|
||||
readonly kind: "class";
|
||||
|
||||
/** The name of the decorated class. */
|
||||
readonly name: string | undefined;
|
||||
|
||||
/**
|
||||
* Adds a callback to be invoked after the class definition has been finalized.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* function customElement(name: string): ClassDecoratorFunction {
|
||||
* return (target, context) => {
|
||||
* context.addInitializer(function () {
|
||||
* customElements.define(name, this);
|
||||
* });
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @customElement("my-element")
|
||||
* class MyElement {}
|
||||
* ```
|
||||
*/
|
||||
addInitializer(initializer: (this: Class) => void): void;
|
||||
|
||||
readonly metadata: DecoratorMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Context provided to a class method decorator.
|
||||
* @template This The type on which the class element will be defined. For a static class element, this will be
|
||||
* the type of the constructor. For a non-static class element, this will be the type of the instance.
|
||||
* @template Value The type of the decorated class method.
|
||||
*/
|
||||
interface ClassMethodDecoratorContext<
|
||||
This = unknown,
|
||||
Value extends (this: This, ...args: any) => any = (this: This, ...args: any) => any,
|
||||
> {
|
||||
/** The kind of class element that was decorated. */
|
||||
readonly kind: "method";
|
||||
|
||||
/** The name of the decorated class element. */
|
||||
readonly name: string | symbol;
|
||||
|
||||
/** A value indicating whether the class element is a static (`true`) or instance (`false`) element. */
|
||||
readonly static: boolean;
|
||||
|
||||
/** A value indicating whether the class element has a private name. */
|
||||
readonly private: boolean;
|
||||
|
||||
/** An object that can be used to access the current value of the class element at runtime. */
|
||||
readonly access: {
|
||||
/**
|
||||
* Determines whether an object has a property with the same name as the decorated element.
|
||||
*/
|
||||
has(object: This): boolean;
|
||||
/**
|
||||
* Gets the current value of the method from the provided object.
|
||||
*
|
||||
* @example
|
||||
* let fn = context.access.get(instance);
|
||||
*/
|
||||
get(object: This): Value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a callback to be invoked either after static methods are defined but before
|
||||
* static initializers are run (when decorating a `static` element), or before instance
|
||||
* initializers are run (when decorating a non-`static` element).
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const bound: ClassMethodDecoratorFunction = (value, context) {
|
||||
* if (context.private) throw new TypeError("Not supported on private methods.");
|
||||
* context.addInitializer(function () {
|
||||
* this[context.name] = this[context.name].bind(this);
|
||||
* });
|
||||
* }
|
||||
*
|
||||
* class C {
|
||||
* message = "Hello";
|
||||
*
|
||||
* @bound
|
||||
* m() {
|
||||
* console.log(this.message);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
addInitializer(initializer: (this: This) => void): void;
|
||||
|
||||
readonly metadata: DecoratorMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Context provided to a class getter decorator.
|
||||
* @template This The type on which the class element will be defined. For a static class element, this will be
|
||||
* the type of the constructor. For a non-static class element, this will be the type of the instance.
|
||||
* @template Value The property type of the decorated class getter.
|
||||
*/
|
||||
interface ClassGetterDecoratorContext<
|
||||
This = unknown,
|
||||
Value = unknown,
|
||||
> {
|
||||
/** The kind of class element that was decorated. */
|
||||
readonly kind: "getter";
|
||||
|
||||
/** The name of the decorated class element. */
|
||||
readonly name: string | symbol;
|
||||
|
||||
/** A value indicating whether the class element is a static (`true`) or instance (`false`) element. */
|
||||
readonly static: boolean;
|
||||
|
||||
/** A value indicating whether the class element has a private name. */
|
||||
readonly private: boolean;
|
||||
|
||||
/** An object that can be used to access the current value of the class element at runtime. */
|
||||
readonly access: {
|
||||
/**
|
||||
* Determines whether an object has a property with the same name as the decorated element.
|
||||
*/
|
||||
has(object: This): boolean;
|
||||
/**
|
||||
* Invokes the getter on the provided object.
|
||||
*
|
||||
* @example
|
||||
* let value = context.access.get(instance);
|
||||
*/
|
||||
get(object: This): Value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a callback to be invoked either after static methods are defined but before
|
||||
* static initializers are run (when decorating a `static` element), or before instance
|
||||
* initializers are run (when decorating a non-`static` element).
|
||||
*/
|
||||
addInitializer(initializer: (this: This) => void): void;
|
||||
|
||||
readonly metadata: DecoratorMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Context provided to a class setter decorator.
|
||||
* @template This The type on which the class element will be defined. For a static class element, this will be
|
||||
* the type of the constructor. For a non-static class element, this will be the type of the instance.
|
||||
* @template Value The type of the decorated class setter.
|
||||
*/
|
||||
interface ClassSetterDecoratorContext<
|
||||
This = unknown,
|
||||
Value = unknown,
|
||||
> {
|
||||
/** The kind of class element that was decorated. */
|
||||
readonly kind: "setter";
|
||||
|
||||
/** The name of the decorated class element. */
|
||||
readonly name: string | symbol;
|
||||
|
||||
/** A value indicating whether the class element is a static (`true`) or instance (`false`) element. */
|
||||
readonly static: boolean;
|
||||
|
||||
/** A value indicating whether the class element has a private name. */
|
||||
readonly private: boolean;
|
||||
|
||||
/** An object that can be used to access the current value of the class element at runtime. */
|
||||
readonly access: {
|
||||
/**
|
||||
* Determines whether an object has a property with the same name as the decorated element.
|
||||
*/
|
||||
has(object: This): boolean;
|
||||
/**
|
||||
* Invokes the setter on the provided object.
|
||||
*
|
||||
* @example
|
||||
* context.access.set(instance, value);
|
||||
*/
|
||||
set(object: This, value: Value): void;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a callback to be invoked either after static methods are defined but before
|
||||
* static initializers are run (when decorating a `static` element), or before instance
|
||||
* initializers are run (when decorating a non-`static` element).
|
||||
*/
|
||||
addInitializer(initializer: (this: This) => void): void;
|
||||
|
||||
readonly metadata: DecoratorMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Context provided to a class `accessor` field decorator.
|
||||
* @template This The type on which the class element will be defined. For a static class element, this will be
|
||||
* the type of the constructor. For a non-static class element, this will be the type of the instance.
|
||||
* @template Value The type of decorated class field.
|
||||
*/
|
||||
interface ClassAccessorDecoratorContext<
|
||||
This = unknown,
|
||||
Value = unknown,
|
||||
> {
|
||||
/** The kind of class element that was decorated. */
|
||||
readonly kind: "accessor";
|
||||
|
||||
/** The name of the decorated class element. */
|
||||
readonly name: string | symbol;
|
||||
|
||||
/** A value indicating whether the class element is a static (`true`) or instance (`false`) element. */
|
||||
readonly static: boolean;
|
||||
|
||||
/** A value indicating whether the class element has a private name. */
|
||||
readonly private: boolean;
|
||||
|
||||
/** An object that can be used to access the current value of the class element at runtime. */
|
||||
readonly access: {
|
||||
/**
|
||||
* Determines whether an object has a property with the same name as the decorated element.
|
||||
*/
|
||||
has(object: This): boolean;
|
||||
|
||||
/**
|
||||
* Invokes the getter on the provided object.
|
||||
*
|
||||
* @example
|
||||
* let value = context.access.get(instance);
|
||||
*/
|
||||
get(object: This): Value;
|
||||
|
||||
/**
|
||||
* Invokes the setter on the provided object.
|
||||
*
|
||||
* @example
|
||||
* context.access.set(instance, value);
|
||||
*/
|
||||
set(object: This, value: Value): void;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a callback to be invoked immediately after the auto `accessor` being
|
||||
* decorated is initialized (regardless if the `accessor` is `static` or not).
|
||||
*/
|
||||
addInitializer(initializer: (this: This) => void): void;
|
||||
|
||||
readonly metadata: DecoratorMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the target provided to class `accessor` field decorators.
|
||||
* @template This The `this` type to which the target applies.
|
||||
* @template Value The property type for the class `accessor` field.
|
||||
*/
|
||||
interface ClassAccessorDecoratorTarget<This, Value> {
|
||||
/**
|
||||
* Invokes the getter that was defined prior to decorator application.
|
||||
*
|
||||
* @example
|
||||
* let value = target.get.call(instance);
|
||||
*/
|
||||
get(this: This): Value;
|
||||
|
||||
/**
|
||||
* Invokes the setter that was defined prior to decorator application.
|
||||
*
|
||||
* @example
|
||||
* target.set.call(instance, value);
|
||||
*/
|
||||
set(this: This, value: Value): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the allowed return value from a class `accessor` field decorator.
|
||||
* @template This The `this` type to which the target applies.
|
||||
* @template Value The property type for the class `accessor` field.
|
||||
*/
|
||||
interface ClassAccessorDecoratorResult<This, Value> {
|
||||
/**
|
||||
* An optional replacement getter function. If not provided, the existing getter function is used instead.
|
||||
*/
|
||||
get?(this: This): Value;
|
||||
|
||||
/**
|
||||
* An optional replacement setter function. If not provided, the existing setter function is used instead.
|
||||
*/
|
||||
set?(this: This, value: Value): void;
|
||||
|
||||
/**
|
||||
* An optional initializer mutator that is invoked when the underlying field initializer is evaluated.
|
||||
* @param value The incoming initializer value.
|
||||
* @returns The replacement initializer value.
|
||||
*/
|
||||
init?(this: This, value: Value): Value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Context provided to a class field decorator.
|
||||
* @template This The type on which the class element will be defined. For a static class element, this will be
|
||||
* the type of the constructor. For a non-static class element, this will be the type of the instance.
|
||||
* @template Value The type of the decorated class field.
|
||||
*/
|
||||
interface ClassFieldDecoratorContext<
|
||||
This = unknown,
|
||||
Value = unknown,
|
||||
> {
|
||||
/** The kind of class element that was decorated. */
|
||||
readonly kind: "field";
|
||||
|
||||
/** The name of the decorated class element. */
|
||||
readonly name: string | symbol;
|
||||
|
||||
/** A value indicating whether the class element is a static (`true`) or instance (`false`) element. */
|
||||
readonly static: boolean;
|
||||
|
||||
/** A value indicating whether the class element has a private name. */
|
||||
readonly private: boolean;
|
||||
|
||||
/** An object that can be used to access the current value of the class element at runtime. */
|
||||
readonly access: {
|
||||
/**
|
||||
* Determines whether an object has a property with the same name as the decorated element.
|
||||
*/
|
||||
has(object: This): boolean;
|
||||
|
||||
/**
|
||||
* Gets the value of the field on the provided object.
|
||||
*/
|
||||
get(object: This): Value;
|
||||
|
||||
/**
|
||||
* Sets the value of the field on the provided object.
|
||||
*/
|
||||
set(object: This, value: Value): void;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a callback to be invoked immediately after the field being decorated
|
||||
* is initialized (regardless if the field is `static` or not).
|
||||
*/
|
||||
addInitializer(initializer: (this: This) => void): void;
|
||||
|
||||
readonly metadata: DecoratorMetadata;
|
||||
}
|
||||
20
tools/tsgo/internal/bundled/libs/lib.decorators.legacy.d.ts
vendored
Normal file
20
tools/tsgo/internal/bundled/libs/lib.decorators.legacy.d.ts
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
|
||||
declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
|
||||
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
|
||||
declare type ParameterDecorator = (target: Object, propertyKey: string | symbol | undefined, parameterIndex: number) => void;
|
||||
18
tools/tsgo/internal/bundled/libs/lib.dom.asynciterable.d.ts
vendored
Normal file
18
tools/tsgo/internal/bundled/libs/lib.dom.asynciterable.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
// This file's contents are now included in the main types file.
|
||||
// The file has been left for backward compatibility.
|
||||
45125
tools/tsgo/internal/bundled/libs/lib.dom.d.ts
vendored
Normal file
45125
tools/tsgo/internal/bundled/libs/lib.dom.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
18
tools/tsgo/internal/bundled/libs/lib.dom.iterable.d.ts
vendored
Normal file
18
tools/tsgo/internal/bundled/libs/lib.dom.iterable.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
// This file's contents are now included in the main types file.
|
||||
// The file has been left for backward compatibility.
|
||||
159
tools/tsgo/internal/bundled/libs/lib.es2015.collection.d.ts
vendored
Normal file
159
tools/tsgo/internal/bundled/libs/lib.es2015.collection.d.ts
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
interface Map<K, V> {
|
||||
/**
|
||||
* Removes all elements from the Map.
|
||||
*/
|
||||
clear(): void;
|
||||
/**
|
||||
* @returns true if an element in the Map existed and has been removed, or false if the element does not exist.
|
||||
*/
|
||||
delete(key: K): boolean;
|
||||
/**
|
||||
* Executes a provided function once per each key/value pair in the Map, in insertion order.
|
||||
*/
|
||||
forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;
|
||||
/**
|
||||
* Returns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
|
||||
* @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.
|
||||
*/
|
||||
get(key: K): V | undefined;
|
||||
/**
|
||||
* @returns boolean indicating whether an element with the specified key exists or not.
|
||||
*/
|
||||
has(key: K): boolean;
|
||||
/**
|
||||
* Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
|
||||
*/
|
||||
set(key: K, value: V): this;
|
||||
/**
|
||||
* @returns the number of elements in the Map.
|
||||
*/
|
||||
readonly size: number;
|
||||
}
|
||||
|
||||
interface MapConstructor {
|
||||
new (): Map<any, any>;
|
||||
new <K, V>(entries?: readonly (readonly [K, V])[] | null): Map<K, V>;
|
||||
readonly prototype: Map<any, any>;
|
||||
}
|
||||
declare var Map: MapConstructor;
|
||||
|
||||
interface ReadonlyMap<K, V> {
|
||||
forEach(callbackfn: (value: V, key: K, map: ReadonlyMap<K, V>) => void, thisArg?: any): void;
|
||||
get(key: K): V | undefined;
|
||||
has(key: K): boolean;
|
||||
readonly size: number;
|
||||
}
|
||||
|
||||
interface WeakMap<K extends WeakKey, V> {
|
||||
/**
|
||||
* Removes the specified element from the WeakMap.
|
||||
* @returns true if the element was successfully removed, or false if it was not present.
|
||||
*/
|
||||
delete(key: K): boolean;
|
||||
/**
|
||||
* @returns a specified element.
|
||||
*/
|
||||
get(key: K): V | undefined;
|
||||
/**
|
||||
* @returns a boolean indicating whether an element with the specified key exists or not.
|
||||
*/
|
||||
has(key: K): boolean;
|
||||
/**
|
||||
* Adds a new element with a specified key and value.
|
||||
* @param key Must be an object or symbol.
|
||||
*/
|
||||
set(key: K, value: V): this;
|
||||
}
|
||||
|
||||
interface WeakMapConstructor {
|
||||
new <K extends WeakKey = WeakKey, V = any>(entries?: readonly (readonly [K, V])[] | null): WeakMap<K, V>;
|
||||
readonly prototype: WeakMap<WeakKey, any>;
|
||||
}
|
||||
declare var WeakMap: WeakMapConstructor;
|
||||
|
||||
interface Set<T> {
|
||||
/**
|
||||
* Appends a new element with a specified value to the end of the Set.
|
||||
*/
|
||||
add(value: T): this;
|
||||
/**
|
||||
* Removes all elements from the Set.
|
||||
*/
|
||||
clear(): void;
|
||||
/**
|
||||
* Removes a specified value from the Set.
|
||||
* @returns Returns true if an element in the Set existed and has been removed, or false if the element does not exist.
|
||||
*/
|
||||
delete(value: T): boolean;
|
||||
/**
|
||||
* Executes a provided function once per each value in the Set object, in insertion order.
|
||||
*/
|
||||
forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any): void;
|
||||
/**
|
||||
* @returns a boolean indicating whether an element with the specified value exists in the Set or not.
|
||||
*/
|
||||
has(value: T): boolean;
|
||||
/**
|
||||
* @returns the number of (unique) elements in the Set.
|
||||
*/
|
||||
readonly size: number;
|
||||
}
|
||||
|
||||
interface SetConstructor {
|
||||
new <T = any>(values?: readonly T[] | null): Set<T>;
|
||||
readonly prototype: Set<any>;
|
||||
}
|
||||
declare var Set: SetConstructor;
|
||||
|
||||
interface ReadonlySet<T> {
|
||||
/**
|
||||
* Executes a provided function once per each value in the ReadonlySet object, in insertion order.
|
||||
*/
|
||||
forEach(callbackfn: (value: T, value2: T, set: ReadonlySet<T>) => void, thisArg?: any): void;
|
||||
/**
|
||||
* @returns a boolean indicating whether an element with the specified value exists in the Set or not.
|
||||
*/
|
||||
has(value: T): boolean;
|
||||
/**
|
||||
* @returns the number of (unique) elements in the Set.
|
||||
*/
|
||||
readonly size: number;
|
||||
}
|
||||
|
||||
interface WeakSet<T extends WeakKey> {
|
||||
/**
|
||||
* Appends a new value to the end of the WeakSet.
|
||||
*/
|
||||
add(value: T): this;
|
||||
/**
|
||||
* Removes the specified element from the WeakSet.
|
||||
* @returns Returns true if the element existed and has been removed, or false if the element does not exist.
|
||||
*/
|
||||
delete(value: T): boolean;
|
||||
/**
|
||||
* @returns a boolean indicating whether a value exists in the WeakSet or not.
|
||||
*/
|
||||
has(value: T): boolean;
|
||||
}
|
||||
|
||||
interface WeakSetConstructor {
|
||||
new <T extends WeakKey = WeakKey>(values?: readonly T[] | null): WeakSet<T>;
|
||||
readonly prototype: WeakSet<WeakKey>;
|
||||
}
|
||||
declare var WeakSet: WeakSetConstructor;
|
||||
595
tools/tsgo/internal/bundled/libs/lib.es2015.core.d.ts
vendored
Normal file
595
tools/tsgo/internal/bundled/libs/lib.es2015.core.d.ts
vendored
Normal file
@@ -0,0 +1,595 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
interface Array<T> {
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found, find
|
||||
* immediately returns that element value. Otherwise, find returns undefined.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find<S extends T>(predicate: (value: T, index: number, obj: T[]) => value is S, thisArg?: any): S | undefined;
|
||||
find(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): T | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found,
|
||||
* findIndex immediately returns that element index. Otherwise, findIndex returns -1.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): number;
|
||||
|
||||
/**
|
||||
* Changes all array elements from `start` to `end` index to a static `value` and returns the modified array
|
||||
* @param value value to fill array section with
|
||||
* @param start index to start filling the array at. If start is negative, it is treated as
|
||||
* length+start where length is the length of the array.
|
||||
* @param end index to stop filling the array at. If end is negative, it is treated as
|
||||
* length+end.
|
||||
*/
|
||||
fill(value: T, start?: number, end?: number): this;
|
||||
|
||||
/**
|
||||
* Returns the this object after copying a section of the array identified by start and end
|
||||
* to the same array starting at position target
|
||||
* @param target If target is negative, it is treated as length+target where length is the
|
||||
* length of the array.
|
||||
* @param start If start is negative, it is treated as length+start. If end is negative, it
|
||||
* is treated as length+end.
|
||||
* @param end If not specified, length of the this object is used as its default value.
|
||||
*/
|
||||
copyWithin(target: number, start: number, end?: number): this;
|
||||
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string;
|
||||
}
|
||||
|
||||
interface ArrayConstructor {
|
||||
/**
|
||||
* Creates an array from an array-like object.
|
||||
* @param arrayLike An array-like object to convert to an array.
|
||||
*/
|
||||
from<T>(arrayLike: ArrayLike<T>): T[];
|
||||
|
||||
/**
|
||||
* Creates an array from an iterable object.
|
||||
* @param arrayLike An array-like object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array from a set of elements.
|
||||
* @param items A set of elements to include in the new array object.
|
||||
*/
|
||||
of<T>(...items: T[]): T[];
|
||||
}
|
||||
|
||||
interface DateConstructor {
|
||||
new (value: number | string | Date): Date;
|
||||
}
|
||||
|
||||
interface Function {
|
||||
/**
|
||||
* Returns the name of the function. Function names are read-only and can not be changed.
|
||||
*/
|
||||
readonly name: string;
|
||||
}
|
||||
|
||||
interface Math {
|
||||
/**
|
||||
* Returns the number of leading zero bits in the 32-bit binary representation of a number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
clz32(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the result of 32-bit multiplication of two numbers.
|
||||
* @param x First number
|
||||
* @param y Second number
|
||||
*/
|
||||
imul(x: number, y: number): number;
|
||||
|
||||
/**
|
||||
* Returns the sign of x, indicating whether x is positive, negative, or zero.
|
||||
* @param x The numeric expression to test
|
||||
*/
|
||||
sign(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the base 10 logarithm of a number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
log10(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the base 2 logarithm of a number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
log2(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the natural logarithm of 1 + x.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
log1p(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the result of (e^x - 1), which is an implementation-dependent approximation to
|
||||
* subtracting 1 from the exponential function of x (e raised to the power of x, where e
|
||||
* is the base of the natural logarithms).
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
expm1(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic cosine of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
cosh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic sine of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
sinh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic tangent of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
tanh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic cosine of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
acosh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic sine of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
asinh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic tangent of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
atanh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the square root of the sum of squares of its arguments.
|
||||
* @param values Values to compute the square root for.
|
||||
* If no arguments are passed, the result is +0.
|
||||
* If there is only one argument, the result is the absolute value.
|
||||
* If any argument is +Infinity or -Infinity, the result is +Infinity.
|
||||
* If any argument is NaN, the result is NaN.
|
||||
* If all arguments are either +0 or −0, the result is +0.
|
||||
*/
|
||||
hypot(...values: number[]): number;
|
||||
|
||||
/**
|
||||
* Returns the integral part of the numeric expression x, removing any fractional digits.
|
||||
* If x is already an integer, the result is x.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
trunc(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the nearest single precision float representation of a number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
fround(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns an implementation-dependent approximation to the cube root of number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
cbrt(x: number): number;
|
||||
}
|
||||
|
||||
interface NumberConstructor {
|
||||
/**
|
||||
* The value of Number.EPSILON is the difference between 1 and the smallest value greater than 1
|
||||
* that is representable as a Number value, which is approximately:
|
||||
* 2.2204460492503130808472633361816 x 10−16.
|
||||
*/
|
||||
readonly EPSILON: number;
|
||||
|
||||
/**
|
||||
* Returns true if passed value is finite.
|
||||
* Unlike the global isFinite, Number.isFinite doesn't forcibly convert the parameter to a
|
||||
* number. Only finite values of the type number, result in true.
|
||||
* @param number A numeric value.
|
||||
*/
|
||||
isFinite(number: unknown): boolean;
|
||||
|
||||
/**
|
||||
* Returns true if the value passed is an integer, false otherwise.
|
||||
* @param number A numeric value.
|
||||
*/
|
||||
isInteger(number: unknown): boolean;
|
||||
|
||||
/**
|
||||
* Returns a Boolean value that indicates whether a value is the reserved value NaN (not a
|
||||
* number). Unlike the global isNaN(), Number.isNaN() doesn't forcefully convert the parameter
|
||||
* to a number. Only values of the type number, that are also NaN, result in true.
|
||||
* @param number A numeric value.
|
||||
*/
|
||||
isNaN(number: unknown): boolean;
|
||||
|
||||
/**
|
||||
* Returns true if the value passed is a safe integer.
|
||||
* @param number A numeric value.
|
||||
*/
|
||||
isSafeInteger(number: unknown): boolean;
|
||||
|
||||
/**
|
||||
* The value of the largest integer n such that n and n + 1 are both exactly representable as
|
||||
* a Number value.
|
||||
* The value of Number.MAX_SAFE_INTEGER is 9007199254740991 2^53 − 1.
|
||||
*/
|
||||
readonly MAX_SAFE_INTEGER: number;
|
||||
|
||||
/**
|
||||
* The value of the smallest integer n such that n and n − 1 are both exactly representable as
|
||||
* a Number value.
|
||||
* The value of Number.MIN_SAFE_INTEGER is −9007199254740991 (−(2^53 − 1)).
|
||||
*/
|
||||
readonly MIN_SAFE_INTEGER: number;
|
||||
|
||||
/**
|
||||
* Converts a string to a floating-point number.
|
||||
* @param string A string that contains a floating-point number.
|
||||
*/
|
||||
parseFloat(string: string): number;
|
||||
|
||||
/**
|
||||
* Converts A string to an integer.
|
||||
* @param string A string to convert into a number.
|
||||
* @param radix A value between 2 and 36 that specifies the base of the number in `string`.
|
||||
* If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal.
|
||||
* All other strings are considered decimal.
|
||||
*/
|
||||
parseInt(string: string, radix?: number): number;
|
||||
}
|
||||
|
||||
interface ObjectConstructor {
|
||||
/**
|
||||
* Copy the values of all of the enumerable own properties from one or more source objects to a
|
||||
* target object. Returns the target object.
|
||||
* @param target The target object to copy to.
|
||||
* @param source The source object from which to copy properties.
|
||||
*/
|
||||
assign<T extends {}, U>(target: T, source: U): T & U;
|
||||
|
||||
/**
|
||||
* Copy the values of all of the enumerable own properties from one or more source objects to a
|
||||
* target object. Returns the target object.
|
||||
* @param target The target object to copy to.
|
||||
* @param source1 The first source object from which to copy properties.
|
||||
* @param source2 The second source object from which to copy properties.
|
||||
*/
|
||||
assign<T extends {}, U, V>(target: T, source1: U, source2: V): T & U & V;
|
||||
|
||||
/**
|
||||
* Copy the values of all of the enumerable own properties from one or more source objects to a
|
||||
* target object. Returns the target object.
|
||||
* @param target The target object to copy to.
|
||||
* @param source1 The first source object from which to copy properties.
|
||||
* @param source2 The second source object from which to copy properties.
|
||||
* @param source3 The third source object from which to copy properties.
|
||||
*/
|
||||
assign<T extends {}, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
|
||||
|
||||
/**
|
||||
* Copy the values of all of the enumerable own properties from one or more source objects to a
|
||||
* target object. Returns the target object.
|
||||
* @param target The target object to copy to.
|
||||
* @param sources One or more source objects from which to copy properties
|
||||
*/
|
||||
assign(target: object, ...sources: any[]): any;
|
||||
|
||||
/**
|
||||
* Returns an array of all symbol properties found directly on object o.
|
||||
* @param o Object to retrieve the symbols from.
|
||||
*/
|
||||
getOwnPropertySymbols(o: any): symbol[];
|
||||
|
||||
/**
|
||||
* Returns the names of the enumerable string properties and methods of an object.
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
keys(o: {}): string[];
|
||||
|
||||
/**
|
||||
* Returns true if the values are the same value, false otherwise.
|
||||
* @param value1 The first value.
|
||||
* @param value2 The second value.
|
||||
*/
|
||||
is(value1: any, value2: any): boolean;
|
||||
|
||||
/**
|
||||
* Sets the prototype of a specified object o to object proto or null. Returns the object o.
|
||||
* @param o The object to change its prototype.
|
||||
* @param proto The value of the new prototype or null.
|
||||
*/
|
||||
setPrototypeOf(o: any, proto: object | null): any;
|
||||
}
|
||||
|
||||
interface ReadonlyArray<T> {
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found, find
|
||||
* immediately returns that element value. Otherwise, find returns undefined.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find<S extends T>(predicate: (value: T, index: number, obj: readonly T[]) => value is S, thisArg?: any): S | undefined;
|
||||
find(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): T | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found,
|
||||
* findIndex immediately returns that element index. Otherwise, findIndex returns -1.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): number;
|
||||
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string;
|
||||
}
|
||||
|
||||
interface RegExp {
|
||||
/**
|
||||
* Returns a string indicating the flags of the regular expression in question. This field is read-only.
|
||||
* The characters in this string are sequenced and concatenated in the following order:
|
||||
*
|
||||
* - "g" for global
|
||||
* - "i" for ignoreCase
|
||||
* - "m" for multiline
|
||||
* - "u" for unicode
|
||||
* - "y" for sticky
|
||||
*
|
||||
* If no flags are set, the value is the empty string.
|
||||
*/
|
||||
readonly flags: string;
|
||||
|
||||
/**
|
||||
* Returns a Boolean value indicating the state of the sticky flag (y) used with a regular
|
||||
* expression. Default is false. Read-only.
|
||||
*/
|
||||
readonly sticky: boolean;
|
||||
|
||||
/**
|
||||
* Returns a Boolean value indicating the state of the Unicode flag (u) used with a regular
|
||||
* expression. Default is false. Read-only.
|
||||
*/
|
||||
readonly unicode: boolean;
|
||||
}
|
||||
|
||||
interface RegExpConstructor {
|
||||
new (pattern: RegExp | string, flags?: string): RegExp;
|
||||
(pattern: RegExp | string, flags?: string): RegExp;
|
||||
}
|
||||
|
||||
interface String {
|
||||
/**
|
||||
* Returns a nonnegative integer Number less than 1114112 (0x110000) that is the code point
|
||||
* value of the UTF-16 encoded code point starting at the string element at position pos in
|
||||
* the String resulting from converting this object to a String.
|
||||
* If there is no element at that position, the result is undefined.
|
||||
* If a valid UTF-16 surrogate pair does not begin at pos, the result is the code unit at pos.
|
||||
*/
|
||||
codePointAt(pos: number): number | undefined;
|
||||
|
||||
/**
|
||||
* Returns true if searchString appears as a substring of the result of converting this
|
||||
* object to a String, at one or more positions that are
|
||||
* greater than or equal to position; otherwise, returns false.
|
||||
* @param searchString search string
|
||||
* @param position If position is undefined, 0 is assumed, so as to search all of the String.
|
||||
*/
|
||||
includes(searchString: string, position?: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns true if the sequence of elements of searchString converted to a String is the
|
||||
* same as the corresponding elements of this object (converted to a String) starting at
|
||||
* endPosition – length(this). Otherwise returns false.
|
||||
*/
|
||||
endsWith(searchString: string, endPosition?: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns the String value result of normalizing the string into the normalization form
|
||||
* named by form as specified in Unicode Standard Annex #15, Unicode Normalization Forms.
|
||||
* @param form Applicable values: "NFC", "NFD", "NFKC", or "NFKD", If not specified default
|
||||
* is "NFC"
|
||||
*/
|
||||
normalize(form: "NFC" | "NFD" | "NFKC" | "NFKD"): string;
|
||||
|
||||
/**
|
||||
* Returns the String value result of normalizing the string into the normalization form
|
||||
* named by form as specified in Unicode Standard Annex #15, Unicode Normalization Forms.
|
||||
* @param form Applicable values: "NFC", "NFD", "NFKC", or "NFKD", If not specified default
|
||||
* is "NFC"
|
||||
*/
|
||||
normalize(form?: string): string;
|
||||
|
||||
/**
|
||||
* Returns a String value that is made from count copies appended together. If count is 0,
|
||||
* the empty string is returned.
|
||||
* @param count number of copies to append
|
||||
*/
|
||||
repeat(count: number): string;
|
||||
|
||||
/**
|
||||
* Returns true if the sequence of elements of searchString converted to a String is the
|
||||
* same as the corresponding elements of this object (converted to a String) starting at
|
||||
* position. Otherwise returns false.
|
||||
*/
|
||||
startsWith(searchString: string, position?: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns an `<a>` HTML anchor element and sets the name attribute to the text value
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
* @param name
|
||||
*/
|
||||
anchor(name: string): string;
|
||||
|
||||
/**
|
||||
* Returns a `<big>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
big(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<blink>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
blink(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<b>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
bold(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<tt>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
fixed(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<font>` HTML element and sets the color attribute value
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
fontcolor(color: string): string;
|
||||
|
||||
/**
|
||||
* Returns a `<font>` HTML element and sets the size attribute value
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
fontsize(size: number): string;
|
||||
|
||||
/**
|
||||
* Returns a `<font>` HTML element and sets the size attribute value
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
fontsize(size: string): string;
|
||||
|
||||
/**
|
||||
* Returns an `<i>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
italics(): string;
|
||||
|
||||
/**
|
||||
* Returns an `<a>` HTML element and sets the href attribute value
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
link(url: string): string;
|
||||
|
||||
/**
|
||||
* Returns a `<small>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
small(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<strike>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
strike(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<sub>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
sub(): string;
|
||||
|
||||
/**
|
||||
* Returns a `<sup>` HTML element
|
||||
* @deprecated A legacy feature for browser compatibility
|
||||
*/
|
||||
sup(): string;
|
||||
}
|
||||
|
||||
interface StringConstructor {
|
||||
/**
|
||||
* Return the String value whose elements are, in order, the elements in the List elements.
|
||||
* If length is 0, the empty string is returned.
|
||||
*/
|
||||
fromCodePoint(...codePoints: number[]): string;
|
||||
|
||||
/**
|
||||
* String.raw is usually used as a tag function of a Tagged Template String. When called as
|
||||
* such, the first argument will be a well formed template call site object and the rest
|
||||
* parameter will contain the substitution values. It can also be called directly, for example,
|
||||
* to interleave strings and values from your own tag function, and in this case the only thing
|
||||
* it needs from the first argument is the raw property.
|
||||
* @param template A well-formed template string call site representation.
|
||||
* @param substitutions A set of substitution values.
|
||||
*/
|
||||
raw(template: { raw: readonly string[] | ArrayLike<string>; }, ...substitutions: any[]): string;
|
||||
}
|
||||
|
||||
interface Int8Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Uint8Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Uint8ClampedArray<TArrayBuffer extends ArrayBufferLike> {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Int16Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Uint16Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Int32Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Uint32Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Float32Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
|
||||
interface Float64Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions): string;
|
||||
}
|
||||
26
tools/tsgo/internal/bundled/libs/lib.es2015.d.ts
vendored
Normal file
26
tools/tsgo/internal/bundled/libs/lib.es2015.d.ts
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es5" />
|
||||
/// <reference lib="es2015.core" />
|
||||
/// <reference lib="es2015.collection" />
|
||||
/// <reference lib="es2015.iterable" />
|
||||
/// <reference lib="es2015.generator" />
|
||||
/// <reference lib="es2015.promise" />
|
||||
/// <reference lib="es2015.proxy" />
|
||||
/// <reference lib="es2015.reflect" />
|
||||
/// <reference lib="es2015.symbol" />
|
||||
/// <reference lib="es2015.symbol.wellknown" />
|
||||
75
tools/tsgo/internal/bundled/libs/lib.es2015.generator.d.ts
vendored
Normal file
75
tools/tsgo/internal/bundled/libs/lib.es2015.generator.d.ts
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2015.iterable" />
|
||||
|
||||
interface Generator<T = unknown, TReturn = any, TNext = any> extends IteratorObject<T, TReturn, TNext> {
|
||||
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
|
||||
next(...[value]: [] | [TNext]): IteratorResult<T, TReturn>;
|
||||
return(value: TReturn): IteratorResult<T, TReturn>;
|
||||
throw(e: any): IteratorResult<T, TReturn>;
|
||||
[Symbol.iterator](): Generator<T, TReturn, TNext>;
|
||||
}
|
||||
|
||||
interface GeneratorFunction {
|
||||
/**
|
||||
* Creates a new Generator object.
|
||||
* @param args A list of arguments the function accepts.
|
||||
*/
|
||||
new (...args: any[]): Generator;
|
||||
/**
|
||||
* Creates a new Generator object.
|
||||
* @param args A list of arguments the function accepts.
|
||||
*/
|
||||
(...args: any[]): Generator;
|
||||
/**
|
||||
* The length of the arguments.
|
||||
*/
|
||||
readonly length: number;
|
||||
/**
|
||||
* Returns the name of the function.
|
||||
*/
|
||||
readonly name: string;
|
||||
/**
|
||||
* A reference to the prototype.
|
||||
*/
|
||||
readonly prototype: Generator;
|
||||
}
|
||||
|
||||
interface GeneratorFunctionConstructor {
|
||||
/**
|
||||
* Creates a new Generator function.
|
||||
* @param args A list of arguments the function accepts.
|
||||
*/
|
||||
new (...args: string[]): GeneratorFunction;
|
||||
/**
|
||||
* Creates a new Generator function.
|
||||
* @param args A list of arguments the function accepts.
|
||||
*/
|
||||
(...args: string[]): GeneratorFunction;
|
||||
/**
|
||||
* The length of the arguments.
|
||||
*/
|
||||
readonly length: number;
|
||||
/**
|
||||
* Returns the name of the function.
|
||||
*/
|
||||
readonly name: string;
|
||||
/**
|
||||
* A reference to the prototype.
|
||||
*/
|
||||
readonly prototype: GeneratorFunction;
|
||||
}
|
||||
603
tools/tsgo/internal/bundled/libs/lib.es2015.iterable.d.ts
vendored
Normal file
603
tools/tsgo/internal/bundled/libs/lib.es2015.iterable.d.ts
vendored
Normal file
@@ -0,0 +1,603 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2015.symbol" />
|
||||
|
||||
interface SymbolConstructor {
|
||||
/**
|
||||
* A method that returns the default iterator for an object. Called by the semantics of the
|
||||
* for-of statement.
|
||||
*/
|
||||
readonly iterator: unique symbol;
|
||||
}
|
||||
|
||||
interface IteratorYieldResult<TYield> {
|
||||
done?: false;
|
||||
value: TYield;
|
||||
}
|
||||
|
||||
interface IteratorReturnResult<TReturn> {
|
||||
done: true;
|
||||
value: TReturn;
|
||||
}
|
||||
|
||||
type IteratorResult<T, TReturn = any> = IteratorYieldResult<T> | IteratorReturnResult<TReturn>;
|
||||
|
||||
interface Iterator<T, TReturn = any, TNext = any> {
|
||||
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
|
||||
next(...[value]: [] | [TNext]): IteratorResult<T, TReturn>;
|
||||
return?(value?: TReturn): IteratorResult<T, TReturn>;
|
||||
throw?(e?: any): IteratorResult<T, TReturn>;
|
||||
}
|
||||
|
||||
interface Iterable<T, TReturn = any, TNext = any> {
|
||||
[Symbol.iterator](): Iterator<T, TReturn, TNext>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes a user-defined {@link Iterator} that is also iterable.
|
||||
*/
|
||||
interface IterableIterator<T, TReturn = any, TNext = any> extends Iterator<T, TReturn, TNext> {
|
||||
[Symbol.iterator](): IterableIterator<T, TReturn, TNext>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes an {@link Iterator} produced by the runtime that inherits from the intrinsic `Iterator.prototype`.
|
||||
*/
|
||||
interface IteratorObject<T, TReturn = unknown, TNext = unknown> extends Iterator<T, TReturn, TNext> {
|
||||
[Symbol.iterator](): IteratorObject<T, TReturn, TNext>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the `TReturn` type used for built-in iterators produced by `Array`, `Map`, `Set`, and others.
|
||||
* This is `undefined` when `strictBuiltInIteratorReturn` is `true`; otherwise, this is `any`.
|
||||
*/
|
||||
type BuiltinIteratorReturn = intrinsic;
|
||||
|
||||
interface ArrayIterator<T> extends IteratorObject<T, BuiltinIteratorReturn, unknown> {
|
||||
[Symbol.iterator](): ArrayIterator<T>;
|
||||
}
|
||||
|
||||
interface Array<T> {
|
||||
/** Iterator */
|
||||
[Symbol.iterator](): ArrayIterator<T>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): ArrayIterator<[number, T]>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of keys in the array
|
||||
*/
|
||||
keys(): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of values in the array
|
||||
*/
|
||||
values(): ArrayIterator<T>;
|
||||
}
|
||||
|
||||
interface ArrayConstructor {
|
||||
/**
|
||||
* Creates an array from an iterable object.
|
||||
* @param iterable An iterable object to convert to an array.
|
||||
*/
|
||||
from<T>(iterable: Iterable<T> | ArrayLike<T>): T[];
|
||||
|
||||
/**
|
||||
* Creates an array from an iterable object.
|
||||
* @param iterable An iterable object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T, U>(iterable: Iterable<T> | ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[];
|
||||
}
|
||||
|
||||
interface ReadonlyArray<T> {
|
||||
/** Iterator of values in the array. */
|
||||
[Symbol.iterator](): ArrayIterator<T>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): ArrayIterator<[number, T]>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of keys in the array
|
||||
*/
|
||||
keys(): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of values in the array
|
||||
*/
|
||||
values(): ArrayIterator<T>;
|
||||
}
|
||||
|
||||
interface IArguments {
|
||||
/** Iterator */
|
||||
[Symbol.iterator](): ArrayIterator<any>;
|
||||
}
|
||||
|
||||
interface MapIterator<T> extends IteratorObject<T, BuiltinIteratorReturn, unknown> {
|
||||
[Symbol.iterator](): MapIterator<T>;
|
||||
}
|
||||
|
||||
interface Map<K, V> {
|
||||
/** Returns an iterable of entries in the map. */
|
||||
[Symbol.iterator](): MapIterator<[K, V]>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of key, value pairs for every entry in the map.
|
||||
*/
|
||||
entries(): MapIterator<[K, V]>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of keys in the map
|
||||
*/
|
||||
keys(): MapIterator<K>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of values in the map
|
||||
*/
|
||||
values(): MapIterator<V>;
|
||||
}
|
||||
|
||||
interface ReadonlyMap<K, V> {
|
||||
/** Returns an iterable of entries in the map. */
|
||||
[Symbol.iterator](): MapIterator<[K, V]>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of key, value pairs for every entry in the map.
|
||||
*/
|
||||
entries(): MapIterator<[K, V]>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of keys in the map
|
||||
*/
|
||||
keys(): MapIterator<K>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of values in the map
|
||||
*/
|
||||
values(): MapIterator<V>;
|
||||
}
|
||||
|
||||
interface MapConstructor {
|
||||
new (): Map<any, any>;
|
||||
new <K, V>(iterable?: Iterable<readonly [K, V]> | null): Map<K, V>;
|
||||
}
|
||||
|
||||
interface WeakMap<K extends WeakKey, V> {}
|
||||
|
||||
interface WeakMapConstructor {
|
||||
new <K extends WeakKey = WeakKey, V = any>(iterable?: Iterable<readonly [K, V]> | null): WeakMap<K, V>;
|
||||
}
|
||||
|
||||
interface SetIterator<T> extends IteratorObject<T, BuiltinIteratorReturn, unknown> {
|
||||
[Symbol.iterator](): SetIterator<T>;
|
||||
}
|
||||
|
||||
interface Set<T> {
|
||||
/** Iterates over values in the set. */
|
||||
[Symbol.iterator](): SetIterator<T>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of [v,v] pairs for every value `v` in the set.
|
||||
*/
|
||||
entries(): SetIterator<[T, T]>;
|
||||
|
||||
/**
|
||||
* Despite its name, returns an iterable of the values in the set.
|
||||
*/
|
||||
keys(): SetIterator<T>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of values in the set.
|
||||
*/
|
||||
values(): SetIterator<T>;
|
||||
}
|
||||
|
||||
interface ReadonlySet<T> {
|
||||
/** Iterates over values in the set. */
|
||||
[Symbol.iterator](): SetIterator<T>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of [v,v] pairs for every value `v` in the set.
|
||||
*/
|
||||
entries(): SetIterator<[T, T]>;
|
||||
|
||||
/**
|
||||
* Despite its name, returns an iterable of the values in the set.
|
||||
*/
|
||||
keys(): SetIterator<T>;
|
||||
|
||||
/**
|
||||
* Returns an iterable of values in the set.
|
||||
*/
|
||||
values(): SetIterator<T>;
|
||||
}
|
||||
|
||||
interface SetConstructor {
|
||||
new <T>(iterable?: Iterable<T> | null): Set<T>;
|
||||
}
|
||||
|
||||
interface WeakSet<T extends WeakKey> {}
|
||||
|
||||
interface WeakSetConstructor {
|
||||
new <T extends WeakKey = WeakKey>(iterable: Iterable<T>): WeakSet<T>;
|
||||
}
|
||||
|
||||
interface Promise<T> {}
|
||||
|
||||
interface PromiseConstructor {
|
||||
/**
|
||||
* Creates a Promise that is resolved with an array of results when all of the provided Promises
|
||||
* resolve, or rejected when any Promise is rejected.
|
||||
* @param values An iterable of Promises.
|
||||
* @returns A new Promise.
|
||||
*/
|
||||
all<T>(values: Iterable<T | PromiseLike<T>>): Promise<Awaited<T>[]>;
|
||||
|
||||
/**
|
||||
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
|
||||
* or rejected.
|
||||
* @param values An iterable of Promises.
|
||||
* @returns A new Promise.
|
||||
*/
|
||||
race<T>(values: Iterable<T | PromiseLike<T>>): Promise<Awaited<T>>;
|
||||
}
|
||||
|
||||
interface StringIterator<T> extends IteratorObject<T, BuiltinIteratorReturn, unknown> {
|
||||
[Symbol.iterator](): StringIterator<T>;
|
||||
}
|
||||
|
||||
interface String {
|
||||
/** Iterator */
|
||||
[Symbol.iterator](): StringIterator<string>;
|
||||
}
|
||||
|
||||
interface Int8Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
[Symbol.iterator](): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): ArrayIterator<[number, number]>;
|
||||
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): ArrayIterator<number>;
|
||||
}
|
||||
|
||||
interface Int8ArrayConstructor {
|
||||
new (elements: Iterable<number>): Int8Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
*/
|
||||
from(elements: Iterable<number>): Int8Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T>(elements: Iterable<T>, mapfn?: (v: T, k: number) => number, thisArg?: any): Int8Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Uint8Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
[Symbol.iterator](): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): ArrayIterator<[number, number]>;
|
||||
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): ArrayIterator<number>;
|
||||
}
|
||||
|
||||
interface Uint8ArrayConstructor {
|
||||
new (elements: Iterable<number>): Uint8Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
*/
|
||||
from(elements: Iterable<number>): Uint8Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T>(elements: Iterable<T>, mapfn?: (v: T, k: number) => number, thisArg?: any): Uint8Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Uint8ClampedArray<TArrayBuffer extends ArrayBufferLike> {
|
||||
[Symbol.iterator](): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): ArrayIterator<[number, number]>;
|
||||
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): ArrayIterator<number>;
|
||||
}
|
||||
|
||||
interface Uint8ClampedArrayConstructor {
|
||||
new (elements: Iterable<number>): Uint8ClampedArray<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
*/
|
||||
from(elements: Iterable<number>): Uint8ClampedArray<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T>(elements: Iterable<T>, mapfn?: (v: T, k: number) => number, thisArg?: any): Uint8ClampedArray<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Int16Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
[Symbol.iterator](): ArrayIterator<number>;
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): ArrayIterator<[number, number]>;
|
||||
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): ArrayIterator<number>;
|
||||
}
|
||||
|
||||
interface Int16ArrayConstructor {
|
||||
new (elements: Iterable<number>): Int16Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
*/
|
||||
from(elements: Iterable<number>): Int16Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T>(elements: Iterable<T>, mapfn?: (v: T, k: number) => number, thisArg?: any): Int16Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Uint16Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
[Symbol.iterator](): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): ArrayIterator<[number, number]>;
|
||||
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): ArrayIterator<number>;
|
||||
}
|
||||
|
||||
interface Uint16ArrayConstructor {
|
||||
new (elements: Iterable<number>): Uint16Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
*/
|
||||
from(elements: Iterable<number>): Uint16Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T>(elements: Iterable<T>, mapfn?: (v: T, k: number) => number, thisArg?: any): Uint16Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Int32Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
[Symbol.iterator](): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): ArrayIterator<[number, number]>;
|
||||
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): ArrayIterator<number>;
|
||||
}
|
||||
|
||||
interface Int32ArrayConstructor {
|
||||
new (elements: Iterable<number>): Int32Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
*/
|
||||
from(elements: Iterable<number>): Int32Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T>(elements: Iterable<T>, mapfn?: (v: T, k: number) => number, thisArg?: any): Int32Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Uint32Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
[Symbol.iterator](): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): ArrayIterator<[number, number]>;
|
||||
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): ArrayIterator<number>;
|
||||
}
|
||||
|
||||
interface Uint32ArrayConstructor {
|
||||
new (elements: Iterable<number>): Uint32Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
*/
|
||||
from(elements: Iterable<number>): Uint32Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T>(elements: Iterable<T>, mapfn?: (v: T, k: number) => number, thisArg?: any): Uint32Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Float32Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
[Symbol.iterator](): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): ArrayIterator<[number, number]>;
|
||||
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): ArrayIterator<number>;
|
||||
}
|
||||
|
||||
interface Float32ArrayConstructor {
|
||||
new (elements: Iterable<number>): Float32Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
*/
|
||||
from(elements: Iterable<number>): Float32Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T>(elements: Iterable<T>, mapfn?: (v: T, k: number) => number, thisArg?: any): Float32Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Float64Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
[Symbol.iterator](): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): ArrayIterator<[number, number]>;
|
||||
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): ArrayIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): ArrayIterator<number>;
|
||||
}
|
||||
|
||||
interface Float64ArrayConstructor {
|
||||
new (elements: Iterable<number>): Float64Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
*/
|
||||
from(elements: Iterable<number>): Float64Array<ArrayBuffer>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like or iterable object.
|
||||
* @param elements An iterable object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T>(elements: Iterable<T>, mapfn?: (v: T, k: number) => number, thisArg?: any): Float64Array<ArrayBuffer>;
|
||||
}
|
||||
79
tools/tsgo/internal/bundled/libs/lib.es2015.promise.d.ts
vendored
Normal file
79
tools/tsgo/internal/bundled/libs/lib.es2015.promise.d.ts
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
interface PromiseConstructor {
|
||||
/**
|
||||
* A reference to the prototype.
|
||||
*/
|
||||
readonly prototype: Promise<any>;
|
||||
|
||||
/**
|
||||
* Creates a new Promise.
|
||||
* @param executor A callback used to initialize the promise. This callback is passed two arguments:
|
||||
* a resolve callback used to resolve the promise with a value or the result of another promise,
|
||||
* and a reject callback used to reject the promise with a provided reason or error.
|
||||
*/
|
||||
new <T>(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;
|
||||
|
||||
/**
|
||||
* Creates a Promise that is resolved with an array of results when all of the provided Promises
|
||||
* resolve, or rejected when any Promise is rejected.
|
||||
* @param values An array of Promises.
|
||||
* @returns A new Promise.
|
||||
*/
|
||||
all<T extends readonly unknown[] | []>(values: T): Promise<{ -readonly [P in keyof T]: Awaited<T[P]>; }>;
|
||||
|
||||
// see: lib.es2015.iterable.d.ts
|
||||
// all<T>(values: Iterable<T | PromiseLike<T>>): Promise<Awaited<T>[]>;
|
||||
|
||||
/**
|
||||
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
|
||||
* or rejected.
|
||||
* @param values An array of Promises.
|
||||
* @returns A new Promise.
|
||||
*/
|
||||
race<T extends readonly unknown[] | []>(values: T): Promise<Awaited<T[number]>>;
|
||||
|
||||
// see: lib.es2015.iterable.d.ts
|
||||
// race<T>(values: Iterable<T | PromiseLike<T>>): Promise<Awaited<T>>;
|
||||
|
||||
/**
|
||||
* Creates a new rejected promise for the provided reason.
|
||||
* @param reason The reason the promise was rejected.
|
||||
* @returns A new rejected Promise.
|
||||
*/
|
||||
reject<T = never>(reason?: any): Promise<T>;
|
||||
|
||||
/**
|
||||
* Creates a new resolved promise.
|
||||
* @returns A resolved promise.
|
||||
*/
|
||||
resolve(): Promise<void>;
|
||||
/**
|
||||
* Creates a new resolved promise for the provided value.
|
||||
* @param value A promise.
|
||||
* @returns A promise whose internal state matches the provided promise.
|
||||
*/
|
||||
resolve<T>(value: T): Promise<Awaited<T>>;
|
||||
/**
|
||||
* Creates a new resolved promise for the provided value.
|
||||
* @param value A promise.
|
||||
* @returns A promise whose internal state matches the provided promise.
|
||||
*/
|
||||
resolve<T>(value: T | PromiseLike<T>): Promise<Awaited<T>>;
|
||||
}
|
||||
|
||||
declare var Promise: PromiseConstructor;
|
||||
126
tools/tsgo/internal/bundled/libs/lib.es2015.proxy.d.ts
vendored
Normal file
126
tools/tsgo/internal/bundled/libs/lib.es2015.proxy.d.ts
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
interface ProxyHandler<T extends object> {
|
||||
/**
|
||||
* A trap method for a function call.
|
||||
* @param target The original callable object which is being proxied.
|
||||
*/
|
||||
apply?(target: T, thisArg: any, argArray: any[]): any;
|
||||
|
||||
/**
|
||||
* A trap for the `new` operator.
|
||||
* @param target The original object which is being proxied.
|
||||
* @param newTarget The constructor that was originally called.
|
||||
*/
|
||||
construct?(target: T, argArray: any[], newTarget: Function): object;
|
||||
|
||||
/**
|
||||
* A trap for `Object.defineProperty()`.
|
||||
* @param target The original object which is being proxied.
|
||||
* @returns A `Boolean` indicating whether or not the property has been defined.
|
||||
*/
|
||||
defineProperty?(target: T, property: string | symbol, attributes: PropertyDescriptor): boolean;
|
||||
|
||||
/**
|
||||
* A trap for the `delete` operator.
|
||||
* @param target The original object which is being proxied.
|
||||
* @param p The name or `Symbol` of the property to delete.
|
||||
* @returns A `Boolean` indicating whether or not the property was deleted.
|
||||
*/
|
||||
deleteProperty?(target: T, p: string | symbol): boolean;
|
||||
|
||||
/**
|
||||
* A trap for getting a property value.
|
||||
* @param target The original object which is being proxied.
|
||||
* @param p The name or `Symbol` of the property to get.
|
||||
* @param receiver The proxy or an object that inherits from the proxy.
|
||||
*/
|
||||
get?(target: T, p: string | symbol, receiver: any): any;
|
||||
|
||||
/**
|
||||
* A trap for `Object.getOwnPropertyDescriptor()`.
|
||||
* @param target The original object which is being proxied.
|
||||
* @param p The name of the property whose description should be retrieved.
|
||||
*/
|
||||
getOwnPropertyDescriptor?(target: T, p: string | symbol): PropertyDescriptor | undefined;
|
||||
|
||||
/**
|
||||
* A trap for the `[[GetPrototypeOf]]` internal method.
|
||||
* @param target The original object which is being proxied.
|
||||
*/
|
||||
getPrototypeOf?(target: T): object | null;
|
||||
|
||||
/**
|
||||
* A trap for the `in` operator.
|
||||
* @param target The original object which is being proxied.
|
||||
* @param p The name or `Symbol` of the property to check for existence.
|
||||
*/
|
||||
has?(target: T, p: string | symbol): boolean;
|
||||
|
||||
/**
|
||||
* A trap for `Object.isExtensible()`.
|
||||
* @param target The original object which is being proxied.
|
||||
*/
|
||||
isExtensible?(target: T): boolean;
|
||||
|
||||
/**
|
||||
* A trap for `Reflect.ownKeys()`.
|
||||
* @param target The original object which is being proxied.
|
||||
*/
|
||||
ownKeys?(target: T): ArrayLike<string | symbol>;
|
||||
|
||||
/**
|
||||
* A trap for `Object.preventExtensions()`.
|
||||
* @param target The original object which is being proxied.
|
||||
*/
|
||||
preventExtensions?(target: T): boolean;
|
||||
|
||||
/**
|
||||
* A trap for setting a property value.
|
||||
* @param target The original object which is being proxied.
|
||||
* @param p The name or `Symbol` of the property to set.
|
||||
* @param receiver The object to which the assignment was originally directed.
|
||||
* @returns A `Boolean` indicating whether or not the property was set.
|
||||
*/
|
||||
set?(target: T, p: string | symbol, newValue: any, receiver: any): boolean;
|
||||
|
||||
/**
|
||||
* A trap for `Object.setPrototypeOf()`.
|
||||
* @param target The original object which is being proxied.
|
||||
* @param newPrototype The object's new prototype or `null`.
|
||||
*/
|
||||
setPrototypeOf?(target: T, v: object | null): boolean;
|
||||
}
|
||||
|
||||
interface ProxyConstructor {
|
||||
/**
|
||||
* Creates a revocable Proxy object.
|
||||
* @param target A target object to wrap with Proxy.
|
||||
* @param handler An object whose properties define the behavior of Proxy when an operation is attempted on it.
|
||||
*/
|
||||
revocable<T extends object>(target: T, handler: ProxyHandler<T>): { proxy: T; revoke: () => void; };
|
||||
|
||||
/**
|
||||
* Creates a Proxy object. The Proxy object allows you to create an object that can be used in place of the
|
||||
* original object, but which may redefine fundamental Object operations like getting, setting, and defining
|
||||
* properties. Proxy objects are commonly used to log property accesses, validate, format, or sanitize inputs.
|
||||
* @param target A target object to wrap with Proxy.
|
||||
* @param handler An object whose properties define the behavior of Proxy when an operation is attempted on it.
|
||||
*/
|
||||
new <T extends object>(target: T, handler: ProxyHandler<T>): T;
|
||||
}
|
||||
declare var Proxy: ProxyConstructor;
|
||||
142
tools/tsgo/internal/bundled/libs/lib.es2015.reflect.d.ts
vendored
Normal file
142
tools/tsgo/internal/bundled/libs/lib.es2015.reflect.d.ts
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
declare namespace Reflect {
|
||||
/**
|
||||
* Calls the function with the specified object as the this value
|
||||
* and the elements of specified array as the arguments.
|
||||
* @param target The function to call.
|
||||
* @param thisArgument The object to be used as the this object.
|
||||
* @param argumentsList An array of argument values to be passed to the function.
|
||||
*/
|
||||
function apply<T, A extends readonly any[], R>(
|
||||
target: (this: T, ...args: A) => R,
|
||||
thisArgument: T,
|
||||
argumentsList: Readonly<A>,
|
||||
): R;
|
||||
function apply(target: Function, thisArgument: any, argumentsList: ArrayLike<any>): any;
|
||||
|
||||
/**
|
||||
* Constructs the target with the elements of specified array as the arguments
|
||||
* and the specified constructor as the `new.target` value.
|
||||
* @param target The constructor to invoke.
|
||||
* @param argumentsList An array of argument values to be passed to the constructor.
|
||||
* @param newTarget The constructor to be used as the `new.target` object.
|
||||
*/
|
||||
function construct<A extends readonly any[], R>(
|
||||
target: new (...args: A) => R,
|
||||
argumentsList: Readonly<A>,
|
||||
newTarget?: new (...args: any) => any,
|
||||
): R;
|
||||
function construct(target: Function, argumentsList: ArrayLike<any>, newTarget?: Function): any;
|
||||
|
||||
/**
|
||||
* Adds a property to an object, or modifies attributes of an existing property.
|
||||
* @param target Object on which to add or modify the property. This can be a native JavaScript object
|
||||
* (that is, a user-defined object or a built in object) or a DOM object.
|
||||
* @param propertyKey The property name.
|
||||
* @param attributes Descriptor for the property. It can be for a data property or an accessor property.
|
||||
*/
|
||||
function defineProperty(target: object, propertyKey: PropertyKey, attributes: PropertyDescriptor & ThisType<any>): boolean;
|
||||
|
||||
/**
|
||||
* Removes a property from an object, equivalent to `delete target[propertyKey]`,
|
||||
* except it won't throw if `target[propertyKey]` is non-configurable.
|
||||
* @param target Object from which to remove the own property.
|
||||
* @param propertyKey The property name.
|
||||
*/
|
||||
function deleteProperty(target: object, propertyKey: PropertyKey): boolean;
|
||||
|
||||
/**
|
||||
* Gets the property of target, equivalent to `target[propertyKey]` when `receiver === target`.
|
||||
* @param target Object that contains the property on itself or in its prototype chain.
|
||||
* @param propertyKey The property name.
|
||||
* @param receiver The reference to use as the `this` value in the getter function,
|
||||
* if `target[propertyKey]` is an accessor property.
|
||||
*/
|
||||
function get<T extends object, P extends PropertyKey>(
|
||||
target: T,
|
||||
propertyKey: P,
|
||||
receiver?: unknown,
|
||||
): P extends keyof T ? T[P] : any;
|
||||
|
||||
/**
|
||||
* Gets the own property descriptor of the specified object.
|
||||
* An own property descriptor is one that is defined directly on the object and is not inherited from the object's prototype.
|
||||
* @param target Object that contains the property.
|
||||
* @param propertyKey The property name.
|
||||
*/
|
||||
function getOwnPropertyDescriptor<T extends object, P extends PropertyKey>(
|
||||
target: T,
|
||||
propertyKey: P,
|
||||
): TypedPropertyDescriptor<P extends keyof T ? T[P] : any> | undefined;
|
||||
|
||||
/**
|
||||
* Returns the prototype of an object.
|
||||
* @param target The object that references the prototype.
|
||||
*/
|
||||
function getPrototypeOf(target: object): object | null;
|
||||
|
||||
/**
|
||||
* Equivalent to `propertyKey in target`.
|
||||
* @param target Object that contains the property on itself or in its prototype chain.
|
||||
* @param propertyKey Name of the property.
|
||||
*/
|
||||
function has(target: object, propertyKey: PropertyKey): boolean;
|
||||
|
||||
/**
|
||||
* Returns a value that indicates whether new properties can be added to an object.
|
||||
* @param target Object to test.
|
||||
*/
|
||||
function isExtensible(target: object): boolean;
|
||||
|
||||
/**
|
||||
* Returns the string and symbol keys of the own properties of an object. The own properties of an object
|
||||
* are those that are defined directly on that object, and are not inherited from the object's prototype.
|
||||
* @param target Object that contains the own properties.
|
||||
*/
|
||||
function ownKeys(target: object): (string | symbol)[];
|
||||
|
||||
/**
|
||||
* Prevents the addition of new properties to an object.
|
||||
* @param target Object to make non-extensible.
|
||||
* @return Whether the object has been made non-extensible.
|
||||
*/
|
||||
function preventExtensions(target: object): boolean;
|
||||
|
||||
/**
|
||||
* Sets the property of target, equivalent to `target[propertyKey] = value` when `receiver === target`.
|
||||
* @param target Object that contains the property on itself or in its prototype chain.
|
||||
* @param propertyKey Name of the property.
|
||||
* @param receiver The reference to use as the `this` value in the setter function,
|
||||
* if `target[propertyKey]` is an accessor property.
|
||||
*/
|
||||
function set<T extends object, P extends PropertyKey>(
|
||||
target: T,
|
||||
propertyKey: P,
|
||||
value: P extends keyof T ? T[P] : any,
|
||||
receiver?: any,
|
||||
): boolean;
|
||||
function set(target: object, propertyKey: PropertyKey, value: any, receiver?: any): boolean;
|
||||
|
||||
/**
|
||||
* Sets the prototype of a specified object o to object proto or null.
|
||||
* @param target The object to change its prototype.
|
||||
* @param proto The value of the new prototype or null.
|
||||
* @return Whether setting the prototype was successful.
|
||||
*/
|
||||
function setPrototypeOf(target: object, proto: object | null): boolean;
|
||||
}
|
||||
44
tools/tsgo/internal/bundled/libs/lib.es2015.symbol.d.ts
vendored
Normal file
44
tools/tsgo/internal/bundled/libs/lib.es2015.symbol.d.ts
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
interface SymbolConstructor {
|
||||
/**
|
||||
* A reference to the prototype.
|
||||
*/
|
||||
readonly prototype: Symbol;
|
||||
|
||||
/**
|
||||
* Returns a new unique Symbol value.
|
||||
* @param description Description of the new Symbol object.
|
||||
*/
|
||||
(description?: string | number): symbol;
|
||||
|
||||
/**
|
||||
* Returns a Symbol object from the global symbol registry matching the given key if found.
|
||||
* Otherwise, returns a new symbol with this key.
|
||||
* @param key key to search for.
|
||||
*/
|
||||
for(key: string): symbol;
|
||||
|
||||
/**
|
||||
* Returns a key from the global symbol registry matching the given Symbol if found.
|
||||
* Otherwise, returns undefined.
|
||||
* @param sym Symbol to find the key for.
|
||||
*/
|
||||
keyFor(sym: symbol): string | undefined;
|
||||
}
|
||||
|
||||
declare var Symbol: SymbolConstructor;
|
||||
324
tools/tsgo/internal/bundled/libs/lib.es2015.symbol.wellknown.d.ts
vendored
Normal file
324
tools/tsgo/internal/bundled/libs/lib.es2015.symbol.wellknown.d.ts
vendored
Normal file
@@ -0,0 +1,324 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2015.symbol" />
|
||||
|
||||
interface SymbolConstructor {
|
||||
/**
|
||||
* A method that determines if a constructor object recognizes an object as one of the
|
||||
* constructor’s instances. Called by the semantics of the instanceof operator.
|
||||
*/
|
||||
readonly hasInstance: unique symbol;
|
||||
|
||||
/**
|
||||
* A Boolean value that if true indicates that an object should flatten to its array elements
|
||||
* by Array.prototype.concat.
|
||||
*/
|
||||
readonly isConcatSpreadable: unique symbol;
|
||||
|
||||
/**
|
||||
* A regular expression method that matches the regular expression against a string. Called
|
||||
* by the String.prototype.match method.
|
||||
*/
|
||||
readonly match: unique symbol;
|
||||
|
||||
/**
|
||||
* A regular expression method that replaces matched substrings of a string. Called by the
|
||||
* String.prototype.replace method.
|
||||
*/
|
||||
readonly replace: unique symbol;
|
||||
|
||||
/**
|
||||
* A regular expression method that returns the index within a string that matches the
|
||||
* regular expression. Called by the String.prototype.search method.
|
||||
*/
|
||||
readonly search: unique symbol;
|
||||
|
||||
/**
|
||||
* A function valued property that is the constructor function that is used to create
|
||||
* derived objects.
|
||||
*/
|
||||
readonly species: unique symbol;
|
||||
|
||||
/**
|
||||
* A regular expression method that splits a string at the indices that match the regular
|
||||
* expression. Called by the String.prototype.split method.
|
||||
*/
|
||||
readonly split: unique symbol;
|
||||
|
||||
/**
|
||||
* A method that converts an object to a corresponding primitive value.
|
||||
* Called by the ToPrimitive abstract operation.
|
||||
*/
|
||||
readonly toPrimitive: unique symbol;
|
||||
|
||||
/**
|
||||
* A String value that is used in the creation of the default string description of an object.
|
||||
* Called by the built-in method Object.prototype.toString.
|
||||
*/
|
||||
readonly toStringTag: unique symbol;
|
||||
|
||||
/**
|
||||
* An Object whose truthy properties are properties that are excluded from the 'with'
|
||||
* environment bindings of the associated objects.
|
||||
*/
|
||||
readonly unscopables: unique symbol;
|
||||
}
|
||||
|
||||
interface Symbol {
|
||||
/**
|
||||
* Converts a Symbol object to a symbol.
|
||||
*/
|
||||
[Symbol.toPrimitive](hint: string): symbol;
|
||||
|
||||
readonly [Symbol.toStringTag]: string;
|
||||
}
|
||||
|
||||
interface Array<T> {
|
||||
/**
|
||||
* Is an object whose properties have the value 'true'
|
||||
* when they will be absent when used in a 'with' statement.
|
||||
*/
|
||||
readonly [Symbol.unscopables]: {
|
||||
[K in keyof any[]]?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
interface ReadonlyArray<T> {
|
||||
/**
|
||||
* Is an object whose properties have the value 'true'
|
||||
* when they will be absent when used in a 'with' statement.
|
||||
*/
|
||||
readonly [Symbol.unscopables]: {
|
||||
[K in keyof readonly any[]]?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
interface Date {
|
||||
/**
|
||||
* Converts a Date object to a string.
|
||||
*/
|
||||
[Symbol.toPrimitive](hint: "default"): string;
|
||||
/**
|
||||
* Converts a Date object to a string.
|
||||
*/
|
||||
[Symbol.toPrimitive](hint: "string"): string;
|
||||
/**
|
||||
* Converts a Date object to a number.
|
||||
*/
|
||||
[Symbol.toPrimitive](hint: "number"): number;
|
||||
/**
|
||||
* Converts a Date object to a string or number.
|
||||
*
|
||||
* @param hint The strings "number", "string", or "default" to specify what primitive to return.
|
||||
*
|
||||
* @throws {TypeError} If 'hint' was given something other than "number", "string", or "default".
|
||||
* @returns A number if 'hint' was "number", a string if 'hint' was "string" or "default".
|
||||
*/
|
||||
[Symbol.toPrimitive](hint: string): string | number;
|
||||
}
|
||||
|
||||
interface Map<K, V> {
|
||||
readonly [Symbol.toStringTag]: string;
|
||||
}
|
||||
|
||||
interface WeakMap<K extends WeakKey, V> {
|
||||
readonly [Symbol.toStringTag]: string;
|
||||
}
|
||||
|
||||
interface Set<T> {
|
||||
readonly [Symbol.toStringTag]: string;
|
||||
}
|
||||
|
||||
interface WeakSet<T extends WeakKey> {
|
||||
readonly [Symbol.toStringTag]: string;
|
||||
}
|
||||
|
||||
interface JSON {
|
||||
readonly [Symbol.toStringTag]: string;
|
||||
}
|
||||
|
||||
interface Function {
|
||||
/**
|
||||
* Determines whether the given value inherits from this function if this function was used
|
||||
* as a constructor function.
|
||||
*
|
||||
* A constructor function can control which objects are recognized as its instances by
|
||||
* 'instanceof' by overriding this method.
|
||||
*/
|
||||
[Symbol.hasInstance](value: any): boolean;
|
||||
}
|
||||
|
||||
interface GeneratorFunction {
|
||||
readonly [Symbol.toStringTag]: string;
|
||||
}
|
||||
|
||||
interface Math {
|
||||
readonly [Symbol.toStringTag]: string;
|
||||
}
|
||||
|
||||
interface Promise<T> {
|
||||
readonly [Symbol.toStringTag]: string;
|
||||
}
|
||||
|
||||
interface PromiseConstructor {
|
||||
readonly [Symbol.species]: PromiseConstructor;
|
||||
}
|
||||
|
||||
interface RegExp {
|
||||
/**
|
||||
* Matches a string with this regular expression, and returns an array containing the results of
|
||||
* that search.
|
||||
* @param string A string to search within.
|
||||
*/
|
||||
[Symbol.match](string: string): RegExpMatchArray | null;
|
||||
|
||||
/**
|
||||
* Replaces text in a string, using this regular expression.
|
||||
* @param string A String object or string literal whose contents matching against
|
||||
* this regular expression will be replaced
|
||||
* @param replaceValue A String object or string literal containing the text to replace for every
|
||||
* successful match of this regular expression.
|
||||
*/
|
||||
[Symbol.replace](string: string, replaceValue: string): string;
|
||||
|
||||
/**
|
||||
* Replaces text in a string, using this regular expression.
|
||||
* @param string A String object or string literal whose contents matching against
|
||||
* this regular expression will be replaced
|
||||
* @param replacer A function that returns the replacement text.
|
||||
*/
|
||||
[Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string;
|
||||
|
||||
/**
|
||||
* Finds the position beginning first substring match in a regular expression search
|
||||
* using this regular expression.
|
||||
*
|
||||
* @param string The string to search within.
|
||||
*/
|
||||
[Symbol.search](string: string): number;
|
||||
|
||||
/**
|
||||
* Returns an array of substrings that were delimited by strings in the original input that
|
||||
* match against this regular expression.
|
||||
*
|
||||
* If the regular expression contains capturing parentheses, then each time this
|
||||
* regular expression matches, the results (including any undefined results) of the
|
||||
* capturing parentheses are spliced.
|
||||
*
|
||||
* @param string string value to split
|
||||
* @param limit if not undefined, the output array is truncated so that it contains no more
|
||||
* than 'limit' elements.
|
||||
*/
|
||||
[Symbol.split](string: string, limit?: number): string[];
|
||||
}
|
||||
|
||||
interface RegExpConstructor {
|
||||
readonly [Symbol.species]: RegExpConstructor;
|
||||
}
|
||||
|
||||
interface String {
|
||||
/**
|
||||
* Matches a string or an object that supports being matched against, and returns an array
|
||||
* containing the results of that search, or null if no matches are found.
|
||||
* @param matcher An object that supports being matched against.
|
||||
*/
|
||||
match(matcher: { [Symbol.match](string: string): RegExpMatchArray | null; }): RegExpMatchArray | null;
|
||||
|
||||
/**
|
||||
* Passes a string and {@linkcode replaceValue} to the `[Symbol.replace]` method on {@linkcode searchValue}. This method is expected to implement its own replacement algorithm.
|
||||
* @param searchValue An object that supports searching for and replacing matches within a string.
|
||||
* @param replaceValue The replacement text.
|
||||
*/
|
||||
replace(searchValue: { [Symbol.replace](string: string, replaceValue: string): string; }, replaceValue: string): string;
|
||||
|
||||
/**
|
||||
* Replaces text in a string, using an object that supports replacement within a string.
|
||||
* @param searchValue A object can search for and replace matches within a string.
|
||||
* @param replacer A function that returns the replacement text.
|
||||
*/
|
||||
replace(searchValue: { [Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string; }, replacer: (substring: string, ...args: any[]) => string): string;
|
||||
|
||||
/**
|
||||
* Finds the first substring match in a regular expression search.
|
||||
* @param searcher An object which supports searching within a string.
|
||||
*/
|
||||
search(searcher: { [Symbol.search](string: string): number; }): number;
|
||||
|
||||
/**
|
||||
* Split a string into substrings using the specified separator and return them as an array.
|
||||
* @param splitter An object that can split a string.
|
||||
* @param limit A value used to limit the number of elements returned in the array.
|
||||
*/
|
||||
split(splitter: { [Symbol.split](string: string, limit?: number): string[]; }, limit?: number): string[];
|
||||
}
|
||||
|
||||
interface ArrayBuffer {
|
||||
readonly [Symbol.toStringTag]: "ArrayBuffer";
|
||||
}
|
||||
|
||||
interface DataView<TArrayBuffer extends ArrayBufferLike> {
|
||||
readonly [Symbol.toStringTag]: string;
|
||||
}
|
||||
|
||||
interface Int8Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
readonly [Symbol.toStringTag]: "Int8Array";
|
||||
}
|
||||
|
||||
interface Uint8Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
readonly [Symbol.toStringTag]: "Uint8Array";
|
||||
}
|
||||
|
||||
interface Uint8ClampedArray<TArrayBuffer extends ArrayBufferLike> {
|
||||
readonly [Symbol.toStringTag]: "Uint8ClampedArray";
|
||||
}
|
||||
|
||||
interface Int16Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
readonly [Symbol.toStringTag]: "Int16Array";
|
||||
}
|
||||
|
||||
interface Uint16Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
readonly [Symbol.toStringTag]: "Uint16Array";
|
||||
}
|
||||
|
||||
interface Int32Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
readonly [Symbol.toStringTag]: "Int32Array";
|
||||
}
|
||||
|
||||
interface Uint32Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
readonly [Symbol.toStringTag]: "Uint32Array";
|
||||
}
|
||||
|
||||
interface Float32Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
readonly [Symbol.toStringTag]: "Float32Array";
|
||||
}
|
||||
|
||||
interface Float64Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
readonly [Symbol.toStringTag]: "Float64Array";
|
||||
}
|
||||
|
||||
interface ArrayConstructor {
|
||||
readonly [Symbol.species]: ArrayConstructor;
|
||||
}
|
||||
interface MapConstructor {
|
||||
readonly [Symbol.species]: MapConstructor;
|
||||
}
|
||||
interface SetConstructor {
|
||||
readonly [Symbol.species]: SetConstructor;
|
||||
}
|
||||
interface ArrayBufferConstructor {
|
||||
readonly [Symbol.species]: ArrayBufferConstructor;
|
||||
}
|
||||
114
tools/tsgo/internal/bundled/libs/lib.es2016.array.include.d.ts
vendored
Normal file
114
tools/tsgo/internal/bundled/libs/lib.es2016.array.include.d.ts
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
interface Array<T> {
|
||||
/**
|
||||
* Determines whether an array includes a certain element, returning true or false as appropriate.
|
||||
* @param searchElement The element to search for.
|
||||
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
||||
*/
|
||||
includes(searchElement: T, fromIndex?: number): boolean;
|
||||
}
|
||||
|
||||
interface ReadonlyArray<T> {
|
||||
/**
|
||||
* Determines whether an array includes a certain element, returning true or false as appropriate.
|
||||
* @param searchElement The element to search for.
|
||||
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
||||
*/
|
||||
includes(searchElement: T, fromIndex?: number): boolean;
|
||||
}
|
||||
|
||||
interface Int8Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
/**
|
||||
* Determines whether an array includes a certain element, returning true or false as appropriate.
|
||||
* @param searchElement The element to search for.
|
||||
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
||||
*/
|
||||
includes(searchElement: number, fromIndex?: number): boolean;
|
||||
}
|
||||
|
||||
interface Uint8Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
/**
|
||||
* Determines whether an array includes a certain element, returning true or false as appropriate.
|
||||
* @param searchElement The element to search for.
|
||||
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
||||
*/
|
||||
includes(searchElement: number, fromIndex?: number): boolean;
|
||||
}
|
||||
|
||||
interface Uint8ClampedArray<TArrayBuffer extends ArrayBufferLike> {
|
||||
/**
|
||||
* Determines whether an array includes a certain element, returning true or false as appropriate.
|
||||
* @param searchElement The element to search for.
|
||||
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
||||
*/
|
||||
includes(searchElement: number, fromIndex?: number): boolean;
|
||||
}
|
||||
|
||||
interface Int16Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
/**
|
||||
* Determines whether an array includes a certain element, returning true or false as appropriate.
|
||||
* @param searchElement The element to search for.
|
||||
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
||||
*/
|
||||
includes(searchElement: number, fromIndex?: number): boolean;
|
||||
}
|
||||
|
||||
interface Uint16Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
/**
|
||||
* Determines whether an array includes a certain element, returning true or false as appropriate.
|
||||
* @param searchElement The element to search for.
|
||||
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
||||
*/
|
||||
includes(searchElement: number, fromIndex?: number): boolean;
|
||||
}
|
||||
|
||||
interface Int32Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
/**
|
||||
* Determines whether an array includes a certain element, returning true or false as appropriate.
|
||||
* @param searchElement The element to search for.
|
||||
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
||||
*/
|
||||
includes(searchElement: number, fromIndex?: number): boolean;
|
||||
}
|
||||
|
||||
interface Uint32Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
/**
|
||||
* Determines whether an array includes a certain element, returning true or false as appropriate.
|
||||
* @param searchElement The element to search for.
|
||||
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
||||
*/
|
||||
includes(searchElement: number, fromIndex?: number): boolean;
|
||||
}
|
||||
|
||||
interface Float32Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
/**
|
||||
* Determines whether an array includes a certain element, returning true or false as appropriate.
|
||||
* @param searchElement The element to search for.
|
||||
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
||||
*/
|
||||
includes(searchElement: number, fromIndex?: number): boolean;
|
||||
}
|
||||
|
||||
interface Float64Array<TArrayBuffer extends ArrayBufferLike> {
|
||||
/**
|
||||
* Determines whether an array includes a certain element, returning true or false as appropriate.
|
||||
* @param searchElement The element to search for.
|
||||
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
||||
*/
|
||||
includes(searchElement: number, fromIndex?: number): boolean;
|
||||
}
|
||||
19
tools/tsgo/internal/bundled/libs/lib.es2016.d.ts
vendored
Normal file
19
tools/tsgo/internal/bundled/libs/lib.es2016.d.ts
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2015" />
|
||||
/// <reference lib="es2016.array.include" />
|
||||
/// <reference lib="es2016.intl" />
|
||||
21
tools/tsgo/internal/bundled/libs/lib.es2016.full.d.ts
vendored
Normal file
21
tools/tsgo/internal/bundled/libs/lib.es2016.full.d.ts
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2016" />
|
||||
/// <reference lib="dom" />
|
||||
/// <reference lib="webworker.importscripts" />
|
||||
/// <reference lib="scripthost" />
|
||||
/// <reference lib="dom.iterable" />
|
||||
29
tools/tsgo/internal/bundled/libs/lib.es2016.intl.d.ts
vendored
Normal file
29
tools/tsgo/internal/bundled/libs/lib.es2016.intl.d.ts
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
declare namespace Intl {
|
||||
/**
|
||||
* The `Intl.getCanonicalLocales()` method returns an array containing
|
||||
* the canonical locale names. Duplicates will be omitted and elements
|
||||
* will be validated as structurally valid language tags.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/getCanonicalLocales)
|
||||
*
|
||||
* @param locale A list of String values for which to get the canonical locale names
|
||||
* @returns An array containing the canonical and validated locale names.
|
||||
*/
|
||||
function getCanonicalLocales(locale?: string | readonly string[]): string[];
|
||||
}
|
||||
19
tools/tsgo/internal/bundled/libs/lib.es2017.arraybuffer.d.ts
vendored
Normal file
19
tools/tsgo/internal/bundled/libs/lib.es2017.arraybuffer.d.ts
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
interface ArrayBufferConstructor {
|
||||
new (): ArrayBuffer;
|
||||
}
|
||||
24
tools/tsgo/internal/bundled/libs/lib.es2017.d.ts
vendored
Normal file
24
tools/tsgo/internal/bundled/libs/lib.es2017.d.ts
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2016" />
|
||||
/// <reference lib="es2017.arraybuffer" />
|
||||
/// <reference lib="es2017.date" />
|
||||
/// <reference lib="es2017.intl" />
|
||||
/// <reference lib="es2017.object" />
|
||||
/// <reference lib="es2017.sharedmemory" />
|
||||
/// <reference lib="es2017.string" />
|
||||
/// <reference lib="es2017.typedarrays" />
|
||||
29
tools/tsgo/internal/bundled/libs/lib.es2017.date.d.ts
vendored
Normal file
29
tools/tsgo/internal/bundled/libs/lib.es2017.date.d.ts
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
interface DateConstructor {
|
||||
/**
|
||||
* Returns the number of milliseconds between midnight, January 1, 1970 Universal Coordinated Time (UTC) (or GMT) and the specified date.
|
||||
* @param year The full year designation is required for cross-century date accuracy. If year is between 0 and 99 is used, then year is assumed to be 1900 + year.
|
||||
* @param monthIndex The month as a number between 0 and 11 (January to December).
|
||||
* @param date The date as a number between 1 and 31.
|
||||
* @param hours Must be supplied if minutes is supplied. A number from 0 to 23 (midnight to 11pm) that specifies the hour.
|
||||
* @param minutes Must be supplied if seconds is supplied. A number from 0 to 59 that specifies the minutes.
|
||||
* @param seconds Must be supplied if milliseconds is supplied. A number from 0 to 59 that specifies the seconds.
|
||||
* @param ms A number from 0 to 999 that specifies the milliseconds.
|
||||
*/
|
||||
UTC(year: number, monthIndex?: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number;
|
||||
}
|
||||
21
tools/tsgo/internal/bundled/libs/lib.es2017.full.d.ts
vendored
Normal file
21
tools/tsgo/internal/bundled/libs/lib.es2017.full.d.ts
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2017" />
|
||||
/// <reference lib="dom" />
|
||||
/// <reference lib="webworker.importscripts" />
|
||||
/// <reference lib="scripthost" />
|
||||
/// <reference lib="dom.iterable" />
|
||||
42
tools/tsgo/internal/bundled/libs/lib.es2017.intl.d.ts
vendored
Normal file
42
tools/tsgo/internal/bundled/libs/lib.es2017.intl.d.ts
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
declare namespace Intl {
|
||||
interface DateTimeFormatPartTypesRegistry {
|
||||
day: any;
|
||||
dayPeriod: any;
|
||||
era: any;
|
||||
hour: any;
|
||||
literal: any;
|
||||
minute: any;
|
||||
month: any;
|
||||
second: any;
|
||||
timeZoneName: any;
|
||||
weekday: any;
|
||||
year: any;
|
||||
}
|
||||
|
||||
type DateTimeFormatPartTypes = keyof DateTimeFormatPartTypesRegistry;
|
||||
|
||||
interface DateTimeFormatPart {
|
||||
type: DateTimeFormatPartTypes;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface DateTimeFormat {
|
||||
formatToParts(date?: Date | number): DateTimeFormatPart[];
|
||||
}
|
||||
}
|
||||
47
tools/tsgo/internal/bundled/libs/lib.es2017.object.d.ts
vendored
Normal file
47
tools/tsgo/internal/bundled/libs/lib.es2017.object.d.ts
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
interface ObjectConstructor {
|
||||
/**
|
||||
* Returns an array of values of the enumerable own properties of an object
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
values<T>(o: { [s: string]: T; } | ArrayLike<T>): T[];
|
||||
|
||||
/**
|
||||
* Returns an array of values of the enumerable own properties of an object
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
values(o: {}): any[];
|
||||
|
||||
/**
|
||||
* Returns an array of key/values of the enumerable own properties of an object
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
entries<T>(o: { [s: string]: T; } | ArrayLike<T>): [string, T][];
|
||||
|
||||
/**
|
||||
* Returns an array of key/values of the enumerable own properties of an object
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
entries(o: {}): [string, any][];
|
||||
|
||||
/**
|
||||
* Returns an object containing all own property descriptors of an object
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
getOwnPropertyDescriptors<T>(o: T): { [P in keyof T]: TypedPropertyDescriptor<T[P]>; } & { [x: string]: PropertyDescriptor; };
|
||||
}
|
||||
133
tools/tsgo/internal/bundled/libs/lib.es2017.sharedmemory.d.ts
vendored
Normal file
133
tools/tsgo/internal/bundled/libs/lib.es2017.sharedmemory.d.ts
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2015.symbol" />
|
||||
/// <reference lib="es2015.symbol.wellknown" />
|
||||
|
||||
interface SharedArrayBuffer {
|
||||
/**
|
||||
* Read-only. The length of the ArrayBuffer (in bytes).
|
||||
*/
|
||||
readonly byteLength: number;
|
||||
|
||||
/**
|
||||
* Returns a section of an SharedArrayBuffer.
|
||||
*/
|
||||
slice(begin?: number, end?: number): SharedArrayBuffer;
|
||||
readonly [Symbol.toStringTag]: "SharedArrayBuffer";
|
||||
}
|
||||
|
||||
interface SharedArrayBufferConstructor {
|
||||
readonly prototype: SharedArrayBuffer;
|
||||
new (byteLength?: number): SharedArrayBuffer;
|
||||
readonly [Symbol.species]: SharedArrayBufferConstructor;
|
||||
}
|
||||
declare var SharedArrayBuffer: SharedArrayBufferConstructor;
|
||||
|
||||
interface ArrayBufferTypes {
|
||||
SharedArrayBuffer: SharedArrayBuffer;
|
||||
}
|
||||
|
||||
interface Atomics {
|
||||
/**
|
||||
* Adds a value to the value at the given position in the array, returning the original value.
|
||||
* Until this atomic operation completes, any other read or write operation against the array
|
||||
* will block.
|
||||
*/
|
||||
add(typedArray: Int8Array<ArrayBufferLike> | Uint8Array<ArrayBufferLike> | Int16Array<ArrayBufferLike> | Uint16Array<ArrayBufferLike> | Int32Array<ArrayBufferLike> | Uint32Array<ArrayBufferLike>, index: number, value: number): number;
|
||||
|
||||
/**
|
||||
* Stores the bitwise AND of a value with the value at the given position in the array,
|
||||
* returning the original value. Until this atomic operation completes, any other read or
|
||||
* write operation against the array will block.
|
||||
*/
|
||||
and(typedArray: Int8Array<ArrayBufferLike> | Uint8Array<ArrayBufferLike> | Int16Array<ArrayBufferLike> | Uint16Array<ArrayBufferLike> | Int32Array<ArrayBufferLike> | Uint32Array<ArrayBufferLike>, index: number, value: number): number;
|
||||
|
||||
/**
|
||||
* Replaces the value at the given position in the array if the original value equals the given
|
||||
* expected value, returning the original value. Until this atomic operation completes, any
|
||||
* other read or write operation against the array will block.
|
||||
*/
|
||||
compareExchange(typedArray: Int8Array<ArrayBufferLike> | Uint8Array<ArrayBufferLike> | Int16Array<ArrayBufferLike> | Uint16Array<ArrayBufferLike> | Int32Array<ArrayBufferLike> | Uint32Array<ArrayBufferLike>, index: number, expectedValue: number, replacementValue: number): number;
|
||||
|
||||
/**
|
||||
* Replaces the value at the given position in the array, returning the original value. Until
|
||||
* this atomic operation completes, any other read or write operation against the array will
|
||||
* block.
|
||||
*/
|
||||
exchange(typedArray: Int8Array<ArrayBufferLike> | Uint8Array<ArrayBufferLike> | Int16Array<ArrayBufferLike> | Uint16Array<ArrayBufferLike> | Int32Array<ArrayBufferLike> | Uint32Array<ArrayBufferLike>, index: number, value: number): number;
|
||||
|
||||
/**
|
||||
* Returns a value indicating whether high-performance algorithms can use atomic operations
|
||||
* (`true`) or must use locks (`false`) for the given number of bytes-per-element of a typed
|
||||
* array.
|
||||
*/
|
||||
isLockFree(size: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns the value at the given position in the array. Until this atomic operation completes,
|
||||
* any other read or write operation against the array will block.
|
||||
*/
|
||||
load(typedArray: Int8Array<ArrayBufferLike> | Uint8Array<ArrayBufferLike> | Int16Array<ArrayBufferLike> | Uint16Array<ArrayBufferLike> | Int32Array<ArrayBufferLike> | Uint32Array<ArrayBufferLike>, index: number): number;
|
||||
|
||||
/**
|
||||
* Stores the bitwise OR of a value with the value at the given position in the array,
|
||||
* returning the original value. Until this atomic operation completes, any other read or write
|
||||
* operation against the array will block.
|
||||
*/
|
||||
or(typedArray: Int8Array<ArrayBufferLike> | Uint8Array<ArrayBufferLike> | Int16Array<ArrayBufferLike> | Uint16Array<ArrayBufferLike> | Int32Array<ArrayBufferLike> | Uint32Array<ArrayBufferLike>, index: number, value: number): number;
|
||||
|
||||
/**
|
||||
* Stores a value at the given position in the array, returning the new value. Until this
|
||||
* atomic operation completes, any other read or write operation against the array will block.
|
||||
*/
|
||||
store(typedArray: Int8Array<ArrayBufferLike> | Uint8Array<ArrayBufferLike> | Int16Array<ArrayBufferLike> | Uint16Array<ArrayBufferLike> | Int32Array<ArrayBufferLike> | Uint32Array<ArrayBufferLike>, index: number, value: number): number;
|
||||
|
||||
/**
|
||||
* Subtracts a value from the value at the given position in the array, returning the original
|
||||
* value. Until this atomic operation completes, any other read or write operation against the
|
||||
* array will block.
|
||||
*/
|
||||
sub(typedArray: Int8Array<ArrayBufferLike> | Uint8Array<ArrayBufferLike> | Int16Array<ArrayBufferLike> | Uint16Array<ArrayBufferLike> | Int32Array<ArrayBufferLike> | Uint32Array<ArrayBufferLike>, index: number, value: number): number;
|
||||
|
||||
/**
|
||||
* If the value at the given position in the array is equal to the provided value, the current
|
||||
* agent is put to sleep causing execution to suspend until the timeout expires (returning
|
||||
* `"timed-out"`) or until the agent is awoken (returning `"ok"`); otherwise, returns
|
||||
* `"not-equal"`.
|
||||
*/
|
||||
wait(typedArray: Int32Array<ArrayBufferLike>, index: number, value: number, timeout?: number): "ok" | "not-equal" | "timed-out";
|
||||
|
||||
/**
|
||||
* Wakes up sleeping agents that are waiting on the given index of the array, returning the
|
||||
* number of agents that were awoken.
|
||||
* @param typedArray A shared Int32Array<ArrayBufferLike>.
|
||||
* @param index The position in the typedArray to wake up on.
|
||||
* @param count The number of sleeping agents to notify. Defaults to +Infinity.
|
||||
*/
|
||||
notify(typedArray: Int32Array<ArrayBufferLike>, index: number, count?: number): number;
|
||||
|
||||
/**
|
||||
* Stores the bitwise XOR of a value with the value at the given position in the array,
|
||||
* returning the original value. Until this atomic operation completes, any other read or write
|
||||
* operation against the array will block.
|
||||
*/
|
||||
xor(typedArray: Int8Array<ArrayBufferLike> | Uint8Array<ArrayBufferLike> | Int16Array<ArrayBufferLike> | Uint16Array<ArrayBufferLike> | Int32Array<ArrayBufferLike> | Uint32Array<ArrayBufferLike>, index: number, value: number): number;
|
||||
|
||||
readonly [Symbol.toStringTag]: "Atomics";
|
||||
}
|
||||
|
||||
declare var Atomics: Atomics;
|
||||
47
tools/tsgo/internal/bundled/libs/lib.es2017.string.d.ts
vendored
Normal file
47
tools/tsgo/internal/bundled/libs/lib.es2017.string.d.ts
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
interface String {
|
||||
/**
|
||||
* Pads the current string with a given string (repeated and/or truncated, if needed) so that the resulting string has a given length.
|
||||
* The padding is applied from the start of the current string.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart)
|
||||
*
|
||||
* @param targetLength The length of the resulting string once the current `str` has been padded.
|
||||
* If the value is less than or equal to `str.length`, then `str` is returned as-is.
|
||||
*
|
||||
* @param padString The string to pad the current `str` with.
|
||||
* If `padString` is too long to stay within `targetLength`, it will be truncated from the end.
|
||||
* The default value is the space character (U+0020).
|
||||
*/
|
||||
padStart(targetLength: number, padString?: string): string;
|
||||
|
||||
/**
|
||||
* Pads the current string with a given string (repeated and/or truncated, if needed) so that the resulting string has a given length.
|
||||
* The padding is applied from the end of the current string.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd)
|
||||
*
|
||||
* @param targetLength The length of the resulting string once the current `str` has been padded.
|
||||
* If the value is less than or equal to `str.length`, then `str` is returned as-is.
|
||||
*
|
||||
* @param padString The string to pad the current `str` with.
|
||||
* If `padString` is too long to stay within `targetLength`, it will be truncated from the end.
|
||||
* The default value is the space character (U+0020).
|
||||
*/
|
||||
padEnd(targetLength: number, padString?: string): string;
|
||||
}
|
||||
51
tools/tsgo/internal/bundled/libs/lib.es2017.typedarrays.d.ts
vendored
Normal file
51
tools/tsgo/internal/bundled/libs/lib.es2017.typedarrays.d.ts
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
interface Int8ArrayConstructor {
|
||||
new (): Int8Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Uint8ArrayConstructor {
|
||||
new (): Uint8Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Uint8ClampedArrayConstructor {
|
||||
new (): Uint8ClampedArray<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Int16ArrayConstructor {
|
||||
new (): Int16Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Uint16ArrayConstructor {
|
||||
new (): Uint16Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Int32ArrayConstructor {
|
||||
new (): Int32Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Uint32ArrayConstructor {
|
||||
new (): Uint32Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Float32ArrayConstructor {
|
||||
new (): Float32Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface Float64ArrayConstructor {
|
||||
new (): Float64Array<ArrayBuffer>;
|
||||
}
|
||||
75
tools/tsgo/internal/bundled/libs/lib.es2018.asyncgenerator.d.ts
vendored
Normal file
75
tools/tsgo/internal/bundled/libs/lib.es2018.asyncgenerator.d.ts
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2018.asynciterable" />
|
||||
|
||||
interface AsyncGenerator<T = unknown, TReturn = any, TNext = any> extends AsyncIteratorObject<T, TReturn, TNext> {
|
||||
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
|
||||
next(...[value]: [] | [TNext]): Promise<IteratorResult<T, TReturn>>;
|
||||
return(value: TReturn | PromiseLike<TReturn>): Promise<IteratorResult<T, TReturn>>;
|
||||
throw(e: any): Promise<IteratorResult<T, TReturn>>;
|
||||
[Symbol.asyncIterator](): AsyncGenerator<T, TReturn, TNext>;
|
||||
}
|
||||
|
||||
interface AsyncGeneratorFunction {
|
||||
/**
|
||||
* Creates a new AsyncGenerator object.
|
||||
* @param args A list of arguments the function accepts.
|
||||
*/
|
||||
new (...args: any[]): AsyncGenerator;
|
||||
/**
|
||||
* Creates a new AsyncGenerator object.
|
||||
* @param args A list of arguments the function accepts.
|
||||
*/
|
||||
(...args: any[]): AsyncGenerator;
|
||||
/**
|
||||
* The length of the arguments.
|
||||
*/
|
||||
readonly length: number;
|
||||
/**
|
||||
* Returns the name of the function.
|
||||
*/
|
||||
readonly name: string;
|
||||
/**
|
||||
* A reference to the prototype.
|
||||
*/
|
||||
readonly prototype: AsyncGenerator;
|
||||
}
|
||||
|
||||
interface AsyncGeneratorFunctionConstructor {
|
||||
/**
|
||||
* Creates a new AsyncGenerator function.
|
||||
* @param args A list of arguments the function accepts.
|
||||
*/
|
||||
new (...args: string[]): AsyncGeneratorFunction;
|
||||
/**
|
||||
* Creates a new AsyncGenerator function.
|
||||
* @param args A list of arguments the function accepts.
|
||||
*/
|
||||
(...args: string[]): AsyncGeneratorFunction;
|
||||
/**
|
||||
* The length of the arguments.
|
||||
*/
|
||||
readonly length: number;
|
||||
/**
|
||||
* Returns the name of the function.
|
||||
*/
|
||||
readonly name: string;
|
||||
/**
|
||||
* A reference to the prototype.
|
||||
*/
|
||||
readonly prototype: AsyncGeneratorFunction;
|
||||
}
|
||||
51
tools/tsgo/internal/bundled/libs/lib.es2018.asynciterable.d.ts
vendored
Normal file
51
tools/tsgo/internal/bundled/libs/lib.es2018.asynciterable.d.ts
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2015.symbol" />
|
||||
/// <reference lib="es2015.iterable" />
|
||||
|
||||
interface SymbolConstructor {
|
||||
/**
|
||||
* A method that returns the default async iterator for an object. Called by the semantics of
|
||||
* the for-await-of statement.
|
||||
*/
|
||||
readonly asyncIterator: unique symbol;
|
||||
}
|
||||
|
||||
interface AsyncIterator<T, TReturn = any, TNext = any> {
|
||||
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
|
||||
next(...[value]: [] | [TNext]): Promise<IteratorResult<T, TReturn>>;
|
||||
return?(value?: TReturn | PromiseLike<TReturn>): Promise<IteratorResult<T, TReturn>>;
|
||||
throw?(e?: any): Promise<IteratorResult<T, TReturn>>;
|
||||
}
|
||||
|
||||
interface AsyncIterable<T, TReturn = any, TNext = any> {
|
||||
[Symbol.asyncIterator](): AsyncIterator<T, TReturn, TNext>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes a user-defined {@link AsyncIterator} that is also async iterable.
|
||||
*/
|
||||
interface AsyncIterableIterator<T, TReturn = any, TNext = any> extends AsyncIterator<T, TReturn, TNext> {
|
||||
[Symbol.asyncIterator](): AsyncIterableIterator<T, TReturn, TNext>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes an {@link AsyncIterator} produced by the runtime that inherits from the intrinsic `AsyncIterator.prototype`.
|
||||
*/
|
||||
interface AsyncIteratorObject<T, TReturn = unknown, TNext = unknown> extends AsyncIterator<T, TReturn, TNext> {
|
||||
[Symbol.asyncIterator](): AsyncIteratorObject<T, TReturn, TNext>;
|
||||
}
|
||||
22
tools/tsgo/internal/bundled/libs/lib.es2018.d.ts
vendored
Normal file
22
tools/tsgo/internal/bundled/libs/lib.es2018.d.ts
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2017" />
|
||||
/// <reference lib="es2018.asynciterable" />
|
||||
/// <reference lib="es2018.asyncgenerator" />
|
||||
/// <reference lib="es2018.promise" />
|
||||
/// <reference lib="es2018.regexp" />
|
||||
/// <reference lib="es2018.intl" />
|
||||
22
tools/tsgo/internal/bundled/libs/lib.es2018.full.d.ts
vendored
Normal file
22
tools/tsgo/internal/bundled/libs/lib.es2018.full.d.ts
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2018" />
|
||||
/// <reference lib="dom" />
|
||||
/// <reference lib="webworker.importscripts" />
|
||||
/// <reference lib="scripthost" />
|
||||
/// <reference lib="dom.iterable" />
|
||||
/// <reference lib="dom.asynciterable" />
|
||||
81
tools/tsgo/internal/bundled/libs/lib.es2018.intl.d.ts
vendored
Normal file
81
tools/tsgo/internal/bundled/libs/lib.es2018.intl.d.ts
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
declare namespace Intl {
|
||||
// http://cldr.unicode.org/index/cldr-spec/plural-rules#TOC-Determining-Plural-Categories
|
||||
type LDMLPluralRule = "zero" | "one" | "two" | "few" | "many" | "other";
|
||||
type PluralRuleType = "cardinal" | "ordinal";
|
||||
|
||||
interface PluralRulesOptions {
|
||||
localeMatcher?: "lookup" | "best fit" | undefined;
|
||||
type?: PluralRuleType | undefined;
|
||||
minimumIntegerDigits?: number | undefined;
|
||||
minimumFractionDigits?: number | undefined;
|
||||
maximumFractionDigits?: number | undefined;
|
||||
minimumSignificantDigits?: number | undefined;
|
||||
maximumSignificantDigits?: number | undefined;
|
||||
}
|
||||
|
||||
interface ResolvedPluralRulesOptions {
|
||||
locale: string;
|
||||
pluralCategories: LDMLPluralRule[];
|
||||
type: PluralRuleType;
|
||||
minimumIntegerDigits: number;
|
||||
minimumFractionDigits: number;
|
||||
maximumFractionDigits: number;
|
||||
minimumSignificantDigits?: number;
|
||||
maximumSignificantDigits?: number;
|
||||
}
|
||||
|
||||
interface PluralRules {
|
||||
resolvedOptions(): ResolvedPluralRulesOptions;
|
||||
select(n: number): LDMLPluralRule;
|
||||
}
|
||||
|
||||
interface PluralRulesConstructor {
|
||||
new (locales?: string | readonly string[], options?: PluralRulesOptions): PluralRules;
|
||||
(locales?: string | readonly string[], options?: PluralRulesOptions): PluralRules;
|
||||
supportedLocalesOf(locales: string | readonly string[], options?: { localeMatcher?: "lookup" | "best fit"; }): string[];
|
||||
}
|
||||
|
||||
const PluralRules: PluralRulesConstructor;
|
||||
|
||||
interface NumberFormatPartTypeRegistry {
|
||||
literal: never;
|
||||
nan: never;
|
||||
infinity: never;
|
||||
percent: never;
|
||||
integer: never;
|
||||
group: never;
|
||||
decimal: never;
|
||||
fraction: never;
|
||||
plusSign: never;
|
||||
minusSign: never;
|
||||
percentSign: never;
|
||||
currency: never;
|
||||
}
|
||||
|
||||
type NumberFormatPartTypes = keyof NumberFormatPartTypeRegistry;
|
||||
|
||||
interface NumberFormatPart {
|
||||
type: NumberFormatPartTypes;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface NumberFormat {
|
||||
formatToParts(number?: number | bigint): NumberFormatPart[];
|
||||
}
|
||||
}
|
||||
28
tools/tsgo/internal/bundled/libs/lib.es2018.promise.d.ts
vendored
Normal file
28
tools/tsgo/internal/bundled/libs/lib.es2018.promise.d.ts
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/**
|
||||
* Represents the completion of an asynchronous operation
|
||||
*/
|
||||
interface Promise<T> {
|
||||
/**
|
||||
* Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The
|
||||
* resolved value cannot be modified from the callback.
|
||||
* @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected).
|
||||
* @returns A Promise for the completion of the callback.
|
||||
*/
|
||||
finally(onfinally?: (() => void) | undefined | null): Promise<T>;
|
||||
}
|
||||
35
tools/tsgo/internal/bundled/libs/lib.es2018.regexp.d.ts
vendored
Normal file
35
tools/tsgo/internal/bundled/libs/lib.es2018.regexp.d.ts
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
interface RegExpMatchArray {
|
||||
groups?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface RegExpExecArray {
|
||||
groups?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface RegExp {
|
||||
/**
|
||||
* Returns a Boolean value indicating the state of the dotAll flag (s) used with a regular expression.
|
||||
* Default is false. Read-only.
|
||||
*/
|
||||
readonly dotAll: boolean;
|
||||
}
|
||||
77
tools/tsgo/internal/bundled/libs/lib.es2019.array.d.ts
vendored
Normal file
77
tools/tsgo/internal/bundled/libs/lib.es2019.array.d.ts
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
type FlatArray<Arr, Depth extends number> = {
|
||||
done: Arr;
|
||||
recur: Arr extends ReadonlyArray<infer InnerArr> ? FlatArray<InnerArr, [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20][Depth]>
|
||||
: Arr;
|
||||
}[Depth extends -1 ? "done" : "recur"];
|
||||
|
||||
interface ReadonlyArray<T> {
|
||||
/**
|
||||
* Calls a defined callback function on each element of an array. Then, flattens the result into
|
||||
* a new array.
|
||||
* This is identical to a map followed by flat with depth 1.
|
||||
*
|
||||
* @param callback A function that accepts up to three arguments. The flatMap method calls the
|
||||
* callback function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callback function. If
|
||||
* thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
flatMap<U, This = undefined>(
|
||||
callback: (this: This, value: T, index: number, array: T[]) => U | ReadonlyArray<U>,
|
||||
thisArg?: This,
|
||||
): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flat<A, D extends number = 1>(
|
||||
this: A,
|
||||
depth?: D,
|
||||
): FlatArray<A, D>[];
|
||||
}
|
||||
|
||||
interface Array<T> {
|
||||
/**
|
||||
* Calls a defined callback function on each element of an array. Then, flattens the result into
|
||||
* a new array.
|
||||
* This is identical to a map followed by flat with depth 1.
|
||||
*
|
||||
* @param callback A function that accepts up to three arguments. The flatMap method calls the
|
||||
* callback function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callback function. If
|
||||
* thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
flatMap<U, This = undefined>(
|
||||
callback: (this: This, value: T, index: number, array: T[]) => U | ReadonlyArray<U>,
|
||||
thisArg?: This,
|
||||
): U[];
|
||||
|
||||
/**
|
||||
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
||||
* specified depth.
|
||||
*
|
||||
* @param depth The maximum recursion depth
|
||||
*/
|
||||
flat<A, D extends number = 1>(
|
||||
this: A,
|
||||
depth?: D,
|
||||
): FlatArray<A, D>[];
|
||||
}
|
||||
22
tools/tsgo/internal/bundled/libs/lib.es2019.d.ts
vendored
Normal file
22
tools/tsgo/internal/bundled/libs/lib.es2019.d.ts
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2018" />
|
||||
/// <reference lib="es2019.array" />
|
||||
/// <reference lib="es2019.object" />
|
||||
/// <reference lib="es2019.string" />
|
||||
/// <reference lib="es2019.symbol" />
|
||||
/// <reference lib="es2019.intl" />
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user