198 lines
5.5 KiB
Go
198 lines
5.5 KiB
Go
package module
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/microsoft/typescript-go/internal/ast"
|
|
"github.com/microsoft/typescript-go/internal/core"
|
|
"github.com/microsoft/typescript-go/internal/diagnostics"
|
|
"github.com/microsoft/typescript-go/internal/semver"
|
|
"github.com/microsoft/typescript-go/internal/tspath"
|
|
)
|
|
|
|
var typeScriptVersion = semver.MustParse(core.Version())
|
|
|
|
const InferredTypesContainingFile = "__inferred type names__.ts"
|
|
|
|
func IsApplicableVersionedTypesKey(key string) bool {
|
|
if !strings.HasPrefix(key, "types@") {
|
|
return false
|
|
}
|
|
range_, ok := semver.TryParseVersionRange(key[len("types@"):])
|
|
if !ok {
|
|
return false
|
|
}
|
|
return range_.Test(&typeScriptVersion)
|
|
}
|
|
|
|
func ParseNodeModuleFromPath(resolved string, isFolder bool) string {
|
|
path := tspath.NormalizePath(resolved)
|
|
idx := strings.LastIndex(path, "/node_modules/")
|
|
if idx == -1 {
|
|
return ""
|
|
}
|
|
|
|
indexAfterNodeModules := idx + len("/node_modules/")
|
|
indexAfterPackageName := moveToNextDirectorySeparatorIfAvailable(path, indexAfterNodeModules, isFolder)
|
|
if path[indexAfterNodeModules] == '@' {
|
|
indexAfterPackageName = moveToNextDirectorySeparatorIfAvailable(path, indexAfterPackageName, isFolder)
|
|
}
|
|
return path[:indexAfterPackageName]
|
|
}
|
|
|
|
func ParsePackageName(moduleName string) (packageName, rest string) {
|
|
idx := strings.Index(moduleName, "/")
|
|
if len(moduleName) > 0 && moduleName[0] == '@' {
|
|
offset := idx + 1
|
|
idx = strings.Index(moduleName[offset:], "/")
|
|
if idx != -1 {
|
|
idx += offset
|
|
}
|
|
}
|
|
if idx == -1 {
|
|
return moduleName, ""
|
|
}
|
|
return moduleName[:idx], moduleName[idx+1:]
|
|
}
|
|
|
|
func MangleScopedPackageName(packageName string) string {
|
|
if len(packageName) > 0 && packageName[0] == '@' {
|
|
idx := strings.Index(packageName, "/")
|
|
if idx == -1 {
|
|
return packageName
|
|
}
|
|
return packageName[1:idx] + "__" + packageName[idx+1:]
|
|
}
|
|
return packageName
|
|
}
|
|
|
|
func UnmangleScopedPackageName(packageName string) string {
|
|
before, after, ok := strings.Cut(packageName, "__")
|
|
if ok {
|
|
return "@" + before + "/" + after
|
|
}
|
|
return packageName
|
|
}
|
|
|
|
func GetTypesPackageName(packageName string) string {
|
|
return "@types/" + MangleScopedPackageName(packageName)
|
|
}
|
|
|
|
func GetPackageNameFromTypesPackageName(mangledName string) string {
|
|
withoutAtTypePrefix := strings.TrimPrefix(mangledName, "@types/")
|
|
if withoutAtTypePrefix != mangledName {
|
|
return UnmangleScopedPackageName(withoutAtTypePrefix)
|
|
}
|
|
return mangledName
|
|
}
|
|
|
|
func ComparePatternKeys(a, b string) int {
|
|
aPatternIndex := strings.Index(a, "*")
|
|
bPatternIndex := strings.Index(b, "*")
|
|
baseLenA := len(a)
|
|
if aPatternIndex != -1 {
|
|
baseLenA = aPatternIndex + 1
|
|
}
|
|
baseLenB := len(b)
|
|
if bPatternIndex != -1 {
|
|
baseLenB = bPatternIndex + 1
|
|
}
|
|
|
|
if baseLenA > baseLenB {
|
|
return -1
|
|
}
|
|
if baseLenB > baseLenA {
|
|
return 1
|
|
}
|
|
if aPatternIndex == -1 {
|
|
return 1
|
|
}
|
|
if bPatternIndex == -1 {
|
|
return -1
|
|
}
|
|
if len(a) > len(b) {
|
|
return -1
|
|
}
|
|
if len(b) > len(a) {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// Returns a DiagnosticMessage if we won't include a resolved module due to its extension.
|
|
// The DiagnosticMessage's parameters are the imported module name, and the filename it resolved to.
|
|
// This returns a diagnostic even if the module will be an untyped module.
|
|
func GetResolutionDiagnostic(options *core.CompilerOptions, resolvedModule *ResolvedModule, file *ast.SourceFile) *diagnostics.Message {
|
|
needJsx := func() *diagnostics.Message {
|
|
if options.Jsx != core.JsxEmitNone {
|
|
return nil
|
|
}
|
|
return diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set
|
|
}
|
|
|
|
needAllowJs := func() *diagnostics.Message {
|
|
if options.GetAllowJS() || !options.NoImplicitAny.DefaultIfUnknown(options.Strict).IsTrue() {
|
|
return nil
|
|
}
|
|
return diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type
|
|
}
|
|
|
|
needResolveJsonModule := func() *diagnostics.Message {
|
|
if options.GetResolveJsonModule() {
|
|
return nil
|
|
}
|
|
return diagnostics.Module_0_was_resolved_to_1_but_resolveJsonModule_is_not_used
|
|
}
|
|
|
|
needAllowArbitraryExtensions := func() *diagnostics.Message {
|
|
if file.IsDeclarationFile || options.AllowArbitraryExtensions.IsTrue() {
|
|
return nil
|
|
}
|
|
return diagnostics.Module_0_was_resolved_to_1_but_allowArbitraryExtensions_is_not_set
|
|
}
|
|
|
|
switch resolvedModule.Extension {
|
|
case tspath.ExtensionTs, tspath.ExtensionDts,
|
|
tspath.ExtensionMts, tspath.ExtensionDmts,
|
|
tspath.ExtensionCts, tspath.ExtensionDcts:
|
|
// These are always allowed.
|
|
return nil
|
|
case tspath.ExtensionTsx:
|
|
return needJsx()
|
|
case tspath.ExtensionJsx:
|
|
if message := needJsx(); message != nil {
|
|
return message
|
|
}
|
|
return needAllowJs()
|
|
case tspath.ExtensionJs, tspath.ExtensionMjs, tspath.ExtensionCjs:
|
|
return needAllowJs()
|
|
case tspath.ExtensionJson:
|
|
return needResolveJsonModule()
|
|
default:
|
|
return needAllowArbitraryExtensions()
|
|
}
|
|
}
|
|
|
|
// TryGetJSExtensionForFile maps TS/JS/DTS extensions to the output JS-side extension.
|
|
// Returns an empty string if the extension is unsupported.
|
|
func TryGetJSExtensionForFile(fileName string, options *core.CompilerOptions) string {
|
|
ext := tspath.TryGetExtensionFromPath(fileName)
|
|
switch ext {
|
|
case tspath.ExtensionTs, tspath.ExtensionDts:
|
|
return tspath.ExtensionJs
|
|
case tspath.ExtensionTsx:
|
|
if options.Jsx == core.JsxEmitPreserve {
|
|
return tspath.ExtensionJsx
|
|
}
|
|
return tspath.ExtensionJs
|
|
case tspath.ExtensionJs, tspath.ExtensionJsx, tspath.ExtensionJson:
|
|
return ext
|
|
case tspath.ExtensionDmts, tspath.ExtensionMts, tspath.ExtensionMjs:
|
|
return tspath.ExtensionMjs
|
|
case tspath.ExtensionDcts, tspath.ExtensionCts, tspath.ExtensionCjs:
|
|
return tspath.ExtensionCjs
|
|
default:
|
|
return ""
|
|
}
|
|
}
|