Skip to content

Refactored node builder flags and tests #59440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Aug 8, 2024
150 changes: 83 additions & 67 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

16 changes: 9 additions & 7 deletions src/compiler/transformers/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ import {
ImportTypeNode,
IndexSignatureDeclaration,
InterfaceDeclaration,
InternalNodeBuilderFlags,
isAmbientModule,
isArray,
isArrayBindingElement,
Expand Down Expand Up @@ -239,10 +240,11 @@ const declarationEmitNodeBuilderFlags = NodeBuilderFlags.MultilineObjectLiterals
NodeBuilderFlags.UseTypeOfFunction |
NodeBuilderFlags.UseStructuralFallback |
NodeBuilderFlags.AllowEmptyTuple |
NodeBuilderFlags.AllowUnresolvedNames |
NodeBuilderFlags.GenerateNamesForShadowedTypeParams |
NodeBuilderFlags.NoTruncation;

const declarationEmitInternalNodeBuilderFlags = InternalNodeBuilderFlags.AllowUnresolvedNames;

/**
* Transforms a ts file into a .d.ts file
* This process requires type information, which is retrieved through the emit resolver. Because of this,
Expand Down Expand Up @@ -429,7 +431,7 @@ export function transformDeclarations(context: TransformationContext) {
: Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_An_explicit_type_annotation_may_unblock_declaration_emit,
errorNode: s.errorNode || sourceFile,
}));
const result = resolver.getDeclarationStatementsForSourceFile(sourceFile, declarationEmitNodeBuilderFlags, symbolTracker);
const result = resolver.getDeclarationStatementsForSourceFile(sourceFile, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, symbolTracker);
getSymbolAccessibilityDiagnostic = oldDiag;
return result;
}
Expand Down Expand Up @@ -696,15 +698,15 @@ export function transformDeclarations(context: TransformationContext) {
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.VariableDeclaration:
typeNode = resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker);
typeNode = resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, symbolTracker);
break;
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ConstructSignature:
case SyntaxKind.MethodSignature:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.CallSignature:
typeNode = resolver.createReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker);
typeNode = resolver.createReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, symbolTracker);
break;
default:
Debug.assertNever(node);
Expand Down Expand Up @@ -1329,7 +1331,7 @@ export function transformDeclarations(context: TransformationContext) {
errorNode: input,
});
errorFallbackNode = input;
const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined);
const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, symbolTracker), /*initializer*/ undefined);
errorFallbackNode = undefined;
const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const));

Expand Down Expand Up @@ -1471,7 +1473,7 @@ export function transformDeclarations(context: TransformationContext) {
return undefined; // unique symbol or non-identifier name - omit, since there's no syntax that can preserve it
}
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p.valueDeclaration);
const type = resolver.createTypeOfDeclaration(p.valueDeclaration, fakespace, declarationEmitNodeBuilderFlags | NodeBuilderFlags.NoSyntacticPrinter, symbolTracker);
const type = resolver.createTypeOfDeclaration(p.valueDeclaration, fakespace, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags | InternalNodeBuilderFlags.NoSyntacticPrinter, symbolTracker);
getSymbolAccessibilityDiagnostic = oldDiag;
const isNonContextualKeywordName = isStringANonContextualKeyword(nameStr);
const name = isNonContextualKeywordName ? factory.getGeneratedNameForNode(p.valueDeclaration) : factory.createIdentifier(nameStr);
Expand Down Expand Up @@ -1666,7 +1668,7 @@ export function transformDeclarations(context: TransformationContext) {
errorNode: extendsClause,
typeName: input.name,
});
const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined);
const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, declarationEmitInternalNodeBuilderFlags, symbolTracker), /*initializer*/ undefined);
const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const));
const heritageClauses = factory.createNodeArray(map(input.heritageClauses, clause => {
if (clause.token === SyntaxKind.ExtendsKeyword) {
Expand Down
33 changes: 20 additions & 13 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5073,14 +5073,14 @@ export interface TypeChecker {
// TODO: GH#18217 `xToDeclaration` calls are frequently asserted as defined.
/** Note that the resulting nodes cannot be checked. */
typeToTypeNode(type: Type, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): TypeNode | undefined;
/** @internal */ typeToTypeNode(type: Type, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker?: SymbolTracker): TypeNode | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
/** @internal */ typePredicateToTypePredicateNode(typePredicate: TypePredicate, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker?: SymbolTracker): TypePredicateNode | undefined;
/** @internal */ typeToTypeNode(type: Type, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, internalFlags?: InternalNodeBuilderFlags | undefined, tracker?: SymbolTracker): TypeNode | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
/** @internal */ typePredicateToTypePredicateNode(typePredicate: TypePredicate, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, internalFlags?: InternalNodeBuilderFlags | undefined, tracker?: SymbolTracker): TypePredicateNode | undefined;
/** Note that the resulting nodes cannot be checked. */
signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): SignatureDeclaration & { typeArguments?: NodeArray<TypeNode>; } | undefined;
/** @internal */ signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker?: SymbolTracker): SignatureDeclaration & { typeArguments?: NodeArray<TypeNode>; } | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
/** @internal */ signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, internalFlags?: InternalNodeBuilderFlags | undefined, tracker?: SymbolTracker): SignatureDeclaration & { typeArguments?: NodeArray<TypeNode>; } | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
/** Note that the resulting nodes cannot be checked. */
indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): IndexSignatureDeclaration | undefined;
/** @internal */ indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker?: SymbolTracker): IndexSignatureDeclaration | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
/** @internal */ indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, internalFlags?: InternalNodeBuilderFlags | undefined, tracker?: SymbolTracker): IndexSignatureDeclaration | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
/** Note that the resulting nodes cannot be checked. */
symbolToEntityName(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): EntityName | undefined;
/** Note that the resulting nodes cannot be checked. */
Expand All @@ -5090,7 +5090,7 @@ export interface TypeChecker {
*
* @internal
*/
symbolToNode(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): Node | undefined;
symbolToNode(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, internalFlags: InternalNodeBuilderFlags | undefined): Node | undefined;
/** Note that the resulting nodes cannot be checked. */
symbolToTypeParameterDeclarations(symbol: Symbol, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): NodeArray<TypeParameterDeclaration> | undefined;
/** Note that the resulting nodes cannot be checked. */
Expand Down Expand Up @@ -5459,12 +5459,9 @@ export const enum NodeBuilderFlags {
AllowEmptyTuple = 1 << 19,
AllowUniqueESSymbolType = 1 << 20,
AllowEmptyIndexInfoType = 1 << 21,
/** @internal */ WriteComputedProps = 1 << 30, // { [E.A]: 1 }
/** @internal */ NoSyntacticPrinter = 1 << 31,
// Errors (cont.)
AllowNodeModulesRelativePaths = 1 << 26,
/** @internal */ DoNotIncludeSymbolChain = 1 << 27, // Skip looking up and printing an accessible symbol chain
/** @internal */ AllowUnresolvedNames = 1 << 32,


IgnoreErrors = AllowThisInObjectLiteral | AllowQualifiedNameInPlaceOfIdentifier | AllowAnonymousIdentifier | AllowEmptyUnionOrIntersection | AllowEmptyTuple | AllowEmptyIndexInfoType | AllowNodeModulesRelativePaths,

Expand All @@ -5474,6 +5471,16 @@ export const enum NodeBuilderFlags {
InInitialEntityName = 1 << 24, // Set when writing the LHS of an entity name or entity name expression
}

/** @internal */
// dprint-ignore
export const enum InternalNodeBuilderFlags {
None = 0,
WriteComputedProps = 1 << 0, // { [E.A]: 1 }
NoSyntacticPrinter = 1 << 1,
DoNotIncludeSymbolChain = 1 << 2, // Skip looking up and printing an accessible symbol chain
AllowUnresolvedNames = 1 << 3,
}

// Ensure the shared flags between this and `NodeBuilderFlags` stay in alignment
// dprint-ignore
export const enum TypeFormatFlags {
Expand Down Expand Up @@ -5810,9 +5817,9 @@ export interface EmitResolver {
requiresAddingImplicitUndefined(node: ParameterDeclaration): boolean;
isExpandoFunctionDeclaration(node: FunctionDeclaration | VariableDeclaration): boolean;
getPropertiesOfContainerFunction(node: Declaration): Symbol[];
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;
createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression | ElementAccessExpression | BinaryExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, internalFlags: InternalNodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined;
createReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, internalFlags: InternalNodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined;
createTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, internalFlags: InternalNodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined;
createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, tracker: SymbolTracker): Expression;
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags | undefined, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult;
isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult;
Expand All @@ -5829,7 +5836,7 @@ export interface EmitResolver {
getJsxFactoryEntity(location?: Node): EntityName | undefined;
getJsxFragmentFactoryEntity(location?: Node): EntityName | undefined;
isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement): boolean;
getDeclarationStatementsForSourceFile(node: SourceFile, flags: NodeBuilderFlags, tracker: SymbolTracker): Statement[] | undefined;
getDeclarationStatementsForSourceFile(node: SourceFile, flags: NodeBuilderFlags, internalFlags: InternalNodeBuilderFlags, tracker: SymbolTracker): Statement[] | undefined;
isImportRequiredByAugmentation(decl: ImportDeclaration): boolean;
isDefinitelyReferenceToGlobalSymbolObject(node: Node): boolean;
}
Expand Down
2 changes: 1 addition & 1 deletion src/harness/typeWriter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ export class TypeWriterWalker {
}
else {
const typeFormatFlags = ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.AllowUniqueESSymbolType | ts.TypeFormatFlags.GenerateNamesForShadowedTypeParams;
let typeNode = this.checker.typeToTypeNode(type, node.parent, (typeFormatFlags & ts.TypeFormatFlags.NodeBuilderFlagsMask) | ts.NodeBuilderFlags.IgnoreErrors)!;
let typeNode = this.checker.typeToTypeNode(type, node.parent, (typeFormatFlags & ts.TypeFormatFlags.NodeBuilderFlagsMask) | ts.NodeBuilderFlags.IgnoreErrors, ts.InternalNodeBuilderFlags.AllowUnresolvedNames)!;
if (ts.isIdentifier(node) && ts.isTypeAliasDeclaration(node.parent) && node.parent.name === node && ts.isIdentifier(typeNode) && ts.idText(typeNode) === ts.idText(node)) {
// for a complex type alias `type T = ...`, showing "T : T" isn't very helpful for type tests. When the type produced is the same as
// the name of the type alias, recreate the type string without reusing the alias name
Expand Down
2 changes: 1 addition & 1 deletion src/services/codefixes/fixAddMissingConstraint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ function addMissingConstraint(changes: textChanges.ChangeTracker, program: Progr
const scriptTarget = getEmitScriptTarget(program.getCompilerOptions());
const tracker = getNoopSymbolTrackerWithResolver({ program, host });
const importAdder = createImportAdder(sourceFile, program, preferences, host);
const typeNode = typeToAutoImportableTypeNode(checker, importAdder, constraint, /*contextNode*/ undefined, scriptTarget, /*flags*/ undefined, tracker);
const typeNode = typeToAutoImportableTypeNode(checker, importAdder, constraint, /*contextNode*/ undefined, scriptTarget, /*flags*/ undefined, /*internalFlags*/ undefined, tracker);
if (typeNode) {
changes.replaceNode(sourceFile, declaration, factory.updateTypeParameterDeclaration(declaration, /*modifiers*/ undefined, declaration.name, typeNode, declaration.default));
importAdder.writeFixes(changes);
Expand Down
7 changes: 4 additions & 3 deletions src/services/codefixes/fixAddMissingMember.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import {
Identifier,
idText,
InterfaceDeclaration,
InternalNodeBuilderFlags,
isCallExpression,
isClassLike,
isComputedPropertyName,
Expand Down Expand Up @@ -493,11 +494,11 @@ function getTypeNode(checker: TypeChecker, node: ClassLikeDeclaration | Interfac
const binaryExpression = token.parent.parent as BinaryExpression;
const otherExpression = token.parent === binaryExpression.left ? binaryExpression.right : binaryExpression.left;
const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression)));
typeNode = checker.typeToTypeNode(widenedType, node, NodeBuilderFlags.NoTruncation);
typeNode = checker.typeToTypeNode(widenedType, node, NodeBuilderFlags.NoTruncation, InternalNodeBuilderFlags.AllowUnresolvedNames);
}
else {
const contextualType = checker.getContextualType(token.parent as Expression);
typeNode = contextualType ? checker.typeToTypeNode(contextualType, /*enclosingDeclaration*/ undefined, NodeBuilderFlags.NoTruncation) : undefined;
typeNode = contextualType ? checker.typeToTypeNode(contextualType, /*enclosingDeclaration*/ undefined, NodeBuilderFlags.NoTruncation, InternalNodeBuilderFlags.AllowUnresolvedNames) : undefined;
}
return typeNode || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
}
Expand Down Expand Up @@ -775,7 +776,7 @@ function tryGetContainingMethodDeclaration(node: ClassLikeDeclaration | Interfac

function createPropertyNameFromSymbol(symbol: Symbol, target: ScriptTarget, quotePreference: QuotePreference, checker: TypeChecker) {
if (isTransientSymbol(symbol)) {
const prop = checker.symbolToNode(symbol, SymbolFlags.Value, /*enclosingDeclaration*/ undefined, NodeBuilderFlags.WriteComputedProps);
const prop = checker.symbolToNode(symbol, SymbolFlags.Value, /*enclosingDeclaration*/ undefined, /*flags*/ undefined, InternalNodeBuilderFlags.WriteComputedProps);
if (prop && isComputedPropertyName(prop)) return prop;
}
// We're using these nodes as property names in an object literal; no need to quote names when not needed.
Expand Down
3 changes: 2 additions & 1 deletion src/services/codefixes/fixAddMissingParam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
getNameOfDeclaration,
getSourceFileOfNode,
getTokenAtPosition,
InternalNodeBuilderFlags,
isAccessExpression,
isCallExpression,
isIdentifier,
Expand Down Expand Up @@ -221,7 +222,7 @@ function tryGetName(node: FunctionLikeDeclaration) {
}

function typeToTypeNode(checker: TypeChecker, type: Type, enclosingDeclaration: Node) {
return checker.typeToTypeNode(checker.getWidenedType(type), enclosingDeclaration, NodeBuilderFlags.NoTruncation)
return checker.typeToTypeNode(checker.getWidenedType(type), enclosingDeclaration, NodeBuilderFlags.NoTruncation, InternalNodeBuilderFlags.AllowUnresolvedNames)
?? factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword);
}

Expand Down
Loading