Skip to content

Commit a35f7a6

Browse files
authored
Merge branch 'main' into main
2 parents 5748fef + 7f6a846 commit a35f7a6

File tree

2,828 files changed

+19761
-8139
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

2,828 files changed

+19761
-8139
lines changed

src/compiler/checker.ts

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15332,6 +15332,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1533215332
undefined;
1533315333
}
1533415334
if (t.flags & TypeFlags.Index) {
15335+
if (isGenericMappedType((t as IndexType).type)) {
15336+
const mappedType = (t as IndexType).type as MappedType;
15337+
if (getNameTypeFromMappedType(mappedType) && !isMappedTypeWithKeyofConstraintDeclaration(mappedType)) {
15338+
return getBaseConstraint(getIndexTypeForMappedType(mappedType, IndexFlags.None));
15339+
}
15340+
}
1533515341
return stringNumberSymbolType;
1533615342
}
1533715343
if (t.flags & TypeFlags.TemplateLiteral) {
@@ -18824,7 +18830,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1882418830
// a circular definition. For this reason, we only eagerly manifest the keys if the constraint is non-generic.
1882518831
if (isGenericIndexType(constraintType)) {
1882618832
if (isMappedTypeWithKeyofConstraintDeclaration(type)) {
18827-
// We have a generic index and a homomorphic mapping (but a distributive key remapping) - we need to defer
18833+
// We have a generic index and a homomorphic mapping and a key remapping - we need to defer
1882818834
// the whole `keyof whatever` for later since it's not safe to resolve the shape of modifier type.
1882918835
return getIndexTypeForGenericType(type, indexFlags);
1883018836
}
@@ -18854,25 +18860,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1885418860
}
1885518861
}
1885618862

18857-
// Ordinarily we reduce a keyof M, where M is a mapped type { [P in K as N<P>]: X }, to simply N<K>. This however presumes
18858-
// that N distributes over union types, i.e. that N<A | B | C> is equivalent to N<A> | N<B> | N<C>. Specifically, we only
18859-
// want to perform the reduction when the name type of a mapped type is distributive with respect to the type variable
18860-
// introduced by the 'in' clause of the mapped type. Note that non-generic types are considered to be distributive because
18861-
// they're the same type regardless of what's being distributed over.
18862-
function hasDistributiveNameType(mappedType: MappedType) {
18863-
const typeVariable = getTypeParameterFromMappedType(mappedType);
18864-
return isDistributive(getNameTypeFromMappedType(mappedType) || typeVariable);
18865-
function isDistributive(type: Type): boolean {
18866-
return type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Primitive | TypeFlags.Never | TypeFlags.TypeParameter | TypeFlags.Object | TypeFlags.NonPrimitive) ? true :
18867-
type.flags & TypeFlags.Conditional ? (type as ConditionalType).root.isDistributive && (type as ConditionalType).checkType === typeVariable :
18868-
type.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral) ? every((type as UnionOrIntersectionType | TemplateLiteralType).types, isDistributive) :
18869-
type.flags & TypeFlags.IndexedAccess ? isDistributive((type as IndexedAccessType).objectType) && isDistributive((type as IndexedAccessType).indexType) :
18870-
type.flags & TypeFlags.Substitution ? isDistributive((type as SubstitutionType).baseType) && isDistributive((type as SubstitutionType).constraint) :
18871-
type.flags & TypeFlags.StringMapping ? isDistributive((type as StringMappingType).type) :
18872-
false;
18873-
}
18874-
}
18875-
1887618863
function getLiteralTypeFromPropertyName(name: PropertyName | JsxAttributeName) {
1887718864
if (isPrivateIdentifier(name)) {
1887818865
return neverType;
@@ -18924,7 +18911,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1892418911
function shouldDeferIndexType(type: Type, indexFlags = IndexFlags.None) {
1892518912
return !!(type.flags & TypeFlags.InstantiableNonPrimitive ||
1892618913
isGenericTupleType(type) ||
18927-
isGenericMappedType(type) && (!hasDistributiveNameType(type) || getMappedTypeNameTypeKind(type) === MappedTypeNameTypeKind.Remapping) ||
18914+
isGenericMappedType(type) && getNameTypeFromMappedType(type) ||
1892818915
type.flags & TypeFlags.Union && !(indexFlags & IndexFlags.NoReducibleCheck) && isGenericReducibleType(type) ||
1892918916
type.flags & TypeFlags.Intersection && maybeTypeOfKind(type, TypeFlags.Instantiable) && some((type as IntersectionType).types, isEmptyAnonymousObjectType));
1893018917
}
@@ -19445,6 +19432,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1944519432
function getSimplifiedType(type: Type, writing: boolean): Type {
1944619433
return type.flags & TypeFlags.IndexedAccess ? getSimplifiedIndexedAccessType(type as IndexedAccessType, writing) :
1944719434
type.flags & TypeFlags.Conditional ? getSimplifiedConditionalType(type as ConditionalType, writing) :
19435+
type.flags & TypeFlags.Index ? getSimplifiedIndexType(type as IndexType) :
1944819436
type;
1944919437
}
1945019438

@@ -19544,6 +19532,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1954419532
return type;
1954519533
}
1954619534

19535+
function getSimplifiedIndexType(type: IndexType) {
19536+
if (isGenericMappedType(type.type) && getNameTypeFromMappedType(type.type) && !isMappedTypeWithKeyofConstraintDeclaration(type.type)) {
19537+
return getIndexTypeForMappedType(type.type, IndexFlags.None);
19538+
}
19539+
return type;
19540+
}
19541+
1954719542
/**
1954819543
* Invokes union simplification logic to determine if an intersection is considered empty as a union constituent
1954919544
*/
@@ -24881,7 +24876,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2488124876

2488224877
function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: (readonly [() => Type, __String])[], related: (source: Type, target: Type) => boolean | Ternary) {
2488324878
const types = target.types;
24884-
const include: Ternary[] = types.map(t => t.flags & TypeFlags.Primitive ? Ternary.False : Ternary.True);
24879+
const include: Ternary[] = types.map(t => t.flags & TypeFlags.Primitive || getReducedType(t).flags & TypeFlags.Never ? Ternary.False : Ternary.True);
2488524880
for (const [getDiscriminatingType, propertyName] of discriminators) {
2488624881
// If the remaining target types include at least one with a matching discriminant, eliminate those that
2488724882
// have non-matching discriminants. This ensures that we ignore erroneous discriminators and gradually
@@ -42839,12 +42834,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4283942834
// Check if the index type is assignable to 'keyof T' for the object type.
4284042835
const objectType = (type as IndexedAccessType).objectType;
4284142836
const indexType = (type as IndexedAccessType).indexType;
42842-
// skip index type deferral on remapping mapped types
42843-
const objectIndexType = isGenericMappedType(objectType) && getMappedTypeNameTypeKind(objectType) === MappedTypeNameTypeKind.Remapping
42844-
? getIndexTypeForMappedType(objectType, IndexFlags.None)
42845-
: getIndexType(objectType, IndexFlags.None);
4284642837
const hasNumberIndexInfo = !!getIndexInfoOfType(objectType, numberType);
42847-
if (everyType(indexType, t => isTypeAssignableTo(t, objectIndexType) || hasNumberIndexInfo && isApplicableIndexType(t, numberType))) {
42838+
if (everyType(indexType, t => isTypeAssignableTo(t, getIndexType(objectType, IndexFlags.None)) || hasNumberIndexInfo && isApplicableIndexType(t, numberType))) {
4284842839
if (
4284942840
accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) &&
4285042841
getObjectFlags(objectType) & ObjectFlags.Mapped && getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.IncludeReadonly

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4480,6 +4480,10 @@
44804480
"category": "Error",
44814481
"code": 5010
44824482
},
4483+
"The common source directory of '{0}' is '{1}'. The 'rootDir' setting must be explicitly set to this or another path to adjust your output's file layout.": {
4484+
"category": "Error",
4485+
"code": 5011
4486+
},
44834487
"Cannot read file '{0}': {1}.": {
44844488
"category": "Error",
44854489
"code": 5012

src/compiler/emitter.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ export function getCommonSourceDirectory(
646646
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory);
647647
checkSourceFilesBelongToPath?.(options.rootDir);
648648
}
649-
else if (options.composite && options.configFilePath) {
649+
else if (options.configFilePath) {
650650
// Project compilations never infer their root from the input source paths
651651
commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath));
652652
checkSourceFilesBelongToPath?.(commonSourceDirectory);
@@ -664,6 +664,23 @@ export function getCommonSourceDirectory(
664664
return commonSourceDirectory;
665665
}
666666

667+
/** @internal */
668+
export function getComputedCommonSourceDirectory(
669+
emittedFiles: readonly string[],
670+
currentDirectory: string,
671+
getCanonicalFileName: GetCanonicalFileName,
672+
): string {
673+
let commonSourceDirectory = computeCommonSourceDirectoryOfFilenames(emittedFiles, currentDirectory, getCanonicalFileName);
674+
675+
if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== directorySeparator) {
676+
// Make sure directory path ends with directory separator so this string can directly
677+
// used to replace with "" to get the relative path of the source file and the relative path doesn't
678+
// start with / making it rooted path
679+
commonSourceDirectory += directorySeparator;
680+
}
681+
return commonSourceDirectory;
682+
}
683+
667684
/** @internal */
668685
export function getCommonSourceDirectoryOfConfig({ options, fileNames }: ParsedCommandLine, ignoreCase: boolean): string {
669686
return getCommonSourceDirectory(

src/compiler/moduleNameResolver.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2889,7 +2889,7 @@ function getLoadModuleFromTargetExportOrImport(extensions: Extensions, state: Mo
28892889
const commonSourceDirGuesses: string[] = [];
28902890
// A `rootDir` compiler option strongly indicates the root location
28912891
// A `composite` project is using project references and has it's common src dir set to `.`, so it shouldn't need to check any other locations
2892-
if (state.compilerOptions.rootDir || (state.compilerOptions.composite && state.compilerOptions.configFilePath)) {
2892+
if (state.compilerOptions.rootDir || state.compilerOptions.configFilePath) {
28932893
const commonDir = toAbsolutePath(getCommonSourceDirectory(state.compilerOptions, () => [], state.host.getCurrentDirectory?.() || "", getCanonicalFileName));
28942894
commonSourceDirGuesses.push(commonDir);
28952895
}

src/compiler/program.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ import {
109109
GetCanonicalFileName,
110110
getCommonSourceDirectory as ts_getCommonSourceDirectory,
111111
getCommonSourceDirectoryOfConfig,
112+
getComputedCommonSourceDirectory,
112113
getDeclarationDiagnostics as ts_getDeclarationDiagnostics,
113114
getDefaultLibFileName,
114115
getDirectoryPath,
@@ -132,6 +133,7 @@ import {
132133
getPackageScopeForPath,
133134
getPathFromPathComponents,
134135
getPositionOfLineAndCharacter,
136+
getRelativePathFromFile,
135137
getResolvedModuleFromResolution,
136138
getResolvedTypeReferenceDirectiveFromResolution,
137139
getResolveJsonModule,
@@ -4254,6 +4256,35 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
42544256
}
42554257
}
42564258

4259+
if (
4260+
!options.noEmit &&
4261+
!options.composite &&
4262+
!options.rootDir &&
4263+
options.configFilePath &&
4264+
(options.outDir || // there is --outDir specified
4265+
(getEmitDeclarations(options) && options.declarationDir) || // there is --declarationDir specified
4266+
options.outFile)
4267+
) {
4268+
// Check if rootDir inferred changed and issue diagnostic
4269+
const dir = getCommonSourceDirectory();
4270+
const emittedFiles = mapDefined(files, file => !file.isDeclarationFile && sourceFileMayBeEmitted(file, program) ? file.fileName : undefined);
4271+
const dir59 = getComputedCommonSourceDirectory(emittedFiles, currentDirectory, getCanonicalFileName);
4272+
if (dir59 !== "" && getCanonicalFileName(dir) !== getCanonicalFileName(dir59)) {
4273+
// change in layout
4274+
createDiagnosticForOption(
4275+
/*onKey*/ true,
4276+
options.outFile ? "outFile" : options.outDir ? "outDir" : "declarationDir",
4277+
!options.outFile && options.outDir ? "declarationDir" : undefined,
4278+
chainDiagnosticMessages(
4279+
chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Visit_https_Colon_Slash_Slashaka_ms_Slashts6_for_migration_information),
4280+
Diagnostics.The_common_source_directory_of_0_is_1_The_rootDir_setting_must_be_explicitly_set_to_this_or_another_path_to_adjust_your_output_s_file_layout,
4281+
getBaseFileName(options.configFilePath),
4282+
getRelativePathFromFile(options.configFilePath, dir59, getCanonicalFileName),
4283+
),
4284+
);
4285+
}
4286+
}
4287+
42574288
if (options.checkJs && !getAllowJSCompilerOption(options)) {
42584289
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "checkJs", "allowJs");
42594290
}
@@ -4484,7 +4515,7 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
44844515
createDeprecatedDiagnostic("charset");
44854516
}
44864517
if (options.out) {
4487-
createDeprecatedDiagnostic("out", /*value*/ undefined, "outFile");
4518+
createDeprecatedDiagnostic("out");
44884519
}
44894520
if (options.importsNotUsedAsValues) {
44904521
createDeprecatedDiagnostic("importsNotUsedAsValues", /*value*/ undefined, "verbatimModuleSyntax");
@@ -4510,6 +4541,9 @@ export function createProgram(_rootNamesOrOptions: readonly string[] | CreatePro
45104541
if (options.allowSyntheticDefaultImports === false) {
45114542
createDeprecatedDiagnostic("allowSyntheticDefaultImports", "false", /*useInstead*/ undefined, /*related*/ undefined);
45124543
}
4544+
if (options.outFile) {
4545+
createDeprecatedDiagnostic("outFile");
4546+
}
45134547
if (options.module === ModuleKind.None || options.module === ModuleKind.AMD || options.module === ModuleKind.UMD || options.module === ModuleKind.System) {
45144548
createDeprecatedDiagnostic("module", ModuleKind[options.module], /*useInstead*/ undefined, /*related*/ undefined);
45154549
}

src/compiler/resolutionCache.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ export interface ResolutionCacheHost extends MinimalResolutionCacheHost {
199199
fileIsOpen(filePath: Path): boolean;
200200
onDiscoveredSymlink?(): void;
201201

202+
skipWatchingFailedLookups?(path: Path): boolean | undefined;
203+
skipWatchingTypeRoots?(): boolean | undefined;
204+
202205
// For incremental testing
203206
beforeResolveSingleModuleNameWithoutWatching?(
204207
moduleResolutionCache: ModuleResolutionCache,
@@ -895,7 +898,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
895898
resolutionHost.onDiscoveredSymlink();
896899
}
897900
resolutionsInFile.set(name, mode, resolution);
898-
if (resolution !== existingResolution) {
901+
if (resolution !== existingResolution && !resolutionHost.skipWatchingFailedLookups?.(path)) {
899902
watchFailedLookupLocationsOfExternalModuleResolutions(name, resolution, path, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution);
900903
if (existingResolution) {
901904
stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolutionWithResolvedFileName);
@@ -947,7 +950,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
947950
// Stop watching and remove the unused name
948951
resolutionsInFile.forEach((resolution, name, mode) => {
949952
if (!seenNamesInFile.has(name, mode)) {
950-
stopWatchFailedLookupLocationOfResolution(resolution, path, getResolutionWithResolvedFileName);
953+
if (!resolutionHost.skipWatchingFailedLookups?.(path)) {
954+
stopWatchFailedLookupLocationOfResolution(resolution, path, getResolutionWithResolvedFileName);
955+
}
951956
resolutionsInFile.delete(name, mode);
952957
}
953958
});
@@ -1434,13 +1439,15 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
14341439
// Deleted file, stop watching failed lookups for all the resolutions in the file
14351440
const resolutions = cache.get(filePath);
14361441
if (resolutions) {
1437-
resolutions.forEach(resolution =>
1438-
stopWatchFailedLookupLocationOfResolution(
1439-
resolution,
1440-
filePath,
1441-
getResolutionWithResolvedFileName,
1442-
)
1443-
);
1442+
if (!resolutionHost.skipWatchingFailedLookups?.(filePath)) {
1443+
resolutions.forEach(resolution =>
1444+
stopWatchFailedLookupLocationOfResolution(
1445+
resolution,
1446+
filePath,
1447+
getResolutionWithResolvedFileName,
1448+
)
1449+
);
1450+
}
14441451
cache.delete(filePath);
14451452
}
14461453
}
@@ -1667,6 +1674,12 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
16671674
return;
16681675
}
16691676

1677+
// if this is inferred project with non watchable root or current directory that is lib location, skip watching type roots
1678+
if (!isRootWatchable || resolutionHost.skipWatchingTypeRoots?.()) {
1679+
closeTypeRootsWatch();
1680+
return;
1681+
}
1682+
16701683
// we need to assume the directories exist to ensure that we can get all the type root directories that get included
16711684
// But filter directories that are at root level to say directory doesnt exist, so that we arent watching them
16721685
const typeRoots = getEffectiveTypeRoots(options, { getCurrentDirectory });

src/compiler/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6394,7 +6394,7 @@ export const enum TypeFlags {
63946394
/** @internal */
63956395
ObjectFlagsType = Any | Nullable | Never | Object | Union | Intersection,
63966396
/** @internal */
6397-
Simplifiable = IndexedAccess | Conditional,
6397+
Simplifiable = IndexedAccess | Conditional | Index,
63986398
/** @internal */
63996399
Singleton = Any | Unknown | String | Number | Boolean | BigInt | ESSymbol | Void | Undefined | Null | Never | NonPrimitive,
64006400
// 'Narrowable' types are types where narrowing actually narrows.

src/compiler/utilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6632,7 +6632,7 @@ export function sourceFileMayBeEmitted(sourceFile: SourceFile, host: SourceFileM
66326632
// Json file is not emitted if outDir is not specified
66336633
if (!options.outDir) return false;
66346634
// Otherwise if rootDir or composite config file, we know common sourceDir and can check if file would be emitted in same location
6635-
if (options.rootDir || (options.composite && options.configFilePath)) {
6635+
if (options.rootDir || options.configFilePath) {
66366636
const commonDir = getNormalizedAbsolutePath(getCommonSourceDirectory(options, () => [], host.getCurrentDirectory(), host.getCanonicalFileName), host.getCurrentDirectory());
66376637
const outputPath = getSourceFilePathInNewDirWorker(sourceFile.fileName, options.outDir, host.getCurrentDirectory(), commonDir, host.getCanonicalFileName);
66386638
if (comparePaths(sourceFile.fileName, outputPath, host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === Comparison.EqualTo) return false;

0 commit comments

Comments
 (0)