diff --git a/packages/typescript-estree/src/convert-guards.ts b/packages/typescript-estree/src/convert-guards.ts new file mode 100644 index 00000000000..36da34ae62a --- /dev/null +++ b/packages/typescript-estree/src/convert-guards.ts @@ -0,0 +1,478 @@ +import { TSESTree } from '@typescript-eslint/types'; +import * as ts from 'typescript'; +import { TSNodeUsed } from './ts-estree/ts-nodes'; + +/** + * this is not correct yet, additional refining is required + */ +export type BaseGuardType< + T extends TSNodeUsed, + KIND = T['kind'] +> = KIND extends ts.SyntaxKind.SourceFile + ? TSESTree.Program + : KIND extends ts.SyntaxKind.Block + ? TSESTree.BlockStatement + : KIND extends ts.SyntaxKind.Identifier + ? TSESTree.Identifier + : KIND extends ts.SyntaxKind.WithStatement + ? TSESTree.WithStatement + : KIND extends ts.SyntaxKind.WithStatement + ? TSESTree.WithStatement + : KIND extends ts.SyntaxKind.ReturnStatement + ? TSESTree.ReturnStatement + : KIND extends ts.SyntaxKind.LabeledStatement + ? TSESTree.LabeledStatement + : KIND extends ts.SyntaxKind.ContinueStatement + ? TSESTree.ContinueStatement + : KIND extends ts.SyntaxKind.BreakStatement + ? TSESTree.BreakStatement + : KIND extends ts.SyntaxKind.IfStatement + ? TSESTree.IfStatement + : KIND extends ts.SyntaxKind.SwitchStatement + ? TSESTree.SwitchStatement + : KIND extends ts.SyntaxKind.CaseClause + ? TSESTree.SwitchCase + : KIND extends ts.SyntaxKind.DefaultClause + ? TSESTree.SwitchCase + : KIND extends ts.SyntaxKind.ThrowStatement + ? TSESTree.ThrowStatement + : KIND extends ts.SyntaxKind.TryStatement + ? TSESTree.TryStatement + : KIND extends ts.SyntaxKind.CatchClause + ? TSESTree.CatchClause + : KIND extends ts.SyntaxKind.WhileStatement + ? TSESTree.WhileStatement + : KIND extends ts.SyntaxKind.DoStatement + ? TSESTree.DoWhileStatement + : KIND extends ts.SyntaxKind.ForStatement + ? TSESTree.ForStatement + : KIND extends ts.SyntaxKind.ForInStatement + ? TSESTree.ForInStatement + : KIND extends ts.SyntaxKind.ForOfStatement + ? TSESTree.ForOfStatement + : KIND extends ts.SyntaxKind.FunctionDeclaration + ? TSESTree.TSDeclareFunction | TSESTree.FunctionDeclaration + : KIND extends ts.SyntaxKind.VariableDeclaration + ? TSESTree.VariableDeclarator + : KIND extends ts.SyntaxKind.VariableStatement + ? TSESTree.VariableDeclaration + : KIND extends ts.SyntaxKind.VariableDeclarationList + ? TSESTree.VariableDeclaration + : KIND extends ts.SyntaxKind.ExpressionStatement + ? TSESTree.ExpressionStatement + : KIND extends ts.SyntaxKind.ThisKeyword + ? TSESTree.ThisExpression + : KIND extends ts.SyntaxKind.PropertyAssignment + ? TSESTree.Property + : KIND extends ts.SyntaxKind.ShorthandPropertyAssignment + ? TSESTree.Property + : KIND extends ts.SyntaxKind.PropertyDeclaration + ? TSESTree.TSAbstractClassProperty | TSESTree.ClassProperty // TODO: skipped node + : // TODO: conditional + KIND extends ts.SyntaxKind.GetAccessor + ? + | TSESTree.TSEmptyBodyFunctionExpression + | TSESTree.TSAbstractMethodDefinition + | TSESTree.MethodDefinition + | TSESTree.FunctionExpression + | TSESTree.Property + : KIND extends ts.SyntaxKind.SetAccessor + ? + | TSESTree.TSEmptyBodyFunctionExpression + | TSESTree.TSAbstractMethodDefinition + | TSESTree.MethodDefinition + | TSESTree.FunctionExpression + | TSESTree.Property + : KIND extends ts.SyntaxKind.MethodDeclaration + ? + | TSESTree.TSEmptyBodyFunctionExpression + | TSESTree.TSAbstractMethodDefinition + | TSESTree.MethodDefinition + | TSESTree.FunctionExpression + | TSESTree.Property + : KIND extends ts.SyntaxKind.Constructor + ? TSESTree.TSAbstractMethodDefinition | TSESTree.MethodDefinition + : KIND extends ts.SyntaxKind.FunctionExpression + ? TSESTree.FunctionExpression + : KIND extends ts.SyntaxKind.SuperKeyword + ? TSESTree.Super + : KIND extends ts.SyntaxKind.ArrayBindingPattern + ? TSESTree.ArrayPattern + : KIND extends ts.SyntaxKind.OmittedExpression + ? null + : KIND extends ts.SyntaxKind.ObjectBindingPattern + ? TSESTree.ObjectPattern + : KIND extends ts.SyntaxKind.ArrowFunction + ? TSESTree.ArrowFunctionExpression + : KIND extends ts.SyntaxKind.YieldExpression + ? TSESTree.YieldExpression + : KIND extends ts.SyntaxKind.AwaitExpression + ? TSESTree.AwaitExpression + : KIND extends + | ts.SyntaxKind.NoSubstitutionTemplateLiteral + | ts.SyntaxKind.TemplateExpression + ? TSESTree.TemplateLiteral + : KIND extends ts.SyntaxKind.TaggedTemplateExpression + ? TSESTree.TaggedTemplateExpression + : KIND extends + | ts.SyntaxKind.TemplateHead + | ts.SyntaxKind.TemplateMiddle + | ts.SyntaxKind.TemplateTail + ? TSESTree.TemplateElement + : KIND extends ts.SyntaxKind.Parameter + ? + | TSESTree.RestElement + | TSESTree.AssignmentPattern + | TSESTree.BindingName + | TSESTree.TSParameterProperty + : KIND extends ts.SyntaxKind.ClassDeclaration + ? TSESTree.ClassDeclaration + : KIND extends ts.SyntaxKind.ClassExpression + ? TSESTree.ClassExpression + : KIND extends ts.SyntaxKind.ModuleBlock + ? TSESTree.TSModuleBlock + : KIND extends ts.SyntaxKind.ImportDeclaration + ? TSESTree.ImportDeclaration + : KIND extends ts.SyntaxKind.NamespaceImport + ? TSESTree.ImportNamespaceSpecifier + : KIND extends ts.SyntaxKind.ImportSpecifier + ? TSESTree.ImportSpecifier + : KIND extends ts.SyntaxKind.ImportClause + ? TSESTree.ImportDefaultSpecifier + : KIND extends ts.SyntaxKind.ExportDeclaration + ? TSESTree.ExportNamedDeclaration | TSESTree.ExportAllDeclaration + : KIND extends ts.SyntaxKind.ExportSpecifier + ? TSESTree.ExportSpecifier + : KIND extends ts.SyntaxKind.ExportAssignment + ? TSESTree.TSExportAssignment | TSESTree.ExportDefaultDeclaration + : KIND extends + | ts.SyntaxKind.PrefixUnaryExpression + | ts.SyntaxKind.PostfixUnaryExpression + ? TSESTree.UpdateExpression | TSESTree.UnaryExpression + : KIND extends + | ts.SyntaxKind.DeleteExpression + | ts.SyntaxKind.VoidExpression + | ts.SyntaxKind.TypeOfExpression + ? TSESTree.UnaryExpression + : KIND extends ts.SyntaxKind.TypeOperator + ? TSESTree.TSTypeOperator + : KIND extends + | ts.SyntaxKind.PropertyAccessExpression + | ts.SyntaxKind.ElementAccessExpression + ? TSESTree.MemberExpression | TSESTree.ChainExpression + : KIND extends ts.SyntaxKind.CallExpression + ? + | TSESTree.ImportExpression + | TSESTree.CallExpression + | TSESTree.ChainExpression + : KIND extends ts.SyntaxKind.NewExpression + ? TSESTree.NewExpression + : KIND extends ts.SyntaxKind.ConditionalExpression + ? TSESTree.ConditionalExpression + : KIND extends ts.SyntaxKind.MetaProperty + ? TSESTree.MetaProperty + : KIND extends ts.SyntaxKind.Decorator + ? TSESTree.Decorator + : KIND extends ts.SyntaxKind.StringLiteral + ? TSESTree.StringLiteral + : KIND extends ts.SyntaxKind.NumericLiteral + ? TSESTree.NumberLiteral + : KIND extends ts.SyntaxKind.BigIntLiteral + ? TSESTree.BigIntLiteral + : KIND extends ts.SyntaxKind.RegularExpressionLiteral + ? TSESTree.RegExpLiteral + : KIND extends ts.SyntaxKind.TrueKeyword + ? TSESTree.BooleanLiteral + : KIND extends ts.SyntaxKind.FalseKeyword + ? TSESTree.BooleanLiteral + : KIND extends ts.SyntaxKind.NullKeyword + ? TSESTree.NullLiteral + : KIND extends ts.SyntaxKind.EmptyStatement + ? TSESTree.EmptyStatement + : KIND extends ts.SyntaxKind.DebuggerStatement + ? TSESTree.DebuggerStatement + : KIND extends ts.SyntaxKind.JsxFragment + ? TSESTree.JSXFragment + : KIND extends ts.SyntaxKind.JsxElement | ts.SyntaxKind.JsxSelfClosingElement + ? TSESTree.JSXElement + : KIND extends ts.SyntaxKind.JsxOpeningElement + ? TSESTree.JSXOpeningElement + : KIND extends ts.SyntaxKind.JsxClosingElement + ? TSESTree.JSXClosingElement + : KIND extends ts.SyntaxKind.JsxOpeningFragment + ? TSESTree.JSXOpeningFragment + : KIND extends ts.SyntaxKind.JsxClosingFragment + ? TSESTree.JSXClosingFragment + : KIND extends ts.SyntaxKind.JsxExpression + ? TSESTree.JSXSpreadChild | TSESTree.JSXExpressionContainer + : KIND extends ts.SyntaxKind.JsxAttribute + ? TSESTree.JSXAttribute + : KIND extends ts.SyntaxKind.JsxText + ? TSESTree.JSXText + : KIND extends ts.SyntaxKind.JsxSpreadAttribute + ? TSESTree.JSXSpreadAttribute + : KIND extends ts.SyntaxKind.QualifiedName + ? TSESTree.TSQualifiedName + : KIND extends ts.SyntaxKind.TypeReference + ? TSESTree.TSTypeReference + : KIND extends ts.SyntaxKind.TypeParameter + ? TSESTree.TSTypeParameter + : KIND extends ts.SyntaxKind.ThisType + ? TSESTree.TSThisType + : KIND extends ts.SyntaxKind.AbstractKeyword + ? TSESTree.TSAbstractKeyword + : KIND extends ts.SyntaxKind.AnyKeyword + ? TSESTree.TSAnyKeyword + : KIND extends ts.SyntaxKind.BigIntKeyword + ? TSESTree.TSBigIntKeyword + : KIND extends ts.SyntaxKind.BooleanKeyword + ? TSESTree.TSBooleanKeyword + : KIND extends ts.SyntaxKind.NeverKeyword + ? TSESTree.TSNeverKeyword + : KIND extends ts.SyntaxKind.NumberKeyword + ? TSESTree.TSNumberKeyword + : KIND extends ts.SyntaxKind.ObjectKeyword + ? TSESTree.TSObjectKeyword + : KIND extends ts.SyntaxKind.StringKeyword + ? TSESTree.TSStringKeyword + : KIND extends ts.SyntaxKind.SymbolKeyword + ? TSESTree.TSSymbolKeyword + : KIND extends ts.SyntaxKind.UnknownKeyword + ? TSESTree.TSUnknownKeyword + : KIND extends ts.SyntaxKind.VoidKeyword + ? TSESTree.TSVoidKeyword + : KIND extends ts.SyntaxKind.UndefinedKeyword + ? TSESTree.TSUndefinedKeyword + : KIND extends ts.SyntaxKind.NonNullExpression + ? TSESTree.TSNonNullExpression | TSESTree.ChainExpression + : KIND extends ts.SyntaxKind.TypeLiteral + ? TSESTree.TSTypeLiteral + : KIND extends ts.SyntaxKind.ArrayType + ? TSESTree.TSArrayType + : KIND extends ts.SyntaxKind.IndexedAccessType + ? TSESTree.TSIndexedAccessType + : KIND extends ts.SyntaxKind.ConditionalType + ? TSESTree.TSConditionalType + : KIND extends ts.SyntaxKind.TypeQuery + ? TSESTree.TSTypeQuery + : KIND extends ts.SyntaxKind.MappedType + ? TSESTree.TSMappedType + : KIND extends ts.SyntaxKind.TypeAliasDeclaration // TODO: exports + ? TSESTree.TSTypeAliasDeclaration + : KIND extends ts.SyntaxKind.MethodSignature + ? TSESTree.TSMethodSignature + : KIND extends ts.SyntaxKind.PropertySignature + ? TSESTree.TSPropertySignature + : KIND extends ts.SyntaxKind.IndexSignature + ? TSESTree.TSIndexSignature + : KIND extends ts.SyntaxKind.ConstructorType + ? TSESTree.TSConstructorType + : KIND extends ts.SyntaxKind.FunctionType + ? TSESTree.TSFunctionType + : KIND extends ts.SyntaxKind.ConstructSignature + ? TSESTree.TSConstructSignatureDeclaration + : KIND extends ts.SyntaxKind.CallSignature + ? TSESTree.TSCallSignatureDeclaration + : KIND extends ts.SyntaxKind.ExpressionWithTypeArguments + ? TSESTree.TSInterfaceHeritage | TSESTree.TSClassImplements + : KIND extends ts.SyntaxKind.InterfaceDeclaration // TODO: exports + ? TSESTree.TSInterfaceDeclaration + : KIND extends ts.SyntaxKind.TypePredicate + ? TSESTree.TSTypePredicate + : KIND extends ts.SyntaxKind.ImportType + ? TSESTree.TSImportType + : KIND extends ts.SyntaxKind.EnumDeclaration + ? TSESTree.TSEnumDeclaration + : KIND extends ts.SyntaxKind.EnumMember + ? TSESTree.TSEnumMember + : KIND extends ts.SyntaxKind.ModuleDeclaration + ? TSESTree.TSModuleDeclaration + : KIND extends ts.SyntaxKind.ParenthesizedType + ? TSESTree.TSParenthesizedType + : KIND extends ts.SyntaxKind.UnionType + ? TSESTree.TSUnionType + : KIND extends ts.SyntaxKind.IntersectionType + ? TSESTree.TSIntersectionType + : KIND extends ts.SyntaxKind.AsExpression + ? TSESTree.TSAsExpression + : KIND extends ts.SyntaxKind.InferType + ? TSESTree.TSInferType + : KIND extends ts.SyntaxKind.LiteralType + ? TSESTree.TSLiteralType | TSESTree.TSNullKeyword + : KIND extends ts.SyntaxKind.TypeAssertionExpression + ? TSESTree.TSTypeAssertion + : KIND extends ts.SyntaxKind.ImportEqualsDeclaration + ? TSESTree.TSImportEqualsDeclaration + : KIND extends ts.SyntaxKind.ExternalModuleReference + ? TSESTree.TSExternalModuleReference + : KIND extends ts.SyntaxKind.NamespaceExportDeclaration + ? TSESTree.TSNamespaceExportDeclaration + : KIND extends ts.SyntaxKind.AbstractKeyword + ? TSESTree.TSAbstractKeyword + : KIND extends ts.SyntaxKind.TupleType + ? TSESTree.TSTupleType + : KIND extends ts.SyntaxKind.NamedTupleMember + ? TSESTree.TSNamedTupleMember | TSESTree.TSRestType + : KIND extends ts.SyntaxKind.OptionalType + ? TSESTree.TSOptionalType + : KIND extends ts.SyntaxKind.RestType + ? TSESTree.TSRestType + : KIND extends ts.SyntaxKind.TemplateLiteralType + ? TSESTree.TSTemplateLiteralType + : KIND extends ts.SyntaxKind.IntrinsicKeyword + ? TSESTree.TSIntrinsicKeyword + : KIND extends ts.SyntaxKind.BindingElement + ? + | TSESTree.AssignmentPattern // This is possible only when parent is ArrayPattern... + | TSESTree.RestElement + | TSESTree.Property + : KIND extends ts.SyntaxKind.ReadonlyKeyword // we should delete those + ? TSESTree.TSReadonlyKeyword + : KIND extends ts.SyntaxKind.ExportKeyword + ? TSESTree.TSExportKeyword + : KIND extends ts.SyntaxKind.PrivateKeyword + ? TSESTree.TSPrivateKeyword + : KIND extends ts.SyntaxKind.ProtectedKeyword + ? TSESTree.TSProtectedKeyword + : KIND extends ts.SyntaxKind.PublicKeyword + ? TSESTree.TSPublicKeyword + : KIND extends ts.SyntaxKind.StaticKeyword + ? TSESTree.TSStaticKeyword + : KIND extends ts.SyntaxKind.AsyncKeyword + ? TSESTree.TSAsyncKeyword + : KIND extends ts.SyntaxKind.DeclareKeyword + ? TSESTree.TSDeclareKeyword + : never; + +export type NonPatternGuard< + T extends TSNodeUsed, + KIND = T['kind'] +> = KIND extends ts.SyntaxKind.ArrayLiteralExpression + ? TSESTree.ArrayExpression + : KIND extends ts.SyntaxKind.BinaryExpression + ? + | TSESTree.SequenceExpression + | TSESTree.AssignmentExpression + | TSESTree.LogicalExpression + | TSESTree.BinaryExpression + : KIND extends ts.SyntaxKind.SpreadAssignment + ? TSESTree.SpreadElement + : KIND extends ts.SyntaxKind.SpreadElement + ? TSESTree.SpreadElement + : KIND extends ts.SyntaxKind.ObjectLiteralExpression + ? TSESTree.ObjectExpression + : never; + +export type PatternGuard< + T extends TSNodeUsed, + KIND = T['kind'] +> = KIND extends ts.SyntaxKind.ArrayLiteralExpression + ? TSESTree.ArrayPattern + : KIND extends ts.SyntaxKind.BinaryExpression + ? TSESTree.SequenceExpression | TSESTree.AssignmentPattern + : KIND extends ts.SyntaxKind.SpreadAssignment + ? TSESTree.RestElement + : KIND extends ts.SyntaxKind.SpreadElement + ? TSESTree.RestElement + : KIND extends ts.SyntaxKind.ObjectLiteralExpression + ? TSESTree.ObjectPattern + : never; + +// This is really slow - https://github.com/microsoft/TypeScript/pull/42556 +// export type TSNodeBaseGuard = TSNodeUsed & { kind: keyof BaseGuard }; +export type TSNodeBaseGuard = Exclude< + TSNodeUsed, + | TSNodePattern + // manual fixes + | ts.ParenthesizedExpression + | ts.ComputedPropertyName + | ts.Token // this node can be generated only in call expression + | ts.ExpressionWithTypeArguments + | ts.HeritageClause + | ts.CaseBlock + | ts.NamedImports + | ts.TemplateSpan + | ts.NamedExports +>; + +// This is really slow - https://github.com/microsoft/TypeScript/pull/42556 +// export type TSNodePattern = TSNodeUsed & { +// kind: keyof PatternGuard | keyof NonPatternGuard; +// }; +export type TSNodePattern = + | ts.ArrayLiteralExpression + | ts.BinaryExpression + | ts.SpreadAssignment + | ts.SpreadElement + | ts.ObjectLiteralExpression; + +export type TSNodeSupported = TSNodePattern | TSNodeBaseGuard; + +// ---------------- + +export type TSNodeConvertable = + | TSNodeUsed + | ts.Expression + | ts.Statement + | ts.TypeNode + | ts.TypeElement + | ts.ClassElement + | undefined; + +export type TSNodeBaseGuardKind = TSNodeBaseGuard['kind']; +export type TSNodePatternKind = TSNodePattern['kind']; + +export type TSESTreeToTSNodeGuardHelper< + T, + P extends true | false +> = T extends TSNodeBaseGuard + ? BaseGuardType + : T extends TSNodePattern + ? P extends true + ? PatternGuard + : NonPatternGuard + : never; + +export type TSESTreeToTSNodeGuard = T extends + | ts.ParenthesizedExpression + | ts.ComputedPropertyName + ? TSESTreeToTSNodeGuardHelper + : T extends TSNodeBaseGuard + ? TSESTreeToTSNodeGuardHelper + : T extends + | ts.Statement + | ts.Declaration + | ts.Expression + | ts.TypeElement + | ts.TypeNode + ? any // TSESTreeToTSNodeGuardHelper, P> + : null; + +export type x = TSESTreeToTSNodeGuard; + +/*export type TSESTreeToTSNodeGuard< + T extends TSNodeConvertable, + P extends boolean +> = any;*/ + +/* +export type TSESTreeToTSNodeGuard< + T extends TSNodeConvertable, + P extends true | false +> = T extends ts.ParenthesizedExpression | ts.ComputedPropertyName + ? TSESTreeToTSNodeGuardHelper + : T extends TSNodeSupported + ? TSESTreeToTSNodeGuardHelper + : T extends ts.Statement | ts.Declaration | ts.Expression | ts.TypeElement + ? TSESTreeToTSNodeGuardHelper, P> + : null; +*/ +// export type TypeTest = Exclude; + +// export type TypeTest2 = Exclude; + +// Expressions - this is needed for optimization +// export type TSNodeExpression = Extract; +// export type TypeTest3 = TSESTreeToTSNodeGuardHelper; + +// export type TypeTest4 = Exclude; diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index 762df318e6d..d61883ade1c 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -29,7 +29,10 @@ import { TSESTree, TSESTreeToTSNode, TSNode, + TSNodeUsed, } from './ts-estree'; +import { TSESTreeToTSNodeGuard, TSNodeConvertable } from './convert-guards'; + import { typescriptVersionIsAtLeast } from './version-check'; const SyntaxKind = ts.SyntaxKind; @@ -86,7 +89,7 @@ export class Converter { } convertProgram(): TSESTree.Program { - return this.converter(this.ast) as TSESTree.Program; + return this.converter(this.ast); } /** @@ -97,12 +100,18 @@ export class Converter { * @param allowPattern flag to determine if patterns are allowed * @returns the converted ESTree node */ + private converter( + node: T, + parent?: ts.Node, + inTypeMode?: boolean, + allowPattern?: P, + ): TSESTreeToTSNodeGuard; private converter( - node?: ts.Node, + node: TSNodeConvertable, parent?: ts.Node, inTypeMode?: boolean, allowPattern?: boolean, - ): any { + ): TSESTree.Node | null { /** * Exit early for null and undefined */ @@ -119,10 +128,7 @@ export class Converter { this.allowPattern = allowPattern; } - const result = this.convertNode( - node as TSNode, - (parent ?? node.parent) as TSNode, - ); + const result = this.convertNode(node as TSNodeUsed, parent ?? node.parent); this.registerTSNodeInNodeMap(node, result); @@ -214,8 +220,11 @@ export class Converter { * @param parent parentNode * @returns the converted ESTree node */ - private convertPattern(child?: ts.Node, parent?: ts.Node): any | null { - return this.converter(child, parent, this.inTypeMode, true); + private convertPattern( + child: T, + parent?: ts.Node, + ): TSESTreeToTSNodeGuard { + return this.converter(child, parent, this.inTypeMode, true) as any; } /** @@ -224,8 +233,11 @@ export class Converter { * @param parent parentNode * @returns the converted ESTree node */ - private convertChild(child?: ts.Node, parent?: ts.Node): any | null { - return this.converter(child, parent, this.inTypeMode, false); + private convertChild( + child: T, + parent?: ts.Node, + ): TSESTreeToTSNodeGuard { + return this.converter(child, parent, this.inTypeMode, false) as any; } /** @@ -234,21 +246,24 @@ export class Converter { * @param parent parentNode * @returns the converted ESTree node */ - private convertType(child?: ts.Node, parent?: ts.Node): any | null { - return this.converter(child, parent, true, false); + private convertType( + child: T, + parent?: ts.Node, + ): TSESTreeToTSNodeGuard { + return this.converter(child, parent, true, false) as any; } - private createNode( + private createNode( node: TSESTreeToTSNode, data: TSESTree.OptionalRangeAndLoc, - ): T { + ): T; + private createNode( + node: TSNodeUsed, + data: TSESTree.OptionalRangeAndLoc, + ): TSESTree.Node { const result = data; if (!result.range) { - result.range = getRange( - // this is completely valid, but TS hates it - node as never, - this.ast, - ); + result.range = getRange(node, this.ast); } if (!result.loc) { result.loc = getLocFor(result.range[0], result.range[1], this.ast); @@ -257,7 +272,7 @@ export class Converter { if (result && this.options.shouldPreserveNodeMaps) { this.esTreeNodeToTSNodeMap.set(result, node); } - return result as T; + return result as TSESTree.Node; } private convertBindingNameWithTypeAnnotation( @@ -335,7 +350,9 @@ export class Converter { return child; // child can be null, but it's filtered below }) // filter out unknown nodes for now - .filter(statement => statement) + .filter((statement): statement is TSESTree.Statement => + Boolean(statement), + ) ); } @@ -390,7 +407,7 @@ export class Converter { return []; } return parameters.map(param => { - const convertedParam = this.convertChild(param) as TSESTree.Parameter; + const convertedParam = this.convertChild(param); if (param.decorators?.length) { convertedParam.decorators = param.decorators.map(el => @@ -469,7 +486,7 @@ export class Converter { throw new Error(`Unknown AST_NODE_TYPE: "${customType}"`); } - const result = this.createNode(node, { + const result = this.createNode(node as any, { type: customType, }); @@ -523,6 +540,14 @@ export class Converter { * @param parent * @returns the converted ESTree name object */ + private convertJSXTagName( + node: T, + parent: ts.Node, + ): T extends ts.JsxTagNamePropertyAccess + ? TSESTree.JSXMemberExpression + : T extends ts.ThisExpression | ts.Identifier + ? TSESTree.JSXIdentifier + : TSESTree.JSXMemberExpression | TSESTree.JSXIdentifier; private convertJSXTagName( node: ts.JsxTagNameExpression, parent: ts.Node, @@ -539,10 +564,7 @@ export class Converter { result = this.createNode(node, { type: AST_NODE_TYPES.JSXMemberExpression, object: this.convertJSXTagName(node.expression, parent), - property: this.convertJSXTagName( - node.name, - parent, - ) as TSESTree.JSXIdentifier, + property: this.convertJSXTagName(node.name, parent), }); break; @@ -608,6 +630,7 @@ export class Converter { break; } } + /** * If there are still valid modifiers available which have * not been explicitly handled above, we just convert and @@ -645,7 +668,10 @@ export class Converter { * @param parent parentNode * @returns the converted ESTree node */ - private convertNode(node: TSNode, parent: TSNode): TSESTree.Node | null { + private convertNode( + node: TSNodeUsed, + parent: TSNode | ts.Node, + ): TSESTree.Node | null { switch (node.kind) { case SyntaxKind.SourceFile: { return this.createNode(node, { @@ -827,7 +853,7 @@ export class Converter { expression: false, async: hasModifier(SyntaxKind.AsyncKeyword, node), params: this.convertParameters(node.parameters), - body: this.convertChild(node.body) || undefined, + body: this.convertChild(node.body) ?? undefined, }); // Process returnType @@ -1431,7 +1457,10 @@ export class Converter { case SyntaxKind.Parameter: { let parameter: TSESTree.RestElement | TSESTree.BindingName; - let result: TSESTree.RestElement | TSESTree.AssignmentPattern; + let result: + | TSESTree.RestElement + | TSESTree.AssignmentPattern + | TSESTree.BindingName; if (node.dotDotDotToken) { parameter = result = this.createNode(node, { @@ -1439,7 +1468,7 @@ export class Converter { argument: this.convertChild(node.name), }); } else if (node.initializer) { - parameter = this.convertChild(node.name) as TSESTree.BindingName; + parameter = this.convertChild(node.name); result = this.createNode(node, { type: AST_NODE_TYPES.AssignmentPattern, left: parameter, @@ -2113,7 +2142,9 @@ export class Converter { } case SyntaxKind.JsxAttribute: { - const attributeName = this.convertChild(node.name); + const attributeName = (this.convertChild( + node.name, + ) as unknown) as TSESTree.JSXIdentifier; attributeName.type = AST_NODE_TYPES.JSXIdentifier; return this.createNode(node, { @@ -2196,6 +2227,7 @@ export class Converter { type: AST_NODE_TYPES.TSThisType, }); + case SyntaxKind.AbstractKeyword: case SyntaxKind.AnyKeyword: case SyntaxKind.BigIntKeyword: case SyntaxKind.BooleanKeyword: @@ -2365,7 +2397,7 @@ export class Converter { typeAnnotation: node.type ? this.convertTypeAnnotation(node.type, node) : undefined, - initializer: this.convertChild(node.initializer) || undefined, + initializer: this.convertChild(node.initializer) ?? undefined, readonly: hasModifier(SyntaxKind.ReadonlyKeyword, node) || undefined, static: hasModifier(SyntaxKind.StaticKeyword, node) || undefined, export: hasModifier(SyntaxKind.ExportKeyword, node) || undefined, @@ -2588,7 +2620,10 @@ export class Converter { id: this.convertChild(node.name), }); if (node.body) { - result.body = this.convertChild(node.body); + // type is not correct as is include JSDoc + result.body = this.convertChild( + node.body as Exclude, + )!; } // apply modifiers first... this.applyModifiersToResult(result, node.modifiers); @@ -2678,11 +2713,6 @@ export class Converter { id: this.convertChild(node.name), }); } - case SyntaxKind.AbstractKeyword: { - return this.createNode(node, { - type: AST_NODE_TYPES.TSAbstractKeyword, - }); - } // Tuple case SyntaxKind.TupleType: { @@ -2691,10 +2721,10 @@ export class Converter { // if the former does not exist. const elementTypes = 'elementTypes' in node - ? (node as any).elementTypes.map((el: ts.Node) => + ? (node as any).elementTypes.map((el: ts.TypeElement) => this.convertType(el), ) - : node.elements.map((el: ts.Node) => this.convertType(el)); + : node.elements.map(el => this.convertType(el)); return this.createNode(node, { type: AST_NODE_TYPES.TSTupleType, diff --git a/packages/typescript-estree/src/ts-estree/estree-to-ts-node-types.ts b/packages/typescript-estree/src/ts-estree/estree-to-ts-node-types.ts index 2eebfc93b12..480a0b3cddf 100644 --- a/packages/typescript-estree/src/ts-estree/estree-to-ts-node-types.ts +++ b/packages/typescript-estree/src/ts-estree/estree-to-ts-node-types.ts @@ -1,6 +1,6 @@ import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/types'; import * as ts from 'typescript'; -import { TSNode } from './ts-nodes'; +import { TSNodeUsed } from './ts-nodes'; export interface EstreeToTsNodeTypes { [AST_NODE_TYPES.ArrayExpression]: ts.ArrayLiteralExpression; @@ -280,7 +280,7 @@ export interface EstreeToTsNodeTypes { * This mapping is based on the internal logic of the parser. */ export type TSESTreeToTSNode = Extract< - TSNode | ts.Token, + TSNodeUsed | ts.Token, // if this errors, it means that one of the AST_NODE_TYPES is not defined in the above interface EstreeToTsNodeTypes[T['type']] >; diff --git a/packages/typescript-estree/src/ts-estree/ts-nodes.ts b/packages/typescript-estree/src/ts-estree/ts-nodes.ts index 80a7b34e0c8..c984be251a0 100644 --- a/packages/typescript-estree/src/ts-estree/ts-nodes.ts +++ b/packages/typescript-estree/src/ts-estree/ts-nodes.ts @@ -11,14 +11,66 @@ declare module 'typescript' { export type TSToken = ts.Token; -export type TSNode = - | ts.Modifier +export type TSNodeUnused = + // Those nodes can't be generated + | ts.PartiallyEmittedExpression + | ts.SyntheticExpression + | ts.NotEmittedStatement + | ts.CommaListExpression + | ts.MissingDeclaration + | ts.Bundle + | ts.InputFiles + | ts.UnparsedNode + | ts.UnparsedSource + | ts.SemicolonClassElement // A list of comma-separated expressions. This node is only created by transformations. + + // Modifiers + | ts.ConstKeyword + | ts.DefaultKeyword + + // Type Unions + // | ts.SignatureDeclarationBase -> CallSignatureDeclaration, ConstructSignatureDeclaration + // | ts.FunctionOrConstructorTypeNodeBase -> FunctionTypeNode, ConstructorTypeNode + // | ts.ClassLikeDeclarationBase -> ClassDeclaration | ClassExpression + + // JSON: Unsupported + // | ts.JsonMinusNumericLiteral // same node as PrefixUnaryExpression + + // JSDoc: Unsupported + | ts.JSDoc + | ts.JSDocTypeExpression + | ts.JSDocNameReference + | ts.JSDocNamespaceDeclaration + | ts.JSDocUnknownTag + | ts.JSDocAugmentsTag + | ts.JSDocClassTag + | ts.JSDocEnumTag + | ts.JSDocThisTag + | ts.JSDocTemplateTag + | ts.JSDocReturnTag + | ts.JSDocTypeTag + | ts.JSDocTypedefTag + | ts.JSDocCallbackTag + | ts.JSDocSignature + | ts.JSDocPropertyTag + | ts.JSDocParameterTag + | ts.JSDocTypeLiteral + | ts.JSDocFunctionType + | ts.JSDocAllType + | ts.JSDocUnknownType + | ts.JSDocNullableType + | ts.JSDocNonNullableType + | ts.JSDocOptionalType + | ts.JSDocVariadicType + | ts.JSDocAuthorTag; + +export type TSNodeUsed = + | Exclude | ts.Identifier | ts.QualifiedName | ts.ComputedPropertyName | ts.Decorator | ts.TypeParameterDeclaration - // | ts.SignatureDeclarationBase -> CallSignatureDeclaration, ConstructSignatureDeclaration | ts.CallSignatureDeclaration | ts.ConstructSignatureDeclaration | ts.VariableDeclaration @@ -36,14 +88,12 @@ export type TSNode = | ts.MethodSignature | ts.MethodDeclaration | ts.ConstructorDeclaration - | ts.SemicolonClassElement | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration | ts.IndexSignatureDeclaration | ts.KeywordTypeNode // TODO: This node is bad, maybe we should report this | ts.ImportTypeNode | ts.ThisTypeNode - // | ts.FunctionOrConstructorTypeNodeBase -> FunctionTypeNode, ConstructorTypeNode | ts.ConstructorTypeNode | ts.FunctionTypeNode | ts.TypeReferenceNode @@ -66,7 +116,6 @@ export type TSNode = | ts.LiteralTypeNode | ts.StringLiteral | ts.OmittedExpression - | ts.PartiallyEmittedExpression | ts.PrefixUnaryExpression | ts.PostfixUnaryExpression | ts.NullLiteral @@ -79,7 +128,6 @@ export type TSNode = | ts.VoidExpression | ts.AwaitExpression | ts.YieldExpression - | ts.SyntheticExpression | ts.BinaryExpression | ts.ConditionalExpression | ts.FunctionExpression @@ -118,11 +166,8 @@ export type TSNode = | ts.JsxClosingElement | ts.JsxExpression | ts.JsxText - | ts.NotEmittedStatement - | ts.CommaListExpression | ts.EmptyStatement | ts.DebuggerStatement - | ts.MissingDeclaration | ts.Block | ts.VariableStatement | ts.ExpressionStatement @@ -144,7 +189,6 @@ export type TSNode = | ts.ThrowStatement | ts.TryStatement | ts.CatchClause - // | ts.ClassLikeDeclarationBase -> ClassDeclaration | ClassExpression | ts.ClassDeclaration | ts.ClassExpression | ts.InterfaceDeclaration @@ -167,34 +211,9 @@ export type TSNode = | ts.ExportSpecifier | ts.ExportAssignment | ts.SourceFile - | ts.Bundle - | ts.InputFiles - | ts.UnparsedSource - | ts.JsonMinusNumericLiteral - | ts.TemplateLiteralTypeNode + | ts.TemplateLiteralTypeNode; - // JSDoc: Unsupported - | ts.JSDoc - | ts.JSDocTypeExpression - | ts.JSDocUnknownTag - | ts.JSDocAugmentsTag - | ts.JSDocClassTag - | ts.JSDocEnumTag - | ts.JSDocThisTag - | ts.JSDocTemplateTag - | ts.JSDocReturnTag - | ts.JSDocTypeTag - | ts.JSDocTypedefTag - | ts.JSDocCallbackTag - | ts.JSDocSignature - | ts.JSDocPropertyTag - | ts.JSDocParameterTag - | ts.JSDocTypeLiteral - | ts.JSDocFunctionType - | ts.JSDocAllType - | ts.JSDocUnknownType - | ts.JSDocNullableType - | ts.JSDocNonNullableType - | ts.JSDocOptionalType - | ts.JSDocVariadicType - | ts.JSDocAuthorTag; +export type TSNode = TSNodeUnused | TSNodeUsed; + +// type _Test = Extract +// type _Test2 = Exclude