2025-10-15 10:12:44 +03:00

95 lines
3.3 KiB
Go

package encoder_test
import (
"encoding/binary"
"fmt"
"os"
"path/filepath"
"strings"
"testing"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/api/encoder"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/core"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/parser"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/repo"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/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 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 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())
}
if ast.Kind(kind) == ast.KindIdentifier || ast.Kind(kind) == ast.KindStringLiteral {
stringIndex := readUint32(encoded, i+encoder.NodeOffsetData) & 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()
}