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

114 lines
3.8 KiB
Go

package build
import (
"time"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/collections"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/compiler"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/execute/incremental"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/execute/tsc"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/tsoptions"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/tspath"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/vfs"
)
type host struct {
orchestrator *Orchestrator
host compiler.CompilerHost
// Caches that last only for build cycle and then cleared out
extendedConfigCache tsc.ExtendedConfigCache
sourceFiles parseCache[ast.SourceFileParseOptions, *ast.SourceFile]
configTimes collections.SyncMap[tspath.Path, time.Duration]
// caches that stay as long as they are needed
resolvedReferences parseCache[tspath.Path, *tsoptions.ParsedCommandLine]
mTimes *collections.SyncMap[tspath.Path, time.Time]
}
var (
_ compiler.CompilerHost = (*host)(nil)
_ incremental.BuildInfoReader = (*host)(nil)
_ incremental.Host = (*host)(nil)
)
func (h *host) FS() vfs.FS {
return h.host.FS()
}
func (h *host) DefaultLibraryPath() string {
return h.host.DefaultLibraryPath()
}
func (h *host) GetCurrentDirectory() string {
return h.host.GetCurrentDirectory()
}
func (h *host) Trace(msg string) {
panic("build.Orchestrator.host does not support tracing, use a different host for tracing")
}
func (h *host) GetSourceFile(opts ast.SourceFileParseOptions) *ast.SourceFile {
// Cache dts and json files as they will be reused
return h.sourceFiles.loadOrStoreNewIf(opts, h.host.GetSourceFile, func(value *ast.SourceFile) bool {
return value != nil && (tspath.IsDeclarationFileName(opts.FileName) || tspath.FileExtensionIs(opts.FileName, tspath.ExtensionJson))
})
}
func (h *host) GetResolvedProjectReference(fileName string, path tspath.Path) *tsoptions.ParsedCommandLine {
return h.resolvedReferences.loadOrStoreNew(path, func(path tspath.Path) *tsoptions.ParsedCommandLine {
configStart := h.orchestrator.opts.Sys.Now()
commandLine, _ := tsoptions.GetParsedCommandLineOfConfigFilePath(fileName, path, h.orchestrator.opts.Command.CompilerOptions, h, &h.extendedConfigCache)
configTime := h.orchestrator.opts.Sys.Now().Sub(configStart)
h.configTimes.Store(path, configTime)
return commandLine
})
}
func (h *host) ReadBuildInfo(config *tsoptions.ParsedCommandLine) *incremental.BuildInfo {
configPath := h.orchestrator.toPath(config.ConfigName())
task := h.orchestrator.getTask(configPath)
buildInfo, _ := task.loadOrStoreBuildInfo(h.orchestrator, h.orchestrator.toPath(config.ConfigName()), config.GetBuildInfoFileName())
return buildInfo
}
func (h *host) GetMTime(file string) time.Time {
return h.loadOrStoreMTime(file, nil, true)
}
func (h *host) SetMTime(file string, mTime time.Time) error {
return h.FS().Chtimes(file, time.Time{}, mTime)
}
func (h *host) loadOrStoreMTime(file string, oldCache *collections.SyncMap[tspath.Path, time.Time], store bool) time.Time {
path := h.orchestrator.toPath(file)
if existing, loaded := h.mTimes.Load(path); loaded {
return existing
}
var found bool
var mTime time.Time
if oldCache != nil {
mTime, found = oldCache.Load(path)
}
if !found {
mTime = incremental.GetMTime(h.host, file)
}
if store {
mTime, _ = h.mTimes.LoadOrStore(path, mTime)
}
return mTime
}
func (h *host) storeMTime(file string, mTime time.Time) {
path := h.orchestrator.toPath(file)
h.mTimes.Store(path, mTime)
}
func (h *host) storeMTimeFromOldCache(file string, oldCache *collections.SyncMap[tspath.Path, time.Time]) {
path := h.orchestrator.toPath(file)
if mTime, found := oldCache.Load(path); found {
h.mTimes.Store(path, mTime)
}
}