mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Implement 'deferred' modifier, remove Deferred<T> marker type
This commit is contained in:
+23
-27
@@ -1396,7 +1396,6 @@ const enum IntrinsicTypeKind {
|
||||
Capitalize,
|
||||
Uncapitalize,
|
||||
NoInfer,
|
||||
Deferred,
|
||||
}
|
||||
|
||||
const intrinsicTypeKinds: ReadonlyMap<string, IntrinsicTypeKind> = new Map(Object.entries({
|
||||
@@ -1405,7 +1404,6 @@ const intrinsicTypeKinds: ReadonlyMap<string, IntrinsicTypeKind> = new Map(Objec
|
||||
Capitalize: IntrinsicTypeKind.Capitalize,
|
||||
Uncapitalize: IntrinsicTypeKind.Uncapitalize,
|
||||
NoInfer: IntrinsicTypeKind.NoInfer,
|
||||
Deferred: IntrinsicTypeKind.Deferred,
|
||||
}));
|
||||
|
||||
const SymbolLinks = class implements SymbolLinks {
|
||||
@@ -16105,9 +16103,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (type === intrinsicMarkerType) {
|
||||
const typeKind = intrinsicTypeKinds.get(symbol.escapedName as string);
|
||||
if (typeKind !== undefined && typeArguments && typeArguments.length === 1) {
|
||||
return typeKind === IntrinsicTypeKind.NoInfer ? getNoInferType(typeArguments[0]) :
|
||||
typeKind === IntrinsicTypeKind.Deferred ? getDeferredCallbackType(typeArguments[0], aliasSymbol, aliasTypeArguments) :
|
||||
getStringMappingType(symbol, typeArguments[0]);
|
||||
return typeKind === IntrinsicTypeKind.NoInfer ? getNoInferType(typeArguments[0]) : getStringMappingType(symbol, typeArguments[0]);
|
||||
}
|
||||
}
|
||||
const links = getSymbolLinks(symbol);
|
||||
@@ -16120,27 +16116,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return instantiation;
|
||||
}
|
||||
|
||||
function getDeferredCallbackType(type: Type, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined) {
|
||||
if (type.flags & TypeFlags.Object) {
|
||||
const key = `F${getTypeId(type)}${getAliasId(aliasSymbol, aliasTypeArguments)}`;
|
||||
return getCachedType(key) ?? setCachedType(key, createDeferredCallbackType(type as ObjectType, aliasSymbol, aliasTypeArguments));
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function createDeferredCallbackType(type: ObjectType, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined) {
|
||||
const resolved = resolveStructuredTypeMembers(type);
|
||||
const result = createObjectType(ObjectFlags.Anonymous | ObjectFlags.DeferredCallback, type.symbol);
|
||||
result.members = resolved.members;
|
||||
result.properties = resolved.properties;
|
||||
result.callSignatures = resolved.callSignatures;
|
||||
result.constructSignatures = resolved.constructSignatures;
|
||||
result.indexInfos = resolved.indexInfos;
|
||||
result.aliasSymbol = aliasSymbol;
|
||||
result.aliasTypeArguments = aliasTypeArguments;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type from reference to type alias. When a type alias is generic, the declared type of the type alias may include
|
||||
* references to the type parameters of the alias. We replace those with the actual type arguments by instantiating the
|
||||
@@ -28190,7 +28165,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// circularities. Instead, we simply check if any signature has a deferred callback marker in the
|
||||
// particular argument position.
|
||||
signatures ??= getSignaturesOfType(getTypeOfExpression(flow.node.expression), SignatureKind.Call);
|
||||
if (!some(signatures, sig => !!(getObjectFlags(getTypeAtPosition(sig, i)) & ObjectFlags.DeferredCallback))) {
|
||||
if (!some(signatures, sig => !!(getModifiersAtPosition(sig, i) & ModifierFlags.Deferred))) {
|
||||
const lambdaType = getTypeFromFlowType(getTypeAtFlowNode(lambda.returnFlowNode));
|
||||
if (lambdaType !== initialType) {
|
||||
lambdaTypes ??= [initialType];
|
||||
@@ -37257,6 +37232,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return elementType && isTypeAny(elementType) ? anyType : restType;
|
||||
}
|
||||
|
||||
function getModifiersAtPosition(signature: Signature, pos: number) {
|
||||
const index = pos < signature.parameters.length ? pos : signatureHasRestParameter(signature) ? signature.parameters.length - 1 : -1;
|
||||
return index >= 0 ? getDeclarationModifierFlagsFromSymbol(signature.parameters[index]) : ModifierFlags.None;
|
||||
}
|
||||
|
||||
// Return the number of parameters in a signature. The rest parameter, if present, counts as one
|
||||
// parameter. For example, the parameter count of (x: number, y: number, ...z: string[]) is 3 and
|
||||
// the parameter count of (x: number, ...args: [number, ...string[], boolean])) is also 3. In the
|
||||
@@ -40570,6 +40550,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
error(node.name, Diagnostics.constructor_cannot_be_used_as_a_parameter_property_name);
|
||||
}
|
||||
}
|
||||
if (hasSyntacticModifier(node, ModifierFlags.Deferred)) {
|
||||
const funcType = node.dotDotDotToken ? createArrayType(globalFunctionType, /*readonly*/ true) : globalFunctionType;
|
||||
if (!isTypeAssignableTo(getTypeOfSymbol(node.symbol), funcType)) {
|
||||
error(node, Diagnostics.A_deferred_parameter_must_have_a_function_type);
|
||||
}
|
||||
}
|
||||
if (!node.initializer && isOptionalDeclaration(node) && isBindingPattern(node.name) && (func as FunctionLikeDeclaration).body) {
|
||||
error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature);
|
||||
}
|
||||
@@ -50151,6 +50137,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
flags |= inOutFlag;
|
||||
break;
|
||||
}
|
||||
|
||||
case SyntaxKind.DeferredKeyword:
|
||||
if (node.kind !== SyntaxKind.Parameter) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics.deferred_modifier_can_only_appear_on_a_parameter_declaration);
|
||||
}
|
||||
if (flags & ModifierFlags.Deferred) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "deferred");
|
||||
}
|
||||
flags |= ModifierFlags.Deferred;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -971,6 +971,10 @@
|
||||
"category": "Error",
|
||||
"code": 1293
|
||||
},
|
||||
"'deferred' modifier can only appear on a parameter declaration.": {
|
||||
"category": "Error",
|
||||
"code": 1294
|
||||
},
|
||||
|
||||
"'with' statements are not allowed in an async function block.": {
|
||||
"category": "Error",
|
||||
@@ -3911,6 +3915,10 @@
|
||||
"category": "Error",
|
||||
"code": 2868
|
||||
},
|
||||
"A 'deferred' parameter must have a function type.": {
|
||||
"category": "Error",
|
||||
"code": 2869
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
|
||||
@@ -1471,6 +1471,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
|
||||
case SyntaxKind.ReadonlyKeyword:
|
||||
case SyntaxKind.AbstractKeyword:
|
||||
case SyntaxKind.DeclareKeyword:
|
||||
case SyntaxKind.DeferredKeyword:
|
||||
case SyntaxKind.ConstKeyword:
|
||||
case SyntaxKind.AnyKeyword:
|
||||
case SyntaxKind.NumberKeyword:
|
||||
@@ -1566,6 +1567,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
|
||||
if (flags & ModifierFlags.Async) result.push(createModifier(SyntaxKind.AsyncKeyword));
|
||||
if (flags & ModifierFlags.In) result.push(createModifier(SyntaxKind.InKeyword));
|
||||
if (flags & ModifierFlags.Out) result.push(createModifier(SyntaxKind.OutKeyword));
|
||||
if (flags & ModifierFlags.Deferred) result.push(createModifier(SyntaxKind.DeferredKeyword));
|
||||
return result.length ? result : undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -3322,6 +3322,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
case SyntaxKind.ProtectedKeyword:
|
||||
case SyntaxKind.ReadonlyKeyword:
|
||||
case SyntaxKind.DeclareKeyword:
|
||||
case SyntaxKind.DeferredKeyword:
|
||||
case SyntaxKind.AbstractKeyword:
|
||||
case SyntaxKind.OverrideKeyword:
|
||||
case SyntaxKind.InKeyword:
|
||||
|
||||
@@ -148,6 +148,7 @@ export const textToKeywordObj: MapLike<KeywordSyntaxKind> = {
|
||||
debugger: SyntaxKind.DebuggerKeyword,
|
||||
declare: SyntaxKind.DeclareKeyword,
|
||||
default: SyntaxKind.DefaultKeyword,
|
||||
deferred: SyntaxKind.DeferredKeyword,
|
||||
delete: SyntaxKind.DeleteKeyword,
|
||||
do: SyntaxKind.DoKeyword,
|
||||
else: SyntaxKind.ElseKeyword,
|
||||
|
||||
@@ -661,6 +661,7 @@ export function transformTypeScript(context: TransformationContext) {
|
||||
case SyntaxKind.OverrideKeyword:
|
||||
case SyntaxKind.ConstKeyword:
|
||||
case SyntaxKind.DeclareKeyword:
|
||||
case SyntaxKind.DeferredKeyword:
|
||||
case SyntaxKind.ReadonlyKeyword:
|
||||
case SyntaxKind.InKeyword:
|
||||
case SyntaxKind.OutKeyword:
|
||||
|
||||
+11
-6
@@ -196,6 +196,7 @@ export const enum SyntaxKind {
|
||||
BooleanKeyword,
|
||||
ConstructorKeyword,
|
||||
DeclareKeyword,
|
||||
DeferredKeyword,
|
||||
GetKeyword,
|
||||
InferKeyword,
|
||||
IntrinsicKeyword,
|
||||
@@ -598,6 +599,7 @@ export type KeywordSyntaxKind =
|
||||
| SyntaxKind.DebuggerKeyword
|
||||
| SyntaxKind.DeclareKeyword
|
||||
| SyntaxKind.DefaultKeyword
|
||||
| SyntaxKind.DeferredKeyword
|
||||
| SyntaxKind.DeleteKeyword
|
||||
| SyntaxKind.DoKeyword
|
||||
| SyntaxKind.ElseKeyword
|
||||
@@ -669,6 +671,7 @@ export type ModifierSyntaxKind =
|
||||
| SyntaxKind.ConstKeyword
|
||||
| SyntaxKind.DeclareKeyword
|
||||
| SyntaxKind.DefaultKeyword
|
||||
| SyntaxKind.DeferredKeyword
|
||||
| SyntaxKind.ExportKeyword
|
||||
| SyntaxKind.InKeyword
|
||||
| SyntaxKind.PrivateKeyword
|
||||
@@ -865,10 +868,11 @@ export const enum ModifierFlags {
|
||||
Const = 1 << 12, // Const enum
|
||||
In = 1 << 13, // Contravariance modifier
|
||||
Out = 1 << 14, // Covariance modifier
|
||||
Decorator = 1 << 15, // Contains a decorator.
|
||||
Deferred = 1 << 15, // Parameter
|
||||
Decorator = 1 << 16, // Contains a decorator.
|
||||
|
||||
// JSDoc-only modifiers
|
||||
Deprecated = 1 << 16, // Deprecated tag.
|
||||
Deprecated = 1 << 17, // Deprecated tag.
|
||||
|
||||
// Cache-only JSDoc-modifiers. Should match order of Syntactic/JSDoc modifiers, above.
|
||||
/** @internal */ JSDocPublic = 1 << 23, // if this value changes, `selectEffectiveModifierFlags` must change accordingly
|
||||
@@ -878,7 +882,7 @@ export const enum ModifierFlags {
|
||||
/** @internal */ JSDocOverride = 1 << 27,
|
||||
|
||||
/** @internal */ SyntacticOrJSDocModifiers = Public | Private | Protected | Readonly | Override,
|
||||
/** @internal */ SyntacticOnlyModifiers = Export | Ambient | Abstract | Static | Accessor | Async | Default | Const | In | Out | Decorator,
|
||||
/** @internal */ SyntacticOnlyModifiers = Export | Ambient | Abstract | Static | Accessor | Async | Default | Const | In | Out | Deferred | Decorator,
|
||||
/** @internal */ SyntacticModifiers = SyntacticOrJSDocModifiers | SyntacticOnlyModifiers,
|
||||
/** @internal */ JSDocCacheOnlyModifiers = JSDocPublic | JSDocPrivate | JSDocProtected | JSDocReadonly | JSDocOverride,
|
||||
/** @internal */ JSDocOnlyModifiers = Deprecated,
|
||||
@@ -892,9 +896,9 @@ export const enum ModifierFlags {
|
||||
ParameterPropertyModifier = AccessibilityModifier | Readonly | Override,
|
||||
NonPublicAccessibilityModifier = Private | Protected,
|
||||
|
||||
TypeScriptModifier = Ambient | Public | Private | Protected | Readonly | Abstract | Const | Override | In | Out,
|
||||
TypeScriptModifier = Ambient | Public | Private | Protected | Readonly | Abstract | Const | Override | In | Out | Deferred,
|
||||
ExportDefault = Export | Default,
|
||||
All = Export | Ambient | Public | Private | Protected | Static | Readonly | Abstract | Accessor | Async | Default | Const | Deprecated | Override | In | Out | Decorator,
|
||||
All = Export | Ambient | Public | Private | Protected | Static | Readonly | Abstract | Accessor | Async | Default | Const | Deprecated | Override | In | Out | Deferred | Decorator,
|
||||
Modifier = All & ~Decorator,
|
||||
}
|
||||
|
||||
@@ -1620,6 +1624,7 @@ export type AsyncKeyword = ModifierToken<SyntaxKind.AsyncKeyword>;
|
||||
export type ConstKeyword = ModifierToken<SyntaxKind.ConstKeyword>;
|
||||
export type DeclareKeyword = ModifierToken<SyntaxKind.DeclareKeyword>;
|
||||
export type DefaultKeyword = ModifierToken<SyntaxKind.DefaultKeyword>;
|
||||
export type DeferredKeyword = ModifierToken<SyntaxKind.DeferredKeyword>;
|
||||
export type ExportKeyword = ModifierToken<SyntaxKind.ExportKeyword>;
|
||||
export type InKeyword = ModifierToken<SyntaxKind.InKeyword>;
|
||||
export type PrivateKeyword = ModifierToken<SyntaxKind.PrivateKeyword>;
|
||||
@@ -1637,6 +1642,7 @@ export type Modifier =
|
||||
| ConstKeyword
|
||||
| DeclareKeyword
|
||||
| DefaultKeyword
|
||||
| DeferredKeyword
|
||||
| ExportKeyword
|
||||
| InKeyword
|
||||
| PrivateKeyword
|
||||
@@ -6389,7 +6395,6 @@ export const enum ObjectFlags {
|
||||
/** @internal */
|
||||
IdenticalBaseTypeExists = 1 << 26, // has a defined cachedEquivalentBaseType member
|
||||
SingleSignatureType = 1 << 27, // A single signature type extracted from a potentially broader type
|
||||
DeferredCallback = 1 << 28, // Function type with Deferred<T> marker
|
||||
|
||||
// Flags that require TypeFlags.UnionOrIntersection or TypeFlags.Substitution
|
||||
/** @internal */
|
||||
|
||||
@@ -7159,6 +7159,8 @@ export function modifierToFlag(token: SyntaxKind): ModifierFlags {
|
||||
return ModifierFlags.In;
|
||||
case SyntaxKind.OutKeyword:
|
||||
return ModifierFlags.Out;
|
||||
case SyntaxKind.DeferredKeyword:
|
||||
return ModifierFlags.Deferred;
|
||||
case SyntaxKind.Decorator:
|
||||
return ModifierFlags.Decorator;
|
||||
}
|
||||
|
||||
@@ -1568,6 +1568,7 @@ export function isModifierKind(token: SyntaxKind): token is Modifier["kind"] {
|
||||
case SyntaxKind.ConstKeyword:
|
||||
case SyntaxKind.DeclareKeyword:
|
||||
case SyntaxKind.DefaultKeyword:
|
||||
case SyntaxKind.DeferredKeyword:
|
||||
case SyntaxKind.ExportKeyword:
|
||||
case SyntaxKind.InKeyword:
|
||||
case SyntaxKind.PublicKeyword:
|
||||
|
||||
@@ -1210,7 +1210,6 @@ export namespace Completion {
|
||||
typeEntry("Capitalize"),
|
||||
typeEntry("Uncapitalize"),
|
||||
typeEntry("NoInfer"),
|
||||
typeEntry("Deferred"),
|
||||
interfaceEntry("ThisType"),
|
||||
varEntry("ArrayBuffer"),
|
||||
interfaceEntry("ArrayBufferTypes"),
|
||||
|
||||
Vendored
-5
@@ -1654,11 +1654,6 @@ type Uncapitalize<S extends string> = intrinsic;
|
||||
*/
|
||||
type NoInfer<T> = intrinsic;
|
||||
|
||||
/**
|
||||
* Marker for deferred callbacks
|
||||
*/
|
||||
type Deferred<T extends (...args: any) => any> = intrinsic;
|
||||
|
||||
/**
|
||||
* Marker for contextual 'this' type
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user