mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Replace addUndefined in serializeTypeForDeclaration with the actual declaration (#58085)
This commit is contained in:
+93
-35
@@ -964,7 +964,7 @@ import {
|
||||
setOriginalNode,
|
||||
setParent,
|
||||
setSyntheticLeadingComments,
|
||||
setTextRange,
|
||||
setTextRange as setTextRangeWorker,
|
||||
setTextRangePosEnd,
|
||||
setValueDeclaration,
|
||||
ShorthandPropertyAssignment,
|
||||
@@ -6475,7 +6475,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
typeToTypeNode: (type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => typeToTypeNodeHelper(type, context)),
|
||||
typePredicateToTypePredicateNode: (typePredicate: TypePredicate, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => typePredicateToTypePredicateNodeHelper(typePredicate, context)),
|
||||
expressionOrTypeToTypeNode: (expr: Expression | JsxAttributeValue | undefined, type: Type, addUndefined?: boolean, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => expressionOrTypeToTypeNode(context, expr, type, addUndefined)),
|
||||
serializeTypeForDeclaration: (type: Type, symbol: Symbol, addUndefined?: boolean, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => serializeTypeForDeclaration(context, type, symbol, enclosingDeclaration, addUndefined)),
|
||||
serializeTypeForDeclaration: (declaration: Declaration, type: Type, symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => serializeTypeForDeclaration(context, declaration, type, symbol)),
|
||||
serializeReturnTypeForSignature: (signature: Signature, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => serializeReturnTypeForSignature(context, signature)),
|
||||
indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => indexInfoToIndexSignatureDeclarationHelper(indexInfo, context, /*typeNode*/ undefined)),
|
||||
signatureToSignatureDeclaration: (signature: Signature, kind: SignatureDeclaration["kind"], enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => signatureToSignatureDeclarationHelper(signature, kind, context)),
|
||||
@@ -6488,6 +6488,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
symbolToNode: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => symbolToNode(symbol, context, meaning)),
|
||||
};
|
||||
|
||||
/**
|
||||
* Unlike the utilities `setTextRange`, this checks if the `location` we're trying to set on `range` is within the
|
||||
* same file as the active context. If not, the range is not applied. This prevents us from copying ranges across files,
|
||||
* which will confuse the node printer (as it assumes all node ranges are within the current file).
|
||||
* Additionally, if `range` _isn't synthetic_, and isn't in the current file, it will _copy_ it to _remove_ its' position
|
||||
* information.
|
||||
*
|
||||
* It also calls `setOriginalNode` to setup a `.original` pointer, since you basically *always* want these in the node builder.
|
||||
*/
|
||||
function setTextRange<T extends Node>(context: NodeBuilderContext, range: T, location: Node | undefined): T {
|
||||
if (!nodeIsSynthesized(range) && !(range.flags & NodeFlags.Synthesized) && (!context.enclosingFile || context.enclosingFile !== getSourceFileOfNode(range))) {
|
||||
range = factory.cloneNode(range);
|
||||
}
|
||||
if (!location) {
|
||||
return range;
|
||||
}
|
||||
if (!context.enclosingFile || context.enclosingFile !== getSourceFileOfNode(getOriginalNode(location))) {
|
||||
return setOriginalNode(range, location);
|
||||
}
|
||||
return setTextRangeWorker(setOriginalNode(range, location), location);
|
||||
}
|
||||
|
||||
function expressionOrTypeToTypeNode(context: NodeBuilderContext, expr: Expression | JsxAttributeValue | undefined, type: Type, addUndefined?: boolean) {
|
||||
if (expr) {
|
||||
const typeNode = isAssertionExpression(expr) ? expr.type
|
||||
@@ -6573,6 +6595,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
undefined;
|
||||
const context: NodeBuilderContext = {
|
||||
enclosingDeclaration,
|
||||
enclosingFile: enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration),
|
||||
flags: flags || NodeBuilderFlags.None,
|
||||
tracker: undefined!,
|
||||
encounteredError: false,
|
||||
@@ -7132,7 +7155,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (!nodeIsSynthesized(node) && getParseTreeNode(node) === node) {
|
||||
return node;
|
||||
}
|
||||
return setTextRange(factory.cloneNode(visitEachChild(node, deepCloneOrReuseNode, /*context*/ undefined, deepCloneOrReuseNodes)), node);
|
||||
return setTextRange(context, factory.cloneNode(visitEachChild(node, deepCloneOrReuseNode, /*context*/ undefined, deepCloneOrReuseNodes)), node);
|
||||
}
|
||||
|
||||
function deepCloneOrReuseNodes(
|
||||
@@ -7145,7 +7168,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (nodes && nodes.length === 0) {
|
||||
// Ensure we explicitly make a copy of an empty array; visitNodes will not do this unless the array has elements,
|
||||
// which can lead to us reusing the same empty NodeArray more than once within the same AST during type noding.
|
||||
return setTextRange(factory.createNodeArray(/*elements*/ undefined, nodes.hasTrailingComma), nodes);
|
||||
return setTextRangeWorker(factory.createNodeArray(/*elements*/ undefined, nodes.hasTrailingComma), nodes);
|
||||
}
|
||||
return visitNodes(nodes, visitor, test, start, count);
|
||||
}
|
||||
@@ -7515,7 +7538,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
context.reverseMappedStack ||= [];
|
||||
context.reverseMappedStack.push(propertySymbol as ReverseMappedSymbol);
|
||||
}
|
||||
propertyTypeNode = propertyType ? serializeTypeForDeclaration(context, propertyType, propertySymbol, saveEnclosingDeclaration) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||
propertyTypeNode = propertyType ? serializeTypeForDeclaration(context, /*declaration*/ undefined, propertyType, propertySymbol) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||
if (propertyIsReverseMapped) {
|
||||
context.reverseMappedStack!.pop();
|
||||
}
|
||||
@@ -7932,8 +7955,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const parameterDeclaration = getEffectiveParameterDeclaration(parameterSymbol);
|
||||
|
||||
const parameterType = getTypeOfSymbol(parameterSymbol);
|
||||
const addUndefined = parameterDeclaration && isRequiredInitializedParameter(parameterDeclaration);
|
||||
const parameterTypeNode = serializeTypeForDeclaration(context, parameterType, parameterSymbol, context.enclosingDeclaration, addUndefined);
|
||||
const parameterTypeNode = serializeTypeForDeclaration(context, parameterDeclaration, parameterType, parameterSymbol);
|
||||
|
||||
const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && canHaveModifiers(parameterDeclaration) ? map(getModifiers(parameterDeclaration), factory.cloneNode) : undefined;
|
||||
const isRest = parameterDeclaration && isRestParameter(parameterDeclaration) || getCheckFlags(parameterSymbol) & CheckFlags.RestParameter;
|
||||
@@ -8589,10 +8611,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
/**
|
||||
* Unlike `typeToTypeNodeHelper`, this handles setting up the `AllowUniqueESSymbolType` flag
|
||||
* so a `unique symbol` is returned when appropriate for the input symbol, rather than `typeof sym`
|
||||
* @param context - The node builder context. Any reused nodes are checked to be pulled from within the scope of the context's enclosingDeclaration.
|
||||
* @param declaration - The preferred declaration to pull existing type nodes from (the symbol will be used as a fallback to find any annotated declaration)
|
||||
* @param type - The type to write; an existing annotation must match this type if it's used, otherwise this is the type serialized as a new type node
|
||||
* @param symbol - The symbol is used both to find an existing annotation if declaration is not provided, and to determine if `unique symbol` should be printed
|
||||
*/
|
||||
function serializeTypeForDeclaration(context: NodeBuilderContext, type: Type, symbol: Symbol, enclosingDeclaration: Node | undefined, addUndefined?: boolean) {
|
||||
function serializeTypeForDeclaration(context: NodeBuilderContext, declaration: Declaration | undefined, type: Type, symbol: Symbol) {
|
||||
const addUndefined = declaration && (isParameter(declaration) || isJSDocParameterTag(declaration)) && requiresAddingImplicitUndefined(declaration);
|
||||
const enclosingDeclaration = context.enclosingDeclaration;
|
||||
if (!isErrorType(type) && enclosingDeclaration) {
|
||||
const declWithExistingAnnotation = getDeclarationWithTypeAnnotation(symbol, getEnclosingDeclarationIgnoringFakeScope(enclosingDeclaration));
|
||||
const declWithExistingAnnotation = declaration && getNonlocalEffectiveTypeAnnotationNode(declaration)
|
||||
? declaration
|
||||
: getDeclarationWithTypeAnnotation(symbol, getEnclosingDeclarationIgnoringFakeScope(enclosingDeclaration));
|
||||
if (declWithExistingAnnotation && !isFunctionLikeDeclaration(declWithExistingAnnotation) && !isGetAccessorDeclaration(declWithExistingAnnotation)) {
|
||||
// try to reuse the existing annotation
|
||||
const existing = getNonlocalEffectiveTypeAnnotationNode(declWithExistingAnnotation)!;
|
||||
@@ -8610,7 +8640,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
context.flags |= NodeBuilderFlags.AllowUniqueESSymbolType;
|
||||
}
|
||||
|
||||
const decl = symbol.valueDeclaration ?? symbol.declarations?.[0];
|
||||
const decl = declaration ?? symbol.valueDeclaration ?? symbol.declarations?.[0];
|
||||
const expr = decl && isDeclarationWithPossibleInnerTypeNodeReuse(decl) ? getPossibleTypeNodeReuseExpression(decl) : undefined;
|
||||
|
||||
const result = expressionOrTypeToTypeNode(context, expr, type, addUndefined);
|
||||
@@ -8719,11 +8749,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const type = getDeclaredTypeOfSymbol(sym!);
|
||||
const name = sym!.flags & SymbolFlags.TypeParameter ? typeParameterToName(type, context) : factory.cloneNode(node as Identifier);
|
||||
name.symbol = sym!; // for quickinfo, which uses identifier symbol information
|
||||
return setTextRange(setEmitFlags(setOriginalNode(name, node), EmitFlags.NoAsciiEscaping), node);
|
||||
return setTextRange(context, setEmitFlags(name, EmitFlags.NoAsciiEscaping), node);
|
||||
}
|
||||
const updated = visitEachChild(node, c => attachSymbolToLeftmostIdentifier(c), /*context*/ undefined);
|
||||
if (updated !== node) {
|
||||
setTextRange(updated, node);
|
||||
setTextRange(context, updated, node);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
@@ -8742,13 +8772,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (hadError) {
|
||||
return undefined;
|
||||
}
|
||||
return transformed === existing ? setTextRange(factory.cloneNode(existing), existing) : transformed;
|
||||
return transformed;
|
||||
|
||||
function visitExistingNodeTreeSymbols(node: Node): Node | undefined {
|
||||
const onExitNewScope = isNewScopeNode(node) ? onEnterNewScope(node) : undefined;
|
||||
const result = visitExistingNodeTreeSymbolsWorker(node);
|
||||
onExitNewScope?.();
|
||||
return result;
|
||||
// We want to clone the subtree, so when we mark it up with __pos and __end in quickfixes,
|
||||
// we don't get odd behavior because of reused nodes. We also need to clone to _remove_
|
||||
// the position information if the node comes from a different file than the one the node builder
|
||||
// is set to build for (even though we are reusing the node structure, the position information
|
||||
// would make the printer print invalid spans for literals and identifiers, and the formatter would
|
||||
// choke on the mismatched positonal spans between a parent and an injected child from another file).
|
||||
return result === node ? setTextRange(context, factory.cloneNode(result), node) : result;
|
||||
}
|
||||
|
||||
function onEnterNewScope(node: IntroducesNewScopeNode | ConditionalTypeNode) {
|
||||
@@ -8885,7 +8921,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
) {
|
||||
let visited = visitEachChild(node, visitExistingNodeTreeSymbols, /*context*/ undefined);
|
||||
if (visited === node) {
|
||||
visited = setTextRange(factory.cloneNode(node), node);
|
||||
visited = setTextRange(context, factory.cloneNode(node), node);
|
||||
}
|
||||
(visited as Mutable<typeof visited>).type = factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||
if (isParameter(node)) {
|
||||
@@ -8906,11 +8942,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
|
||||
if (isTupleTypeNode(node) || isTypeLiteralNode(node) || isMappedTypeNode(node)) {
|
||||
const visited = visitEachChild(node, visitExistingNodeTreeSymbols, /*context*/ undefined);
|
||||
const clone = setTextRange(visited === node ? factory.cloneNode(node) : visited, node);
|
||||
const clone = setTextRange(context, visited === node ? factory.cloneNode(node) : visited, node);
|
||||
const flags = getEmitFlags(clone);
|
||||
setEmitFlags(clone, flags | (context.flags & NodeBuilderFlags.MultilineObjectLiterals && isTypeLiteralNode(node) ? 0 : EmitFlags.SingleLine));
|
||||
return clone;
|
||||
}
|
||||
if (isStringLiteral(node) && !!(context.flags & NodeBuilderFlags.UseSingleQuotesForStringLiteralType) && !node.singleQuote) {
|
||||
const clone = factory.cloneNode(node);
|
||||
(clone as Mutable<typeof clone>).singleQuote = true;
|
||||
return clone;
|
||||
}
|
||||
if (isConditionalTypeNode(node)) {
|
||||
const checkType = visitNode(node.checkType, visitExistingNodeTreeSymbols, isTypeNode)!;
|
||||
|
||||
@@ -9341,10 +9382,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
else {
|
||||
const statement = setTextRange(
|
||||
context,
|
||||
factory.createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
factory.createVariableDeclarationList([
|
||||
factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, serializeTypeForDeclaration(context, type, symbol, enclosingDeclaration)),
|
||||
factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, serializeTypeForDeclaration(context, /*declaration*/ undefined, type, symbol)),
|
||||
], flags),
|
||||
),
|
||||
textRange,
|
||||
@@ -9639,7 +9681,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
for (const sig of signatures) {
|
||||
// Each overload becomes a separate function declaration, in order
|
||||
const decl = signatureToSignatureDeclarationHelper(sig, SyntaxKind.FunctionDeclaration, context, { name: factory.createIdentifier(localName) }) as FunctionDeclaration;
|
||||
addResult(setTextRange(decl, getSignatureTextRangeLocation(sig)), modifierFlags);
|
||||
addResult(setTextRange(context, decl, getSignatureTextRangeLocation(sig)), modifierFlags);
|
||||
}
|
||||
// Module symbol emit will take care of module-y members, provided it has exports
|
||||
if (!(symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) && !!symbol.exports && !!symbol.exports.size)) {
|
||||
@@ -9821,6 +9863,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
context.enclosingDeclaration = oldEnclosing;
|
||||
addResult(
|
||||
setTextRange(
|
||||
context,
|
||||
factory.createClassDeclaration(
|
||||
/*modifiers*/ undefined,
|
||||
localName,
|
||||
@@ -10169,7 +10212,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const statement = factory.createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
factory.createVariableDeclarationList([
|
||||
factory.createVariableDeclaration(varName, /*exclamationToken*/ undefined, serializeTypeForDeclaration(context, typeToSerialize, symbol, enclosingDeclaration)),
|
||||
factory.createVariableDeclaration(varName, /*exclamationToken*/ undefined, serializeTypeForDeclaration(context, /*declaration*/ undefined, typeToSerialize, symbol)),
|
||||
], flags),
|
||||
);
|
||||
// Inlined JSON types exported with [module.]exports= will already emit an export=, so should use `declare`.
|
||||
@@ -10297,6 +10340,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const paramSymbol = isFunctionLikeDeclaration(setter) ? getSignatureFromDeclaration(setter).parameters[0] : undefined;
|
||||
|
||||
result.push(setTextRange(
|
||||
context,
|
||||
factory.createSetAccessorDeclaration(
|
||||
factory.createModifiersFromModifierFlags(flag),
|
||||
name,
|
||||
@@ -10305,7 +10349,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
/*dotDotDotToken*/ undefined,
|
||||
paramSymbol ? parameterToParameterDeclarationName(paramSymbol, getEffectiveParameterDeclaration(paramSymbol), context) : "value",
|
||||
/*questionToken*/ undefined,
|
||||
isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration),
|
||||
isPrivate ? undefined : serializeTypeForDeclaration(context, /*declaration*/ undefined, getTypeOfSymbol(p), p),
|
||||
)],
|
||||
/*body*/ undefined,
|
||||
),
|
||||
@@ -10315,11 +10359,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (p.flags & SymbolFlags.GetAccessor) {
|
||||
const isPrivate = modifierFlags & ModifierFlags.Private;
|
||||
result.push(setTextRange(
|
||||
context,
|
||||
factory.createGetAccessorDeclaration(
|
||||
factory.createModifiersFromModifierFlags(flag),
|
||||
name,
|
||||
[],
|
||||
isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration),
|
||||
isPrivate ? undefined : serializeTypeForDeclaration(context, /*declaration*/ undefined, getTypeOfSymbol(p), p),
|
||||
/*body*/ undefined,
|
||||
),
|
||||
p.declarations?.find(isGetAccessor) || firstPropertyLikeDecl,
|
||||
@@ -10331,11 +10376,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// If this happens, we assume the accessor takes priority, as it imposes more constraints
|
||||
else if (p.flags & (SymbolFlags.Property | SymbolFlags.Variable | SymbolFlags.Accessor)) {
|
||||
return setTextRange(
|
||||
context,
|
||||
createProperty(
|
||||
factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | flag),
|
||||
name,
|
||||
p.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
|
||||
isPrivate ? undefined : serializeTypeForDeclaration(context, getWriteTypeOfSymbol(p), p, enclosingDeclaration),
|
||||
isPrivate ? undefined : serializeTypeForDeclaration(context, /*declaration*/ undefined, getWriteTypeOfSymbol(p), p),
|
||||
// TODO: https://github.com/microsoft/TypeScript/pull/32372#discussion_r328386357
|
||||
// interface members can't have initializers, however class members _can_
|
||||
/*initializer*/ undefined,
|
||||
@@ -10348,6 +10394,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const signatures = getSignaturesOfType(type, SignatureKind.Call);
|
||||
if (flag & ModifierFlags.Private) {
|
||||
return setTextRange(
|
||||
context,
|
||||
createProperty(
|
||||
factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | flag),
|
||||
name,
|
||||
@@ -10373,7 +10420,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
},
|
||||
);
|
||||
const location = sig.declaration && isPrototypePropertyAssignment(sig.declaration.parent) ? sig.declaration.parent : sig.declaration;
|
||||
results.push(setTextRange(decl, location));
|
||||
results.push(setTextRange(context, decl, location));
|
||||
}
|
||||
return results as unknown as T[];
|
||||
}
|
||||
@@ -10419,6 +10466,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
if (privateProtected) {
|
||||
return [setTextRange(
|
||||
context,
|
||||
factory.createConstructorDeclaration(
|
||||
factory.createModifiersFromModifierFlags(privateProtected),
|
||||
/*parameters*/ [],
|
||||
@@ -10433,7 +10481,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
for (const sig of signatures) {
|
||||
// Each overload becomes a separate constructor declaration, in order
|
||||
const decl = signatureToSignatureDeclarationHelper(sig, outputKind, context);
|
||||
results.push(setTextRange(decl, sig.declaration));
|
||||
results.push(setTextRange(context, decl, sig.declaration));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
@@ -11073,9 +11121,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (parentAccess && canHaveFlowNode(parentAccess) && parentAccess.flowNode) {
|
||||
const propName = getDestructuringPropertyName(node);
|
||||
if (propName) {
|
||||
const literal = setTextRange(parseNodeFactory.createStringLiteral(propName), node);
|
||||
const literal = setTextRangeWorker(parseNodeFactory.createStringLiteral(propName), node);
|
||||
const lhsExpr = isLeftHandSideExpression(parentAccess) ? parentAccess : parseNodeFactory.createParenthesizedExpression(parentAccess);
|
||||
const result = setTextRange(parseNodeFactory.createElementAccessExpression(lhsExpr, literal), node);
|
||||
const result = setTextRangeWorker(parseNodeFactory.createElementAccessExpression(lhsExpr, literal), node);
|
||||
setParent(literal, result);
|
||||
setParent(result, node);
|
||||
if (lhsExpr !== parentAccess) {
|
||||
@@ -34724,7 +34772,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
|
||||
function createSyntheticExpression(parent: Node, type: Type, isSpread?: boolean, tupleNameSource?: ParameterDeclaration | NamedTupleMember) {
|
||||
const result = parseNodeFactory.createSyntheticExpression(type, isSpread, tupleNameSource);
|
||||
setTextRange(result, parent);
|
||||
setTextRangeWorker(result, parent);
|
||||
setParent(result, parent);
|
||||
return result;
|
||||
}
|
||||
@@ -48648,12 +48696,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return false;
|
||||
}
|
||||
|
||||
function declaredParameterTypeContainsUndefined(parameter: ParameterDeclaration) {
|
||||
if (!parameter.type) return false;
|
||||
const type = getTypeFromTypeNode(parameter.type);
|
||||
function declaredParameterTypeContainsUndefined(parameter: ParameterDeclaration | JSDocParameterTag) {
|
||||
const typeNode = getNonlocalEffectiveTypeAnnotationNode(parameter);
|
||||
if (!typeNode) return false;
|
||||
const type = getTypeFromTypeNode(typeNode);
|
||||
return containsUndefinedType(type);
|
||||
}
|
||||
function requiresAddingImplicitUndefined(parameter: ParameterDeclaration) {
|
||||
function requiresAddingImplicitUndefined(parameter: ParameterDeclaration | JSDocParameterTag) {
|
||||
return (isRequiredInitializedParameter(parameter) || isOptionalUninitializedParameterProperty(parameter)) && !declaredParameterTypeContainsUndefined(parameter);
|
||||
}
|
||||
|
||||
@@ -48665,10 +48714,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
!hasSyntacticModifier(parameter, ModifierFlags.ParameterPropertyModifier);
|
||||
}
|
||||
|
||||
function isOptionalUninitializedParameterProperty(parameter: ParameterDeclaration) {
|
||||
function isOptionalUninitializedParameterProperty(parameter: ParameterDeclaration | JSDocParameterTag) {
|
||||
return strictNullChecks &&
|
||||
isOptionalParameter(parameter) &&
|
||||
!parameter.initializer &&
|
||||
(isJSDocParameterTag(parameter) || !parameter.initializer) &&
|
||||
hasSyntacticModifier(parameter, ModifierFlags.ParameterPropertyModifier);
|
||||
}
|
||||
|
||||
@@ -48819,7 +48868,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
|
||||
function createTypeOfDeclaration(declarationIn: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean) {
|
||||
function createTypeOfDeclaration(declarationIn: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) {
|
||||
const declaration = getParseTreeNode(declarationIn, isVariableLikeOrAccessor);
|
||||
if (!declaration) {
|
||||
return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode;
|
||||
@@ -48830,7 +48879,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
? getWidenedLiteralType(getTypeOfSymbol(symbol))
|
||||
: errorType;
|
||||
|
||||
return nodeBuilder.serializeTypeForDeclaration(type, symbol, addUndefined, enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker);
|
||||
return nodeBuilder.serializeTypeForDeclaration(declaration, type, symbol, enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker);
|
||||
}
|
||||
|
||||
type DeclarationWithPotentialInnerNodeReuse =
|
||||
@@ -51454,6 +51503,15 @@ function createBasicNodeBuilderModuleSpecifierResolutionHost(host: TypeCheckerHo
|
||||
|
||||
interface NodeBuilderContext {
|
||||
enclosingDeclaration: Node | undefined;
|
||||
/**
|
||||
* `enclosingFile` is generated from the initial `enclosingDeclaration` and
|
||||
* is used to ensure text ranges for generated nodes are not set based on nodes from outside
|
||||
* the original input's containing file. Checking the `enclosingDeclaration` at the time of
|
||||
* `setTextRange` is not sufficient, as the `enclosingDeclaration` is modified by the node builder
|
||||
* as it decends into some types as a shortcut to making certain scopes visible, and may be modified
|
||||
* into a declaration in a different file from the original input `enclosingDeclaration`!
|
||||
*/
|
||||
enclosingFile: SourceFile | undefined;
|
||||
flags: NodeBuilderFlags;
|
||||
tracker: SymbolTrackerImpl;
|
||||
|
||||
|
||||
@@ -638,7 +638,7 @@ export function transformDeclarations(context: TransformationContext) {
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.BindingElement:
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
typeNode = resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldAddImplicitUndefined);
|
||||
typeNode = resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker);
|
||||
break;
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
|
||||
@@ -5653,7 +5653,7 @@ export interface EmitResolver {
|
||||
requiresAddingImplicitUndefined(node: ParameterDeclaration): boolean;
|
||||
isExpandoFunctionDeclaration(node: FunctionDeclaration): boolean;
|
||||
getPropertiesOfContainerFunction(node: Declaration): Symbol[];
|
||||
createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression | ElementAccessExpression | BinaryExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean): TypeNode | undefined;
|
||||
createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression | ElementAccessExpression | BinaryExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined;
|
||||
createReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined;
|
||||
createTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined;
|
||||
createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, tracker: SymbolTracker): Expression;
|
||||
|
||||
Reference in New Issue
Block a user