-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Use union types for all common classes of AST nodes #54148
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -243,7 +243,6 @@ import { | |
JSDocOverrideTag, | ||
JSDocParameterTag, | ||
JSDocPrivateTag, | ||
JSDocPropertyLikeTag, | ||
JSDocPropertyTag, | ||
JSDocProtectedTag, | ||
JSDocPublicTag, | ||
|
@@ -397,7 +396,7 @@ import { | |
setTextRange, | ||
setTextRangePosWidth, | ||
ShorthandPropertyAssignment, | ||
SignatureDeclarationBase, | ||
SignatureDeclaration, | ||
singleOrUndefined, | ||
skipOuterExpressions, | ||
skipParentheses, | ||
|
@@ -414,6 +413,7 @@ import { | |
SuperExpression, | ||
SwitchStatement, | ||
SyntaxKind, | ||
SyntaxKindToNode, | ||
SyntaxList, | ||
SyntheticExpression, | ||
SyntheticReferenceExpression, | ||
|
@@ -1081,7 +1081,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode | |
return node; | ||
} | ||
|
||
function finishUpdateBaseSignatureDeclaration<T extends SignatureDeclarationBase>(updated: Mutable<T>, original: T) { | ||
function finishUpdateBaseSignatureDeclaration<T extends SignatureDeclaration>(updated: Mutable<T>, original: T): T { | ||
if (updated !== original) { | ||
// copy children used for quick info | ||
updated.typeArguments = original.typeArguments; | ||
|
@@ -1304,13 +1304,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode | |
function createToken<TKind extends KeywordTypeSyntaxKind>(token: TKind): KeywordTypeNode<TKind>; | ||
function createToken<TKind extends ModifierSyntaxKind>(token: TKind): ModifierToken<TKind>; | ||
function createToken<TKind extends KeywordSyntaxKind>(token: TKind): KeywordToken<TKind>; | ||
function createToken<TKind extends SyntaxKind>(token: TKind): Token<TKind>; | ||
function createToken<TKind extends SyntaxKind>(token: TKind): SyntaxKindToNode[TKind & keyof SyntaxKindToNode]; | ||
function createToken<TKind extends SyntaxKind>(token: TKind) { | ||
Debug.assert(token >= SyntaxKind.FirstToken && token <= SyntaxKind.LastToken, "Invalid token"); | ||
Debug.assert(token <= SyntaxKind.FirstTemplateToken || token >= SyntaxKind.LastTemplateToken, "Invalid token. Use 'createTemplateLiteralLikeNode' to create template literals."); | ||
Debug.assert(token <= SyntaxKind.FirstLiteralToken || token >= SyntaxKind.LastLiteralToken, "Invalid token. Use 'createLiteralLikeNode' to create literals."); | ||
Debug.assert(token !== SyntaxKind.Identifier, "Invalid token. Use 'createIdentifier' to create identifiers"); | ||
const node = createBaseToken<Token<TKind>>(token); | ||
Debug.assert(token !== SyntaxKind.Count, "Invalid token. `Count` is not a valid node or token syntax kind."); | ||
const node = createBaseToken<SyntaxKindToNode[TKind & keyof SyntaxKindToNode]>(token as SyntaxKindToNode[TKind & keyof SyntaxKindToNode]["kind"]); | ||
let transformFlags = TransformFlags.None; | ||
switch (token) { | ||
case SyntaxKind.AsyncKeyword: | ||
|
@@ -3282,7 +3283,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode | |
// @api | ||
function createBinaryExpression(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression) { | ||
const node = createBaseDeclaration<BinaryExpression>(SyntaxKind.BinaryExpression); | ||
const operatorToken = asToken(operator); | ||
const operatorToken = asToken<BinaryOperator>(operator); | ||
const operatorKind = operatorToken.kind; | ||
node.left = parenthesizerRules().parenthesizeLeftSideOfBinary(operatorKind, left); | ||
node.operatorToken = operatorToken; | ||
|
@@ -4994,15 +4995,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode | |
} | ||
|
||
// @api | ||
function createJSDocTypeLiteral(propertyTags?: readonly JSDocPropertyLikeTag[], isArrayType = false): JSDocTypeLiteral { | ||
function createJSDocTypeLiteral(propertyTags?: readonly JSDocPropertyTag[], isArrayType = false): JSDocTypeLiteral { | ||
const node = createBaseDeclaration<JSDocTypeLiteral>(SyntaxKind.JSDocTypeLiteral); | ||
node.jsDocPropertyTags = asNodeArray(propertyTags); | ||
node.isArrayType = isArrayType; | ||
return node; | ||
} | ||
|
||
// @api | ||
function updateJSDocTypeLiteral(node: JSDocTypeLiteral, propertyTags: readonly JSDocPropertyLikeTag[] | undefined, isArrayType: boolean): JSDocTypeLiteral { | ||
function updateJSDocTypeLiteral(node: JSDocTypeLiteral, propertyTags: readonly JSDocPropertyTag[] | undefined, isArrayType: boolean): JSDocTypeLiteral { | ||
return node.jsDocPropertyTags !== propertyTags | ||
|| node.isArrayType !== isArrayType | ||
? update(createJSDocTypeLiteral(propertyTags, isArrayType), node) | ||
|
@@ -6277,19 +6278,29 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode | |
return node; | ||
} | ||
if (isSourceFile(node)) { | ||
return cloneSourceFile(node) as T & SourceFile; | ||
// TODO: GH#54146 | ||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion | ||
return cloneSourceFile(node) as T; | ||
} | ||
if (isGeneratedIdentifier(node)) { | ||
return cloneGeneratedIdentifier(node) as T & GeneratedIdentifier; | ||
// TODO: GH#54146 | ||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion | ||
return cloneGeneratedIdentifier(node) as T; | ||
} | ||
if (isIdentifier(node)) { | ||
return cloneIdentifier(node) as T & Identifier; | ||
// TODO: GH#54146 | ||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion | ||
return cloneIdentifier(node) as T; | ||
} | ||
if (isGeneratedPrivateIdentifier(node)) { | ||
return cloneGeneratedPrivateIdentifier(node) as T & GeneratedPrivateIdentifier; | ||
// TODO: GH#54146 | ||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion | ||
return cloneGeneratedPrivateIdentifier(node) as T; | ||
} | ||
if (isPrivateIdentifier(node)) { | ||
return clonePrivateIdentifier(node) as T & PrivateIdentifier; | ||
// TODO: GH#54146 | ||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion | ||
return clonePrivateIdentifier(node) as T; | ||
} | ||
|
||
const clone = | ||
|
@@ -6308,7 +6319,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode | |
clone[key] = node[key]; | ||
} | ||
|
||
return clone; | ||
// TODO: GH#54146 | ||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion | ||
return clone as T; | ||
} | ||
|
||
// compound nodes | ||
|
@@ -6530,13 +6543,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode | |
case SyntaxKind.StringLiteral: | ||
return false; | ||
case SyntaxKind.ArrayLiteralExpression: | ||
const elements = (target as ArrayLiteralExpression).elements; | ||
const elements = (target).elements; | ||
if (elements.length === 0) { | ||
return false; | ||
} | ||
return true; | ||
case SyntaxKind.ObjectLiteralExpression: | ||
return (target as ObjectLiteralExpression).properties.length > 0; | ||
return (target).properties.length > 0; | ||
default: | ||
return true; | ||
} | ||
|
@@ -6847,7 +6860,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode | |
*/ | ||
function liftToBlock(nodes: readonly Node[]): Statement { | ||
Debug.assert(every(nodes, isStatementOrBlock), "Cannot lift nodes to a Block."); | ||
return singleOrUndefined(nodes) as Statement || createBlock(nodes as readonly Statement[]); | ||
return singleOrUndefined(nodes) as Statement || createBlock(nodes); | ||
} | ||
|
||
function findSpanEnd<T>(array: readonly T[], test: (value: T) => boolean, start: number) { | ||
|
@@ -7011,14 +7024,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode | |
return node && parenthesizerRules().parenthesizeExpressionForDisallowedComma(node); | ||
} | ||
|
||
function asToken<TKind extends SyntaxKind>(value: TKind | Token<TKind>): Token<TKind> { | ||
function asToken<TKind extends SyntaxKind>(value: TKind | SyntaxKindToNode[TKind & keyof SyntaxKindToNode]): SyntaxKindToNode[TKind & keyof SyntaxKindToNode] { | ||
return typeof value === "number" ? createToken(value) : value; | ||
} | ||
|
||
function asEmbeddedStatement<T extends Node>(statement: T): T | EmptyStatement; | ||
function asEmbeddedStatement<T extends Node>(statement: T | undefined): T | EmptyStatement | undefined; | ||
function asEmbeddedStatement<T extends Node>(statement: T | undefined): T | EmptyStatement | undefined { | ||
return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement; | ||
return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement as T; // TODO: GH#54146 | ||
} | ||
|
||
function asVariableDeclaration(variableDeclaration: string | BindingName | VariableDeclaration | undefined) { | ||
|
@@ -7570,6 +7583,9 @@ export function createSourceMapSource(fileName: string, text: string, skipTrivia | |
|
||
// Utilities | ||
|
||
/** @internal */ export function setOriginalNode<T extends Node>(node: Mutable<T>, original: Node | undefined): T; // TODO: This should probably always require a Mutable<T>, since it mutates `original` | ||
// eslint-disable-next-line @typescript-eslint/unified-signatures | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a bugfix or feature request you'd want to file on typescript-eslint to make |
||
export function setOriginalNode<T extends Node>(node: T, original: Node | undefined): T; // inference is worse if the signatures are combined | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this comment show up in the public API? It would be somewhat confusing if so, since the other overload isn't public. |
||
export function setOriginalNode<T extends Node>(node: T, original: Node | undefined): T { | ||
node.original = original; | ||
if (original) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,7 +35,6 @@ import { | |
last, | ||
LeftHandSideExpression, | ||
NamedTupleMember, | ||
NewExpression, | ||
NodeArray, | ||
NodeFactory, | ||
OperatorPrecedence, | ||
|
@@ -252,14 +251,14 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul | |
return node.kind; | ||
} | ||
|
||
if (node.kind === SyntaxKind.BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind.PlusToken) { | ||
if (node.kind === SyntaxKind.BinaryExpression && (node).operatorToken.kind === SyntaxKind.PlusToken) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Excess parens. |
||
if ((node as BinaryPlusExpression).cachedLiteralKind !== undefined) { | ||
return (node as BinaryPlusExpression).cachedLiteralKind; | ||
} | ||
|
||
const leftKind = getLiteralKindOfBinaryPlusOperand((node as BinaryExpression).left); | ||
const leftKind = getLiteralKindOfBinaryPlusOperand((node).left); | ||
const literalKind = isLiteralKind(leftKind) | ||
&& leftKind === getLiteralKindOfBinaryPlusOperand((node as BinaryExpression).right) | ||
&& leftKind === getLiteralKindOfBinaryPlusOperand((node).right) | ||
? leftKind | ||
: SyntaxKind.Unknown; | ||
|
||
|
@@ -360,7 +359,7 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul | |
return factory.createParenthesizedExpression(expression); | ||
|
||
case SyntaxKind.NewExpression: | ||
return !(leftmostExpr as NewExpression).arguments | ||
return !(leftmostExpr).arguments | ||
? factory.createParenthesizedExpression(expression) | ||
: expression as LeftHandSideExpression; // TODO(rbuckton): Verify this assertion holds | ||
} | ||
|
@@ -381,7 +380,7 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul | |
// | ||
const emittedExpression = skipPartiallyEmittedExpressions(expression); | ||
if (isLeftHandSideExpression(emittedExpression) | ||
&& (emittedExpression.kind !== SyntaxKind.NewExpression || (emittedExpression as NewExpression).arguments) | ||
&& (emittedExpression.kind !== SyntaxKind.NewExpression || (emittedExpression).arguments) | ||
&& (optionalChain || !isOptionalChain(emittedExpression))) { | ||
// TODO(rbuckton): Verify whether this assertion holds. | ||
return expression as LeftHandSideExpression; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TODO isn't relevant since
original
isn't markedreadonly
onNode
.