@venizia/dev-configs 0.4.8-2 → 0.4.8-4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +4 -3
  2. package/dist/cli/codemod/async-style.d.ts +2 -2
  3. package/dist/cli/codemod/async-style.js +4 -2
  4. package/dist/cli/codemod/async-style.js.map +1 -1
  5. package/dist/cli/codemod/namespace-functions/rewriter.js +1 -1
  6. package/dist/cli/codemod/namespace-functions/rewriter.js.map +1 -1
  7. package/dist/linters/eslint.js +6 -1
  8. package/dist/linters/eslint.js.map +1 -1
  9. package/dist/linters/house/async-rules.d.ts +1 -1
  10. package/dist/linters/house/async-rules.js +3 -1
  11. package/dist/linters/house/async-rules.js.map +1 -1
  12. package/dist/linters/house/await-support.js +45 -38
  13. package/dist/linters/house/await-support.js.map +1 -1
  14. package/dist/linters/house/common.d.ts +43 -0
  15. package/dist/linters/house/common.js +43 -0
  16. package/dist/linters/house/common.js.map +1 -1
  17. package/dist/linters/house/const-class-values.rule.js +9 -8
  18. package/dist/linters/house/const-class-values.rule.js.map +1 -1
  19. package/dist/linters/house/hook-support.js +11 -7
  20. package/dist/linters/house/hook-support.js.map +1 -1
  21. package/dist/linters/house/index.d.ts +1 -0
  22. package/dist/linters/house/index.js +1 -0
  23. package/dist/linters/house/index.js.map +1 -1
  24. package/dist/linters/house/max-params-own.rule.js +12 -11
  25. package/dist/linters/house/max-params-own.rule.js.map +1 -1
  26. package/dist/linters/house/no-await-new-chain.rule.d.ts +37 -0
  27. package/dist/linters/house/no-await-new-chain.rule.js +179 -0
  28. package/dist/linters/house/no-await-new-chain.rule.js.map +1 -0
  29. package/dist/linters/house/no-await-promise-chain.rule.js +23 -22
  30. package/dist/linters/house/no-await-promise-chain.rule.js.map +1 -1
  31. package/dist/linters/house/no-inline-await.rule.js +4 -3
  32. package/dist/linters/house/no-inline-await.rule.js.map +1 -1
  33. package/dist/linters/house/no-leaked-render.rule.js +3 -3
  34. package/dist/linters/house/no-leaked-render.rule.js.map +1 -1
  35. package/dist/linters/house/no-new-error.rule.js +1 -1
  36. package/dist/linters/house/no-new-error.rule.js.map +1 -1
  37. package/dist/linters/house/no-return-await.rule.js +5 -4
  38. package/dist/linters/house/no-return-await.rule.js.map +1 -1
  39. package/dist/linters/house/no-silent-catch.rule.js +4 -3
  40. package/dist/linters/house/no-silent-catch.rule.js.map +1 -1
  41. package/dist/linters/house/plugin.js +2 -0
  42. package/dist/linters/house/plugin.js.map +1 -1
  43. package/dist/linters/house/promise-chain-support.js +25 -25
  44. package/dist/linters/house/promise-chain-support.js.map +1 -1
  45. package/dist/linters/oxlint.d.ts +6 -5
  46. package/dist/linters/oxlint.js +8 -3
  47. package/dist/linters/oxlint.js.map +1 -1
  48. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"no-await-promise-chain.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-await-promise-chain.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule, Scope, SourceCode } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport, STATEMENT_LISTS } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { PromiseChainSupport } from './promise-chain-support';\n\n/** The catch variable the fix writes when the handler has no parameter. */\nconst CATCH_NAME = 'error';\n\n/** What the fix needs, read once from a `const x = await f().catch(h)` that passed every check. */\ninterface IFixPlan {\n declaration: Rule.Node;\n kind: string;\n name: string;\n annotation: string;\n receiverText: string;\n catchName: string;\n isErrorRead: boolean;\n valueText: string;\n}\n\n/** The identifiers a fallback value reads, and whether every node of it is a value the fix may move. */\nconst collectValue = (opts: {\n node: unknown;\n parameter: string | undefined;\n identifiers: unknown[];\n}): boolean => {\n const { node, parameter, identifiers } = opts;\n const type = AstNode.getType({ node }) ?? '';\n const value = (child: unknown) => collectValue({ node: child, parameter, identifiers });\n\n switch (type) {\n case 'Literal': {\n return true;\n }\n case 'Identifier': {\n identifiers.push(node);\n\n return true;\n }\n case 'TemplateLiteral': {\n return PromiseChainSupport.isConstant({ node });\n }\n case 'UnaryExpression': {\n return PromiseChainSupport.isConstant({ node });\n }\n case 'ChainExpression': {\n return value(AstNode.readField({ node, key: 'expression' }));\n }\n case 'MemberExpression': {\n // Only a read of the error itself: `error.message`, `error?.response.status`.\n const object = AstNode.readField({ node, key: 'object' });\n const isRead =\n AstNode.readField({ node, key: 'computed' }) !== true ||\n AstNode.getType({ node: AstNode.readField({ node, key: 'property' }) }) === 'Literal';\n const isRooted =\n AstNode.getType({ node: object }) === 'MemberExpression' ||\n (AstNode.getType({ node: object }) === 'Identifier' &&\n AstNode.readField({ node: object, key: 'name' }) === parameter);\n\n return isRead && isRooted && parameter !== undefined && value(object);\n }\n case 'ArrayExpression': {\n const elements = AstNode.readField({ node, key: 'elements' });\n\n return (\n Array.isArray(elements) && elements.every((element) => element === null || value(element))\n );\n }\n case 'ObjectExpression': {\n const properties = AstNode.readField({ node, key: 'properties' });\n\n return (\n Array.isArray(properties) &&\n properties.every(\n (property) =>\n AstNode.getType({ node: property }) === 'Property' &&\n AstNode.readField({ node: property, key: 'computed' }) !== true &&\n AstNode.readField({ node: property, key: 'method' }) !== true &&\n AstNode.readField({ node: property, key: 'kind' }) === 'init' &&\n value(AstNode.readField({ node: property, key: 'value' })),\n )\n );\n }\n default: {\n return false;\n }\n }\n};\n\n/** Whether `name` is declared in `scope` or any scope around it: a catch variable of that name would shadow it. */\nconst isDeclaredAround = (opts: { scope: Scope.Scope | null; name: string }): boolean => {\n for (let scope = opts.scope; scope; scope = scope.upper) {\n if (scope.set.has(opts.name)) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * The plan of the fix for `awaitNode`, or `undefined` when the strict safe shape does not hold:\n * `const|let x[: T] = await f().catch(() => <value>)` or `.catch((error) => <value>)`, alone in its declaration,\n * in a statement list; `x` never written again and, without a type annotation, read only in its own function;\n * the handler an expression-bodied, non-async arrow with at most one plain parameter; `<value>` a literal, an\n * identifier, a read of the error (`error.message`) or an array or object literal of those; `f()` with no\n * `.then`, `.catch` or `.finally` before and no `await` inside; no comment the fix would drop.\n */\nconst planFix = (opts: { awaitNode: Rule.Node; sourceCode: SourceCode }): IFixPlan | undefined => {\n const { awaitNode, sourceCode } = opts;\n const call = AstNode.readField({ node: awaitNode, key: 'argument' });\n const callee = AstNode.readField({ node: call, key: 'callee' });\n const args = AstNode.readField({ node: call, key: 'arguments' });\n\n if (\n AstNode.getType({ node: call }) !== 'CallExpression' ||\n AstNode.readField({ node: call, key: 'optional' }) === true ||\n AstNode.getType({ node: callee }) !== 'MemberExpression' ||\n AstNode.readField({ node: callee, key: 'computed' }) === true ||\n AstNode.readField({ node: callee, key: 'optional' }) === true ||\n PromiseChainSupport.memberName({ member: callee }) !== 'catch' ||\n !Array.isArray(args) ||\n args.length !== 1\n ) {\n return undefined;\n }\n\n const handler: unknown = args[0];\n const params = AstNode.readField({ node: handler, key: 'params' });\n const body = AstNode.readField({ node: handler, key: 'body' });\n const parameter: unknown = Array.isArray(params) ? params[0] : undefined;\n\n if (\n AstNode.getType({ node: handler }) !== 'ArrowFunctionExpression' ||\n AstNode.readField({ node: handler, key: 'async' }) === true ||\n AstNode.getType({ node: body }) === AstNodeTypes.BLOCK_STATEMENT ||\n AstNode.readField({ node: handler, key: 'returnType' }) ||\n AstNode.readField({ node: handler, key: 'typeParameters' }) ||\n !Array.isArray(params) ||\n params.length > 1 ||\n (parameter !== undefined &&\n (AstNode.getType({ node: parameter }) !== 'Identifier' ||\n AstNode.readField({ node: parameter, key: 'typeAnnotation' }) ||\n AstNode.readField({ node: parameter, key: 'optional' }) === true))\n ) {\n return undefined;\n }\n\n const receiver = AstNode.readField({ node: callee, key: 'object' });\n\n if (\n !AwaitSupport.isNode(receiver) ||\n !AwaitSupport.isNode(body) ||\n !AwaitSupport.isNode(handler) ||\n PromiseChainSupport.hasChainOnSpine({ node: receiver }) ||\n /\\b(await|yield)\\b/.test(sourceCode.getText(receiver))\n ) {\n return undefined;\n }\n\n const declarator = AwaitSupport.parentOf({ node: awaitNode });\n const declaration = AwaitSupport.parentOf({ node: declarator });\n const id = AstNode.readField({ node: declarator, key: 'id' });\n const declarations = AstNode.readField({ node: declaration, key: 'declarations' });\n const kind = String(AstNode.readField({ node: declaration, key: 'kind' }));\n\n if (\n AstNode.getType({ node: declarator }) !== 'VariableDeclarator' ||\n AstNode.readField({ node: declarator, key: 'init' }) !== awaitNode ||\n AstNode.readField({ node: declarator, key: 'definite' }) === true ||\n AstNode.getType({ node: id }) !== 'Identifier' ||\n !AwaitSupport.isNode(declarator) ||\n !AwaitSupport.isNode(declaration) ||\n !Array.isArray(declarations) ||\n declarations.length !== 1 ||\n !['const', 'let'].includes(kind) ||\n !STATEMENT_LISTS.has(\n AstNode.getType({ node: AwaitSupport.parentOf({ node: declaration }) }) ?? '',\n )\n ) {\n return undefined;\n }\n\n const name = String(AstNode.readField({ node: id, key: 'name' }));\n const typeAnnotation = AstNode.readField({ node: id, key: 'typeAnnotation' });\n const annotation = AwaitSupport.isNode(typeAnnotation) ? sourceCode.getText(typeAnnotation) : '';\n\n // `let x;` with no annotation takes its type from the assignments that follow, so TypeScript must see every\n // read in the same function: a read from a nested function, an export or a `typeof` makes it an implicit any.\n const variable = sourceCode.getDeclaredVariables(declarator).find((entry) => entry.name === name);\n\n if (!variable) {\n return undefined;\n }\n\n for (const reference of variable.references) {\n if (reference.identifier === id) {\n continue;\n }\n\n const parentType = AstNode.getType({\n node: AwaitSupport.parentOf({ node: reference.identifier }),\n });\n\n if (\n reference.isWrite() ||\n (annotation === '' &&\n (reference.from.variableScope !== variable.scope.variableScope ||\n parentType === 'ExportSpecifier' ||\n parentType === 'TSTypeQuery'))\n ) {\n return undefined;\n }\n }\n\n const parameterName =\n parameter === undefined\n ? undefined\n : String(AstNode.readField({ node: parameter, key: 'name' }));\n const identifiers: unknown[] = [];\n\n if (!collectValue({ node: body, parameter: parameterName, identifiers })) {\n return undefined;\n }\n\n // `x = []` on a `let x;` with no annotation makes an evolving `any[]`, looser than the `never[]` it was.\n const elements = AstNode.readField({ node: body, key: 'elements' });\n\n if (\n annotation === '' &&\n AstNode.getType({ node: body }) === 'ArrayExpression' &&\n Array.isArray(elements) &&\n elements.length === 0\n ) {\n return undefined;\n }\n\n const parameterVariable = sourceCode\n .getDeclaredVariables(handler)\n .find((entry) => entry.name === parameterName);\n const errorReads = new Set<unknown>(\n parameterVariable?.references.map((reference) => reference.identifier) ?? [],\n );\n const freeNames = new Set(\n identifiers\n .filter((identifier) => !errorReads.has(identifier))\n .map((identifier) => String(AstNode.readField({ node: identifier, key: 'name' }))),\n );\n\n // The fallback is evaluated after the `let`: reading the declared name there would read `undefined`.\n if (freeNames.has(name)) {\n return undefined;\n }\n\n const scope = sourceCode.getScope(declaration);\n const isTaken = (candidate: string) =>\n candidate === name ||\n freeNames.has(candidate) ||\n (candidate !== parameterName && isDeclaredAround({ scope, name: candidate }));\n const base = parameterName ?? CATCH_NAME;\n let catchName = base;\n\n for (let index = 2; isTaken(catchName); index += 1) {\n catchName = `${base}${index}`;\n }\n\n const comments = sourceCode.getCommentsInside(declaration);\n const isInside = (range: [number, number] | undefined, inner: [number, number] | undefined) =>\n range !== undefined && inner !== undefined && range[0] <= inner[0] && inner[1] <= range[1];\n\n if (\n comments.some(\n (comment) => !isInside(receiver.range, comment.range) && !isInside(body.range, comment.range),\n )\n ) {\n return undefined;\n }\n\n const bodyStart = body.range?.[0] ?? 0;\n let valueText = sourceCode.getText(body);\n\n if (catchName !== parameterName && errorReads.size > 0) {\n const edits = [...errorReads]\n .filter(AwaitSupport.isNode)\n .map((identifier) => {\n const parent = AwaitSupport.parentOf({ node: identifier });\n const isShorthand =\n AstNode.getType({ node: parent }) === 'Property' &&\n AstNode.readField({ node: parent, key: 'shorthand' }) === true;\n\n return {\n range: identifier.range ?? [0, 0],\n text: isShorthand ? `${parameterName}: ${catchName}` : catchName,\n };\n })\n .sort((left, right) => right.range[0] - left.range[0]);\n\n for (const edit of edits) {\n valueText =\n valueText.slice(0, edit.range[0] - bodyStart) +\n edit.text +\n valueText.slice(edit.range[1] - bodyStart);\n }\n }\n\n return {\n declaration,\n kind,\n name,\n annotation,\n receiverText: sourceCode.getText(receiver),\n catchName,\n isErrorRead: errorReads.size > 0,\n valueText,\n };\n};\n\n/**\n * `venizia/no-await-promise-chain`. One expression uses one async style: `await` (in a try/catch when it can\n * fail), or a promise chain that is not awaited. An `await` whose operand - after parentheses, `!`, `as`,\n * `satisfies` and an optional chain - is a call of `.then`, `.catch` or `.finally` (`?.then(`, `['then'](`, a\n * thenable such as a query builder) is reported once, however long the chain. A chain that is returned or stands\n * as a statement is not awaited and is not reported, nor is `await Promise.all(xs.map(f))`, `await new Promise(...)`,\n * `await x.then` (no call), or an `await` inside a callback of a chain.\n *\n * The fix is made for one shape only, `const|let x = await f().catch(() => <value>)` (see `planFix` for every\n * condition), and writes `let x; try { x = await f(); } catch (error) { x = <value>; }` (`catch { ... }` when the value does not read the error): the `const` becomes a\n * `let`, a type annotation stays, the catch variable takes the handler's parameter name (`error` without one,\n * renamed when the name is taken), and is typed `any` when the value reads it, as the handler's parameter was.\n * The try also catches a synchronous throw of `f()`, which the chain let through. Everything else is reported.\n */\nexport class NoAwaitPromiseChainRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-await-promise-chain`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n schema: [],\n messages: {\n mixed:\n 'Do not `await` a promise chain (`.{{method}}(...)`): wrap `await f()` in try/catch, or drop the `await` and keep the chain.',\n mixedConst:\n 'Do not `await` a promise chain (`.{{method}}(...)`): wrap `await f()` in try/catch, or drop the `await` and keep the chain. The fix writes the try/catch and turns the `const` into a `let`.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n return {\n [AstNodeTypes.AWAIT_EXPRESSION]: (node: Rule.Node) => {\n const method = PromiseChainSupport.chainMethodOf({\n node: AstNode.readField({ node, key: 'argument' }),\n });\n\n if (method === undefined) {\n return;\n }\n\n const plan = planFix({ awaitNode: node, sourceCode });\n\n context.report({\n node,\n messageId: plan?.kind === 'const' ? 'mixedConst' : 'mixed',\n data: { method },\n fix: plan\n ? (fixer) => {\n const indent = AwaitSupport.indentOf({ node: plan.declaration, sourceCode });\n const inner = `${indent} `;\n // The optional catch binding when nothing reads the error: a named one would be an unused variable.\n const head = plan.isErrorRead ? `catch (${plan.catchName}: any)` : 'catch';\n\n return fixer.replaceText(\n plan.declaration,\n [\n `let ${plan.name}${plan.annotation};`,\n `${indent}try {`,\n `${inner}${plan.name} = await ${plan.receiverText};`,\n `${indent}} ${head} {`,\n `${inner}${plan.name} = ${plan.valueText};`,\n `${indent}}`,\n ].join('\\n'),\n );\n }\n : null,\n });\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
1
+ {"version":3,"file":"no-await-promise-chain.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-await-promise-chain.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule, Scope, SourceCode } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport, STATEMENT_LISTS } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { PromiseChainSupport } from './promise-chain-support';\n\n/** The catch variable the fix writes when the handler has no parameter. */\nconst CATCH_NAME = 'error';\n\n/** What the fix needs, read once from a `const x = await f().catch(h)` that passed every check. */\ninterface IFixPlan {\n declaration: Rule.Node;\n kind: string;\n name: string;\n annotation: string;\n receiverText: string;\n catchName: string;\n isErrorRead: boolean;\n valueText: string;\n}\n\n/** The identifiers a fallback value reads, and whether every node of it is a value the fix may move. */\nconst collectValue = (opts: {\n node: unknown;\n parameter: string | undefined;\n identifiers: unknown[];\n}): boolean => {\n const { node, parameter, identifiers } = opts;\n const type = AstNode.getType({ node }) ?? '';\n const value = (child: unknown) => collectValue({ node: child, parameter, identifiers });\n\n switch (type) {\n case AstNodeTypes.LITERAL: {\n return true;\n }\n case AstNodeTypes.IDENTIFIER: {\n identifiers.push(node);\n\n return true;\n }\n case AstNodeTypes.TEMPLATE_LITERAL: {\n return PromiseChainSupport.isConstant({ node });\n }\n case AstNodeTypes.UNARY_EXPRESSION: {\n return PromiseChainSupport.isConstant({ node });\n }\n case AstNodeTypes.CHAIN_EXPRESSION: {\n return value(AstNode.readField({ node, key: 'expression' }));\n }\n case AstNodeTypes.MEMBER_EXPRESSION: {\n // Only a read of the error itself: `error.message`, `error?.response.status`.\n const object = AstNode.readField({ node, key: 'object' });\n const isRead =\n AstNode.readField({ node, key: 'computed' }) !== true ||\n AstNode.getType({ node: AstNode.readField({ node, key: 'property' }) }) ===\n AstNodeTypes.LITERAL;\n const isRooted =\n AstNode.getType({ node: object }) === AstNodeTypes.MEMBER_EXPRESSION ||\n (AstNode.getType({ node: object }) === AstNodeTypes.IDENTIFIER &&\n AstNode.readField({ node: object, key: 'name' }) === parameter);\n\n return isRead && isRooted && parameter !== undefined && value(object);\n }\n case AstNodeTypes.ARRAY_EXPRESSION: {\n const elements = AstNode.readField({ node, key: 'elements' });\n\n return (\n Array.isArray(elements) && elements.every((element) => element === null || value(element))\n );\n }\n case AstNodeTypes.OBJECT_EXPRESSION: {\n const properties = AstNode.readField({ node, key: 'properties' });\n\n return (\n Array.isArray(properties) &&\n properties.every(\n (property) =>\n AstNode.getType({ node: property }) === AstNodeTypes.PROPERTY &&\n AstNode.readField({ node: property, key: 'computed' }) !== true &&\n AstNode.readField({ node: property, key: 'method' }) !== true &&\n AstNode.readField({ node: property, key: 'kind' }) === 'init' &&\n value(AstNode.readField({ node: property, key: 'value' })),\n )\n );\n }\n default: {\n return false;\n }\n }\n};\n\n/** Whether `name` is declared in `scope` or any scope around it: a catch variable of that name would shadow it. */\nconst isDeclaredAround = (opts: { scope: Scope.Scope | null; name: string }): boolean => {\n for (let scope = opts.scope; scope; scope = scope.upper) {\n if (scope.set.has(opts.name)) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * The plan of the fix for `awaitNode`, or `undefined` when the strict safe shape does not hold:\n * `const|let x[: T] = await f().catch(() => <value>)` or `.catch((error) => <value>)`, alone in its declaration,\n * in a statement list; `x` never written again and, without a type annotation, read only in its own function;\n * the handler an expression-bodied, non-async arrow with at most one plain parameter; `<value>` a literal, an\n * identifier, a read of the error (`error.message`) or an array or object literal of those; `f()` with no\n * `.then`, `.catch` or `.finally` before and no `await` inside; no comment the fix would drop.\n */\nconst planFix = (opts: { awaitNode: Rule.Node; sourceCode: SourceCode }): IFixPlan | undefined => {\n const { awaitNode, sourceCode } = opts;\n const call = AstNode.readField({ node: awaitNode, key: 'argument' });\n const callee = AstNode.readField({ node: call, key: 'callee' });\n const args = AstNode.readField({ node: call, key: 'arguments' });\n\n if (\n AstNode.getType({ node: call }) !== AstNodeTypes.CALL_EXPRESSION ||\n AstNode.readField({ node: call, key: 'optional' }) === true ||\n AstNode.getType({ node: callee }) !== AstNodeTypes.MEMBER_EXPRESSION ||\n AstNode.readField({ node: callee, key: 'computed' }) === true ||\n AstNode.readField({ node: callee, key: 'optional' }) === true ||\n PromiseChainSupport.memberName({ member: callee }) !== 'catch' ||\n !Array.isArray(args) ||\n args.length !== 1\n ) {\n return undefined;\n }\n\n const handler: unknown = args[0];\n const params = AstNode.readField({ node: handler, key: 'params' });\n const body = AstNode.readField({ node: handler, key: 'body' });\n const parameter: unknown = Array.isArray(params) ? params[0] : undefined;\n\n if (\n AstNode.getType({ node: handler }) !== AstNodeTypes.ARROW_FUNCTION_EXPRESSION ||\n AstNode.readField({ node: handler, key: 'async' }) === true ||\n AstNode.getType({ node: body }) === AstNodeTypes.BLOCK_STATEMENT ||\n AstNode.readField({ node: handler, key: 'returnType' }) ||\n AstNode.readField({ node: handler, key: 'typeParameters' }) ||\n !Array.isArray(params) ||\n params.length > 1 ||\n (parameter !== undefined &&\n (AstNode.getType({ node: parameter }) !== AstNodeTypes.IDENTIFIER ||\n AstNode.readField({ node: parameter, key: 'typeAnnotation' }) ||\n AstNode.readField({ node: parameter, key: 'optional' }) === true))\n ) {\n return undefined;\n }\n\n const receiver = AstNode.readField({ node: callee, key: 'object' });\n\n if (\n !AwaitSupport.isNode(receiver) ||\n !AwaitSupport.isNode(body) ||\n !AwaitSupport.isNode(handler) ||\n PromiseChainSupport.hasChainOnSpine({ node: receiver }) ||\n /\\b(await|yield)\\b/.test(sourceCode.getText(receiver))\n ) {\n return undefined;\n }\n\n const declarator = AwaitSupport.parentOf({ node: awaitNode });\n const declaration = AwaitSupport.parentOf({ node: declarator });\n const id = AstNode.readField({ node: declarator, key: 'id' });\n const declarations = AstNode.readField({ node: declaration, key: 'declarations' });\n const kind = String(AstNode.readField({ node: declaration, key: 'kind' }));\n\n if (\n AstNode.getType({ node: declarator }) !== AstNodeTypes.VARIABLE_DECLARATOR ||\n AstNode.readField({ node: declarator, key: 'init' }) !== awaitNode ||\n AstNode.readField({ node: declarator, key: 'definite' }) === true ||\n AstNode.getType({ node: id }) !== AstNodeTypes.IDENTIFIER ||\n !AwaitSupport.isNode(declarator) ||\n !AwaitSupport.isNode(declaration) ||\n !Array.isArray(declarations) ||\n declarations.length !== 1 ||\n !['const', 'let'].includes(kind) ||\n !STATEMENT_LISTS.has(\n AstNode.getType({ node: AwaitSupport.parentOf({ node: declaration }) }) ?? '',\n )\n ) {\n return undefined;\n }\n\n const name = String(AstNode.readField({ node: id, key: 'name' }));\n const typeAnnotation = AstNode.readField({ node: id, key: 'typeAnnotation' });\n const annotation = AwaitSupport.isNode(typeAnnotation) ? sourceCode.getText(typeAnnotation) : '';\n\n // `let x;` with no annotation takes its type from the assignments that follow, so TypeScript must see every\n // read in the same function: a read from a nested function, an export or a `typeof` makes it an implicit any.\n const variable = sourceCode.getDeclaredVariables(declarator).find((entry) => entry.name === name);\n\n if (!variable) {\n return undefined;\n }\n\n for (const reference of variable.references) {\n if (reference.identifier === id) {\n continue;\n }\n\n const parentType = AstNode.getType({\n node: AwaitSupport.parentOf({ node: reference.identifier }),\n });\n\n if (\n reference.isWrite() ||\n (annotation === '' &&\n (reference.from.variableScope !== variable.scope.variableScope ||\n parentType === AstNodeTypes.EXPORT_SPECIFIER ||\n parentType === AstNodeTypes.TYPE_QUERY))\n ) {\n return undefined;\n }\n }\n\n const parameterName =\n parameter === undefined\n ? undefined\n : String(AstNode.readField({ node: parameter, key: 'name' }));\n const identifiers: unknown[] = [];\n\n if (!collectValue({ node: body, parameter: parameterName, identifiers })) {\n return undefined;\n }\n\n // `x = []` on a `let x;` with no annotation makes an evolving `any[]`, looser than the `never[]` it was.\n const elements = AstNode.readField({ node: body, key: 'elements' });\n\n if (\n annotation === '' &&\n AstNode.getType({ node: body }) === AstNodeTypes.ARRAY_EXPRESSION &&\n Array.isArray(elements) &&\n elements.length === 0\n ) {\n return undefined;\n }\n\n const parameterVariable = sourceCode\n .getDeclaredVariables(handler)\n .find((entry) => entry.name === parameterName);\n const errorReads = new Set<unknown>(\n parameterVariable?.references.map((reference) => reference.identifier) ?? [],\n );\n const freeNames = new Set(\n identifiers\n .filter((identifier) => !errorReads.has(identifier))\n .map((identifier) => String(AstNode.readField({ node: identifier, key: 'name' }))),\n );\n\n // The fallback is evaluated after the `let`: reading the declared name there would read `undefined`.\n if (freeNames.has(name)) {\n return undefined;\n }\n\n const scope = sourceCode.getScope(declaration);\n const isTaken = (candidate: string) =>\n candidate === name ||\n freeNames.has(candidate) ||\n (candidate !== parameterName && isDeclaredAround({ scope, name: candidate }));\n const base = parameterName ?? CATCH_NAME;\n let catchName = base;\n\n for (let index = 2; isTaken(catchName); index += 1) {\n catchName = `${base}${index}`;\n }\n\n const comments = sourceCode.getCommentsInside(declaration);\n const isInside = (range: [number, number] | undefined, inner: [number, number] | undefined) =>\n range !== undefined && inner !== undefined && range[0] <= inner[0] && inner[1] <= range[1];\n\n if (\n comments.some(\n (comment) => !isInside(receiver.range, comment.range) && !isInside(body.range, comment.range),\n )\n ) {\n return undefined;\n }\n\n const bodyStart = body.range?.[0] ?? 0;\n let valueText = sourceCode.getText(body);\n\n if (catchName !== parameterName && errorReads.size > 0) {\n const edits = [...errorReads]\n .filter(AwaitSupport.isNode)\n .map((identifier) => {\n const parent = AwaitSupport.parentOf({ node: identifier });\n const isShorthand =\n AstNode.getType({ node: parent }) === AstNodeTypes.PROPERTY &&\n AstNode.readField({ node: parent, key: 'shorthand' }) === true;\n\n return {\n range: identifier.range ?? [0, 0],\n text: isShorthand ? `${parameterName}: ${catchName}` : catchName,\n };\n })\n .sort((left, right) => right.range[0] - left.range[0]);\n\n for (const edit of edits) {\n valueText =\n valueText.slice(0, edit.range[0] - bodyStart) +\n edit.text +\n valueText.slice(edit.range[1] - bodyStart);\n }\n }\n\n return {\n declaration,\n kind,\n name,\n annotation,\n receiverText: sourceCode.getText(receiver),\n catchName,\n isErrorRead: errorReads.size > 0,\n valueText,\n };\n};\n\n/**\n * `venizia/no-await-promise-chain`. One expression uses one async style: `await` (in a try/catch when it can\n * fail), or a promise chain that is not awaited. An `await` whose operand - after parentheses, `!`, `as`,\n * `satisfies` and an optional chain - is a call of `.then`, `.catch` or `.finally` (`?.then(`, `['then'](`, a\n * thenable such as a query builder) is reported once, however long the chain. A chain that is returned or stands\n * as a statement is not awaited and is not reported, nor is `await Promise.all(xs.map(f))`, `await new Promise(...)`,\n * `await x.then` (no call), or an `await` inside a callback of a chain.\n *\n * The fix is made for one shape only, `const|let x = await f().catch(() => <value>)` (see `planFix` for every\n * condition), and writes `let x; try { x = await f(); } catch (error) { x = <value>; }` (`catch { ... }` when the value does not read the error): the `const` becomes a\n * `let`, a type annotation stays, the catch variable takes the handler's parameter name (`error` without one,\n * renamed when the name is taken), and is typed `any` when the value reads it, as the handler's parameter was.\n * The try also catches a synchronous throw of `f()`, which the chain let through. Everything else is reported.\n */\nexport class NoAwaitPromiseChainRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-await-promise-chain`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n schema: [],\n messages: {\n mixed:\n 'Do not `await` a promise chain (`.{{method}}(...)`): wrap `await f()` in try/catch, or drop the `await` and keep the chain.',\n mixedConst:\n 'Do not `await` a promise chain (`.{{method}}(...)`): wrap `await f()` in try/catch, or drop the `await` and keep the chain. The fix writes the try/catch and turns the `const` into a `let`.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n return {\n [AstNodeTypes.AWAIT_EXPRESSION]: (node: Rule.Node) => {\n const method = PromiseChainSupport.chainMethodOf({\n node: AstNode.readField({ node, key: 'argument' }),\n });\n\n if (method === undefined) {\n return;\n }\n\n const plan = planFix({ awaitNode: node, sourceCode });\n\n context.report({\n node,\n messageId: plan?.kind === 'const' ? 'mixedConst' : 'mixed',\n data: { method },\n fix: plan\n ? (fixer) => {\n const indent = AwaitSupport.indentOf({ node: plan.declaration, sourceCode });\n const inner = `${indent} `;\n // The optional catch binding when nothing reads the error: a named one would be an unused variable.\n const head = plan.isErrorRead ? `catch (${plan.catchName}: any)` : 'catch';\n\n return fixer.replaceText(\n plan.declaration,\n [\n `let ${plan.name}${plan.annotation};`,\n `${indent}try {`,\n `${inner}${plan.name} = await ${plan.receiverText};`,\n `${indent}} ${head} {`,\n `${inner}${plan.name} = ${plan.valueText};`,\n `${indent}}`,\n ].join('\\n'),\n );\n }\n : null,\n });\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
@@ -30,11 +30,12 @@ class NoInlineAwaitRule {
30
30
  [common_1.AstNodeTypes.AWAIT_EXPRESSION]: (node) => {
31
31
  const parent = await_support_1.AwaitSupport.parentOf({ node });
32
32
  const parentType = common_1.AstNode.getType({ node: parent });
33
- const isWhole = (parentType === 'ExpressionStatement' &&
33
+ const isWhole = (parentType === common_1.AstNodeTypes.EXPRESSION_STATEMENT &&
34
34
  common_1.AstNode.readField({ node: parent, key: 'expression' }) === node) ||
35
- (parentType === 'VariableDeclarator' &&
35
+ (parentType === common_1.AstNodeTypes.VARIABLE_DECLARATOR &&
36
36
  common_1.AstNode.readField({ node: parent, key: 'init' }) === node);
37
- const isReturned = (parentType === 'ReturnStatement' || parentType === 'ArrowFunctionExpression') &&
37
+ const isReturned = (parentType === common_1.AstNodeTypes.RETURN_STATEMENT ||
38
+ parentType === common_1.AstNodeTypes.ARROW_FUNCTION_EXPRESSION) &&
38
39
  (common_1.AstNode.readField({ node: parent, key: 'argument' }) === node ||
39
40
  common_1.AstNode.readField({ node: parent, key: 'body' }) === node);
40
41
  if (isWhole || isReturned) {
@@ -1 +1 @@
1
- {"version":3,"file":"no-inline-await.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-inline-await.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/**\n * `venizia/no-inline-await`. `await` stands alone: as a whole statement (`await f();`) or as the whole initializer\n * of a declaration (`const result = await f();`). Inside any other expression - a call argument, a spread, an\n * array or object, a ternary, a logical operator, a template literal, a member access, an assignment - it is\n * reported, and `return g(await f())` is the same report. `return await f()` is `no-return-await`'s.\n *\n * The fix moves the `await` into a `const` in front of the statement. It is made only when nothing that does more\n * than read a value runs before the `await` inside the statement, and when the `await` is not in a branch, a loop\n * test, an unbraced `if` branch or an arrow expression body; those cases are reported and left alone.\n */\nexport class NoInlineAwaitRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-inline-await`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n schema: [],\n messages: {\n inline:\n '`await` stands alone as a statement or as the whole initializer of a declaration (`const result = await f();`), not inside an expression.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n return {\n [AstNodeTypes.AWAIT_EXPRESSION]: (node: Rule.Node) => {\n const parent = AwaitSupport.parentOf({ node });\n const parentType = AstNode.getType({ node: parent });\n const isWhole =\n (parentType === 'ExpressionStatement' &&\n AstNode.readField({ node: parent, key: 'expression' }) === node) ||\n (parentType === 'VariableDeclarator' &&\n AstNode.readField({ node: parent, key: 'init' }) === node);\n const isReturned =\n (parentType === 'ReturnStatement' || parentType === 'ArrowFunctionExpression') &&\n (AstNode.readField({ node: parent, key: 'argument' }) === node ||\n AstNode.readField({ node: parent, key: 'body' }) === node);\n\n if (isWhole || isReturned) {\n return;\n }\n\n const statement = AwaitSupport.hoistTarget({ awaitNode: node });\n const canFix =\n statement !== undefined &&\n !AwaitSupport.hasEffectBefore({ statement, awaitNode: node, sourceCode });\n\n context.report({\n node,\n messageId: 'inline',\n fix: canFix\n ? (fixer) => {\n const name = AwaitSupport.freshName({ node, base: 'result', sourceCode });\n const [start, end] = AwaitSupport.replaceRangeOf({ awaitNode: node, sourceCode });\n const indent = AwaitSupport.indentOf({ node: statement, sourceCode });\n\n return [\n fixer.insertTextBefore(\n statement,\n `const ${name} = ${sourceCode.getText(node)};\\n${indent}`,\n ),\n fixer.replaceTextRange([start, end], name),\n ];\n }\n : null,\n });\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
1
+ {"version":3,"file":"no-inline-await.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-inline-await.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/**\n * `venizia/no-inline-await`. `await` stands alone: as a whole statement (`await f();`) or as the whole initializer\n * of a declaration (`const result = await f();`). Inside any other expression - a call argument, a spread, an\n * array or object, a ternary, a logical operator, a template literal, a member access, an assignment - it is\n * reported, and `return g(await f())` is the same report. `return await f()` is `no-return-await`'s.\n *\n * The fix moves the `await` into a `const` in front of the statement. It is made only when nothing that does more\n * than read a value runs before the `await` inside the statement, and when the `await` is not in a branch, a loop\n * test, an unbraced `if` branch or an arrow expression body; those cases are reported and left alone.\n */\nexport class NoInlineAwaitRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-inline-await`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n schema: [],\n messages: {\n inline:\n '`await` stands alone as a statement or as the whole initializer of a declaration (`const result = await f();`), not inside an expression.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n return {\n [AstNodeTypes.AWAIT_EXPRESSION]: (node: Rule.Node) => {\n const parent = AwaitSupport.parentOf({ node });\n const parentType = AstNode.getType({ node: parent });\n const isWhole =\n (parentType === AstNodeTypes.EXPRESSION_STATEMENT &&\n AstNode.readField({ node: parent, key: 'expression' }) === node) ||\n (parentType === AstNodeTypes.VARIABLE_DECLARATOR &&\n AstNode.readField({ node: parent, key: 'init' }) === node);\n const isReturned =\n (parentType === AstNodeTypes.RETURN_STATEMENT ||\n parentType === AstNodeTypes.ARROW_FUNCTION_EXPRESSION) &&\n (AstNode.readField({ node: parent, key: 'argument' }) === node ||\n AstNode.readField({ node: parent, key: 'body' }) === node);\n\n if (isWhole || isReturned) {\n return;\n }\n\n const statement = AwaitSupport.hoistTarget({ awaitNode: node });\n const canFix =\n statement !== undefined &&\n !AwaitSupport.hasEffectBefore({ statement, awaitNode: node, sourceCode });\n\n context.report({\n node,\n messageId: 'inline',\n fix: canFix\n ? (fixer) => {\n const name = AwaitSupport.freshName({ node, base: 'result', sourceCode });\n const [start, end] = AwaitSupport.replaceRangeOf({ awaitNode: node, sourceCode });\n const indent = AwaitSupport.indentOf({ node: statement, sourceCode });\n\n return [\n fixer.insertTextBefore(\n statement,\n `const ${name} = ${sourceCode.getText(node)};\\n${indent}`,\n ),\n fixer.replaceTextRange([start, end], name),\n ];\n }\n : null,\n });\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NoLeakedRenderRule = void 0;
4
4
  const common_1 = require("./common");
5
5
  /** `&&` directly under a JSX child: `disabled={a && b}` is a value, not something drawn. */
6
- const LEAKED_RENDER_SELECTOR = ['JSXElement', 'JSXFragment']
7
- .map((parent) => `${parent} > JSXExpressionContainer > LogicalExpression[operator='&&']`)
6
+ const LEAKED_RENDER_SELECTOR = [common_1.AstNodeTypes.JSX_ELEMENT, common_1.AstNodeTypes.JSX_FRAGMENT]
7
+ .map((parent) => `${parent} > ${common_1.AstNodeTypes.JSX_EXPRESSION_CONTAINER} > ${common_1.AstNodeTypes.LOGICAL_EXPRESSION}[operator='&&']`)
8
8
  .join(', ');
9
9
  /**
10
10
  * `venizia/no-leaked-render`. `{count && <X />}` draws `0` when `count` is `0`; draw nothing with
@@ -24,7 +24,7 @@ class NoLeakedRenderRule {
24
24
  },
25
25
  create: (context) => ({
26
26
  [LEAKED_RENDER_SELECTOR]: (node) => {
27
- if (node.type !== 'LogicalExpression') {
27
+ if (node.type !== common_1.AstNodeTypes.LOGICAL_EXPRESSION) {
28
28
  return;
29
29
  }
30
30
  const source = context.sourceCode;
@@ -1 +1 @@
1
- {"version":3,"file":"no-leaked-render.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-leaked-render.rule.ts"],"names":[],"mappings":";;;AAEA,qCAAkD;AAElD,4FAA4F;AAC5F,MAAM,sBAAsB,GAAG,CAAC,YAAY,EAAE,aAAa,CAAC;KACzD,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,MAAM,8DAA8D,CAAC;KACxF,IAAI,CAAC,IAAI,CAAC,CAAC;AAEd;;;;GAIG;AACH,MAAa,kBAAkB;aACb,SAAI,GAAG,GAAG,+BAAsB,mBAAmB,CAAC;aAEpD,SAAI,GAAoB;QACtC,IAAI,EAAE;YACJ,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE;gBACR,MAAM,EAAE,uEAAuE;aAChF;SACF;QACD,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACpB,CAAC,sBAAsB,CAAC,EAAE,CAAC,IAAe,EAAE,EAAE;gBAC5C,IAAI,IAAI,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;oBACtC,OAAO;gBACT,CAAC;gBAED,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;gBAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;gBAElF,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,OAAO;gBACT,CAAC;gBAED,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC3E,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI;oBACJ,SAAS,EAAE,QAAQ;oBACnB,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC;iBAC1F,CAAC,CAAC;YACL,CAAC;SACF,CAAC;KACH,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,OAAqC,EAAE;QAClD,OAAO,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;IAClC,CAAC;;AArCH,gDAsCC","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/** `&&` directly under a JSX child: `disabled={a && b}` is a value, not something drawn. */\nconst LEAKED_RENDER_SELECTOR = ['JSXElement', 'JSXFragment']\n .map((parent) => `${parent} > JSXExpressionContainer > LogicalExpression[operator='&&']`)\n .join(', ');\n\n/**\n * `venizia/no-leaked-render`. `{count && <X />}` draws `0` when `count` is `0`; draw nothing with\n * `cond ? <X /> : null`. Only a child of JSX is checked. The fix rewrites it to the ternary and keeps\n * any comment between `&&` and the drawn part.\n */\nexport class NoLeakedRenderRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-leaked-render`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'problem',\n fixable: 'code',\n schema: [],\n messages: {\n leaked: 'Draw nothing with `cond ? <X /> : null`; `&&` draws 0 when cond is 0.',\n },\n },\n create: (context) => ({\n [LEAKED_RENDER_SELECTOR]: (node: Rule.Node) => {\n if (node.type !== 'LogicalExpression') {\n return;\n }\n\n const source = context.sourceCode;\n const operator = source.getTokenAfter(node.left, (token) => token.value === '&&');\n\n if (!operator) {\n return;\n }\n\n const drawn = source.text.slice(operator.range[1], node.range?.[1]).trim();\n context.report({\n node,\n messageId: 'leaked',\n fix: (fixer) => fixer.replaceText(node, `${source.getText(node.left)} ? ${drawn} : null`),\n });\n },\n }),\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
1
+ {"version":3,"file":"no-leaked-render.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-leaked-render.rule.ts"],"names":[],"mappings":";;;AAEA,qCAAgE;AAEhE,4FAA4F;AAC5F,MAAM,sBAAsB,GAAG,CAAC,qBAAY,CAAC,WAAW,EAAE,qBAAY,CAAC,YAAY,CAAC;KACjF,GAAG,CACF,CAAC,MAAM,EAAE,EAAE,CACT,GAAG,MAAM,MAAM,qBAAY,CAAC,wBAAwB,MAAM,qBAAY,CAAC,kBAAkB,iBAAiB,CAC7G;KACA,IAAI,CAAC,IAAI,CAAC,CAAC;AAEd;;;;GAIG;AACH,MAAa,kBAAkB;aACb,SAAI,GAAG,GAAG,+BAAsB,mBAAmB,CAAC;aAEpD,SAAI,GAAoB;QACtC,IAAI,EAAE;YACJ,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE;gBACR,MAAM,EAAE,uEAAuE;aAChF;SACF;QACD,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACpB,CAAC,sBAAsB,CAAC,EAAE,CAAC,IAAe,EAAE,EAAE;gBAC5C,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAY,CAAC,kBAAkB,EAAE,CAAC;oBAClD,OAAO;gBACT,CAAC;gBAED,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;gBAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;gBAElF,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,OAAO;gBACT,CAAC;gBAED,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC3E,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI;oBACJ,SAAS,EAAE,QAAQ;oBACnB,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC;iBAC1F,CAAC,CAAC;YACL,CAAC;SACF,CAAC;KACH,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,OAAqC,EAAE;QAClD,OAAO,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;IAClC,CAAC;;AArCH,gDAsCC","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/** `&&` directly under a JSX child: `disabled={a && b}` is a value, not something drawn. */\nconst LEAKED_RENDER_SELECTOR = [AstNodeTypes.JSX_ELEMENT, AstNodeTypes.JSX_FRAGMENT]\n .map(\n (parent) =>\n `${parent} > ${AstNodeTypes.JSX_EXPRESSION_CONTAINER} > ${AstNodeTypes.LOGICAL_EXPRESSION}[operator='&&']`,\n )\n .join(', ');\n\n/**\n * `venizia/no-leaked-render`. `{count && <X />}` draws `0` when `count` is `0`; draw nothing with\n * `cond ? <X /> : null`. Only a child of JSX is checked. The fix rewrites it to the ternary and keeps\n * any comment between `&&` and the drawn part.\n */\nexport class NoLeakedRenderRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-leaked-render`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'problem',\n fixable: 'code',\n schema: [],\n messages: {\n leaked: 'Draw nothing with `cond ? <X /> : null`; `&&` draws 0 when cond is 0.',\n },\n },\n create: (context) => ({\n [LEAKED_RENDER_SELECTOR]: (node: Rule.Node) => {\n if (node.type !== AstNodeTypes.LOGICAL_EXPRESSION) {\n return;\n }\n\n const source = context.sourceCode;\n const operator = source.getTokenAfter(node.left, (token) => token.value === '&&');\n\n if (!operator) {\n return;\n }\n\n const drawn = source.text.slice(operator.range[1], node.range?.[1]).trim();\n context.report({\n node,\n messageId: 'leaked',\n fix: (fixer) => fixer.replaceText(node, `${source.getText(node.left)} ? ${drawn} : null`),\n });\n },\n }),\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
@@ -19,7 +19,7 @@ class NoNewErrorRule {
19
19
  },
20
20
  create: (context) => {
21
21
  const report = (opts) => context.report({ node: opts.node, messageId: 'newError', data: { form: opts.form } });
22
- const isErrorIdentifier = (callee) => common_1.AstNode.getType({ node: callee }) === 'Identifier' &&
22
+ const isErrorIdentifier = (callee) => common_1.AstNode.getType({ node: callee }) === common_1.AstNodeTypes.IDENTIFIER &&
23
23
  common_1.AstNode.readField({ node: callee, key: 'name' }) === 'Error';
24
24
  return {
25
25
  [common_1.AstNodeTypes.NEW_EXPRESSION]: (node) => {
@@ -1 +1 @@
1
- {"version":3,"file":"no-new-error.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-new-error.rule.ts"],"names":[],"mappings":";;;AAEA,qCAAyE;AAEzE;;;;GAIG;AACH,MAAa,cAAc;aACT,SAAI,GAAG,GAAG,+BAAsB,eAAe,CAAC;aAEhD,SAAI,GAAoB;QACtC,IAAI,EAAE;YACJ,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE;gBACR,QAAQ,EACN,2IAA2I;aAC9I;SACF;QACD,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE;YAClB,MAAM,MAAM,GAAG,CAAC,IAAuC,EAAE,EAAE,CACzD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAExF,MAAM,iBAAiB,GAAG,CAAC,MAAe,EAAE,EAAE,CAC5C,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,YAAY;gBAClD,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC;YAE/D,OAAO;gBACL,CAAC,qBAAY,CAAC,cAAc,CAAC,EAAE,CAAC,IAAe,EAAE,EAAE;oBACjD,IAAI,iBAAiB,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC;wBAClE,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;oBAC3C,CAAC;gBACH,CAAC;gBACD,CAAC,qBAAY,CAAC,eAAe,CAAC,EAAE,CAAC,IAAe,EAAE,EAAE;oBAClD,IAAI,iBAAiB,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC;wBAClE,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;oBACvC,CAAC;gBACH,CAAC;aACF,CAAC;QACJ,CAAC;KACF,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,OAAqC,EAAE;QAClD,OAAO,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;IAClC,CAAC;;AArCH,wCAsCC","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/**\n * `venizia/no-new-error`. An error is thrown through `getError({ message })` (or an `ApplicationError`),\n * never `new Error(...)` or `Error(...)`: only an ApplicationError carries the status, the message code and\n * args, and the `extra` every IGNIS layer reads.\n */\nexport class NoNewErrorRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-new-error`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'problem',\n schema: [],\n messages: {\n newError:\n 'Throw through getError({ message }) (or an ApplicationError), not `{{form}}`: only an ApplicationError carries the status, code and args.',\n },\n },\n create: (context) => {\n const report = (opts: { node: Rule.Node; form: string }) =>\n context.report({ node: opts.node, messageId: 'newError', data: { form: opts.form } });\n\n const isErrorIdentifier = (callee: unknown) =>\n AstNode.getType({ node: callee }) === 'Identifier' &&\n AstNode.readField({ node: callee, key: 'name' }) === 'Error';\n\n return {\n [AstNodeTypes.NEW_EXPRESSION]: (node: Rule.Node) => {\n if (isErrorIdentifier(AstNode.readField({ node, key: 'callee' }))) {\n report({ node, form: 'new Error(...)' });\n }\n },\n [AstNodeTypes.CALL_EXPRESSION]: (node: Rule.Node) => {\n if (isErrorIdentifier(AstNode.readField({ node, key: 'callee' }))) {\n report({ node, form: 'Error(...)' });\n }\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
1
+ {"version":3,"file":"no-new-error.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-new-error.rule.ts"],"names":[],"mappings":";;;AAEA,qCAAyE;AAEzE;;;;GAIG;AACH,MAAa,cAAc;aACT,SAAI,GAAG,GAAG,+BAAsB,eAAe,CAAC;aAEhD,SAAI,GAAoB;QACtC,IAAI,EAAE;YACJ,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE;gBACR,QAAQ,EACN,2IAA2I;aAC9I;SACF;QACD,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE;YAClB,MAAM,MAAM,GAAG,CAAC,IAAuC,EAAE,EAAE,CACzD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAExF,MAAM,iBAAiB,GAAG,CAAC,MAAe,EAAE,EAAE,CAC5C,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,qBAAY,CAAC,UAAU;gBAC7D,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC;YAE/D,OAAO;gBACL,CAAC,qBAAY,CAAC,cAAc,CAAC,EAAE,CAAC,IAAe,EAAE,EAAE;oBACjD,IAAI,iBAAiB,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC;wBAClE,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;oBAC3C,CAAC;gBACH,CAAC;gBACD,CAAC,qBAAY,CAAC,eAAe,CAAC,EAAE,CAAC,IAAe,EAAE,EAAE;oBAClD,IAAI,iBAAiB,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC;wBAClE,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;oBACvC,CAAC;gBACH,CAAC;aACF,CAAC;QACJ,CAAC;KACF,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,OAAqC,EAAE;QAClD,OAAO,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;IAClC,CAAC;;AArCH,wCAsCC","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/**\n * `venizia/no-new-error`. An error is thrown through `getError({ message })` (or an `ApplicationError`),\n * never `new Error(...)` or `Error(...)`: only an ApplicationError carries the status, the message code and\n * args, and the `extra` every IGNIS layer reads.\n */\nexport class NoNewErrorRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-new-error`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'problem',\n schema: [],\n messages: {\n newError:\n 'Throw through getError({ message }) (or an ApplicationError), not `{{form}}`: only an ApplicationError carries the status, code and args.',\n },\n },\n create: (context) => {\n const report = (opts: { node: Rule.Node; form: string }) =>\n context.report({ node: opts.node, messageId: 'newError', data: { form: opts.form } });\n\n const isErrorIdentifier = (callee: unknown) =>\n AstNode.getType({ node: callee }) === AstNodeTypes.IDENTIFIER &&\n AstNode.readField({ node: callee, key: 'name' }) === 'Error';\n\n return {\n [AstNodeTypes.NEW_EXPRESSION]: (node: Rule.Node) => {\n if (isErrorIdentifier(AstNode.readField({ node, key: 'callee' }))) {\n report({ node, form: 'new Error(...)' });\n }\n },\n [AstNodeTypes.CALL_EXPRESSION]: (node: Rule.Node) => {\n if (isErrorIdentifier(AstNode.readField({ node, key: 'callee' }))) {\n report({ node, form: 'Error(...)' });\n }\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
@@ -7,7 +7,7 @@ const common_1 = require("./common");
7
7
  const isInTry = (node) => {
8
8
  let current = await_support_1.AwaitSupport.parentOf({ node });
9
9
  while (current && !await_support_1.FUNCTION_TYPES.has(common_1.AstNode.getType({ node: current }) ?? '')) {
10
- if (common_1.AstNode.getType({ node: current }) === 'TryStatement') {
10
+ if (common_1.AstNode.getType({ node: current }) === common_1.AstNodeTypes.TRY_STATEMENT) {
11
11
  return true;
12
12
  }
13
13
  current = await_support_1.AwaitSupport.parentOf({ node: current });
@@ -35,7 +35,7 @@ class NoReturnAwaitRule {
35
35
  const reportAwait = (opts) => {
36
36
  const argument = common_1.AstNode.readField({ node: opts.awaitNode, key: 'argument' });
37
37
  const argumentText = await_support_1.AwaitSupport.isNode(argument) &&
38
- common_1.AstNode.getType({ node: argument }) !== 'SequenceExpression'
38
+ common_1.AstNode.getType({ node: argument }) !== common_1.AstNodeTypes.SEQUENCE_EXPRESSION
39
39
  ? sourceCode.getText(argument)
40
40
  : undefined;
41
41
  context.report({
@@ -65,13 +65,14 @@ class NoReturnAwaitRule {
65
65
  [common_1.AstNodeTypes.RETURN_STATEMENT]: (node) => {
66
66
  const argument = common_1.AstNode.readField({ node, key: 'argument' });
67
67
  if (await_support_1.AwaitSupport.isNode(argument) &&
68
- common_1.AstNode.getType({ node: argument }) === 'AwaitExpression') {
68
+ common_1.AstNode.getType({ node: argument }) === common_1.AstNodeTypes.AWAIT_EXPRESSION) {
69
69
  reportAwait({ reported: node, awaitNode: argument, statement: node });
70
70
  }
71
71
  },
72
72
  [common_1.AstNodeTypes.ARROW_FUNCTION_EXPRESSION]: (node) => {
73
73
  const body = common_1.AstNode.readField({ node, key: 'body' });
74
- if (await_support_1.AwaitSupport.isNode(body) && common_1.AstNode.getType({ node: body }) === 'AwaitExpression') {
74
+ if (await_support_1.AwaitSupport.isNode(body) &&
75
+ common_1.AstNode.getType({ node: body }) === common_1.AstNodeTypes.AWAIT_EXPRESSION) {
75
76
  reportAwait({ reported: node, awaitNode: body });
76
77
  }
77
78
  },
@@ -1 +1 @@
1
- {"version":3,"file":"no-return-await.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-return-await.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport, FUNCTION_TYPES, STATEMENT_LISTS } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/** `node` sits inside a `try`, `catch` or `finally` of its own function. */\nconst isInTry = (node: unknown): boolean => {\n let current = AwaitSupport.parentOf({ node });\n\n while (current && !FUNCTION_TYPES.has(AstNode.getType({ node: current }) ?? '')) {\n if (AstNode.getType({ node: current }) === 'TryStatement') {\n return true;\n }\n\n current = AwaitSupport.parentOf({ node: current });\n }\n\n return false;\n};\n\n/**\n * `venizia/no-return-await`. A function returns the promise (`return f()`), never `return await f()`. Where the\n * `await` matters (inside `try`, `catch` or `finally`) it is written on its own line:\n * `const result = await f(); return result;`. An arrow whose body is an `await` is the same: `() => f()`.\n */\nexport class NoReturnAwaitRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-return-await`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n schema: [],\n messages: {\n returnAwait:\n 'Return the promise (`return f()`), not `return await f()`; where the await matters (inside try, catch or finally) write `const result = await f(); return result;`.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n const reportAwait = (opts: {\n reported: Rule.Node;\n awaitNode: Rule.Node;\n statement?: Rule.Node;\n }) => {\n const argument = AstNode.readField({ node: opts.awaitNode, key: 'argument' });\n const argumentText =\n AwaitSupport.isNode(argument) &&\n AstNode.getType({ node: argument }) !== 'SequenceExpression'\n ? sourceCode.getText(argument)\n : undefined;\n\n context.report({\n node: opts.reported,\n messageId: 'returnAwait',\n fix:\n argumentText === undefined\n ? null\n : (fixer) => {\n if (!opts.statement || !isInTry(opts.statement)) {\n return fixer.replaceText(opts.awaitNode, argumentText);\n }\n\n const outer = AwaitSupport.parentOf({ node: opts.statement });\n\n if (!STATEMENT_LISTS.has(AstNode.getType({ node: outer }) ?? '')) {\n return null;\n }\n\n const name = AwaitSupport.freshName({\n node: opts.statement,\n base: 'result',\n sourceCode,\n });\n const indent = AwaitSupport.indentOf({ node: opts.statement, sourceCode });\n\n return fixer.replaceText(\n opts.statement,\n `const ${name} = await ${argumentText};\\n${indent}return ${name};`,\n );\n },\n });\n };\n\n return {\n [AstNodeTypes.RETURN_STATEMENT]: (node: Rule.Node) => {\n const argument = AstNode.readField({ node, key: 'argument' });\n\n if (\n AwaitSupport.isNode(argument) &&\n AstNode.getType({ node: argument }) === 'AwaitExpression'\n ) {\n reportAwait({ reported: node, awaitNode: argument, statement: node });\n }\n },\n [AstNodeTypes.ARROW_FUNCTION_EXPRESSION]: (node: Rule.Node) => {\n const body = AstNode.readField({ node, key: 'body' });\n\n if (AwaitSupport.isNode(body) && AstNode.getType({ node: body }) === 'AwaitExpression') {\n reportAwait({ reported: node, awaitNode: body });\n }\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
1
+ {"version":3,"file":"no-return-await.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-return-await.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport, FUNCTION_TYPES, STATEMENT_LISTS } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/** `node` sits inside a `try`, `catch` or `finally` of its own function. */\nconst isInTry = (node: unknown): boolean => {\n let current = AwaitSupport.parentOf({ node });\n\n while (current && !FUNCTION_TYPES.has(AstNode.getType({ node: current }) ?? '')) {\n if (AstNode.getType({ node: current }) === AstNodeTypes.TRY_STATEMENT) {\n return true;\n }\n\n current = AwaitSupport.parentOf({ node: current });\n }\n\n return false;\n};\n\n/**\n * `venizia/no-return-await`. A function returns the promise (`return f()`), never `return await f()`. Where the\n * `await` matters (inside `try`, `catch` or `finally`) it is written on its own line:\n * `const result = await f(); return result;`. An arrow whose body is an `await` is the same: `() => f()`.\n */\nexport class NoReturnAwaitRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-return-await`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n schema: [],\n messages: {\n returnAwait:\n 'Return the promise (`return f()`), not `return await f()`; where the await matters (inside try, catch or finally) write `const result = await f(); return result;`.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n const reportAwait = (opts: {\n reported: Rule.Node;\n awaitNode: Rule.Node;\n statement?: Rule.Node;\n }) => {\n const argument = AstNode.readField({ node: opts.awaitNode, key: 'argument' });\n const argumentText =\n AwaitSupport.isNode(argument) &&\n AstNode.getType({ node: argument }) !== AstNodeTypes.SEQUENCE_EXPRESSION\n ? sourceCode.getText(argument)\n : undefined;\n\n context.report({\n node: opts.reported,\n messageId: 'returnAwait',\n fix:\n argumentText === undefined\n ? null\n : (fixer) => {\n if (!opts.statement || !isInTry(opts.statement)) {\n return fixer.replaceText(opts.awaitNode, argumentText);\n }\n\n const outer = AwaitSupport.parentOf({ node: opts.statement });\n\n if (!STATEMENT_LISTS.has(AstNode.getType({ node: outer }) ?? '')) {\n return null;\n }\n\n const name = AwaitSupport.freshName({\n node: opts.statement,\n base: 'result',\n sourceCode,\n });\n const indent = AwaitSupport.indentOf({ node: opts.statement, sourceCode });\n\n return fixer.replaceText(\n opts.statement,\n `const ${name} = await ${argumentText};\\n${indent}return ${name};`,\n );\n },\n });\n };\n\n return {\n [AstNodeTypes.RETURN_STATEMENT]: (node: Rule.Node) => {\n const argument = AstNode.readField({ node, key: 'argument' });\n\n if (\n AwaitSupport.isNode(argument) &&\n AstNode.getType({ node: argument }) === AstNodeTypes.AWAIT_EXPRESSION\n ) {\n reportAwait({ reported: node, awaitNode: argument, statement: node });\n }\n },\n [AstNodeTypes.ARROW_FUNCTION_EXPRESSION]: (node: Rule.Node) => {\n const body = AstNode.readField({ node, key: 'body' });\n\n if (\n AwaitSupport.isNode(body) &&\n AstNode.getType({ node: body }) === AstNodeTypes.AWAIT_EXPRESSION\n ) {\n reportAwait({ reported: node, awaitNode: body });\n }\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
@@ -7,11 +7,11 @@ const promise_chain_support_1 = require("./promise-chain-support");
7
7
  /** Whether a parameter of `owner` (a function or a catch clause) is read or written anywhere. */
8
8
  const isParameterUsed = (opts) => opts.sourceCode
9
9
  .getDeclaredVariables(opts.owner)
10
- .some((variable) => variable.defs.some((definition) => ['Parameter', 'CatchClause'].includes(definition.type)) && variable.references.length > 0);
10
+ .some((variable) => variable.defs.some((definition) => ['Parameter', common_1.AstNodeTypes.CATCH_CLAUSE].includes(definition.type)) && variable.references.length > 0);
11
11
  /** A parameter that is not a plain name (`({ message }) =>`, `catch ({ message })`) reads the error by itself. */
12
12
  const isPlainParameter = (opts) => opts.parameter === null ||
13
13
  opts.parameter === undefined ||
14
- common_1.AstNode.getType({ node: opts.parameter }) === 'Identifier';
14
+ common_1.AstNode.getType({ node: opts.parameter }) === common_1.AstNodeTypes.IDENTIFIER;
15
15
  /**
16
16
  * `venizia/no-silent-catch`. A handled error leaves a trace (V-C-06). Reported: a `.catch(h)` (also `?.catch`,
17
17
  * `['catch']`) whose handler is an arrow or function expression that ignores its parameter and whose body is empty
@@ -46,7 +46,8 @@ class NoSilentCatchRule {
46
46
  const handler = Array.isArray(args) ? args[0] : undefined;
47
47
  const handlerType = common_1.AstNode.getType({ node: handler });
48
48
  if (!await_support_1.AwaitSupport.isNode(handler) ||
49
- (handlerType !== 'ArrowFunctionExpression' && handlerType !== 'FunctionExpression')) {
49
+ (handlerType !== common_1.AstNodeTypes.ARROW_FUNCTION_EXPRESSION &&
50
+ handlerType !== common_1.AstNodeTypes.FUNCTION_EXPRESSION)) {
50
51
  return;
51
52
  }
52
53
  const params = common_1.AstNode.readField({ node: handler, key: 'params' });
@@ -1 +1 @@
1
- {"version":3,"file":"no-silent-catch.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-silent-catch.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule, SourceCode } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { PromiseChainSupport } from './promise-chain-support';\n\n/** Whether a parameter of `owner` (a function or a catch clause) is read or written anywhere. */\nconst isParameterUsed = (opts: { owner: Rule.Node; sourceCode: SourceCode }): boolean =>\n opts.sourceCode\n .getDeclaredVariables(opts.owner)\n .some(\n (variable) =>\n variable.defs.some((definition) =>\n ['Parameter', 'CatchClause'].includes(definition.type),\n ) && variable.references.length > 0,\n );\n\n/** A parameter that is not a plain name (`({ message }) =>`, `catch ({ message })`) reads the error by itself. */\nconst isPlainParameter = (opts: { parameter: unknown }): boolean =>\n opts.parameter === null ||\n opts.parameter === undefined ||\n AstNode.getType({ node: opts.parameter }) === 'Identifier';\n\n/**\n * `venizia/no-silent-catch`. A handled error leaves a trace (V-C-06). Reported: a `.catch(h)` (also `?.catch`,\n * `['catch']`) whose handler is an arrow or function expression that ignores its parameter and whose body is empty\n * or only gives back a constant (`() => null`, `() => undefined`, `() => ({})`, `() => []`, `() => {}`,\n * `function () {}`), and a `catch` block that is empty, holds only a comment, or only assigns or returns a constant\n * without reading the error. Handled, and not reported: anything that reads the error (logs, wraps or rethrows\n * it), makes any call (a log, a cleanup, a fallback), throws, or reads another variable.\n *\n * It is not ESLint's `no-empty`: `no-empty` reports an empty block only, lets a block that holds a comment pass,\n * and never sees `.catch(() => null)`. Both report `catch {}`, each with its own message. There is no fix: what to\n * log is a decision. A deliberate silent catch carries an `eslint-disable-next-line` with its reason.\n */\nexport class NoSilentCatchRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-silent-catch`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n schema: [],\n messages: {\n silentHandler:\n 'This `.catch` handler swallows the error with no trace: log it, rethrow it or wrap it (V-C-06), or keep it with an `eslint-disable-next-line` and the reason.',\n silentBlock:\n 'This `catch` block swallows the error with no trace: log it, rethrow it or wrap it (V-C-06), or keep it with an `eslint-disable-next-line` and the reason.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n return {\n [AstNodeTypes.CALL_EXPRESSION]: (node: Rule.Node) => {\n if (PromiseChainSupport.chainMethodOf({ node }) !== 'catch') {\n return;\n }\n\n const args = AstNode.readField({ node, key: 'arguments' });\n const handler: unknown = Array.isArray(args) ? args[0] : undefined;\n const handlerType = AstNode.getType({ node: handler });\n\n if (\n !AwaitSupport.isNode(handler) ||\n (handlerType !== 'ArrowFunctionExpression' && handlerType !== 'FunctionExpression')\n ) {\n return;\n }\n\n const params = AstNode.readField({ node: handler, key: 'params' });\n\n if (\n !Array.isArray(params) ||\n !params.every((parameter) => isPlainParameter({ parameter })) ||\n isParameterUsed({ owner: handler, sourceCode })\n ) {\n return;\n }\n\n const body = AstNode.readField({ node: handler, key: 'body' });\n const isSilent =\n AstNode.getType({ node: body }) === AstNodeTypes.BLOCK_STATEMENT\n ? PromiseChainSupport.isSilentBlock({\n statements: AstNode.readField({ node: body, key: 'body' }),\n })\n : PromiseChainSupport.isConstant({ node: body });\n\n if (isSilent) {\n context.report({ node: handler, messageId: 'silentHandler' });\n }\n },\n [AstNodeTypes.CATCH_CLAUSE]: (node: Rule.Node) => {\n if (\n !isPlainParameter({ parameter: AstNode.readField({ node, key: 'param' }) }) ||\n isParameterUsed({ owner: node, sourceCode })\n ) {\n return;\n }\n\n const body = AstNode.readField({ node, key: 'body' });\n\n if (\n PromiseChainSupport.isSilentBlock({\n statements: AstNode.readField({ node: body, key: 'body' }),\n })\n ) {\n context.report({ node, messageId: 'silentBlock' });\n }\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
1
+ {"version":3,"file":"no-silent-catch.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-silent-catch.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule, SourceCode } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { PromiseChainSupport } from './promise-chain-support';\n\n/** Whether a parameter of `owner` (a function or a catch clause) is read or written anywhere. */\nconst isParameterUsed = (opts: { owner: Rule.Node; sourceCode: SourceCode }): boolean =>\n opts.sourceCode\n .getDeclaredVariables(opts.owner)\n .some(\n (variable) =>\n variable.defs.some((definition) =>\n ['Parameter', AstNodeTypes.CATCH_CLAUSE].includes(definition.type),\n ) && variable.references.length > 0,\n );\n\n/** A parameter that is not a plain name (`({ message }) =>`, `catch ({ message })`) reads the error by itself. */\nconst isPlainParameter = (opts: { parameter: unknown }): boolean =>\n opts.parameter === null ||\n opts.parameter === undefined ||\n AstNode.getType({ node: opts.parameter }) === AstNodeTypes.IDENTIFIER;\n\n/**\n * `venizia/no-silent-catch`. A handled error leaves a trace (V-C-06). Reported: a `.catch(h)` (also `?.catch`,\n * `['catch']`) whose handler is an arrow or function expression that ignores its parameter and whose body is empty\n * or only gives back a constant (`() => null`, `() => undefined`, `() => ({})`, `() => []`, `() => {}`,\n * `function () {}`), and a `catch` block that is empty, holds only a comment, or only assigns or returns a constant\n * without reading the error. Handled, and not reported: anything that reads the error (logs, wraps or rethrows\n * it), makes any call (a log, a cleanup, a fallback), throws, or reads another variable.\n *\n * It is not ESLint's `no-empty`: `no-empty` reports an empty block only, lets a block that holds a comment pass,\n * and never sees `.catch(() => null)`. Both report `catch {}`, each with its own message. There is no fix: what to\n * log is a decision. A deliberate silent catch carries an `eslint-disable-next-line` with its reason.\n */\nexport class NoSilentCatchRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-silent-catch`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n schema: [],\n messages: {\n silentHandler:\n 'This `.catch` handler swallows the error with no trace: log it, rethrow it or wrap it (V-C-06), or keep it with an `eslint-disable-next-line` and the reason.',\n silentBlock:\n 'This `catch` block swallows the error with no trace: log it, rethrow it or wrap it (V-C-06), or keep it with an `eslint-disable-next-line` and the reason.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n return {\n [AstNodeTypes.CALL_EXPRESSION]: (node: Rule.Node) => {\n if (PromiseChainSupport.chainMethodOf({ node }) !== 'catch') {\n return;\n }\n\n const args = AstNode.readField({ node, key: 'arguments' });\n const handler: unknown = Array.isArray(args) ? args[0] : undefined;\n const handlerType = AstNode.getType({ node: handler });\n\n if (\n !AwaitSupport.isNode(handler) ||\n (handlerType !== AstNodeTypes.ARROW_FUNCTION_EXPRESSION &&\n handlerType !== AstNodeTypes.FUNCTION_EXPRESSION)\n ) {\n return;\n }\n\n const params = AstNode.readField({ node: handler, key: 'params' });\n\n if (\n !Array.isArray(params) ||\n !params.every((parameter) => isPlainParameter({ parameter })) ||\n isParameterUsed({ owner: handler, sourceCode })\n ) {\n return;\n }\n\n const body = AstNode.readField({ node: handler, key: 'body' });\n const isSilent =\n AstNode.getType({ node: body }) === AstNodeTypes.BLOCK_STATEMENT\n ? PromiseChainSupport.isSilentBlock({\n statements: AstNode.readField({ node: body, key: 'body' }),\n })\n : PromiseChainSupport.isConstant({ node: body });\n\n if (isSilent) {\n context.report({ node: handler, messageId: 'silentHandler' });\n }\n },\n [AstNodeTypes.CATCH_CLAUSE]: (node: Rule.Node) => {\n if (\n !isPlainParameter({ parameter: AstNode.readField({ node, key: 'param' }) }) ||\n isParameterUsed({ owner: node, sourceCode })\n ) {\n return;\n }\n\n const body = AstNode.readField({ node, key: 'body' });\n\n if (\n PromiseChainSupport.isSilentBlock({\n statements: AstNode.readField({ node: body, key: 'body' }),\n })\n ) {\n context.report({ node, messageId: 'silentBlock' });\n }\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
@@ -6,6 +6,7 @@ const const_class_values_rule_1 = require("./const-class-values.rule");
6
6
  const effect_cleanup_consistency_rule_1 = require("./effect-cleanup-consistency.rule");
7
7
  const max_params_own_rule_1 = require("./max-params-own.rule");
8
8
  const no_async_hook_callback_rule_1 = require("./no-async-hook-callback.rule");
9
+ const no_await_new_chain_rule_1 = require("./no-await-new-chain.rule");
9
10
  const no_await_promise_chain_rule_1 = require("./no-await-promise-chain.rule");
10
11
  const no_inline_await_rule_1 = require("./no-inline-await.rule");
11
12
  const no_leaked_render_rule_1 = require("./no-leaked-render.rule");
@@ -21,6 +22,7 @@ exports.houseEslintPlugin = {
21
22
  'effect-cleanup-consistency': effect_cleanup_consistency_rule_1.EffectCleanupConsistencyRule.RULE,
22
23
  'max-params-own': max_params_own_rule_1.MaxParamsOwnRule.RULE,
23
24
  'no-async-hook-callback': no_async_hook_callback_rule_1.NoAsyncHookCallbackRule.RULE,
25
+ 'no-await-new-chain': no_await_new_chain_rule_1.NoAwaitNewChainRule.RULE,
24
26
  'no-await-promise-chain': no_await_promise_chain_rule_1.NoAwaitPromiseChainRule.RULE,
25
27
  'no-inline-await': no_inline_await_rule_1.NoInlineAwaitRule.RULE,
26
28
  'no-leaked-render': no_leaked_render_rule_1.NoLeakedRenderRule.RULE,
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/linters/house/plugin.ts"],"names":[],"mappings":";;;AACA,qCAAkD;AAClD,uEAAiE;AACjE,uFAAiF;AACjF,+DAAyD;AACzD,+EAAwE;AACxE,+EAAwE;AACxE,iEAA2D;AAC3D,mEAA6D;AAC7D,2DAAqD;AACrD,iEAA2D;AAC3D,iEAA2D;AAC3D,mEAA6D;AAE7D,qGAAqG;AACxF,QAAA,iBAAiB,GAAkB;IAC9C,IAAI,EAAE,EAAE,IAAI,EAAE,iBAAiB,+BAAsB,EAAE,EAAE;IACzD,KAAK,EAAE;QACL,oBAAoB,EAAE,8CAAoB,CAAC,IAAI;QAC/C,4BAA4B,EAAE,8DAA4B,CAAC,IAAI;QAC/D,gBAAgB,EAAE,sCAAgB,CAAC,IAAI;QACvC,wBAAwB,EAAE,qDAAuB,CAAC,IAAI;QACtD,wBAAwB,EAAE,qDAAuB,CAAC,IAAI;QACtD,iBAAiB,EAAE,wCAAiB,CAAC,IAAI;QACzC,kBAAkB,EAAE,0CAAkB,CAAC,IAAI;QAC3C,cAAc,EAAE,kCAAc,CAAC,IAAI;QACnC,iBAAiB,EAAE,wCAAiB,CAAC,IAAI;QACzC,iBAAiB,EAAE,wCAAiB,CAAC,IAAI;QACzC,kBAAkB,EAAE,0CAAkB,CAAC,IAAI;KAC5C;CACF,CAAC","sourcesContent":["import type { ESLint } from 'eslint';\nimport { HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { ConstClassValuesRule } from './const-class-values.rule';\nimport { EffectCleanupConsistencyRule } from './effect-cleanup-consistency.rule';\nimport { MaxParamsOwnRule } from './max-params-own.rule';\nimport { NoAsyncHookCallbackRule } from './no-async-hook-callback.rule';\nimport { NoAwaitPromiseChainRule } from './no-await-promise-chain.rule';\nimport { NoInlineAwaitRule } from './no-inline-await.rule';\nimport { NoLeakedRenderRule } from './no-leaked-render.rule';\nimport { NoNewErrorRule } from './no-new-error.rule';\nimport { NoReturnAwaitRule } from './no-return-await.rule';\nimport { NoSilentCatchRule } from './no-silent-catch.rule';\nimport { NoUnbracedCaseRule } from './no-unbraced-case.rule';\n\n/** The ESLint plugin that carries the house rules oxlint cannot express, registered as `venizia`. */\nexport const houseEslintPlugin: ESLint.Plugin = {\n meta: { name: `eslint-plugin-${HOUSE_PLUGIN_NAMESPACE}` },\n rules: {\n 'const-class-values': ConstClassValuesRule.RULE,\n 'effect-cleanup-consistency': EffectCleanupConsistencyRule.RULE,\n 'max-params-own': MaxParamsOwnRule.RULE,\n 'no-async-hook-callback': NoAsyncHookCallbackRule.RULE,\n 'no-await-promise-chain': NoAwaitPromiseChainRule.RULE,\n 'no-inline-await': NoInlineAwaitRule.RULE,\n 'no-leaked-render': NoLeakedRenderRule.RULE,\n 'no-new-error': NoNewErrorRule.RULE,\n 'no-return-await': NoReturnAwaitRule.RULE,\n 'no-silent-catch': NoSilentCatchRule.RULE,\n 'no-unbraced-case': NoUnbracedCaseRule.RULE,\n },\n};\n"]}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/linters/house/plugin.ts"],"names":[],"mappings":";;;AACA,qCAAkD;AAClD,uEAAiE;AACjE,uFAAiF;AACjF,+DAAyD;AACzD,+EAAwE;AACxE,uEAAgE;AAChE,+EAAwE;AACxE,iEAA2D;AAC3D,mEAA6D;AAC7D,2DAAqD;AACrD,iEAA2D;AAC3D,iEAA2D;AAC3D,mEAA6D;AAE7D,qGAAqG;AACxF,QAAA,iBAAiB,GAAkB;IAC9C,IAAI,EAAE,EAAE,IAAI,EAAE,iBAAiB,+BAAsB,EAAE,EAAE;IACzD,KAAK,EAAE;QACL,oBAAoB,EAAE,8CAAoB,CAAC,IAAI;QAC/C,4BAA4B,EAAE,8DAA4B,CAAC,IAAI;QAC/D,gBAAgB,EAAE,sCAAgB,CAAC,IAAI;QACvC,wBAAwB,EAAE,qDAAuB,CAAC,IAAI;QACtD,oBAAoB,EAAE,6CAAmB,CAAC,IAAI;QAC9C,wBAAwB,EAAE,qDAAuB,CAAC,IAAI;QACtD,iBAAiB,EAAE,wCAAiB,CAAC,IAAI;QACzC,kBAAkB,EAAE,0CAAkB,CAAC,IAAI;QAC3C,cAAc,EAAE,kCAAc,CAAC,IAAI;QACnC,iBAAiB,EAAE,wCAAiB,CAAC,IAAI;QACzC,iBAAiB,EAAE,wCAAiB,CAAC,IAAI;QACzC,kBAAkB,EAAE,0CAAkB,CAAC,IAAI;KAC5C;CACF,CAAC","sourcesContent":["import type { ESLint } from 'eslint';\nimport { HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { ConstClassValuesRule } from './const-class-values.rule';\nimport { EffectCleanupConsistencyRule } from './effect-cleanup-consistency.rule';\nimport { MaxParamsOwnRule } from './max-params-own.rule';\nimport { NoAsyncHookCallbackRule } from './no-async-hook-callback.rule';\nimport { NoAwaitNewChainRule } from './no-await-new-chain.rule';\nimport { NoAwaitPromiseChainRule } from './no-await-promise-chain.rule';\nimport { NoInlineAwaitRule } from './no-inline-await.rule';\nimport { NoLeakedRenderRule } from './no-leaked-render.rule';\nimport { NoNewErrorRule } from './no-new-error.rule';\nimport { NoReturnAwaitRule } from './no-return-await.rule';\nimport { NoSilentCatchRule } from './no-silent-catch.rule';\nimport { NoUnbracedCaseRule } from './no-unbraced-case.rule';\n\n/** The ESLint plugin that carries the house rules oxlint cannot express, registered as `venizia`. */\nexport const houseEslintPlugin: ESLint.Plugin = {\n meta: { name: `eslint-plugin-${HOUSE_PLUGIN_NAMESPACE}` },\n rules: {\n 'const-class-values': ConstClassValuesRule.RULE,\n 'effect-cleanup-consistency': EffectCleanupConsistencyRule.RULE,\n 'max-params-own': MaxParamsOwnRule.RULE,\n 'no-async-hook-callback': NoAsyncHookCallbackRule.RULE,\n 'no-await-new-chain': NoAwaitNewChainRule.RULE,\n 'no-await-promise-chain': NoAwaitPromiseChainRule.RULE,\n 'no-inline-await': NoInlineAwaitRule.RULE,\n 'no-leaked-render': NoLeakedRenderRule.RULE,\n 'no-new-error': NoNewErrorRule.RULE,\n 'no-return-await': NoReturnAwaitRule.RULE,\n 'no-silent-catch': NoSilentCatchRule.RULE,\n 'no-unbraced-case': NoUnbracedCaseRule.RULE,\n },\n};\n"]}
@@ -5,11 +5,11 @@ const common_1 = require("./common");
5
5
  const CHAIN_METHODS = new Set(['then', 'catch', 'finally']);
6
6
  /** Wrappers that leave the value of the expression they hold unchanged: `x!`, `x as T`, `x satisfies T`, `<T>x`, `a?.b`. */
7
7
  const VALUE_WRAPPERS = new Set([
8
- 'TSAsExpression',
9
- 'TSSatisfiesExpression',
10
- 'TSNonNullExpression',
11
- 'TSTypeAssertion',
12
- 'ChainExpression',
8
+ common_1.AstNodeTypes.AS_EXPRESSION,
9
+ common_1.AstNodeTypes.SATISFIES_EXPRESSION,
10
+ common_1.AstNodeTypes.NON_NULL_EXPRESSION,
11
+ common_1.AstNodeTypes.TYPE_ASSERTION,
12
+ common_1.AstNodeTypes.CHAIN_EXPRESSION,
13
13
  ]);
14
14
  const CONSTANT_UNARY_OPERATORS = new Set(['-', '+', '!', 'void']);
15
15
  /** The shared parts of the promise chain rules: what a chain call is, what a constant is, what a silent handler body is. */
@@ -30,13 +30,13 @@ class PromiseChainSupport {
30
30
  const name = common_1.AstNode.readField({ node: property, key: 'name' });
31
31
  return typeof name === 'string' ? name : undefined;
32
32
  }
33
- if (common_1.AstNode.getType({ node: property }) === 'Literal') {
33
+ if (common_1.AstNode.getType({ node: property }) === common_1.AstNodeTypes.LITERAL) {
34
34
  const value = common_1.AstNode.readField({ node: property, key: 'value' });
35
35
  return typeof value === 'string' ? value : undefined;
36
36
  }
37
37
  const expressions = common_1.AstNode.readField({ node: property, key: 'expressions' });
38
38
  const quasis = common_1.AstNode.readField({ node: property, key: 'quasis' });
39
- if (common_1.AstNode.getType({ node: property }) === 'TemplateLiteral' &&
39
+ if (common_1.AstNode.getType({ node: property }) === common_1.AstNodeTypes.TEMPLATE_LITERAL &&
40
40
  Array.isArray(expressions) &&
41
41
  expressions.length === 0 &&
42
42
  Array.isArray(quasis)) {
@@ -54,13 +54,13 @@ class PromiseChainSupport {
54
54
  */
55
55
  static chainMethodOf(opts) {
56
56
  const call = PromiseChainSupport.unwrap({ node: opts.node });
57
- if (common_1.AstNode.getType({ node: call }) !== 'CallExpression') {
57
+ if (common_1.AstNode.getType({ node: call }) !== common_1.AstNodeTypes.CALL_EXPRESSION) {
58
58
  return undefined;
59
59
  }
60
60
  const callee = PromiseChainSupport.unwrap({
61
61
  node: common_1.AstNode.readField({ node: call, key: 'callee' }),
62
62
  });
63
- if (common_1.AstNode.getType({ node: callee }) !== 'MemberExpression') {
63
+ if (common_1.AstNode.getType({ node: callee }) !== common_1.AstNodeTypes.MEMBER_EXPRESSION) {
64
64
  return undefined;
65
65
  }
66
66
  const name = PromiseChainSupport.memberName({ member: callee });
@@ -74,7 +74,7 @@ class PromiseChainSupport {
74
74
  let current = PromiseChainSupport.unwrap({ node: opts.node });
75
75
  for (;;) {
76
76
  const type = common_1.AstNode.getType({ node: current });
77
- if (type === 'CallExpression') {
77
+ if (type === common_1.AstNodeTypes.CALL_EXPRESSION) {
78
78
  if (PromiseChainSupport.chainMethodOf({ node: current }) !== undefined) {
79
79
  return true;
80
80
  }
@@ -83,7 +83,7 @@ class PromiseChainSupport {
83
83
  });
84
84
  continue;
85
85
  }
86
- if (type === 'MemberExpression') {
86
+ if (type === common_1.AstNodeTypes.MEMBER_EXPRESSION) {
87
87
  current = PromiseChainSupport.unwrap({
88
88
  node: common_1.AstNode.readField({ node: current, key: 'object' }),
89
89
  });
@@ -101,29 +101,29 @@ class PromiseChainSupport {
101
101
  const type = common_1.AstNode.getType({ node }) ?? '';
102
102
  const constant = (child) => PromiseChainSupport.isConstant({ node: child });
103
103
  switch (type) {
104
- case 'Literal': {
104
+ case common_1.AstNodeTypes.LITERAL: {
105
105
  return true;
106
106
  }
107
- case 'Identifier': {
107
+ case common_1.AstNodeTypes.IDENTIFIER: {
108
108
  return common_1.AstNode.readField({ node, key: 'name' }) === 'undefined';
109
109
  }
110
- case 'TemplateLiteral': {
110
+ case common_1.AstNodeTypes.TEMPLATE_LITERAL: {
111
111
  const expressions = common_1.AstNode.readField({ node, key: 'expressions' });
112
112
  return Array.isArray(expressions) && expressions.length === 0;
113
113
  }
114
- case 'UnaryExpression': {
114
+ case common_1.AstNodeTypes.UNARY_EXPRESSION: {
115
115
  return (CONSTANT_UNARY_OPERATORS.has(String(common_1.AstNode.readField({ node, key: 'operator' }))) &&
116
116
  constant(common_1.AstNode.readField({ node, key: 'argument' })));
117
117
  }
118
- case 'ArrayExpression': {
118
+ case common_1.AstNodeTypes.ARRAY_EXPRESSION: {
119
119
  const elements = common_1.AstNode.readField({ node, key: 'elements' });
120
120
  return (Array.isArray(elements) &&
121
121
  elements.every((element) => element === null || constant(element)));
122
122
  }
123
- case 'ObjectExpression': {
123
+ case common_1.AstNodeTypes.OBJECT_EXPRESSION: {
124
124
  const properties = common_1.AstNode.readField({ node, key: 'properties' });
125
125
  return (Array.isArray(properties) &&
126
- properties.every((property) => common_1.AstNode.getType({ node: property }) === 'Property' &&
126
+ properties.every((property) => common_1.AstNode.getType({ node: property }) === common_1.AstNodeTypes.PROPERTY &&
127
127
  common_1.AstNode.readField({ node: property, key: 'computed' }) !== true &&
128
128
  common_1.AstNode.readField({ node: property, key: 'method' }) !== true &&
129
129
  common_1.AstNode.readField({ node: property, key: 'kind' }) === 'init' &&
@@ -144,16 +144,16 @@ class PromiseChainSupport {
144
144
  return (Array.isArray(statements) &&
145
145
  statements.every((statement) => {
146
146
  const type = common_1.AstNode.getType({ node: statement });
147
- if (type === 'EmptyStatement') {
147
+ if (type === common_1.AstNodeTypes.EMPTY_STATEMENT) {
148
148
  return true;
149
149
  }
150
- if (type === 'ReturnStatement') {
150
+ if (type === common_1.AstNodeTypes.RETURN_STATEMENT) {
151
151
  const argument = common_1.AstNode.readField({ node: statement, key: 'argument' });
152
152
  return argument === null || PromiseChainSupport.isConstant({ node: argument });
153
153
  }
154
154
  const expression = common_1.AstNode.readField({ node: statement, key: 'expression' });
155
- return (type === 'ExpressionStatement' &&
156
- common_1.AstNode.getType({ node: expression }) === 'AssignmentExpression' &&
155
+ return (type === common_1.AstNodeTypes.EXPRESSION_STATEMENT &&
156
+ common_1.AstNode.getType({ node: expression }) === common_1.AstNodeTypes.ASSIGNMENT_EXPRESSION &&
157
157
  common_1.AstNode.readField({ node: expression, key: 'operator' }) === '=' &&
158
158
  PromiseChainSupport.isPlainTarget({
159
159
  node: common_1.AstNode.readField({ node: expression, key: 'left' }),
@@ -167,10 +167,10 @@ class PromiseChainSupport {
167
167
  static isPlainTarget(opts) {
168
168
  const { node } = opts;
169
169
  const type = common_1.AstNode.getType({ node });
170
- if (type === 'Identifier' || type === 'ThisExpression') {
170
+ if (type === common_1.AstNodeTypes.IDENTIFIER || type === common_1.AstNodeTypes.THIS_EXPRESSION) {
171
171
  return true;
172
172
  }
173
- return (type === 'MemberExpression' &&
173
+ return (type === common_1.AstNodeTypes.MEMBER_EXPRESSION &&
174
174
  common_1.AstNode.readField({ node, key: 'computed' }) !== true &&
175
175
  PromiseChainSupport.isPlainTarget({ node: common_1.AstNode.readField({ node, key: 'object' }) }));
176
176
  }
@@ -178,7 +178,7 @@ class PromiseChainSupport {
178
178
  static unwrapTypes(opts) {
179
179
  let current = opts.node;
180
180
  while (VALUE_WRAPPERS.has(common_1.AstNode.getType({ node: current }) ?? '') &&
181
- common_1.AstNode.getType({ node: current }) !== 'ChainExpression') {
181
+ common_1.AstNode.getType({ node: current }) !== common_1.AstNodeTypes.CHAIN_EXPRESSION) {
182
182
  current = common_1.AstNode.readField({ node: current, key: 'expression' });
183
183
  }
184
184
  return current;