eslint-codemod-utils
Version:
A collection of AST helper functions for more complex ESLint rule fixes.
161 lines (158 loc) • 8.54 kB
JavaScript
import { jsxAttribute, jsxClosingElement, jsxClosingFragment, jsxElement, jsxEmptyExpression, jsxExpressionContainer, jsxFragment, jsxIdentifier, jsxMemberExpression, jsxOpeningElement, jsxOpeningFragment, jsxSpreadAttribute, jsxSpreadChild, jsxText, } from './jsx-nodes';
import { arrayExpression, arrayPattern, arrowFunctionExpression, assignmentExpression, awaitExpression, binaryExpression, blockStatement, breakStatement, callExpression, catchClause, chainExpression, classBody, classDeclaration, classExpression, conditionalExpression, continueStatement, debuggerStatement, decorator, doWhileStatement, emptyStatement, exportAllDeclaration, exportDefaultDeclaration, exportNamedDeclaration, exportSpecifier, expressionStatement, forInStatement, forOfStatement, forStatement, functionDeclaration, functionExpression, identifier, ifStatement, importDeclaration, importDefaultSpecifier, importExpression, importNamespaceSpecifier, importSpecifier, literal, logicalExpression, memberExpression, methodDefinition, newExpression, objectExpression, objectPattern, privateIdentifier, program, property, propertyDefinition, restElement, returnStatement, sequenceExpression, spreadElement, staticBlock, superCallExpression, switchCase, switchStatement, taggedTemplateExpression, templateElement, templateLiteral, thisExpression, throwStatement, tryStatement, unaryExpression, updateExpression, variableDeclaration, variableDeclarator, whileStatement, withStatement, yieldExpression, } from './nodes';
import { tsAbstractKeyword, tsAnyKeyword, tsArrayType, tsAsExpression, tsAsyncKeyword, tsBooleanKeyword, tsConditionalType, tsEmptyBodyFunctionExpression, tsIntersectionType, tsLiteralType, tsNeverKeyword, tsNonNullExpression, tsNullKeyword, tsQualifiedName, tsReadonlyKeyword, tsSatisfiesExpression, tsStringKeyword, tsTypeAliasDeclaration, tsTypeOperator, tsTypeParameter, tsTypeParameterDeclaration, tsTypeParameterInstantiation, tsTypeQuery, tsTypeReference, tsUndefinedKeyword, tsUnionType, tsUnknownKeyword, tsVoidKeyword, } from './ts-nodes';
import { identity } from './utils/identity';
export const DEFAULT_WHITESPACE = '\n ';
// Explicit annotation: the inferred object type for the proxy target is so
// deep (every helper's destructured `Loose<…>` signature is distinct) that
// `tsc --declaration` cannot serialize it into the emitted `.d.ts`. Pinning
// the exported type to the compact `Partial<NodeMap>` shape keeps the public
// declaration portable without weakening the runtime dispatch contract.
export const typeToHelperLookup = new Proxy({
// TODO implement
AssignmentPattern: identity,
AssignmentExpression: assignmentExpression,
AwaitExpression: awaitExpression,
ArrayExpression: arrayExpression,
ArrayPattern: arrayPattern,
BlockStatement: blockStatement,
BinaryExpression: binaryExpression,
ConditionalExpression: conditionalExpression,
ChainExpression: chainExpression,
Decorator: decorator,
JSXFragment: jsxFragment,
JSXSpreadChild: jsxSpreadChild,
JSXExpressionContainer: jsxExpressionContainer,
JSXClosingElement: jsxClosingElement,
JSXOpeningElement: jsxOpeningElement,
JSXOpeningFragment: jsxOpeningFragment,
JSXClosingFragment: jsxClosingFragment,
JSXElement: jsxElement,
JSXText: jsxText,
JSXSpreadAttribute: jsxSpreadAttribute,
JSXAttribute: jsxAttribute,
JSXMemberExpression: jsxMemberExpression,
JSXNamespacedName: identity,
JSXIdentifier: jsxIdentifier,
JSXEmptyExpression: jsxEmptyExpression,
ArrowFunctionExpression: arrowFunctionExpression,
FunctionExpression: functionExpression,
Identifier: identifier,
IfStatement: ifStatement,
// TODO implement
LabeledStatement: identity,
// `literal` is overloaded to accept raw primitives or `WithoutType<Literal>`.
// The dispatch map only ever calls the object-shaped overload, but the
// overload signatures make `satisfies NodeMap` unable to pick a single
// arity. Cast via `unknown` so the map entry satisfies the contract
// without widening the public `literal(…)` signature.
Literal: literal,
LogicalExpression: logicalExpression,
/** this isn't a concrete node type */
ForStatement: forStatement,
ForInStatement: forInStatement,
ForOfStatement: forOfStatement,
ImportSpecifier: importSpecifier,
ImportNamespaceSpecifier: importNamespaceSpecifier,
ImportDefaultSpecifier: importDefaultSpecifier,
ImportDeclaration: importDeclaration,
ImportExpression: importExpression,
ThisExpression: thisExpression,
ThrowStatement: throwStatement,
TemplateLiteral: templateLiteral,
TemplateElement: templateElement,
TaggedTemplateExpression: taggedTemplateExpression,
ObjectExpression: objectExpression,
ObjectPattern: objectPattern,
RestElement: restElement,
MemberExpression: memberExpression,
// TODO: needs implementation
MetaProperty: identity,
MethodDefinition: methodDefinition,
NewExpression: newExpression,
SwitchStatement: switchStatement,
EmptyStatement: emptyStatement,
FunctionDeclaration: functionDeclaration,
CallExpression: callExpression,
CatchClause: catchClause,
ContinueStatement: continueStatement,
ClassDeclaration: classDeclaration,
ClassExpression: classExpression,
ClassBody: classBody,
DebuggerStatement: debuggerStatement,
DoWhileStatement: doWhileStatement,
ExportNamedDeclaration: exportNamedDeclaration,
ExportSpecifier: exportSpecifier,
ExportAllDeclaration: exportAllDeclaration,
ExportDefaultDeclaration: exportDefaultDeclaration,
BreakStatement: breakStatement,
PrivateIdentifier: privateIdentifier,
Property: property,
Program: program,
PropertyDefinition: propertyDefinition,
ReturnStatement: returnStatement,
Super: superCallExpression,
SequenceExpression: sequenceExpression,
SpreadElement: spreadElement,
StaticBlock: staticBlock,
SwitchCase: switchCase,
TryStatement: tryStatement,
WhileStatement: whileStatement,
WithStatement: withStatement,
ExpressionStatement: expressionStatement,
UnaryExpression: unaryExpression,
UpdateExpression: updateExpression,
VariableDeclaration: variableDeclaration,
VariableDeclarator: variableDeclarator,
YieldExpression: yieldExpression,
// typescript
TSArrayType: tsArrayType,
TSAsExpression: tsAsExpression,
TSEmptyBodyFunctionExpression: tsEmptyBodyFunctionExpression,
TSStringKeyword: tsStringKeyword,
TSTypeReference: tsTypeReference,
TSAnyKeyword: tsAnyKeyword,
TSVoidKeyword: tsVoidKeyword,
TSUnknownKeyword: tsUnknownKeyword,
TSBooleanKeyword: tsBooleanKeyword,
TSReadonlyKeyword: tsReadonlyKeyword,
TSNullKeyword: tsNullKeyword,
TSQualifiedName: tsQualifiedName,
TSTypeParameterInstantiation: tsTypeParameterInstantiation,
TSLiteralType: tsLiteralType,
TSNonNullExpression: tsNonNullExpression,
TSIntersectionType: tsIntersectionType,
TSUnionType: tsUnionType,
TSTypeQuery: tsTypeQuery,
TSTypeOperator: tsTypeOperator,
TSTypeAliasDeclaration: tsTypeAliasDeclaration,
TSTypeParameterDeclaration: tsTypeParameterDeclaration,
TSTypeParameter: tsTypeParameter,
TSAbstractKeyword: tsAbstractKeyword,
TSSatisfiesExpression: tsSatisfiesExpression,
TSUndefinedKeyword: tsUndefinedKeyword,
TSConditionalType: tsConditionalType,
TSNeverKeyword: tsNeverKeyword,
TSAsyncKeyword: tsAsyncKeyword,
// `NodeMap` covers every TSESTree node, but this dispatch table is
// incrementally implemented (see the Proxy below — unknown types throw
// an `UnknownNodeError` at runtime). Partial-satisfy so unimplemented
// variants are tolerated at the type level.
}, {
// dynamic getter will fail and provide debug information
get(target, name, receiver) {
if (Reflect.has(target, name)) {
return Reflect.get(target, name, receiver);
}
const nodeName = name.toString();
const error = new Error(`\
type '${nodeName}' missing in typeMap.
This is probably because the type '${nodeName}' is a Typescript or Flow specific node type. These nodes currently have only partial support.
To resolve this you can:
* Use a more constrained parser like esprima in your eslint config
* Lodge a bug at https://github.com/DarkPurple141/eslint-codemod-utils/issues
`);
error.name = 'UnknownNodeError';
throw error;
},
});