112 lines
4.4 KiB
Go
112 lines
4.4 KiB
Go
package compiler
|
|
|
|
import (
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/collections"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/core"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/tsoptions"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/tspath"
|
|
)
|
|
|
|
type projectReferenceParseTask struct {
|
|
configName string
|
|
resolved *tsoptions.ParsedCommandLine
|
|
subTasks []*projectReferenceParseTask
|
|
}
|
|
|
|
func (t *projectReferenceParseTask) parse(projectReferenceParser *projectReferenceParser) {
|
|
t.resolved = projectReferenceParser.loader.opts.Host.GetResolvedProjectReference(t.configName, projectReferenceParser.loader.toPath(t.configName))
|
|
if t.resolved == nil {
|
|
return
|
|
}
|
|
t.resolved.ParseInputOutputNames()
|
|
if subReferences := t.resolved.ResolvedProjectReferencePaths(); len(subReferences) > 0 {
|
|
t.subTasks = createProjectReferenceParseTasks(subReferences)
|
|
}
|
|
}
|
|
|
|
func createProjectReferenceParseTasks(projectReferences []string) []*projectReferenceParseTask {
|
|
return core.Map(projectReferences, func(configName string) *projectReferenceParseTask {
|
|
return &projectReferenceParseTask{
|
|
configName: configName,
|
|
}
|
|
})
|
|
}
|
|
|
|
type projectReferenceParser struct {
|
|
loader *fileLoader
|
|
wg core.WorkGroup
|
|
tasksByFileName collections.SyncMap[tspath.Path, *projectReferenceParseTask]
|
|
}
|
|
|
|
func (p *projectReferenceParser) parse(tasks []*projectReferenceParseTask) {
|
|
p.loader.projectReferenceFileMapper.loader = p.loader
|
|
p.start(tasks)
|
|
p.wg.RunAndWait()
|
|
p.initMapper(tasks)
|
|
}
|
|
|
|
func (p *projectReferenceParser) start(tasks []*projectReferenceParseTask) {
|
|
for i, task := range tasks {
|
|
path := p.loader.toPath(task.configName)
|
|
if loadedTask, loaded := p.tasksByFileName.LoadOrStore(path, task); loaded {
|
|
// dedup tasks to ensure correct file order, regardless of which task would be started first
|
|
tasks[i] = loadedTask
|
|
} else {
|
|
p.wg.Queue(func() {
|
|
task.parse(p)
|
|
p.start(task.subTasks)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *projectReferenceParser) initMapper(tasks []*projectReferenceParseTask) {
|
|
totalReferences := p.tasksByFileName.Size() + 1
|
|
p.loader.projectReferenceFileMapper.configToProjectReference = make(map[tspath.Path]*tsoptions.ParsedCommandLine, totalReferences)
|
|
p.loader.projectReferenceFileMapper.referencesInConfigFile = make(map[tspath.Path][]tspath.Path, totalReferences)
|
|
p.loader.projectReferenceFileMapper.sourceToProjectReference = make(map[tspath.Path]*tsoptions.SourceOutputAndProjectReference)
|
|
p.loader.projectReferenceFileMapper.outputDtsToProjectReference = make(map[tspath.Path]*tsoptions.SourceOutputAndProjectReference)
|
|
p.loader.projectReferenceFileMapper.referencesInConfigFile[p.loader.opts.Config.ConfigFile.SourceFile.Path()] = p.initMapperWorker(tasks, &collections.Set[*projectReferenceParseTask]{})
|
|
if p.loader.projectReferenceFileMapper.opts.canUseProjectReferenceSource() && len(p.loader.projectReferenceFileMapper.outputDtsToProjectReference) != 0 {
|
|
p.loader.projectReferenceFileMapper.host = newProjectReferenceDtsFakingHost(p.loader)
|
|
}
|
|
}
|
|
|
|
func (p *projectReferenceParser) initMapperWorker(tasks []*projectReferenceParseTask, seen *collections.Set[*projectReferenceParseTask]) []tspath.Path {
|
|
if len(tasks) == 0 {
|
|
return nil
|
|
}
|
|
results := make([]tspath.Path, 0, len(tasks))
|
|
for _, task := range tasks {
|
|
path := p.loader.toPath(task.configName)
|
|
results = append(results, path)
|
|
// ensure we only walk each task once
|
|
if !seen.AddIfAbsent(task) {
|
|
continue
|
|
}
|
|
var referencesInConfig []tspath.Path
|
|
referencesInConfig = p.initMapperWorker(task.subTasks, seen)
|
|
p.loader.projectReferenceFileMapper.configToProjectReference[path] = task.resolved
|
|
p.loader.projectReferenceFileMapper.referencesInConfigFile[path] = referencesInConfig
|
|
if task.resolved == nil || p.loader.projectReferenceFileMapper.opts.Config.ConfigFile == task.resolved.ConfigFile {
|
|
continue
|
|
}
|
|
for key, value := range task.resolved.SourceToProjectReference() {
|
|
p.loader.projectReferenceFileMapper.sourceToProjectReference[key] = value
|
|
}
|
|
for key, value := range task.resolved.OutputDtsToProjectReference() {
|
|
p.loader.projectReferenceFileMapper.outputDtsToProjectReference[key] = value
|
|
}
|
|
if p.loader.projectReferenceFileMapper.opts.canUseProjectReferenceSource() {
|
|
declDir := task.resolved.CompilerOptions().DeclarationDir
|
|
if declDir == "" {
|
|
declDir = task.resolved.CompilerOptions().OutDir
|
|
}
|
|
if declDir != "" {
|
|
p.loader.dtsDirectories.Add(p.loader.toPath(declDir))
|
|
}
|
|
}
|
|
}
|
|
return results
|
|
}
|