Skip to content
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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 99 additions & 109 deletions src/compiler/binder.ts

Large diffs are not rendered by default.

1,016 changes: 507 additions & 509 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

15 changes: 6 additions & 9 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,12 @@ import {
nodeNextJsonConfigResolver,
normalizePath,
normalizeSlashes,
NumericLiteral,
ObjectLiteralExpression,
ParseConfigHost,
ParsedCommandLine,
parseJsonText,
Path,
PollingWatchKind,
PrefixUnaryExpression,
ProjectReference,
PropertyAssignment,
PropertyName,
Expand All @@ -104,7 +102,6 @@ import {
ScriptTarget,
startsWith,
stringContains,
StringLiteral,
SyntaxKind,
sys,
toFileNameLowerCase,
Expand Down Expand Up @@ -2360,19 +2357,19 @@ export function convertToJson(
if (!isDoubleQuotedString(valueExpression)) {
errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.String_literal_with_double_quotes_expected));
}
return (valueExpression as StringLiteral).text;
return (valueExpression).text;

case SyntaxKind.NumericLiteral:
return Number((valueExpression as NumericLiteral).text);
return Number((valueExpression).text);

case SyntaxKind.PrefixUnaryExpression:
if ((valueExpression as PrefixUnaryExpression).operator !== SyntaxKind.MinusToken || (valueExpression as PrefixUnaryExpression).operand.kind !== SyntaxKind.NumericLiteral) {
if ((valueExpression).operator !== SyntaxKind.MinusToken || (valueExpression).operand.kind !== SyntaxKind.NumericLiteral) {
break; // not valid JSON syntax
}
return -Number(((valueExpression as PrefixUnaryExpression).operand as NumericLiteral).text);
return -Number(((valueExpression).operand).text);

case SyntaxKind.ObjectLiteralExpression:
const objectLiteralExpression = valueExpression as ObjectLiteralExpression;
const objectLiteralExpression = valueExpression ;

// Currently having element option declaration in the tsconfig with type "object"
// determines if it needs onSetValidOptionKeyValueInParent callback or not
Expand All @@ -2384,7 +2381,7 @@ export function convertToJson(

case SyntaxKind.ArrayLiteralExpression:
return convertArrayLiteralExpressionToJson(
(valueExpression as ArrayLiteralExpression).elements,
(valueExpression).elements,
option && (option as CommandLineOptionOfListType).element);
}

Expand Down
385 changes: 192 additions & 193 deletions src/compiler/emitter.ts

Large diffs are not rendered by default.

54 changes: 35 additions & 19 deletions src/compiler/factory/nodeFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ import {
JSDocOverrideTag,
JSDocParameterTag,
JSDocPrivateTag,
JSDocPropertyLikeTag,
JSDocPropertyTag,
JSDocProtectedTag,
JSDocPublicTag,
Expand Down Expand Up @@ -397,7 +396,7 @@ import {
setTextRange,
setTextRangePosWidth,
ShorthandPropertyAssignment,
SignatureDeclarationBase,
SignatureDeclaration,
singleOrUndefined,
skipOuterExpressions,
skipParentheses,
Expand All @@ -414,6 +413,7 @@ import {
SuperExpression,
SwitchStatement,
SyntaxKind,
SyntaxKindToNode,
SyntaxList,
SyntheticExpression,
SyntheticReferenceExpression,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 =
Expand All @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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`
Copy link
Member

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 marked readonly on Node.

// eslint-disable-next-line @typescript-eslint/unified-signatures
Copy link
Contributor

Choose a reason for hiding this comment

The 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 unified-signatures not complain on this case?

export function setOriginalNode<T extends Node>(node: T, original: Node | undefined): T; // inference is worse if the signatures are combined
Copy link
Member

Choose a reason for hiding this comment

The 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) {
Expand Down
11 changes: 5 additions & 6 deletions src/compiler/factory/parenthesizerRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import {
last,
LeftHandSideExpression,
NamedTupleMember,
NewExpression,
NodeArray,
NodeFactory,
OperatorPrecedence,
Expand Down Expand Up @@ -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) {
Copy link
Member

Choose a reason for hiding this comment

The 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;

Expand Down Expand Up @@ -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
}
Expand All @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/factory/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ export function startsWithUseStrict(statements: readonly Statement[]) {

/** @internal */
export function isCommaExpression(node: Expression): node is BinaryExpression & { operatorToken: Token<SyntaxKind.CommaToken> } {
return node.kind === SyntaxKind.BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken;
return node.kind === SyntaxKind.BinaryExpression && (node).operatorToken.kind === SyntaxKind.CommaToken;
}

/** @internal */
Expand Down Expand Up @@ -660,7 +660,7 @@ export function skipOuterExpressions(node: Expression, kinds?: OuterExpressionKi
/** @internal */
export function skipOuterExpressions(node: Node, kinds?: OuterExpressionKinds): Node;
/** @internal */
export function skipOuterExpressions(node: Node, kinds = OuterExpressionKinds.All) {
export function skipOuterExpressions(node: Node, kinds = OuterExpressionKinds.All): Node {
while (isOuterExpression(node, kinds)) {
node = node.expression;
}
Expand Down
Loading