public string resolveModuleMain(string name, TSFileAdditionalInfo parentInfo) { if (!_owner.ProjectOptions.AllowModuleDeepImport) { if (!parentInfo.Owner.Name.EndsWith(".d.ts") && (name.Contains('/') || name.Contains('\\'))) { parentInfo.ReportDiag(true, -10, "Absolute import '" + name + "' must be just simple module name", 0, 0, 0, 0); return(null); } } var mname = PathUtils.EnumParts(name).First().name; var moduleInfo = TSProject.FindInfoForModule(_owner.Owner, parentInfo.Owner.Parent, _owner.DiskCache, _owner.Logger, mname, out var diskName); if (moduleInfo == null) { return(null); } if (mname != diskName) { parentInfo.ReportDiag(false, -2, "Module import has wrong casing '" + mname + "' on disk '" + diskName + "'", 0, 0, 0, 0); } moduleInfo.LoadProjectJson(true); if (mname.Length != name.Length) { return(ResolveLocalImport(PathUtils.Join(moduleInfo.Owner.FullPath, name.Substring(mname.Length + 1)), parentInfo, moduleInfo, name)); } parentInfo.ImportingModule(moduleInfo); var mainFile = PathUtils.Join(moduleInfo.Owner.FullPath, moduleInfo.MainFile); var item = _owner.DiskCache.TryGetItemPreferReal(mainFile) as IFileCache; if (item == null || item.IsInvalid) { return(null); } var itemInfo = TSFileAdditionalInfo.Get(item, _owner.DiskCache); moduleInfo.MainFileInfo = itemInfo; itemInfo.ImportedAsModule = name; itemInfo.MyProject = moduleInfo; var parentProject = parentInfo.MyProject; if (parentProject != null && parentProject.IsRootProject && !parentInfo.Owner.FullPath.Contains("/node_modules/") && ((parentProject.Dependencies == null || !parentProject.Dependencies.Contains(name)) && (parentProject.DevDependencies == null || !parentProject.DevDependencies.Contains(name)))) { parentInfo.ReportDiag(false, -12, "Importing module " + name + " without being in package.json as dependency", 0, 0, 0, 0); } if (moduleInfo.ProjectOptions?.ObsoleteMessage != null) { if (!PragmaParser.ParseIgnoreImportingObsolete(parentInfo.Owner.Utf8Content).Contains(name)) { parentInfo.ReportDiag(false, -14, "Importing obsolete module: " + moduleInfo.ProjectOptions?.ObsoleteMessage, 0, 0, 0, 0); } } AddSource(itemInfo); if (!IsTsOrTsx(mainFile)) { if (moduleInfo.MainFileNeedsToBeCompiled) { itemInfo.Type = FileCompilationType.EsmJavaScript; CheckAdd(mainFile); TryToResolveFromBuildCache(itemInfo); } else { itemInfo.Type = FileCompilationType.JavaScript; CheckAdd(mainFile); } if (moduleInfo.TypesMainFile != null) { var dtsPath = PathUtils.Join(moduleInfo.Owner.FullPath, moduleInfo.TypesMainFile); item = _owner.DiskCache.TryGetItem(dtsPath) as IFileCache; itemInfo.DtsLink = TSFileAdditionalInfo.Get(item, _owner.DiskCache); if (item != null && !item.IsInvalid) { return(dtsPath); } } return(null); } itemInfo.Type = FileCompilationType.TypeScript; CheckAdd(item.FullPath); TryToResolveFromBuildCache(itemInfo); if (itemInfo.DtsLink != null && !ToCompile.Contains(item.FullPath) && !itemInfo.NeedsCompilation()) { var fp = itemInfo.DtsLink.Owner.FullPath; _readFileMap[fp] = itemInfo.DtsLink.Owner; return(fp); } return(item.FullPath); }
public string resolveModuleMain(string name, TSFileAdditionalInfo parentInfo) { var moduleInfo = TSProject.FindInfoForModule(_owner.Owner, _owner.DiskCache, _owner.Logger, name, out var diskName); if (moduleInfo == null) { return(null); } if (name != diskName) { parentInfo.ReportDiag(false, -2, "Module import has wrong casing '" + name + "' on disk '" + diskName + "'", 0, 0, 0, 0); } moduleInfo.LoadProjectJson(true); parentInfo.ImportingModule(moduleInfo); var mainFile = PathUtils.Join(moduleInfo.Owner.FullPath, moduleInfo.MainFile); var item = _owner.DiskCache.TryGetItem(mainFile) as IFileCache; if (item == null || item.IsInvalid) { return(null); } var itemInfo = TSFileAdditionalInfo.Get(item, _owner.DiskCache); moduleInfo.MainFileInfo = itemInfo; itemInfo.ImportedAsModule = name; itemInfo.MyProject = moduleInfo; var parentProject = parentInfo.MyProject; if (parentProject.IsRootProject && ((parentProject.Dependencies == null || !parentProject.Dependencies.Contains(name)) && (parentProject.DevDependencies == null || !parentProject.DevDependencies.Contains(name)))) { parentInfo.ReportDiag(false, -12, "Importing module " + name + " without being in package.json as dependency", 0, 0, 0, 0); } if (moduleInfo.ProjectOptions?.ObsoleteMessage != null) { if (!PragmaParser.ParseIgnoreImportingObsolete(parentInfo.Owner.Utf8Content).Contains(name)) { parentInfo.ReportDiag(false, -14, "Importing obsolete module: " + moduleInfo.ProjectOptions?.ObsoleteMessage, 0, 0, 0, 0); } } AddSource(itemInfo); if (!IsTsOrTsx(mainFile)) { itemInfo.Type = FileCompilationType.JavaScript; CheckAdd(mainFile); if (moduleInfo.TypesMainFile != null) { var dtsPath = PathUtils.Join(moduleInfo.Owner.FullPath, moduleInfo.TypesMainFile); item = _owner.DiskCache.TryGetItem(dtsPath) as IFileCache; itemInfo.DtsLink = TSFileAdditionalInfo.Get(item, _owner.DiskCache); if (item != null && !item.IsInvalid) { return(dtsPath); } } return(null); } itemInfo.Type = FileCompilationType.TypeScript; CheckAdd(item.FullPath); TryToResolveFromBuildCache(itemInfo); if (itemInfo.DtsLink != null && !ToCompile.Contains(item.FullPath) && !itemInfo.NeedsCompilation()) { return(itemInfo.DtsLink.Owner.FullPath); } return(item.FullPath); }
// returns "?" if error in resolving public string ResolveImport(string from, string name, bool preferDts = false, bool isAsset = false, bool forceResource = false, bool skipCheckAdd = false) { if (Result.ResolveCache.TryGetValue((from, name), out var res)) { if (res.IterationId == IterationId) { return(res.FileName); } if (res.FileName != null && !CheckFileExistence(res.FileName)) { goto again; } for (uint i = 0; i < res.NegativeChecks.Count; i++) { if (CheckItemExistence(res.NegativeChecks[i])) { goto again; } } } again :; if (res == null) { res = new ResolveResult(); Result.ResolveCache.Add((from, name), res); } else { res.FileName = null; res.NegativeChecks.Clear(); } res.IterationId = IterationId; var relative = name.StartsWith("./") || name.StartsWith("../"); Result.Path2FileInfo.TryGetValue(from, out var parentInfo); string?fn = null; if (relative) { fn = PathUtils.Join(parentInfo.Owner.Parent.FullPath, name); var browserResolve = parentInfo.FromModule?.ProjectOptions?.BrowserResolve; if (browserResolve != null) { var relativeToModule = PathUtils.Subtract(fn + ".js", parentInfo.FromModule.Owner.FullPath); if (!relativeToModule.StartsWith("../")) { relativeToModule = "./" + relativeToModule; } if (browserResolve.TryGetValue(relativeToModule, out var resolveReplace)) { fn = PathUtils.Join(parentInfo.FromModule.Owner.FullPath, resolveReplace); } } } relative :; if (relative) { if (fn.EndsWith(".json") || fn.EndsWith(".css")) { var fc = Owner.DiskCache.TryGetItem(fn) as IFileCache; if (fc != null && !fc.IsInvalid) { res.FileName = fn; CheckAdd(fn, forceResource ? FileCompilationType.Resource : fn.EndsWith(".json") ? (isAsset ? FileCompilationType.Resource : FileCompilationType.Json) : (isAsset ? FileCompilationType.Css : FileCompilationType.ImportedCss)); return(res.FileName); } res.NegativeChecks.Add(fn); } var dirPath = PathUtils.Parent(fn).ToString(); var fileOnly = fn.Substring(dirPath.Length + 1); var dc = Owner.DiskCache.TryGetItem(dirPath) as IDirectoryCache; if (dc == null || dc.IsInvalid) { res.FileName = "?"; res.NegativeChecks.Add(dirPath); return(res.FileName); } IFileCache item = (parentInfo.Type == FileCompilationType.EsmJavaScript ? ExtensionsToImportFromJs : ExtensionsToImport).Select(ext => { var ff = dc.TryGetChild(fileOnly + ext) as IFileCache; if (ff == null || ff.IsInvalid) { res.NegativeChecks.Add(dirPath + "/" + fileOnly + ext); return(null); } return(ff); }) .FirstOrDefault(i => i != null); if (item == null) { res.FileName = "?"; return(res.FileName); } res.FileName = item.FullPath; if (item.FullPath.Substring(0, fn.Length) != fn) { parentInfo.ReportDiag(false, -1, "Local import has wrong casing '" + fn + "' on disk '" + item.FullPath + "'", 0, 0, 0, 0); } if (!skipCheckAdd) { if (forceResource) { CheckAdd(item.FullPath, FileCompilationType.Resource); } else if (IsDts(item.Name)) { CheckAdd(item.FullPath, FileCompilationType.TypeScriptDefinition); if (dc.TryGetChild(fileOnly + ".js") is IFileCache jsItem) { CheckAdd(jsItem.FullPath, FileCompilationType.EsmJavaScript); res.FileNameJs = jsItem.FullPath; parentInfo.ReportDependency(jsItem.FullPath); } else { res.NegativeChecks.Add(dirPath + "/" + fileOnly + ".js"); // implementation for .d.ts file does not have same name, it needs to be added to build by b.asset("lib.js") and cannot have dependencies } } else if (IsTsOrTsxOrJsOrJsx(item.Name)) { CheckAdd(item.FullPath, IsTsOrTsx(item.Name) ? FileCompilationType.TypeScript : isAsset?FileCompilationType.JavaScriptAsset: FileCompilationType.EsmJavaScript); } else { CheckAdd(item.FullPath, FileCompilationType.Unknown); } } return(res.FileNameWithPreference(preferDts)); } else { var pos = 0; PathUtils.EnumParts(name, ref pos, out var mn, out _); string mname; if (name[0] == '@') { PathUtils.EnumParts(name, ref pos, out var mn2, out _); mname = mn.ToString() + "/" + mn2.ToString(); } else { mname = mn.ToString(); } string?mainFileReplace = null; if (mname.Length == name.Length && parentInfo != null) { var browserResolve = parentInfo.FromModule?.ProjectOptions?.BrowserResolve; if (browserResolve != null) { if (browserResolve.TryGetValue(name, out var resolveReplace)) { if (resolveReplace == null) { res.FileName = "<empty>"; return(res.FileName); } if (!resolveReplace.StartsWith(name + "/")) { fn = PathUtils.Join(parentInfo.FromModule !.Owner.FullPath, resolveReplace); relative = true; goto relative; } mainFileReplace = resolveReplace.Substring(name.Length + 1); } } } var moduleInfo = ResolveModule(mname); if (moduleInfo == null) { ReportMissingImport(from, name); res.FileName = "?"; return(res.FileName); } if (parentInfo !.FromModule == Owner) { if (!Owner.Dependencies?.Contains(moduleInfo.Name !) ?? false) { var allowDevDependencies = (Owner.ProjectOptions.ExampleSources?.Contains(parentInfo.Owner !.FullPath) ?? false) || (Owner.ProjectOptions.TestSources?.Contains(parentInfo.Owner !.FullPath) ?? false) || IsExampleOrSpecDir(Owner.Owner, parentInfo.Owner !.Parent !) ; if (!allowDevDependencies || (!Owner.DevDependencies?.Contains(moduleInfo.Name !) ?? false)) { parentInfo.ReportDiag(false, -12, $"Importing module {moduleInfo.Name} without being in package.json as dependency", 0, 0, 0, 0); } } } if (mname != moduleInfo.Name) { parentInfo.ReportDiag(false, -2, "Module import has wrong casing '" + mname + "' on disk '" + moduleInfo.Name + "'", 0, 0, 0, 0); } if (mname.Length != name.Length) { fn = PathUtils.Join(moduleInfo.Owner.FullPath, name.Substring(mname.Length + 1)); relative = true; goto relative; } if (mainFileReplace != null) { moduleInfo.MainFile = mainFileReplace; } var mainFile = PathUtils.Join(moduleInfo.Owner.FullPath, moduleInfo.MainFile); res.FileName = mainFile; if (!skipCheckAdd) { CheckAdd(mainFile, IsTsOrTsx(mainFile) ? FileCompilationType.TypeScript : FileCompilationType.EsmJavaScript); } if (moduleInfo.ProjectOptions?.ObsoleteMessage != null) { if (!PragmaParser.ParseIgnoreImportingObsolete(parentInfo.Owner.Utf8Content).Contains(name)) { parentInfo.ReportDiag(false, -14, "Importing obsolete module: " + moduleInfo.ProjectOptions?.ObsoleteMessage, 0, 0, 0, 0); } } return(res.FileName); } }