Skip to content

feat: merge AST structure of TSAsExpression with TSTypeAssertion #3005

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

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
16 changes: 3 additions & 13 deletions packages/eslint-plugin/src/rules/consistent-type-assertions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export default util.createRule<Options, MessageIds>({
}

function reportIncorrectAssertionType(
node: TSESTree.TSTypeAssertion | TSESTree.TSAsExpression,
node: TSESTree.TSTypeAssertion,
): void {
// If this node is `as const`, then don't report an error.
if (isConst(node.typeAnnotation)) {
Expand Down Expand Up @@ -123,9 +123,7 @@ export default util.createRule<Options, MessageIds>({
}
}

function checkExpression(
node: TSESTree.TSTypeAssertion | TSESTree.TSAsExpression,
): void {
function checkExpression(node: TSESTree.TSTypeAssertion): void {
if (
options.assertionStyle === 'never' ||
options.objectLiteralTypeAssertions === 'allow' ||
Expand Down Expand Up @@ -159,15 +157,7 @@ export default util.createRule<Options, MessageIds>({

return {
TSTypeAssertion(node): void {
if (options.assertionStyle !== 'angle-bracket') {
reportIncorrectAssertionType(node);
return;
}

checkExpression(node);
},
TSAsExpression(node): void {
if (options.assertionStyle !== 'as') {
if (options.assertionStyle !== node.kind) {
reportIncorrectAssertionType(node);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ const KNOWN_NODES = new Set([
AST_NODE_TYPES.TSAbstractClassProperty,
AST_NODE_TYPES.TSAbstractMethodDefinition,
AST_NODE_TYPES.TSArrayType,
AST_NODE_TYPES.TSAsExpression,
AST_NODE_TYPES.TSCallSignatureDeclaration,
AST_NODE_TYPES.TSConditionalType,
AST_NODE_TYPES.TSConstructorType,
Expand Down
35 changes: 21 additions & 14 deletions packages/eslint-plugin/src/rules/indent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ const KNOWN_NODES = new Set([
AST_NODE_TYPES.TSAbstractClassProperty,
AST_NODE_TYPES.TSAbstractMethodDefinition,
AST_NODE_TYPES.TSArrayType,
AST_NODE_TYPES.TSAsExpression,
AST_NODE_TYPES.TSCallSignatureDeclaration,
AST_NODE_TYPES.TSConditionalType,
AST_NODE_TYPES.TSConstructorType,
Expand Down Expand Up @@ -177,6 +176,12 @@ export default util.createRule<Options, MessageIds>({
return Object.assign({}, rules, {
// overwrite the base rule here so we can use our KNOWN_NODES list instead
'*:exit'(node: TSESTree.Node) {
if (
node.type === AST_NODE_TYPES.TSTypeAssertion &&
node.kind === 'as'
Comment on lines +180 to +181
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no unit case for type assertion with brackets

) {
return;
}
// For nodes we care about, skip the default handling, because it just marks the node as ignored...
if (!KNOWN_NODES.has(node.type)) {
rules['*:exit'](node);
Expand All @@ -192,20 +197,22 @@ export default util.createRule<Options, MessageIds>({
return rules.VariableDeclaration(node);
},

TSAsExpression(node: TSESTree.TSAsExpression) {
// transform it to a BinaryExpression
return rules['BinaryExpression, LogicalExpression']({
type: AST_NODE_TYPES.BinaryExpression,
operator: 'as',
left: node.expression,
// the first typeAnnotation includes the as token
right: node.typeAnnotation as any,
TSTypeAssertion(node: TSESTree.TSTypeAssertion) {
if (node.kind === 'as') {
// transform it to a BinaryExpression
return rules['BinaryExpression, LogicalExpression']({
type: AST_NODE_TYPES.BinaryExpression,
operator: 'as',
left: node.expression,
// the first typeAnnotation includes the as token
right: node.typeAnnotation as any,

// location data
parent: node.parent,
range: node.range,
loc: node.loc,
});
// location data
parent: node.parent,
range: node.range,
loc: node.loc,
});
}
},

TSConditionalType(node: TSESTree.TSConditionalType) {
Expand Down
5 changes: 4 additions & 1 deletion packages/eslint-plugin/src/rules/keyword-spacing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ export default util.createRule<Options, MessageIds>({
const baseRules = baseRule.create(context);
return {
...baseRules,
TSAsExpression(node): void {
TSTypeAssertion(node): void {
if (node.kind !== 'as') {
return;
}
Comment on lines +34 to +37
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could do this via a selector

Suggested change
TSTypeAssertion(node): void {
if (node.kind !== 'as') {
return;
}
'TSTypeAssertion[kind = "as"]'(node): void {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could also add this as a typed selector to packages/types/src/ast-node-types.ts as it's probably going to be a more common usecase

const asToken = util.nullThrows(
sourceCode.getTokenAfter(
node.expression,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,7 @@ export default util.createRule<Options, MessageIds>({
}
}
},
'TSAsExpression, TSTypeAssertion'(
node: TSESTree.TSTypeAssertion | TSESTree.TSAsExpression,
): void {
TSTypeAssertion(node: TSESTree.TSTypeAssertion): void {
if (
options.typesToIgnore?.includes(
sourceCode.getText(node.typeAnnotation),
Expand Down Expand Up @@ -239,7 +237,7 @@ export default util.createRule<Options, MessageIds>({
node,
messageId: 'unnecessaryAssertion',
fix(fixer) {
return originalNode.kind === ts.SyntaxKind.TypeAssertionExpression
return node.kind === 'angle-bracket'
? fixer.removeRange([
node.range[0],
node.expression.range[0] - 1,
Expand Down
1 change: 0 additions & 1 deletion packages/eslint-plugin/src/rules/no-var-requires.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export default util.createRule<Options, MessageIds>({
parent &&
(parent.type === AST_NODE_TYPES.VariableDeclarator ||
parent.type === AST_NODE_TYPES.CallExpression ||
parent.type === AST_NODE_TYPES.TSAsExpression ||
parent.type === AST_NODE_TYPES.TSTypeAssertion ||
parent.type === AST_NODE_TYPES.MemberExpression)
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,7 @@ export default util.createRule({
return true;
};

const isConstAssertion = (
node: TSESTree.TSTypeAssertion | TSESTree.TSAsExpression,
): boolean => {
const isConstAssertion = (node: TSESTree.TSTypeAssertion): boolean => {
return (
node.typeAnnotation.type === AST_NODE_TYPES.TSTypeReference &&
node.typeAnnotation.typeName.type === AST_NODE_TYPES.Identifier &&
Expand All @@ -83,9 +81,7 @@ export default util.createRule({
};

return {
'TSAsExpression, TSTypeAssertion'(
node: TSESTree.TSTypeAssertion | TSESTree.TSAsExpression,
): void {
TSTypeAssertion(node: TSESTree.TSTypeAssertion): void {
if (isConstAssertion(node)) {
return;
}
Expand Down
3 changes: 0 additions & 3 deletions packages/eslint-plugin/src/rules/prefer-as-const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,6 @@ export default util.createRule({
}

return {
TSAsExpression(node): void {
compareTypes(node.expression, node.typeAnnotation, true);
},
TSTypeAssertion(node): void {
compareTypes(node.expression, node.typeAnnotation, true);
},
Expand Down
1 change: 0 additions & 1 deletion packages/eslint-plugin/src/rules/unbound-method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,6 @@ function isSafeUse(node: TSESTree.Node): boolean {

case AST_NODE_TYPES.ChainExpression:
case AST_NODE_TYPES.TSNonNullExpression:
case AST_NODE_TYPES.TSAsExpression:
case AST_NODE_TYPES.TSTypeAssertion:
return isSafeUse(parent);

Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/tests/rules/indent/indent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ type foo = ArrType[];
],
},
{
node: AST_NODE_TYPES.TSAsExpression,
node: AST_NODE_TYPES.TSTypeAssertion,
code: [
`
const foo = {} as {
Expand Down
7 changes: 2 additions & 5 deletions packages/experimental-utils/src/ast-utils/predicates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,11 @@ function isLogicalOrOperator(
*/
function isTypeAssertion(
node: TSESTree.Node | undefined | null,
): node is TSESTree.TSAsExpression | TSESTree.TSTypeAssertion {
): node is TSESTree.TSTypeAssertion {
if (!node) {
return false;
}
return (
node.type === AST_NODE_TYPES.TSAsExpression ||
node.type === AST_NODE_TYPES.TSTypeAssertion
);
return node.type === AST_NODE_TYPES.TSTypeAssertion;
}

function isVariableDeclarator(
Expand Down
1 change: 0 additions & 1 deletion packages/experimental-utils/src/ts-eslint/Rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,6 @@ interface RuleListener {
TSAbstractMethodDefinition?: RuleFunction<TSESTree.TSAbstractMethodDefinition>;
TSAnyKeyword?: RuleFunction<TSESTree.TSAnyKeyword>;
TSArrayType?: RuleFunction<TSESTree.TSArrayType>;
TSAsExpression?: RuleFunction<TSESTree.TSAsExpression>;
TSAsyncKeyword?: RuleFunction<TSESTree.TSAsyncKeyword>;
TSBigIntKeyword?: RuleFunction<TSESTree.TSBigIntKeyword>;
TSBooleanKeyword?: RuleFunction<TSESTree.TSBooleanKeyword>;
Expand Down
20 changes: 7 additions & 13 deletions packages/scope-manager/src/referencer/Referencer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,13 +297,6 @@ class Referencer extends Visitor {
TypeVisitor.visit(this, node);
}

protected visitTypeAssertion(
node: TSESTree.TSAsExpression | TSESTree.TSTypeAssertion,
): void {
this.visit(node.expression);
this.visitType(node.typeAnnotation);
}

/////////////////////
// Visit selectors //
/////////////////////
Expand All @@ -317,7 +310,6 @@ class Referencer extends Visitor {
protected AssignmentExpression(node: TSESTree.AssignmentExpression): void {
let left = node.left;
switch (left.type) {
case AST_NODE_TYPES.TSAsExpression:
case AST_NODE_TYPES.TSTypeAssertion:
// explicitly visit the type annotation
this.visit(left.typeAnnotation);
Expand Down Expand Up @@ -603,10 +595,6 @@ class Referencer extends Visitor {
this.visitType(node.typeParameters);
}

protected TSAsExpression(node: TSESTree.TSAsExpression): void {
this.visitTypeAssertion(node);
}

protected TSDeclareFunction(node: TSESTree.TSDeclareFunction): void {
this.visitFunction(node);
}
Expand Down Expand Up @@ -707,7 +695,13 @@ class Referencer extends Visitor {
}

protected TSTypeAssertion(node: TSESTree.TSTypeAssertion): void {
this.visitTypeAssertion(node);
if (node.kind === 'as') {
this.visit(node.expression);
this.visitType(node.typeAnnotation);
} else {
this.visitType(node.typeAnnotation);
this.visit(node.expression);
}
Comment on lines +698 to +704
Copy link
Collaborator Author

@armano2 armano2 Feb 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while doing this change i noticed that order of creating references was not correct

}

protected UpdateExpression(node: TSESTree.UpdateExpression): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ ScopeManager {
resolved: Variable$2,
writeExpr: Literal$2,
},
Reference$2 {
Reference$3 {
identifier: Identifier<"x">,
isRead: true,
isTypeReference: false,
Expand All @@ -44,7 +44,7 @@ ScopeManager {
],
name: "T",
references: Array [
Reference$3 {
Reference$2 {
identifier: Identifier<"T">,
isRead: true,
isTypeReference: true,
Expand Down
1 change: 0 additions & 1 deletion packages/types/src/ast-node-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ enum AST_NODE_TYPES {
TSAbstractMethodDefinition = 'TSAbstractMethodDefinition',
TSAnyKeyword = 'TSAnyKeyword',
TSArrayType = 'TSArrayType',
TSAsExpression = 'TSAsExpression',
TSAsyncKeyword = 'TSAsyncKeyword',
TSBigIntKeyword = 'TSBigIntKeyword',
TSBooleanKeyword = 'TSBooleanKeyword',
Expand Down
14 changes: 4 additions & 10 deletions packages/types/src/ts-estree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ export type Node =
| TSAbstractMethodDefinition
| TSAnyKeyword
| TSArrayType
| TSAsExpression
| TSAsyncKeyword
| TSBigIntKeyword
| TSBooleanKeyword
Expand Down Expand Up @@ -373,7 +372,7 @@ export type Expression =
| RestElement
| SequenceExpression
| SpreadElement
| TSAsExpression
| TSTypeAssertion
| TSUnaryExpression
| YieldExpression;
export type ForInitialiser = Expression | VariableDeclaration;
Expand Down Expand Up @@ -409,7 +408,7 @@ export type LeftHandSideExpression =
| PrimaryExpression
| TaggedTemplateExpression
| TSNonNullExpression
| TSAsExpression
| TSTypeAssertion
| ArrowFunctionExpression;
export type Literal =
| BigIntLiteral
Expand Down Expand Up @@ -1261,7 +1260,7 @@ export interface ThisExpression extends BaseNode {

export interface ThrowStatement extends BaseNode {
type: AST_NODE_TYPES.ThrowStatement;
argument: Statement | TSAsExpression | null;
argument: Statement | TSTypeAssertion | null;
}

export interface TryStatement extends BaseNode {
Expand Down Expand Up @@ -1304,12 +1303,6 @@ export interface TSArrayType extends BaseNode {
elementType: TypeNode;
}

export interface TSAsExpression extends BaseNode {
type: AST_NODE_TYPES.TSAsExpression;
expression: Expression;
typeAnnotation: TypeNode;
}

export interface TSAsyncKeyword extends BaseNode {
type: AST_NODE_TYPES.TSAsyncKeyword;
}
Expand Down Expand Up @@ -1647,6 +1640,7 @@ export interface TSTypeAssertion extends BaseNode {
type: AST_NODE_TYPES.TSTypeAssertion;
typeAnnotation: TypeNode;
expression: Expression;
kind: 'as' | 'angle-bracket';
}

export interface TSTypeLiteral extends BaseNode {
Expand Down
6 changes: 4 additions & 2 deletions packages/typescript-estree/src/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2619,10 +2619,11 @@ export class Converter {
});
}
case SyntaxKind.AsExpression: {
return this.createNode<TSESTree.TSAsExpression>(node, {
type: AST_NODE_TYPES.TSAsExpression,
return this.createNode<TSESTree.TSTypeAssertion>(node, {
type: AST_NODE_TYPES.TSTypeAssertion,
expression: this.convertChild(node.expression),
typeAnnotation: this.convertType(node.type),
kind: 'as',
});
}
case SyntaxKind.InferType: {
Expand Down Expand Up @@ -2656,6 +2657,7 @@ export class Converter {
type: AST_NODE_TYPES.TSTypeAssertion,
typeAnnotation: this.convertType(node.type),
expression: this.convertChild(node.expression),
kind: 'angle-bracket',
});
}
case SyntaxKind.ImportEqualsDeclaration: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ export interface EstreeToTsNodeTypes {
| ts.MethodDeclaration
| ts.ConstructorDeclaration;
[AST_NODE_TYPES.TSArrayType]: ts.ArrayTypeNode;
[AST_NODE_TYPES.TSAsExpression]: ts.AsExpression;
[AST_NODE_TYPES.TSCallSignatureDeclaration]: ts.PropertySignature;
[AST_NODE_TYPES.TSClassImplements]: ts.ExpressionWithTypeArguments;
[AST_NODE_TYPES.TSConditionalType]: ts.ConditionalTypeNode;
Expand Down Expand Up @@ -203,7 +202,7 @@ export interface EstreeToTsNodeTypes {
[AST_NODE_TYPES.TSTemplateLiteralType]: ts.TemplateLiteralTypeNode;
[AST_NODE_TYPES.TSTypeAliasDeclaration]: ts.TypeAliasDeclaration;
[AST_NODE_TYPES.TSTypeAnnotation]: undefined;
[AST_NODE_TYPES.TSTypeAssertion]: ts.TypeAssertion;
[AST_NODE_TYPES.TSTypeAssertion]: ts.TypeAssertion | ts.AsExpression;
[AST_NODE_TYPES.TSTypeLiteral]: ts.TypeLiteralNode;
[AST_NODE_TYPES.TSTypeOperator]: ts.TypeOperatorNode;
[AST_NODE_TYPES.TSTypeParameter]: ts.TypeParameterDeclaration;
Expand Down
Loading