From ae3f39e991de9411cb7302f577507c7dab2a1334 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 28 Mar 2024 15:56:01 -0700 Subject: [PATCH] Remove getAllAccessorDeclarations from the EmitResolver --- src/compiler/checker.ts | 73 +++++++++++++++------ src/compiler/emitter.ts | 1 - src/compiler/transformers/declarations.ts | 6 +- src/compiler/transformers/ts.ts | 4 +- src/compiler/transformers/typeSerializer.ts | 14 ++-- src/compiler/types.ts | 1 - 6 files changed, 65 insertions(+), 34 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d6c635fda1344..4764bb112d08d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -235,7 +235,6 @@ import { GenericType, GetAccessorDeclaration, getAliasDeclarationFromName, - getAllAccessorDeclarations, getAllJSDocTags, getAllowSyntheticDefaultImports, getAncestor, @@ -8507,7 +8506,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getDeclarationWithTypeAnnotation(symbol: Symbol, enclosingDeclaration: Node | undefined) { - return symbol.declarations && find(symbol.declarations, s => !!getEffectiveTypeAnnotationNode(s) && (!enclosingDeclaration || !!findAncestor(s, n => n === enclosingDeclaration))); + return symbol.declarations && find(symbol.declarations, s => !!getNonlocalEffectiveTypeAnnotationNode(s) && (!enclosingDeclaration || !!findAncestor(s, n => n === enclosingDeclaration))); } function existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(existing: TypeNode, type: Type) { @@ -8530,7 +8529,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const declWithExistingAnnotation = getDeclarationWithTypeAnnotation(symbol, getEnclosingDeclarationIgnoringFakeScope(enclosingDeclaration)); if (declWithExistingAnnotation && !isFunctionLikeDeclaration(declWithExistingAnnotation) && !isGetAccessorDeclaration(declWithExistingAnnotation)) { // try to reuse the existing annotation - const existing = getEffectiveTypeAnnotationNode(declWithExistingAnnotation)!; + const existing = getNonlocalEffectiveTypeAnnotationNode(declWithExistingAnnotation)!; const result = tryReuseExistingTypeNode(context, existing, type, declWithExistingAnnotation, addUndefined, includePrivateSymbol, bundled); if (result) { return result; @@ -8583,7 +8582,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typePredicate = getTypePredicateOfSignature(signature); const type = getReturnTypeOfSignature(signature); if (!isErrorType(type) && context.enclosingDeclaration) { - const annotation = signature.declaration && getEffectiveReturnTypeNode(signature.declaration); + const annotation = signature.declaration && getNonlocalEffectiveReturnTypeAnnotationNode(signature.declaration); const enclosingDeclarationIgnoringFakeScope = getEnclosingDeclarationIgnoringFakeScope(context.enclosingDeclaration); if (!!findAncestor(annotation, n => n === enclosingDeclarationIgnoringFakeScope) && annotation) { const annotated = getTypeFromTypeNode(annotation); @@ -48696,6 +48695,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return isFunctionLike(declaration) || isExportAssignment(declaration) || isVariableLike(declaration); } + function getAllAccessorDeclarationsForDeclaration(accessor: AccessorDeclaration): AllAccessorDeclarations { + accessor = getParseTreeNode(accessor, isGetOrSetAccessorDeclaration)!; // TODO: GH#18217 + const otherKind = accessor.kind === SyntaxKind.SetAccessor ? SyntaxKind.GetAccessor : SyntaxKind.SetAccessor; + const otherAccessor = getDeclarationOfKind(getSymbolOfDeclaration(accessor), otherKind); + const firstAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? otherAccessor : accessor; + const secondAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? accessor : otherAccessor; + const setAccessor = accessor.kind === SyntaxKind.SetAccessor ? accessor : otherAccessor as SetAccessorDeclaration; + const getAccessor = accessor.kind === SyntaxKind.GetAccessor ? accessor : otherAccessor as GetAccessorDeclaration; + return { + firstAccessor, + secondAccessor, + setAccessor, + getAccessor, + }; + } + function getPossibleTypeNodeReuseExpression(declaration: DeclarationWithPotentialInnerNodeReuse) { return isFunctionLike(declaration) && !isSetAccessor(declaration) ? getSingleReturnExpression(declaration) @@ -48704,7 +48719,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { : !!(declaration as HasInitializer).initializer ? (declaration as HasInitializer & typeof declaration).initializer : isParameter(declaration) && isSetAccessor(declaration.parent) - ? getSingleReturnExpression(getAllAccessorDeclarations(getSymbolOfDeclaration(declaration.parent)?.declarations, declaration.parent).getAccessor) + ? getSingleReturnExpression(getAllAccessorDeclarationsForDeclaration(declaration.parent).getAccessor) : undefined; } @@ -48894,6 +48909,37 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } + function getNonlocalEffectiveTypeAnnotationNode(node: Node) { + const direct = getEffectiveTypeAnnotationNode(node); + if (direct) { + return direct; + } + if (node.kind === SyntaxKind.Parameter && node.parent.kind === SyntaxKind.SetAccessor) { + const other = getAllAccessorDeclarationsForDeclaration(node.parent as SetAccessorDeclaration).getAccessor; + if (other) { + return getEffectiveReturnTypeNode(other); + } + } + return undefined; + } + + function getNonlocalEffectiveReturnTypeAnnotationNode(node: SignatureDeclaration | JSDocSignature) { + const direct = getEffectiveReturnTypeNode(node); + if (direct) { + return direct; + } + if (node.kind === SyntaxKind.GetAccessor) { + const other = getAllAccessorDeclarationsForDeclaration(node).setAccessor; + if (other) { + const param = getSetAccessorValueParameter(other); + if (param) { + return getEffectiveTypeAnnotationNode(param); + } + } + } + return undefined; + } + function createResolver(): EmitResolver { return { getReferencedExportContainer, @@ -48949,21 +48995,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }, getJsxFactoryEntity, getJsxFragmentFactoryEntity, - getAllAccessorDeclarations(accessor: AccessorDeclaration): AllAccessorDeclarations { - accessor = getParseTreeNode(accessor, isGetOrSetAccessorDeclaration)!; // TODO: GH#18217 - const otherKind = accessor.kind === SyntaxKind.SetAccessor ? SyntaxKind.GetAccessor : SyntaxKind.SetAccessor; - const otherAccessor = getDeclarationOfKind(getSymbolOfDeclaration(accessor), otherKind); - const firstAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? otherAccessor : accessor; - const secondAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? accessor : otherAccessor; - const setAccessor = accessor.kind === SyntaxKind.SetAccessor ? accessor : otherAccessor as SetAccessorDeclaration; - const getAccessor = accessor.kind === SyntaxKind.GetAccessor ? accessor : otherAccessor as GetAccessorDeclaration; - return { - firstAccessor, - secondAccessor, - setAccessor, - getAccessor, - }; - }, isBindingCapturedByNode: (node, decl) => { const parseNode = getParseTreeNode(node); const parseDecl = getParseTreeNode(decl); @@ -49280,7 +49311,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else if (legacyDecorators && (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor)) { - const accessors = getAllAccessorDeclarations((node.parent as ClassDeclaration).members, node as AccessorDeclaration); + const accessors = getAllAccessorDeclarationsForDeclaration(node as AccessorDeclaration); if (hasDecorators(accessors.firstAccessor) && node === accessors.secondAccessor) { return grammarErrorOnFirstToken(node, Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 01a525951f844..021b4e24881e6 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1112,7 +1112,6 @@ export const notImplementedResolver: EmitResolver = { isLiteralConstDeclaration: notImplemented, getJsxFactoryEntity: notImplemented, getJsxFragmentFactoryEntity: notImplemented, - getAllAccessorDeclarations: notImplemented, isBindingCapturedByNode: notImplemented, getDeclarationStatementsForSourceFile: notImplemented, isImportRequiredByAugmentation: notImplemented, diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 8e813273f7d0c..172e24a4729d1 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -50,6 +50,7 @@ import { FunctionTypeNode, GeneratedIdentifierFlags, GetAccessorDeclaration, + getAllAccessorDeclarations, getCommentRange, getDirectoryPath, getEffectiveBaseTypeNode, @@ -119,6 +120,7 @@ import { isMethodSignature, isModifier, isModuleDeclaration, + isObjectLiteralExpression, isOmittedExpression, isPrivateIdentifier, isSemicolonClassElement, @@ -728,7 +730,7 @@ export function transformDeclarations(context: TransformationContext) { if (!isPrivate) { const valueParameter = getSetAccessorValueParameter(input); if (valueParameter) { - const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input)); + const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, getAllAccessorDeclarations(isObjectLiteralExpression(input.parent) ? input.parent.properties : input.parent.members, input)); newValueParameter = ensureParameter(valueParameter, /*modifierMask*/ undefined, accessorType); } } @@ -1037,7 +1039,7 @@ export function transformDeclarations(context: TransformationContext) { if (isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } - const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input)); + const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, getAllAccessorDeclarations(isObjectLiteralExpression(input.parent) ? input.parent.properties : input.parent.members, input)); return cleanup(factory.updateGetAccessorDeclaration( input, ensureModifiers(input), diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 7680adf8ada1e..f7af3ceb8eb04 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1122,7 +1122,7 @@ export function transformTypeScript(context: TransformationContext) { if (typeSerializer) { let decorators: Decorator[] | undefined; if (shouldAddTypeMetadata(node)) { - const typeMetadata = emitHelpers().createMetadataHelper("design:type", typeSerializer.serializeTypeOfNode({ currentLexicalScope, currentNameScope: container }, node)); + const typeMetadata = emitHelpers().createMetadataHelper("design:type", typeSerializer.serializeTypeOfNode({ currentLexicalScope, currentNameScope: container }, node, container)); decorators = append(decorators, factory.createDecorator(typeMetadata)); } if (shouldAddParamTypesMetadata(node)) { @@ -1141,7 +1141,7 @@ export function transformTypeScript(context: TransformationContext) { if (typeSerializer) { let properties: ObjectLiteralElementLike[] | undefined; if (shouldAddTypeMetadata(node)) { - const typeProperty = factory.createPropertyAssignment("type", factory.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, factory.createToken(SyntaxKind.EqualsGreaterThanToken), typeSerializer.serializeTypeOfNode({ currentLexicalScope, currentNameScope: container }, node))); + const typeProperty = factory.createPropertyAssignment("type", factory.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, factory.createToken(SyntaxKind.EqualsGreaterThanToken), typeSerializer.serializeTypeOfNode({ currentLexicalScope, currentNameScope: container }, node, container))); properties = append(properties, typeProperty); } if (shouldAddParamTypesMetadata(node)) { diff --git a/src/compiler/transformers/typeSerializer.ts b/src/compiler/transformers/typeSerializer.ts index 5db6762696316..2fcd9264e0b06 100644 --- a/src/compiler/transformers/typeSerializer.ts +++ b/src/compiler/transformers/typeSerializer.ts @@ -115,7 +115,7 @@ export interface RuntimeTypeSerializer { * Serializes the type of a node for use with decorator type metadata. * @param node The node that should have its type serialized. */ - serializeTypeOfNode(serializerContext: RuntimeTypeSerializerContext, node: PropertyDeclaration | ParameterDeclaration | AccessorDeclaration | ClassLikeDeclaration | MethodDeclaration): Expression; + serializeTypeOfNode(serializerContext: RuntimeTypeSerializerContext, node: PropertyDeclaration | ParameterDeclaration | AccessorDeclaration | ClassLikeDeclaration | MethodDeclaration, container: ClassLikeDeclaration): Expression; /** * Serializes the types of the parameters of a node for use with decorator type metadata. * @param node The node that should have its parameter types serialized. @@ -145,7 +145,7 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run return { serializeTypeNode: (serializerContext, node) => setSerializerContextAnd(serializerContext, serializeTypeNode, node), - serializeTypeOfNode: (serializerContext, node) => setSerializerContextAnd(serializerContext, serializeTypeOfNode, node), + serializeTypeOfNode: (serializerContext, node, container) => setSerializerContextAnd(serializerContext, serializeTypeOfNode, node, container), serializeParameterTypesOfNode: (serializerContext, node, container) => setSerializerContextAnd(serializerContext, serializeParameterTypesOfNode, node, container), serializeReturnTypeOfNode: (serializerContext, node) => setSerializerContextAnd(serializerContext, serializeReturnTypeOfNode, node), }; @@ -166,8 +166,8 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run return result; } - function getAccessorTypeNode(node: AccessorDeclaration) { - const accessors = resolver.getAllAccessorDeclarations(node); + function getAccessorTypeNode(node: AccessorDeclaration, container: ClassLikeDeclaration) { + const accessors = getAllAccessorDeclarations(container.members, node); return accessors.setAccessor && getSetAccessorTypeAnnotationNode(accessors.setAccessor) || accessors.getAccessor && getEffectiveReturnTypeNode(accessors.getAccessor); } @@ -176,14 +176,14 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run * Serializes the type of a node for use with decorator type metadata. * @param node The node that should have its type serialized. */ - function serializeTypeOfNode(node: PropertyDeclaration | ParameterDeclaration | AccessorDeclaration | ClassLikeDeclaration | MethodDeclaration): SerializedTypeNode { + function serializeTypeOfNode(node: PropertyDeclaration | ParameterDeclaration | AccessorDeclaration | ClassLikeDeclaration | MethodDeclaration, container: ClassLikeDeclaration): SerializedTypeNode { switch (node.kind) { case SyntaxKind.PropertyDeclaration: case SyntaxKind.Parameter: return serializeTypeNode(node.type); case SyntaxKind.SetAccessor: case SyntaxKind.GetAccessor: - return serializeTypeNode(getAccessorTypeNode(node)); + return serializeTypeNode(getAccessorTypeNode(node, container)); case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: case SyntaxKind.MethodDeclaration: @@ -217,7 +217,7 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run expressions.push(serializeTypeNode(getRestParameterElementType(parameter.type))); } else { - expressions.push(serializeTypeOfNode(parameter)); + expressions.push(serializeTypeOfNode(parameter, container)); } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9e06679f0185f..7afa5cbe305b5 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5635,7 +5635,6 @@ export interface EmitResolver { isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean; getJsxFactoryEntity(location?: Node): EntityName | undefined; getJsxFragmentFactoryEntity(location?: Node): EntityName | undefined; - getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations; isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement): boolean; getDeclarationStatementsForSourceFile(node: SourceFile, flags: NodeBuilderFlags, tracker: SymbolTracker, bundled?: boolean): Statement[] | undefined; isImportRequiredByAugmentation(decl: ImportDeclaration): boolean;