vendor tsgo
This commit is contained in:
427
tools/tsgo/internal/execute/tsctests/readablebuildinfo.go
Normal file
427
tools/tsgo/internal/execute/tsctests/readablebuildinfo.go
Normal file
@@ -0,0 +1,427 @@
|
||||
package tsctests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"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/execute/incremental"
|
||||
"github.com/microsoft/typescript-go/internal/json"
|
||||
)
|
||||
|
||||
type readableBuildInfo struct {
|
||||
buildInfo *incremental.BuildInfo
|
||||
Version string `json:"version,omitzero"`
|
||||
|
||||
// Common between incremental and tsc -b buildinfo for non incremental programs
|
||||
Errors bool `json:"errors,omitzero"`
|
||||
CheckPending bool `json:"checkPending,omitzero"`
|
||||
Root []*readableBuildInfoRoot `json:"root,omitzero"`
|
||||
PackageJsons []string `json:"packageJsons,omitzero"`
|
||||
MissingPackageJsons []string `json:"missingPackageJsons,omitzero"`
|
||||
|
||||
// IncrementalProgram info
|
||||
FileNames []string `json:"fileNames,omitzero"`
|
||||
FileInfos []*readableBuildInfoFileInfo `json:"fileInfos,omitzero"`
|
||||
FileIdsList [][]string `json:"fileIdsList,omitzero"`
|
||||
Options *collections.OrderedMap[string, any] `json:"options,omitzero"`
|
||||
ReferencedMap *collections.OrderedMap[string, []string] `json:"referencedMap,omitzero"`
|
||||
SemanticDiagnosticsPerFile []*readableBuildInfoSemanticDiagnostic `json:"semanticDiagnosticsPerFile,omitzero"`
|
||||
EmitDiagnosticsPerFile []*readableBuildInfoDiagnosticsOfFile `json:"emitDiagnosticsPerFile,omitzero"`
|
||||
ChangeFileSet []string `json:"changeFileSet,omitzero"` // List of changed files in the program, not the whole set of files
|
||||
AffectedFilesPendingEmit []*readableBuildInfoFilePendingEmit `json:"affectedFilesPendingEmit,omitzero"`
|
||||
LatestChangedDtsFile string `json:"latestChangedDtsFile,omitzero"` // Because this is only output file in the program, we dont need fileId to deduplicate name
|
||||
EmitSignatures []*readableBuildInfoEmitSignature `json:"emitSignatures,omitzero"`
|
||||
ResolvedRoot []*readableBuildInfoResolvedRoot `json:"resolvedRoot,omitzero"`
|
||||
Size int `json:"size,omitzero"` // Size of the build info file
|
||||
|
||||
// NonIncrementalProgram info
|
||||
SemanticErrors bool `json:"semanticErrors,omitzero"`
|
||||
}
|
||||
|
||||
type readableBuildInfoRoot struct {
|
||||
Files []string `json:"files,omitzero"`
|
||||
Original *incremental.BuildInfoRoot `json:"original,omitzero"`
|
||||
}
|
||||
|
||||
type readableBuildInfoFileInfo struct {
|
||||
FileName string `json:"fileName,omitzero"`
|
||||
Version string `json:"version,omitzero"`
|
||||
Signature string `json:"signature,omitzero"`
|
||||
AffectsGlobalScope bool `json:"affectsGlobalScope,omitzero"`
|
||||
ImpliedNodeFormat string `json:"impliedNodeFormat,omitzero"`
|
||||
Original *incremental.BuildInfoFileInfo `json:"original,omitzero"` // Original file path, if available
|
||||
}
|
||||
|
||||
type readableBuildInfoDiagnostic struct {
|
||||
// incrementalBuildInfoFileId if it is for a File thats other than its stored for
|
||||
File string `json:"file,omitzero"`
|
||||
NoFile bool `json:"noFile,omitzero"`
|
||||
Pos int `json:"pos,omitzero"`
|
||||
End int `json:"end,omitzero"`
|
||||
Code int32 `json:"code,omitzero"`
|
||||
Category diagnostics.Category `json:"category,omitzero"`
|
||||
MessageKey diagnostics.Key `json:"messageKey,omitzero"`
|
||||
MessageArgs []string `json:"messageArgs,omitzero"`
|
||||
MessageChain []*readableBuildInfoDiagnostic `json:"messageChain,omitzero"`
|
||||
RelatedInformation []*readableBuildInfoDiagnostic `json:"relatedInformation,omitzero"`
|
||||
ReportsUnnecessary bool `json:"reportsUnnecessary,omitzero"`
|
||||
ReportsDeprecated bool `json:"reportsDeprecated,omitzero"`
|
||||
SkippedOnNoEmit bool `json:"skippedOnNoEmit,omitzero"`
|
||||
}
|
||||
|
||||
type readableBuildInfoDiagnosticsOfFile struct {
|
||||
file string
|
||||
diagnostics []*readableBuildInfoDiagnostic
|
||||
}
|
||||
|
||||
func (r *readableBuildInfoDiagnosticsOfFile) MarshalJSON() ([]byte, error) {
|
||||
fileIdAndDiagnostics := make([]any, 0, 2)
|
||||
fileIdAndDiagnostics = append(fileIdAndDiagnostics, r.file)
|
||||
fileIdAndDiagnostics = append(fileIdAndDiagnostics, r.diagnostics)
|
||||
return json.Marshal(fileIdAndDiagnostics)
|
||||
}
|
||||
|
||||
func (r *readableBuildInfoDiagnosticsOfFile) UnmarshalJSON(data []byte) error {
|
||||
var fileIdAndDiagnostics []any
|
||||
if err := json.Unmarshal(data, &fileIdAndDiagnostics); err != nil {
|
||||
return fmt.Errorf("invalid readableBuildInfoDiagnosticsOfFile: %s", data)
|
||||
}
|
||||
if len(fileIdAndDiagnostics) != 2 {
|
||||
return fmt.Errorf("invalid readableBuildInfoDiagnosticsOfFile: expected 2 elements, got %d", len(fileIdAndDiagnostics))
|
||||
}
|
||||
file, ok := fileIdAndDiagnostics[0].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid fileId in readableBuildInfoDiagnosticsOfFile: expected string, got %T", fileIdAndDiagnostics[0])
|
||||
}
|
||||
if diagnostics, ok := fileIdAndDiagnostics[1].([]*readableBuildInfoDiagnostic); !ok {
|
||||
return fmt.Errorf("invalid diagnostics in readableBuildInfoDiagnosticsOfFile: expected []*readableBuildInfoDiagnostic, got %T", fileIdAndDiagnostics[1])
|
||||
} else {
|
||||
*r = readableBuildInfoDiagnosticsOfFile{
|
||||
file: file,
|
||||
diagnostics: diagnostics,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type readableBuildInfoSemanticDiagnostic struct {
|
||||
file string // File is not in changedSet and still doesnt have cached diagnostics
|
||||
diagnostics *readableBuildInfoDiagnosticsOfFile // Diagnostics for file
|
||||
}
|
||||
|
||||
func (r *readableBuildInfoSemanticDiagnostic) MarshalJSON() ([]byte, error) {
|
||||
if r.file != "" {
|
||||
return json.Marshal(r.file)
|
||||
}
|
||||
return json.Marshal(r.diagnostics)
|
||||
}
|
||||
|
||||
func (r *readableBuildInfoSemanticDiagnostic) UnmarshalJSON(data []byte) error {
|
||||
var file string
|
||||
if err := json.Unmarshal(data, &file); err != nil {
|
||||
var diagnostics readableBuildInfoDiagnosticsOfFile
|
||||
if err := json.Unmarshal(data, &diagnostics); err != nil {
|
||||
return fmt.Errorf("invalid readableBuildInfoSemanticDiagnostic: %s", data)
|
||||
}
|
||||
*r = readableBuildInfoSemanticDiagnostic{
|
||||
diagnostics: &diagnostics,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
*r = readableBuildInfoSemanticDiagnostic{
|
||||
file: file,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type readableBuildInfoFilePendingEmit struct {
|
||||
file string
|
||||
emitKind string
|
||||
original *incremental.BuildInfoFilePendingEmit
|
||||
}
|
||||
|
||||
func (b *readableBuildInfoFilePendingEmit) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal([]any{b.file, b.emitKind, b.original})
|
||||
}
|
||||
|
||||
func (b *readableBuildInfoFilePendingEmit) UnmarshalJSON(data []byte) error {
|
||||
var fileIdAndEmitKind []any
|
||||
if err := json.Unmarshal(data, &fileIdAndEmitKind); err != nil {
|
||||
return fmt.Errorf("invalid readableBuildInfoFilePendingEmit: %s", data)
|
||||
}
|
||||
if len(fileIdAndEmitKind) != 3 {
|
||||
return fmt.Errorf("invalid readableBuildInfoFilePendingEmit: expected 3 elements, got %d", len(fileIdAndEmitKind))
|
||||
}
|
||||
file, ok := fileIdAndEmitKind[0].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid fileId in readableBuildInfoFilePendingEmit: expected string, got %T", fileIdAndEmitKind[0])
|
||||
}
|
||||
var emitKind string
|
||||
emitKind, ok = fileIdAndEmitKind[1].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid emitKind in readableBuildInfoFilePendingEmit: expected string, got %T", fileIdAndEmitKind[1])
|
||||
}
|
||||
var original *incremental.BuildInfoFilePendingEmit
|
||||
original, ok = fileIdAndEmitKind[2].(*incremental.BuildInfoFilePendingEmit)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid original in readableBuildInfoFilePendingEmit: expected *incremental.BuildInfoFilePendingEmit, got %T", fileIdAndEmitKind[2])
|
||||
}
|
||||
*b = readableBuildInfoFilePendingEmit{
|
||||
file: file,
|
||||
emitKind: emitKind,
|
||||
original: original,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type readableBuildInfoEmitSignature struct {
|
||||
File string `json:"file,omitzero"`
|
||||
Signature string `json:"signature,omitzero"`
|
||||
DiffersOnlyInDtsMap bool `json:"differsOnlyInDtsMap,omitzero"`
|
||||
DiffersInOptions bool `json:"differsInOptions,omitzero"`
|
||||
Original *incremental.BuildInfoEmitSignature `json:"original,omitzero"`
|
||||
}
|
||||
|
||||
type readableBuildInfoResolvedRoot struct {
|
||||
Resolved string
|
||||
Root string
|
||||
}
|
||||
|
||||
func (b *readableBuildInfoResolvedRoot) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal([2]string{b.Resolved, b.Root})
|
||||
}
|
||||
|
||||
func (b *readableBuildInfoResolvedRoot) UnmarshalJSON(data []byte) error {
|
||||
var resolvedAndRoot [2]string
|
||||
if err := json.Unmarshal(data, &resolvedAndRoot); err != nil {
|
||||
return fmt.Errorf("invalid BuildInfoResolvedRoot: %s", data)
|
||||
}
|
||||
*b = readableBuildInfoResolvedRoot{
|
||||
Resolved: resolvedAndRoot[0],
|
||||
Root: resolvedAndRoot[1],
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func toReadableBuildInfo(buildInfo *incremental.BuildInfo, buildInfoText string) string {
|
||||
readable := readableBuildInfo{
|
||||
buildInfo: buildInfo,
|
||||
Version: buildInfo.Version,
|
||||
Errors: buildInfo.Errors,
|
||||
CheckPending: buildInfo.CheckPending,
|
||||
FileNames: buildInfo.FileNames,
|
||||
Options: buildInfo.Options,
|
||||
LatestChangedDtsFile: buildInfo.LatestChangedDtsFile,
|
||||
SemanticErrors: buildInfo.SemanticErrors,
|
||||
PackageJsons: buildInfo.PackageJsons,
|
||||
MissingPackageJsons: buildInfo.MissingPackageJsons,
|
||||
Size: len(buildInfoText),
|
||||
}
|
||||
readable.setFileInfos()
|
||||
readable.setRoot()
|
||||
readable.setFileIdsList()
|
||||
readable.setReferencedMap()
|
||||
readable.setChangeFileSet()
|
||||
readable.setSemanticDiagnostics()
|
||||
readable.setEmitDiagnostics()
|
||||
readable.setAffectedFilesPendingEmit()
|
||||
readable.setEmitSignatures()
|
||||
readable.setResolvedRoot()
|
||||
contents, err := json.MarshalIndent(&readable, "", " ")
|
||||
if err != nil {
|
||||
panic("readableBuildInfo: failed to marshal readable build info: " + err.Error())
|
||||
}
|
||||
return string(contents)
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) toFilePath(fileId incremental.BuildInfoFileId) string {
|
||||
return r.buildInfo.FileNames[fileId-1]
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) toFilePathSet(fileIdListId incremental.BuildInfoFileIdListId) []string {
|
||||
return r.FileIdsList[fileIdListId-1]
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) toReadableBuildInfoDiagnostic(diagnostics []*incremental.BuildInfoDiagnostic) []*readableBuildInfoDiagnostic {
|
||||
return core.Map(diagnostics, func(d *incremental.BuildInfoDiagnostic) *readableBuildInfoDiagnostic {
|
||||
var file string
|
||||
if d.File != 0 {
|
||||
file = r.toFilePath(d.File)
|
||||
}
|
||||
return &readableBuildInfoDiagnostic{
|
||||
File: file,
|
||||
NoFile: d.NoFile,
|
||||
Pos: d.Pos,
|
||||
End: d.End,
|
||||
Code: d.Code,
|
||||
Category: d.Category,
|
||||
MessageKey: d.MessageKey,
|
||||
MessageArgs: d.MessageArgs,
|
||||
MessageChain: r.toReadableBuildInfoDiagnostic(d.MessageChain),
|
||||
RelatedInformation: r.toReadableBuildInfoDiagnostic(d.RelatedInformation),
|
||||
ReportsUnnecessary: d.ReportsUnnecessary,
|
||||
ReportsDeprecated: d.ReportsDeprecated,
|
||||
SkippedOnNoEmit: d.SkippedOnNoEmit,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) toReadableBuildInfoDiagnosticsOfFile(diagnostics *incremental.BuildInfoDiagnosticsOfFile) *readableBuildInfoDiagnosticsOfFile {
|
||||
return &readableBuildInfoDiagnosticsOfFile{
|
||||
file: r.toFilePath(diagnostics.FileId),
|
||||
diagnostics: r.toReadableBuildInfoDiagnostic(diagnostics.Diagnostics),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) setFileInfos() {
|
||||
r.FileInfos = core.MapIndex(r.buildInfo.FileInfos, func(original *incremental.BuildInfoFileInfo, index int) *readableBuildInfoFileInfo {
|
||||
fileInfo := original.GetFileInfo()
|
||||
// Dont set original for string encoding
|
||||
if original.HasSignature() {
|
||||
original = nil
|
||||
}
|
||||
return &readableBuildInfoFileInfo{
|
||||
FileName: r.toFilePath(incremental.BuildInfoFileId(index + 1)),
|
||||
Version: fileInfo.Version(),
|
||||
Signature: fileInfo.Signature(),
|
||||
AffectsGlobalScope: fileInfo.AffectsGlobalScope(),
|
||||
ImpliedNodeFormat: fileInfo.ImpliedNodeFormat().String(),
|
||||
Original: original,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) setRoot() {
|
||||
r.Root = core.Map(r.buildInfo.Root, func(original *incremental.BuildInfoRoot) *readableBuildInfoRoot {
|
||||
var files []string
|
||||
if original.NonIncremental != "" {
|
||||
files = []string{original.NonIncremental}
|
||||
} else if original.End == 0 {
|
||||
files = []string{r.toFilePath(original.Start)}
|
||||
} else {
|
||||
files = make([]string, 0, original.End-original.Start+1)
|
||||
for i := original.Start; i <= original.End; i++ {
|
||||
files = append(files, r.toFilePath(i))
|
||||
}
|
||||
}
|
||||
return &readableBuildInfoRoot{
|
||||
Files: files,
|
||||
Original: original,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) setFileIdsList() {
|
||||
r.FileIdsList = core.Map(r.buildInfo.FileIdsList, func(ids []incremental.BuildInfoFileId) []string {
|
||||
return core.Map(ids, r.toFilePath)
|
||||
})
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) setReferencedMap() {
|
||||
if r.buildInfo.ReferencedMap != nil {
|
||||
r.ReferencedMap = &collections.OrderedMap[string, []string]{}
|
||||
for _, entry := range r.buildInfo.ReferencedMap {
|
||||
r.ReferencedMap.Set(r.toFilePath(entry.FileId), r.toFilePathSet(entry.FileIdListId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) setChangeFileSet() {
|
||||
r.ChangeFileSet = core.Map(r.buildInfo.ChangeFileSet, r.toFilePath)
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) setSemanticDiagnostics() {
|
||||
r.SemanticDiagnosticsPerFile = core.Map(r.buildInfo.SemanticDiagnosticsPerFile, func(diagnostics *incremental.BuildInfoSemanticDiagnostic) *readableBuildInfoSemanticDiagnostic {
|
||||
if diagnostics.FileId != 0 {
|
||||
return &readableBuildInfoSemanticDiagnostic{
|
||||
file: r.toFilePath(diagnostics.FileId),
|
||||
}
|
||||
}
|
||||
return &readableBuildInfoSemanticDiagnostic{
|
||||
diagnostics: r.toReadableBuildInfoDiagnosticsOfFile(diagnostics.Diagnostics),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) setEmitDiagnostics() {
|
||||
r.EmitDiagnosticsPerFile = core.Map(r.buildInfo.EmitDiagnosticsPerFile, r.toReadableBuildInfoDiagnosticsOfFile)
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) setAffectedFilesPendingEmit() {
|
||||
if r.buildInfo.AffectedFilesPendingEmit == nil {
|
||||
return
|
||||
}
|
||||
fullEmitKind := incremental.GetFileEmitKind(r.buildInfo.GetCompilerOptions(""))
|
||||
r.AffectedFilesPendingEmit = core.Map(r.buildInfo.AffectedFilesPendingEmit, func(pendingEmit *incremental.BuildInfoFilePendingEmit) *readableBuildInfoFilePendingEmit {
|
||||
emitKind := core.IfElse(pendingEmit.EmitKind == 0, fullEmitKind, pendingEmit.EmitKind)
|
||||
return &readableBuildInfoFilePendingEmit{
|
||||
file: r.toFilePath(pendingEmit.FileId),
|
||||
emitKind: toReadableFileEmitKind(emitKind),
|
||||
original: pendingEmit,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func toReadableFileEmitKind(fileEmitKind incremental.FileEmitKind) string {
|
||||
var builder strings.Builder
|
||||
addFlags := func(flags string) {
|
||||
if builder.Len() == 0 {
|
||||
builder.WriteString(flags)
|
||||
} else {
|
||||
builder.WriteString("|")
|
||||
builder.WriteString(flags)
|
||||
}
|
||||
}
|
||||
if fileEmitKind != 0 {
|
||||
if (fileEmitKind & incremental.FileEmitKindJs) != 0 {
|
||||
addFlags("Js")
|
||||
}
|
||||
if (fileEmitKind & incremental.FileEmitKindJsMap) != 0 {
|
||||
addFlags("JsMap")
|
||||
}
|
||||
if (fileEmitKind & incremental.FileEmitKindJsInlineMap) != 0 {
|
||||
addFlags("JsInlineMap")
|
||||
}
|
||||
if (fileEmitKind & incremental.FileEmitKindDts) == incremental.FileEmitKindDts {
|
||||
addFlags("Dts")
|
||||
} else {
|
||||
if (fileEmitKind & incremental.FileEmitKindDtsEmit) != 0 {
|
||||
addFlags("DtsEmit")
|
||||
}
|
||||
if (fileEmitKind & incremental.FileEmitKindDtsErrors) != 0 {
|
||||
addFlags("DtsErrors")
|
||||
}
|
||||
}
|
||||
if (fileEmitKind & incremental.FileEmitKindDtsMap) != 0 {
|
||||
addFlags("DtsMap")
|
||||
}
|
||||
}
|
||||
if builder.Len() != 0 {
|
||||
return builder.String()
|
||||
}
|
||||
return "None"
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) setEmitSignatures() {
|
||||
r.EmitSignatures = core.Map(r.buildInfo.EmitSignatures, func(signature *incremental.BuildInfoEmitSignature) *readableBuildInfoEmitSignature {
|
||||
return &readableBuildInfoEmitSignature{
|
||||
File: r.toFilePath(signature.FileId),
|
||||
Signature: signature.Signature,
|
||||
DiffersOnlyInDtsMap: signature.DiffersOnlyInDtsMap,
|
||||
DiffersInOptions: signature.DiffersInOptions,
|
||||
Original: signature,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (r *readableBuildInfo) setResolvedRoot() {
|
||||
r.ResolvedRoot = core.Map(r.buildInfo.ResolvedRoot, func(original *incremental.BuildInfoResolvedRoot) *readableBuildInfoResolvedRoot {
|
||||
return &readableBuildInfoResolvedRoot{
|
||||
Resolved: r.toFilePath(original.Resolved),
|
||||
Root: r.toFilePath(original.Root),
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user