Skip to content

Commit d309851

Browse files
committed
Merge branch 'main' into extensions
2 parents 137d923 + 9bd1a32 commit d309851

File tree

50 files changed

+2213
-124
lines changed

Some content is hidden

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

50 files changed

+2213
-124
lines changed

src/compiler/checker.ts

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,7 @@ import {
763763
JSDocSatisfiesTag,
764764
JSDocSignature,
765765
JSDocTemplateTag,
766+
JSDocTypeAssertion,
766767
JSDocTypedefTag,
767768
JSDocTypeExpression,
768769
JSDocTypeLiteral,
@@ -1039,7 +1040,6 @@ import {
10391040
TypeReferenceSerializationKind,
10401041
TypeReferenceType,
10411042
TypeVariable,
1042-
UnaryExpression,
10431043
unescapeLeadingUnderscores,
10441044
UnionOrIntersectionType,
10451045
UnionOrIntersectionTypeNode,
@@ -19875,7 +19875,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1987519875
const restIndex = sourceRestType || targetRestType ? paramCount - 1 : -1;
1987619876

1987719877
for (let i = 0; i < paramCount; i++) {
19878-
const sourceType = i === restIndex ? getRestTypeAtPosition(source, i, /*readonly*/ true) : tryGetTypeAtPosition(source, i);
19878+
const sourceType = i === restIndex ? getRestTypeAtPosition(source, i) : tryGetTypeAtPosition(source, i);
1987919879
const targetType = i === restIndex ? getRestTypeAtPosition(target, i) : tryGetTypeAtPosition(target, i);
1988019880
if (sourceType && targetType) {
1988119881
// In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
@@ -20899,14 +20899,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2089920899
if (containsType(targetTypes, source)) {
2090020900
return Ternary.True;
2090120901
}
20902-
if (getObjectFlags(target) & ObjectFlags.PrimitiveUnion && !(source.flags & TypeFlags.EnumLiteral) && (
20902+
if (relation !== comparableRelation && getObjectFlags(target) & ObjectFlags.PrimitiveUnion && !(source.flags & TypeFlags.EnumLiteral) && (
2090320903
source.flags & (TypeFlags.StringLiteral | TypeFlags.BooleanLiteral | TypeFlags.BigIntLiteral) ||
2090420904
(relation === subtypeRelation || relation === strictSubtypeRelation) && source.flags & TypeFlags.NumberLiteral)) {
2090520905
// When relating a literal type to a union of primitive types, we know the relation is false unless
2090620906
// the union contains the base primitive type or the literal type in one of its fresh/regular forms.
2090720907
// We exclude numeric literals for non-subtype relations because numeric literals are assignable to
2090820908
// numeric enum literals with the same value. Similarly, we exclude enum literal types because
20909-
// identically named enum types are related (see isEmumTypeRelatedTo).
20909+
// identically named enum types are related (see isEnumTypeRelatedTo). We exclude the comparable
20910+
// relation in entirety because it needs to be checked in both directions.
2091020911
const alternateForm = source === (source as StringLiteralType).regularType ? (source as StringLiteralType).freshType : (source as StringLiteralType).regularType;
2091120912
const primitive = source.flags & TypeFlags.StringLiteral ? stringType :
2091220913
source.flags & TypeFlags.NumberLiteral ? numberType :
@@ -22485,7 +22486,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2248522486
const targetHasStringIndex = some(indexInfos, info => info.keyType === stringType);
2248622487
let result = Ternary.True;
2248722488
for (const targetInfo of indexInfos) {
22488-
const related = !sourceIsPrimitive && targetHasStringIndex && targetInfo.type.flags & TypeFlags.Any ? Ternary.True :
22489+
const related = relation !== strictSubtypeRelation && !sourceIsPrimitive && targetHasStringIndex && targetInfo.type.flags & TypeFlags.Any ? Ternary.True :
2248922490
isGenericMappedType(source) && targetHasStringIndex ? isRelatedTo(getTemplateTypeFromMappedType(source), targetInfo.type, RecursionFlags.Both, reportErrors) :
2249022491
typeRelatedToIndexInfo(source, targetInfo, reportErrors, intersectionState);
2249122492
if (!related) {
@@ -25890,7 +25891,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2589025891
}
2589125892

2589225893
function isTypeSubsetOf(source: Type, target: Type) {
25893-
return source === target || target.flags & TypeFlags.Union && isTypeSubsetOfUnion(source, target as UnionType);
25894+
return !!(source === target || source.flags & TypeFlags.Never || target.flags & TypeFlags.Union && isTypeSubsetOfUnion(source, target as UnionType));
2589425895
}
2589525896

2589625897
function isTypeSubsetOfUnion(source: Type, target: UnionType) {
@@ -26714,7 +26715,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2671426715
// If an antecedent type is not a subset of the declared type, we need to perform
2671526716
// subtype reduction. This happens when a "foreign" type is injected into the control
2671626717
// flow using the instanceof operator or a user defined type predicate.
26717-
if (!isTypeSubsetOf(type, declaredType)) {
26718+
if (!isTypeSubsetOf(type, initialType)) {
2671826719
subtypeReduction = true;
2671926720
}
2672026721
if (isIncomplete(flowType)) {
@@ -26732,7 +26733,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2673226733
return type;
2673326734
}
2673426735
antecedentTypes.push(type);
26735-
if (!isTypeSubsetOf(type, declaredType)) {
26736+
if (!isTypeSubsetOf(type, initialType)) {
2673626737
subtypeReduction = true;
2673726738
}
2673826739
if (isIncomplete(flowType)) {
@@ -26807,7 +26808,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2680726808
// If an antecedent type is not a subset of the declared type, we need to perform
2680826809
// subtype reduction. This happens when a "foreign" type is injected into the control
2680926810
// flow using the instanceof operator or a user defined type predicate.
26810-
if (!isTypeSubsetOf(type, declaredType)) {
26811+
if (!isTypeSubsetOf(type, initialType)) {
2681126812
subtypeReduction = true;
2681226813
}
2681326814
// If the type at a particular antecedent path is the declared type there is no
@@ -33983,10 +33984,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3398333984
return cached;
3398433985
}
3398533986
links.resolvedSignature = resolvingSignature;
33986-
const result = resolveSignature(node, candidatesOutArray, checkMode || CheckMode.Normal);
33987+
let result = resolveSignature(node, candidatesOutArray, checkMode || CheckMode.Normal);
3398733988
// When CheckMode.SkipGenericFunctions is set we use resolvingSignature to indicate that call
3398833989
// resolution should be deferred.
3398933990
if (result !== resolvingSignature) {
33991+
// if the signature resolution originated on a node that itself depends on the contextual type
33992+
// then it's possible that the resolved signature might not be the same as the one that would be computed in source order
33993+
// since resolving such signature leads to resolving the potential outer signature, its arguments and thus the very same signature
33994+
// it's possible that this inner resolution sets the resolvedSignature first.
33995+
// In such a case we ignore the local result and reuse the correct one that was cached.
33996+
if (links.resolvedSignature !== resolvingSignature) {
33997+
result = links.resolvedSignature;
33998+
}
3399033999
// If signature resolution originated in control flow type analysis (for example to compute the
3399134000
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
3399234001
// types from the control flow analysis.
@@ -34357,14 +34366,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3435734366
return getReturnTypeOfSignature(signature);
3435834367
}
3435934368

34360-
function checkAssertion(node: AssertionExpression) {
34369+
function checkAssertion(node: AssertionExpression, checkMode: CheckMode | undefined) {
3436134370
if (node.kind === SyntaxKind.TypeAssertionExpression) {
3436234371
const file = getSourceFileOfNode(node);
3436334372
if (file && fileExtensionIsOneOf(file.fileName, [Extension.Cts, Extension.Mts])) {
3436434373
grammarErrorOnNode(node, Diagnostics.This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Use_an_as_expression_instead);
3436534374
}
3436634375
}
34367-
return checkAssertionWorker(node, node.type, node.expression);
34376+
return checkAssertionWorker(node, checkMode);
3436834377
}
3436934378

3437034379
function isValidConstAssertionArgument(node: Node): boolean {
@@ -34395,16 +34404,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3439534404
return false;
3439634405
}
3439734406

34398-
function checkAssertionWorker(errNode: Node, type: TypeNode, expression: UnaryExpression | Expression, checkMode?: CheckMode) {
34399-
let exprType = checkExpression(expression, checkMode);
34407+
function checkAssertionWorker(node: JSDocTypeAssertion | AssertionExpression, checkMode: CheckMode | undefined) {
34408+
const { type, expression } = getAssertionTypeAndExpression(node);
34409+
const exprType = checkExpression(expression, checkMode);
3440034410
if (isConstTypeReference(type)) {
3440134411
if (!isValidConstAssertionArgument(expression)) {
3440234412
error(expression, Diagnostics.A_const_assertions_can_only_be_applied_to_references_to_enum_members_or_string_number_boolean_array_or_object_literals);
3440334413
}
3440434414
return getRegularTypeOfLiteralType(exprType);
3440534415
}
3440634416
checkSourceElement(type);
34407-
exprType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(exprType));
34417+
checkNodeDeferred(node);
34418+
return getTypeFromTypeNode(type);
34419+
}
34420+
34421+
function getAssertionTypeAndExpression(node: JSDocTypeAssertion | AssertionExpression) {
34422+
let type: TypeNode;
34423+
let expression: Expression;
34424+
switch (node.kind) {
34425+
case SyntaxKind.AsExpression:
34426+
case SyntaxKind.TypeAssertionExpression:
34427+
type = node.type;
34428+
expression = node.expression;
34429+
break;
34430+
case SyntaxKind.ParenthesizedExpression:
34431+
type = getJSDocTypeAssertionType(node);
34432+
expression = node.expression;
34433+
break;
34434+
}
34435+
34436+
return { type, expression };
34437+
}
34438+
34439+
function checkAssertionDeferred(node: JSDocTypeAssertion | AssertionExpression) {
34440+
const { type, expression } = getAssertionTypeAndExpression(node);
34441+
const errNode = isParenthesizedExpression(node) ? type : node;
34442+
const exprType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(checkExpression(expression)));
3440834443
const targetType = getTypeFromTypeNode(type);
3440934444
if (!isErrorType(targetType)) {
3441034445
addLazyDiagnostic(() => {
@@ -34415,7 +34450,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3441534450
}
3441634451
});
3441734452
}
34418-
return targetType;
3441934453
}
3442034454

3442134455
function checkNonNullChain(node: NonNullChain) {
@@ -34690,12 +34724,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3469034724
return undefined;
3469134725
}
3469234726

34693-
function getRestTypeAtPosition(source: Signature, pos: number, readonly = false): Type {
34727+
function getRestTypeAtPosition(source: Signature, pos: number): Type {
3469434728
const parameterCount = getParameterCount(source);
3469534729
const minArgumentCount = getMinArgumentCount(source);
3469634730
const restType = getEffectiveRestType(source);
3469734731
if (restType && pos >= parameterCount - 1) {
34698-
return pos === parameterCount - 1 ? restType : createArrayType(getIndexedAccessType(restType, numberType), readonly);
34732+
return pos === parameterCount - 1 ? restType : createArrayType(getIndexedAccessType(restType, numberType));
3469934733
}
3470034734
const types = [];
3470134735
const flags = [];
@@ -34714,7 +34748,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3471434748
names.push(name);
3471534749
}
3471634750
}
34717-
return createTupleType(types, flags, readonly, length(names) === length(types) ? names : undefined);
34751+
return createTupleType(types, flags, /*readonly*/ false, length(names) === length(types) ? names : undefined);
3471834752
}
3471934753

3472034754
// Return the number of parameters in a signature. The rest parameter, if present, counts as one
@@ -37661,8 +37695,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3766137695
return checkSatisfiesExpressionWorker(node.expression, getJSDocSatisfiesExpressionType(node), checkMode);
3766237696
}
3766337697
if (isJSDocTypeAssertion(node)) {
37664-
const type = getJSDocTypeAssertionType(node);
37665-
return checkAssertionWorker(type, type, node.expression, checkMode);
37698+
return checkAssertionWorker(node, checkMode);
3766637699
}
3766737700
}
3766837701
return checkExpression(node.expression, checkMode);
@@ -37743,7 +37776,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3774337776
return checkTypeOfExpression(node as TypeOfExpression);
3774437777
case SyntaxKind.TypeAssertionExpression:
3774537778
case SyntaxKind.AsExpression:
37746-
return checkAssertion(node as AssertionExpression);
37779+
return checkAssertion(node as AssertionExpression, checkMode);
3774737780
case SyntaxKind.NonNullExpression:
3774837781
return checkNonNullAssertion(node as NonNullExpression);
3774937782
case SyntaxKind.ExpressionWithTypeArguments:
@@ -44847,6 +44880,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4484744880
case SyntaxKind.JsxElement:
4484844881
checkJsxElementDeferred(node as JsxElement);
4484944882
break;
44883+
case SyntaxKind.TypeAssertionExpression:
44884+
case SyntaxKind.AsExpression:
44885+
case SyntaxKind.ParenthesizedExpression:
44886+
checkAssertionDeferred(node as AssertionExpression | JSDocTypeAssertion);
4485044887
}
4485144888
currentNode = saveCurrentNode;
4485244889
tracing?.pop();
@@ -45308,7 +45345,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4530845345
}
4530945346

4531045347
meaning |= SymbolFlags.Alias;
45311-
const entityNameSymbol = isEntityNameExpression(name) ? resolveEntityName(name, meaning) : undefined;
45348+
const entityNameSymbol = isEntityNameExpression(name) ? resolveEntityName(name, meaning, /*ignoreErrors*/ true) : undefined;
4531245349
if (entityNameSymbol) {
4531345350
return entityNameSymbol;
4531445351
}

src/compiler/moduleNameResolver.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1689,7 +1689,7 @@ export function nodeModuleNameResolver(moduleName: string, containingFile: strin
16891689

16901690
/** @internal */
16911691
export function nodeNextJsonConfigResolver(moduleName: string, containingFile: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
1692-
return nodeModuleNameResolverWorker(NodeResolutionFeatures.Exports, moduleName, getDirectoryPath(containingFile), { moduleResolution: ModuleResolutionKind.NodeNext }, host, /*cache*/ undefined, Extensions.Json, /*isConfigLookup*/ true, /*redirectedReference*/ undefined);
1692+
return nodeModuleNameResolverWorker(NodeResolutionFeatures.NodeNextDefault, moduleName, getDirectoryPath(containingFile), { moduleResolution: ModuleResolutionKind.NodeNext }, host, /*cache*/ undefined, Extensions.Json, /*isConfigLookup*/ true, /*redirectedReference*/ undefined);
16931693
}
16941694

16951695
function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleName: string, containingDirectory: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache: ModuleResolutionCache | undefined, extensions: Extensions, isConfigLookup: boolean, redirectedReference: ResolvedProjectReference | undefined): ResolvedModuleWithFailedLookupLocations {

src/compiler/watchPublic.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,7 +1088,6 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
10881088
}
10891089

10901090
function updateExtendedConfigFilesWatches(forProjectPath: Path, options: CompilerOptions | undefined, watchOptions: WatchOptions | undefined, watchType: WatchTypeRegistry["ExtendedConfigFile"] | WatchTypeRegistry["ExtendedConfigOfReferencedProject"]) {
1091-
Debug.assert(configFileName);
10921091
updateSharedExtendedConfigFileWatcher(
10931092
forProjectPath,
10941093
options,
@@ -1104,7 +1103,7 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
11041103
// If there are no referenced projects this extended config file watcher depend on ignore
11051104
if (!projects?.size) return;
11061105
projects.forEach(projectPath => {
1107-
if (toPath(configFileName) === projectPath) {
1106+
if (configFileName && toPath(configFileName) === projectPath) {
11081107
// If this is the config file of the project, reload completely
11091108
reloadLevel = ConfigFileProgramReloadLevel.Full;
11101109
}

src/services/findAllReferences.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
escapeLeadingUnderscores,
3030
ExportSpecifier,
3131
Expression,
32+
externalHelpersModuleNameText,
3233
FileIncludeReason,
3334
FileReference,
3435
filter,
@@ -41,6 +42,7 @@ import {
4142
firstOrUndefined,
4243
flatMap,
4344
forEachChild,
45+
forEachChildRecursively,
4446
forEachReturnStatement,
4547
ForInOrOfStatement,
4648
FunctionDeclaration,
@@ -130,6 +132,8 @@ import {
130132
isJSDocMemberName,
131133
isJSDocTag,
132134
isJsxClosingElement,
135+
isJsxElement,
136+
isJsxFragment,
133137
isJsxOpeningElement,
134138
isJsxSelfClosingElement,
135139
isJumpStatementTarget,
@@ -231,6 +235,7 @@ import {
231235
textPart,
232236
TextSpan,
233237
tokenToString,
238+
TransformFlags,
234239
tryAddToSet,
235240
tryCast,
236241
tryGetClassExtendingExpressionWithTypeArguments,
@@ -1125,6 +1130,14 @@ export namespace Core {
11251130
// import("foo") with no qualifier will reference the `export =` of the module, which may be referenced anyway.
11261131
return nodeEntry(reference.literal);
11271132
}
1133+
else if (reference.kind === "implicit") {
1134+
// Return either: The first JSX node in the (if not a tslib import), the first statement of the file, or the whole file if neither of those exist
1135+
const range = reference.literal.text !== externalHelpersModuleNameText && forEachChildRecursively(
1136+
reference.referencingFile,
1137+
n => !(n.transformFlags & TransformFlags.ContainsJsx) ? "skip" : isJsxElement(n) || isJsxSelfClosingElement(n) || isJsxFragment(n) ? n : undefined
1138+
) || reference.referencingFile.statements[0] || reference.referencingFile;
1139+
return nodeEntry(range);
1140+
}
11281141
else {
11291142
return {
11301143
kind: EntryKind.Span,

0 commit comments

Comments
 (0)