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

235 lines
8.9 KiB
Go

package outputpaths
import (
"strings"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/core"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/tspath"
)
type OutputPathsHost interface {
CommonSourceDirectory() string
GetCurrentDirectory() string
UseCaseSensitiveFileNames() bool
}
type OutputPaths struct {
jsFilePath string
sourceMapFilePath string
declarationFilePath string
declarationMapPath string
}
// DeclarationFilePath implements declarations.OutputPaths.
func (o *OutputPaths) DeclarationFilePath() string {
return o.declarationFilePath
}
// JsFilePath implements declarations.OutputPaths.
func (o *OutputPaths) JsFilePath() string {
return o.jsFilePath
}
func (o *OutputPaths) SourceMapFilePath() string {
return o.sourceMapFilePath
}
func (o *OutputPaths) DeclarationMapPath() string {
return o.declarationMapPath
}
func GetOutputPathsFor(sourceFile *ast.SourceFile, options *core.CompilerOptions, host OutputPathsHost, forceDtsEmit bool) *OutputPaths {
// !!! bundle not implemented, may be deprecated
ownOutputFilePath := getOwnEmitOutputFilePath(sourceFile.FileName(), options, host, GetOutputExtension(sourceFile.FileName(), options.Jsx))
isJsonFile := ast.IsJsonSourceFile(sourceFile)
// If json file emits to the same location skip writing it, if emitDeclarationOnly skip writing it
isJsonEmittedToSameLocation := isJsonFile &&
tspath.ComparePaths(sourceFile.FileName(), ownOutputFilePath, tspath.ComparePathsOptions{
CurrentDirectory: host.GetCurrentDirectory(),
UseCaseSensitiveFileNames: host.UseCaseSensitiveFileNames(),
}) == 0
paths := &OutputPaths{}
if options.EmitDeclarationOnly != core.TSTrue && !isJsonEmittedToSameLocation {
paths.jsFilePath = ownOutputFilePath
if !ast.IsJsonSourceFile(sourceFile) {
paths.sourceMapFilePath = GetSourceMapFilePath(paths.jsFilePath, options)
}
}
if forceDtsEmit || options.GetEmitDeclarations() && !isJsonFile {
paths.declarationFilePath = GetDeclarationEmitOutputFilePath(sourceFile.FileName(), options, host)
if options.GetAreDeclarationMapsEnabled() {
paths.declarationMapPath = paths.declarationFilePath + ".map"
}
}
return paths
}
func ForEachEmittedFile(host OutputPathsHost, options *core.CompilerOptions, action func(emitFileNames *OutputPaths, sourceFile *ast.SourceFile) bool, sourceFiles []*ast.SourceFile, forceDtsEmit bool) bool {
for _, sourceFile := range sourceFiles {
if action(GetOutputPathsFor(sourceFile, options, host, forceDtsEmit), sourceFile) {
return true
}
}
return false
}
func GetOutputJSFileName(inputFileName string, options *core.CompilerOptions, host OutputPathsHost) string {
if options.EmitDeclarationOnly.IsTrue() {
return ""
}
outputFileName := GetOutputJSFileNameWorker(inputFileName, options, host)
if !tspath.FileExtensionIs(outputFileName, tspath.ExtensionJson) ||
tspath.ComparePaths(inputFileName, outputFileName, tspath.ComparePathsOptions{
CurrentDirectory: host.GetCurrentDirectory(),
UseCaseSensitiveFileNames: host.UseCaseSensitiveFileNames(),
}) != 0 {
return outputFileName
}
return ""
}
func GetOutputJSFileNameWorker(inputFileName string, options *core.CompilerOptions, host OutputPathsHost) string {
return tspath.ChangeExtension(
getOutputPathWithoutChangingExtension(inputFileName, options.OutDir, host),
GetOutputExtension(inputFileName, options.Jsx),
)
}
func GetOutputDeclarationFileNameWorker(inputFileName string, options *core.CompilerOptions, host OutputPathsHost) string {
dir := options.DeclarationDir
if len(dir) == 0 {
dir = options.OutDir
}
return tspath.ChangeExtension(
getOutputPathWithoutChangingExtension(inputFileName, dir, host),
getDeclarationEmitExtensionForPath(inputFileName),
)
}
func GetOutputExtension(fileName string, jsx core.JsxEmit) string {
switch {
case tspath.FileExtensionIs(fileName, tspath.ExtensionJson):
return tspath.ExtensionJson
case jsx == core.JsxEmitPreserve && tspath.FileExtensionIsOneOf(fileName, []string{tspath.ExtensionJsx, tspath.ExtensionTsx}):
return tspath.ExtensionJsx
case tspath.FileExtensionIsOneOf(fileName, []string{tspath.ExtensionMts, tspath.ExtensionMjs}):
return tspath.ExtensionMjs
case tspath.FileExtensionIsOneOf(fileName, []string{tspath.ExtensionCts, tspath.ExtensionCjs}):
return tspath.ExtensionCjs
default:
return tspath.ExtensionJs
}
}
func GetDeclarationEmitOutputFilePath(file string, options *core.CompilerOptions, host OutputPathsHost) string {
var outputDir *string
if len(options.DeclarationDir) > 0 {
outputDir = &options.DeclarationDir
} else if len(options.OutDir) > 0 {
outputDir = &options.OutDir
}
var path string
if outputDir != nil {
path = GetSourceFilePathInNewDirWorker(file, *outputDir, host.GetCurrentDirectory(), host.CommonSourceDirectory(), host.UseCaseSensitiveFileNames())
} else {
path = file
}
declarationExtension := tspath.GetDeclarationEmitExtensionForPath(path)
return tspath.RemoveFileExtension(path) + declarationExtension
}
func GetSourceFilePathInNewDir(fileName string, newDirPath string, currentDirectory string, commonSourceDirectory string, useCaseSensitiveFileNames bool) string {
sourceFilePath := tspath.GetNormalizedAbsolutePath(fileName, currentDirectory)
commonSourceDirectory = tspath.EnsureTrailingDirectorySeparator(commonSourceDirectory)
isSourceFileInCommonSourceDirectory := tspath.ContainsPath(commonSourceDirectory, sourceFilePath, tspath.ComparePathsOptions{
UseCaseSensitiveFileNames: useCaseSensitiveFileNames,
CurrentDirectory: currentDirectory,
})
if isSourceFileInCommonSourceDirectory {
sourceFilePath = sourceFilePath[len(commonSourceDirectory):]
}
return tspath.CombinePaths(newDirPath, sourceFilePath)
}
func getOutputPathWithoutChangingExtension(inputFileName string, outputDirectory string, host OutputPathsHost) string {
if len(outputDirectory) > 0 {
return tspath.ResolvePath(outputDirectory, tspath.GetRelativePathFromDirectory(host.CommonSourceDirectory(), inputFileName, tspath.ComparePathsOptions{
UseCaseSensitiveFileNames: host.UseCaseSensitiveFileNames(),
CurrentDirectory: host.GetCurrentDirectory(),
}))
}
return inputFileName
}
func GetSourceFilePathInNewDirWorker(fileName string, newDirPath string, currentDirectory string, commonSourceDirectory string, useCaseSensitiveFileNames bool) string {
sourceFilePath := tspath.GetNormalizedAbsolutePath(fileName, currentDirectory)
commonDir := tspath.GetCanonicalFileName(commonSourceDirectory, useCaseSensitiveFileNames)
canonFile := tspath.GetCanonicalFileName(sourceFilePath, useCaseSensitiveFileNames)
isSourceFileInCommonSourceDirectory := strings.HasPrefix(canonFile, commonDir)
if isSourceFileInCommonSourceDirectory {
sourceFilePath = sourceFilePath[len(commonSourceDirectory):]
}
return tspath.CombinePaths(newDirPath, sourceFilePath)
}
func getOwnEmitOutputFilePath(fileName string, options *core.CompilerOptions, host OutputPathsHost, extension string) string {
var emitOutputFilePathWithoutExtension string
if len(options.OutDir) > 0 {
currentDirectory := host.GetCurrentDirectory()
emitOutputFilePathWithoutExtension = tspath.RemoveFileExtension(GetSourceFilePathInNewDir(
fileName,
options.OutDir,
currentDirectory,
host.CommonSourceDirectory(),
host.UseCaseSensitiveFileNames(),
))
} else {
emitOutputFilePathWithoutExtension = tspath.RemoveFileExtension(fileName)
}
return emitOutputFilePathWithoutExtension + extension
}
func GetSourceMapFilePath(jsFilePath string, options *core.CompilerOptions) string {
if options.SourceMap.IsTrue() && !options.InlineSourceMap.IsTrue() {
return jsFilePath + ".map"
}
return ""
}
func getDeclarationEmitExtensionForPath(fileName string) string {
if tspath.FileExtensionIsOneOf(fileName, []string{tspath.ExtensionMjs, tspath.ExtensionMts}) {
return tspath.ExtensionDmts
} else if tspath.FileExtensionIsOneOf(fileName, []string{tspath.ExtensionCjs, tspath.ExtensionCts}) {
return tspath.ExtensionDcts
} else if tspath.FileExtensionIs(fileName, tspath.ExtensionJson) {
return ".d.json.ts"
}
return tspath.ExtensionDts
}
func GetBuildInfoFileName(options *core.CompilerOptions, opts tspath.ComparePathsOptions) string {
if !options.IsIncremental() && !options.Build.IsTrue() {
return ""
}
if options.TsBuildInfoFile != "" {
return options.TsBuildInfoFile
}
if options.ConfigFilePath == "" {
return ""
}
configFileExtensionLess := tspath.RemoveFileExtension(options.ConfigFilePath)
var buildInfoExtensionLess string
if options.OutDir != "" {
if options.RootDir != "" {
buildInfoExtensionLess = tspath.ResolvePath(options.OutDir, tspath.GetRelativePathFromDirectory(options.RootDir, configFileExtensionLess, opts))
} else {
buildInfoExtensionLess = tspath.CombinePaths(options.OutDir, tspath.GetBaseFileName(configFileExtensionLess))
}
} else {
buildInfoExtensionLess = configFileExtensionLess
}
return buildInfoExtensionLess + tspath.ExtensionTsBuildInfo
}