Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51385,9 +51385,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// Initialize global symbol table
let augmentations: (readonly (StringLiteral | Identifier)[])[] | undefined;
for (const file of host.getSourceFiles()) {
if (file.redirectInfo) {
continue;
}
if (!isExternalOrCommonJsModule(file)) {
// It is an error for a non-external-module (i.e. script) to declare its own `globalThis`.
const fileGlobalThisSymbol = file.locals!.get("globalThis" as __String);
Expand Down Expand Up @@ -53689,7 +53686,6 @@ function createBasicNodeBuilderModuleSpecifierResolutionHost(host: TypeCheckerHo
getSymlinkCache: maybeBind(host, host.getSymlinkCache),
getPackageJsonInfoCache: () => host.getPackageJsonInfoCache?.(),
useCaseSensitiveFileNames: () => host.useCaseSensitiveFileNames(),
redirectTargetsMap: host.redirectTargetsMap,
getRedirectFromSourceFile: fileName => host.getRedirectFromSourceFile(fileName),
isSourceOfProjectReferenceRedirect: fileName => host.isSourceOfProjectReferenceRedirect(fileName),
fileExists: fileName => host.fileExists(fileName),
Expand Down
41 changes: 1 addition & 40 deletions src/compiler/factory/nodeFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,6 @@ import {
QuestionDotToken,
QuestionToken,
ReadonlyKeyword,
RedirectInfo,
reduceLeft,
RegularExpressionLiteral,
RestTypeNode,
Expand Down Expand Up @@ -1003,7 +1002,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
updateEnumMember,
createSourceFile,
updateSourceFile,
createRedirectedSourceFile,
createBundle,
updateBundle,
createSyntheticExpression,
Expand Down Expand Up @@ -6092,43 +6090,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
return node;
}

function createRedirectedSourceFile(redirectInfo: RedirectInfo) {
const node: SourceFile = Object.create(redirectInfo.redirectTarget);
Object.defineProperties(node, {
id: {
get(this: SourceFile) {
return this.redirectInfo!.redirectTarget.id;
},
set(this: SourceFile, value: SourceFile["id"]) {
this.redirectInfo!.redirectTarget.id = value;
},
},
symbol: {
get(this: SourceFile) {
return this.redirectInfo!.redirectTarget.symbol;
},
set(this: SourceFile, value: SourceFile["symbol"]) {
this.redirectInfo!.redirectTarget.symbol = value;
},
},
});
node.redirectInfo = redirectInfo;
return node;
}

function cloneRedirectedSourceFile(source: SourceFile) {
const node = createRedirectedSourceFile(source.redirectInfo!) as Mutable<SourceFile>;
node.flags |= source.flags & ~NodeFlags.Synthesized;
node.fileName = source.fileName;
node.path = source.path;
node.resolvedPath = source.resolvedPath;
node.originalFileName = source.originalFileName;
node.packageJsonLocations = source.packageJsonLocations;
node.packageJsonScope = source.packageJsonScope;
node.emitNode = undefined;
return node;
}

function cloneSourceFileWorker(source: SourceFile) {
// TODO: This mechanism for cloning results in megamorphic property reads and writes. In future perf-related
// work, we should consider switching explicit property assignments instead of using `for..in`.
Expand All @@ -6148,7 +6109,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
}

function cloneSourceFile(source: SourceFile) {
const node = source.redirectInfo ? cloneRedirectedSourceFile(source) : cloneSourceFileWorker(source);
const node = cloneSourceFileWorker(source);
setOriginal(node, source);
return node;
}
Expand Down
4 changes: 1 addition & 3 deletions src/compiler/moduleSpecifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -720,9 +720,7 @@ export function forEachFileNameOfModule<T>(
const getCanonicalFileName = hostGetCanonicalFileName(host);
const cwd = host.getCurrentDirectory();
const referenceRedirect = host.isSourceOfProjectReferenceRedirect(importedFileName) ? host.getRedirectFromSourceFile(importedFileName)?.outputDts : undefined;
const importedPath = toPath(importedFileName, cwd, getCanonicalFileName);
const redirects = host.redirectTargetsMap.get(importedPath) || emptyArray;
const importedFileNames = [...(referenceRedirect ? [referenceRedirect] : emptyArray), importedFileName, ...redirects];
const importedFileNames = [...(referenceRedirect ? [referenceRedirect] : emptyArray), importedFileName];
const targets = importedFileNames.map(f => getNormalizedAbsolutePath(f, cwd));
let shouldFilterIgnoredPaths = !every(targets, containsIgnoredPath);

Expand Down
91 changes: 2 additions & 89 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import {
createModeAwareCache,
createModeAwareCacheKey,
createModuleResolutionCache,
createMultiMap,
createProgramDiagnostics,
CreateProgramOptions,
createSourceFile,
Expand Down Expand Up @@ -238,15 +237,13 @@ import {
optionDeclarations,
optionsHaveChanges,
PackageId,
packageIdToPackageName,
packageIdToString,
PackageJsonInfoCache,
ParameterDeclaration,
ParseConfigFileHost,
ParsedCommandLine,
parseIsolatedEntityName,
parseJsonSourceFileConfigFileContent,
parseNodeFactory,
Path,
pathContainsNodeModules,
pathIsAbsolute,
Expand Down Expand Up @@ -1688,14 +1685,6 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
actualResolveLibrary = (libraryName, resolveFrom, options) => resolveLibrary(libraryName, resolveFrom, options, host, libraryResolutionCache);
}

// Map from a stringified PackageId to the source file with that id.
// Only one source file may have a given packageId. Others become redirects (see createRedirectSourceFile).
// `packageIdToSourceFile` is only used while building the program, while `sourceFileToPackageName` and `isSourceFileTargetOfRedirect` are kept around.
const packageIdToSourceFile = new Map<string, SourceFile>();
// Maps from a SourceFile's `.path` to the name of the package it was imported with.
let sourceFileToPackageName = new Map<Path, string>();
// Key is a file name. Value is the (non-empty, or undefined) list of files that redirect to it.
let redirectTargetsMap = createMultiMap<Path, string>();
let usesUriStyleNodeCoreModules: boolean | undefined;

/**
Expand Down Expand Up @@ -1910,8 +1899,6 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
getModeForResolutionAtIndex,
getSourceFileFromReference,
getLibFileFromReference,
sourceFileToPackageName,
redirectTargetsMap,
usesUriStyleNodeCoreModules,
resolvedModules,
resolvedTypeReferenceDirectiveNames,
Expand Down Expand Up @@ -2379,15 +2366,10 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
}

const oldSourceFiles = oldProgram.getSourceFiles();
const enum SeenPackageName {
Exists,
Modified,
}
const seenPackageNames = new Map<string, SeenPackageName>();

for (const oldSourceFile of oldSourceFiles) {
const sourceFileOptions = getCreateSourceFileOptions(oldSourceFile.fileName, moduleResolutionCache, host, options);
let newSourceFile = host.getSourceFileByPath
const newSourceFile = host.getSourceFileByPath
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.resolvedPath, sourceFileOptions, /*onError*/ undefined, shouldCreateNewSourceFile)
: host.getSourceFile(oldSourceFile.fileName, sourceFileOptions, /*onError*/ undefined, shouldCreateNewSourceFile); // TODO: GH#18217

Expand All @@ -2397,48 +2379,14 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
newSourceFile.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined;
newSourceFile.packageJsonScope = sourceFileOptions.packageJsonScope;

Debug.assert(!newSourceFile.redirectInfo, "Host should not return a redirect source file from `getSourceFile`");

let fileChanged: boolean;
if (oldSourceFile.redirectInfo) {
// We got `newSourceFile` by path, so it is actually for the unredirected file.
// This lets us know if the unredirected file has changed. If it has we should break the redirect.
if (newSourceFile !== oldSourceFile.redirectInfo.unredirected) {
// Underlying file has changed. Might not redirect anymore. Must rebuild program.
return StructureIsReused.Not;
}
fileChanged = false;
newSourceFile = oldSourceFile; // Use the redirect.
}
else if (oldProgram.redirectTargetsMap.has(oldSourceFile.path)) {
// If a redirected-to source file changes, the redirect may be broken.
if (newSourceFile !== oldSourceFile) {
return StructureIsReused.Not;
}
fileChanged = false;
}
else {
fileChanged = newSourceFile !== oldSourceFile;
}
const fileChanged = newSourceFile !== oldSourceFile;

// Since the project references havent changed, its right to set originalFileName and resolvedPath here
newSourceFile.path = oldSourceFile.path;
newSourceFile.originalFileName = oldSourceFile.originalFileName;
newSourceFile.resolvedPath = oldSourceFile.resolvedPath;
newSourceFile.fileName = oldSourceFile.fileName;

const packageName = oldProgram.sourceFileToPackageName.get(oldSourceFile.path);
if (packageName !== undefined) {
// If there are 2 different source files for the same package name and at least one of them changes,
// they might become redirects. So we must rebuild the program.
const prevKind = seenPackageNames.get(packageName);
const newKind = fileChanged ? SeenPackageName.Modified : SeenPackageName.Exists;
if ((prevKind !== undefined && newKind === SeenPackageName.Modified) || prevKind === SeenPackageName.Modified) {
return StructureIsReused.Not;
}
seenPackageNames.set(packageName, newKind);
}

if (fileChanged) {
if (oldSourceFile.impliedNodeFormat !== newSourceFile.impliedNodeFormat) {
structureIsReused = StructureIsReused.SafeModules;
Expand Down Expand Up @@ -2579,8 +2527,6 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
automaticTypeDirectiveNames = oldProgram.getAutomaticTypeDirectiveNames();
automaticTypeDirectiveResolutions = oldProgram.getAutomaticTypeDirectiveResolutions();

sourceFileToPackageName = oldProgram.sourceFileToPackageName;
redirectTargetsMap = oldProgram.redirectTargetsMap;
usesUriStyleNodeCoreModules = oldProgram.usesUriStyleNodeCoreModules;
resolvedModules = oldProgram.resolvedModules;
resolvedTypeReferenceDirectiveNames = oldProgram.resolvedTypeReferenceDirectiveNames;
Expand Down Expand Up @@ -2622,7 +2568,6 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
useCaseSensitiveFileNames: () => host.useCaseSensitiveFileNames(),
getBuildInfo: () => program.getBuildInfo?.(),
getSourceFileFromReference: (file, ref) => program.getSourceFileFromReference(file, ref),
redirectTargetsMap,
getFileIncludeReasons: program.getFileIncludeReasons,
createHash: maybeBind(host, host.createHash),
getModuleResolutionCache: () => program.getModuleResolutionCache(),
Expand Down Expand Up @@ -3501,18 +3446,6 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
}
}

function createRedirectedSourceFile(redirectTarget: SourceFile, unredirected: SourceFile, fileName: string, path: Path, resolvedPath: Path, originalFileName: string, sourceFileOptions: CreateSourceFileOptions): SourceFile {
const redirect = parseNodeFactory.createRedirectedSourceFile({ redirectTarget, unredirected });
redirect.fileName = fileName;
redirect.path = path;
redirect.resolvedPath = resolvedPath;
redirect.originalFileName = originalFileName;
redirect.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined;
redirect.packageJsonScope = sourceFileOptions.packageJsonScope;
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
return redirect;
}

// Get source file from normalized fileName
function findSourceFile(fileName: string, isDefaultLib: boolean, reason: FileIncludeReason, packageId: PackageId | undefined): SourceFile | undefined {
tracing?.push(tracing.Phase.Program, "findSourceFile", {
Expand Down Expand Up @@ -3634,26 +3567,6 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
shouldCreateNewSourceFile,
);

if (packageId) {
const packageIdKey = packageIdToString(packageId);
const fileFromPackageId = packageIdToSourceFile.get(packageIdKey);
if (fileFromPackageId) {
// Some other SourceFile already exists with this package name and version.
// Instead of creating a duplicate, just redirect to the existing one.
const dupFile = createRedirectedSourceFile(fileFromPackageId, file!, fileName, path, toPath(fileName), originalFileName, sourceFileOptions);
redirectTargetsMap.add(fileFromPackageId.path, fileName);
addFileToFilesByName(dupFile, path, fileName, redirectedPath);
addFileIncludeReason(dupFile, reason, /*checkExisting*/ false);
sourceFileToPackageName.set(path, packageIdToPackageName(packageId));
processingOtherFiles!.push(dupFile);
return dupFile;
}
else if (file) {
// This is the first source file to have this packageId.
packageIdToSourceFile.set(packageIdKey, file);
sourceFileToPackageName.set(path, packageIdToPackageName(packageId));
}
}
addFileToFilesByName(file, path, fileName, redirectedPath);

if (file) {
Expand Down
11 changes: 2 additions & 9 deletions src/compiler/programDiagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
Diagnostics,
DiagnosticWithLocation,
emptyArray,
explainIfFileIsRedirectAndImpliedFormat,
FileIncludeKind,
FileIncludeReason,
fileIncludeReasonToDiagnostics,
Expand Down Expand Up @@ -56,7 +55,6 @@ import {

interface FileReasonToChainCache {
fileIncludeReasonDetails: DiagnosticMessageChain | undefined;
redirectInfo: DiagnosticMessageChain[] | undefined;
details?: DiagnosticMessageChain[];
}

Expand Down Expand Up @@ -207,7 +205,6 @@ export function createProgramDiagnostics(getCompilerOptionsObjectLiteralSyntax:
let fileIncludeReasons: DiagnosticMessageChain[] | undefined;
let relatedInfo: DiagnosticWithLocation[] | undefined;
let fileIncludeReasonDetails: DiagnosticMessageChain | undefined;
let redirectInfo: DiagnosticMessageChain[] | undefined;
let chain: DiagnosticMessageChain | undefined;

const reasons = file && fileReasons.get(file.path);
Expand All @@ -221,11 +218,9 @@ export function createProgramDiagnostics(getCompilerOptionsObjectLiteralSyntax:
else {
reasons?.forEach(processReason);
}
redirectInfo = cachedChain.redirectInfo;
}
else {
reasons?.forEach(processReason);
redirectInfo = file && explainIfFileIsRedirectAndImpliedFormat(file, program.getCompilerOptionsForFile(file));
}

if (fileProcessingReason) processReason(fileProcessingReason);
Expand Down Expand Up @@ -261,9 +256,7 @@ export function createProgramDiagnostics(getCompilerOptionsObjectLiteralSyntax:
if (!chain) {
if (!fileIncludeReasonDetails) fileIncludeReasonDetails = seenReasons && chainDiagnosticMessages(fileIncludeReasons, Diagnostics.The_file_is_in_the_program_because_Colon);
chain = chainDiagnosticMessages(
redirectInfo ?
fileIncludeReasonDetails ? [fileIncludeReasonDetails, ...redirectInfo] : redirectInfo :
fileIncludeReasonDetails,
fileIncludeReasonDetails,
diagnostic,
...args || emptyArray,
);
Expand All @@ -285,7 +278,7 @@ export function createProgramDiagnostics(getCompilerOptionsObjectLiteralSyntax:
}
}
else {
(fileReasonsToChain ??= new Map()).set(file.path, cachedChain = { fileIncludeReasonDetails, redirectInfo });
(fileReasonsToChain ??= new Map()).set(file.path, cachedChain = { fileIncludeReasonDetails });
}
// If we didnt compute extra file include reason , cache the details to use directly
if (!cachedChain.details && !processedExtraReason) cachedChain.details = chain.next;
Expand Down
Loading