Skip to content

Commit

Permalink
Merge pull request #110 from storybookjs/feat/support-ts-4.9
Browse files Browse the repository at this point in the history
Support typescript 4.9
  • Loading branch information
kasperpeulen committed Dec 5, 2022
2 parents c275b81 + e3c5bdd commit 3513226
Show file tree
Hide file tree
Showing 30 changed files with 238 additions and 176 deletions.
30 changes: 13 additions & 17 deletions lib/rules/await-interactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,7 @@
* @author Yann Braga
*/

import type {
ImportDeclaration,
CallExpression,
Identifier,
Node,
VariableDeclarator,
} from '@typescript-eslint/types/dist/ast-spec'
import { TSESTree, TSESLint } from '@typescript-eslint/utils'

import { createStorybookRule } from '../utils/create-storybook-rule'
import { CategoryId } from '../utils/constants'
Expand All @@ -26,7 +20,6 @@ import {
isProgram,
isImportSpecifier,
} from '../utils/ast'
import { ReportFixFunction } from '@typescript-eslint/experimental-utils/dist/ts-eslint'

//------------------------------------------------------------------------------
// Rule Definition
Expand Down Expand Up @@ -70,7 +63,7 @@ export = createStorybookRule({
'play',
]

const getMethodThatShouldBeAwaited = (expr: CallExpression) => {
const getMethodThatShouldBeAwaited = (expr: TSESTree.CallExpression) => {
const shouldAwait = (name: string) => {
return FUNCTIONS_TO_BE_AWAITED.includes(name) || name.startsWith('findBy')
}
Expand Down Expand Up @@ -122,7 +115,7 @@ export = createStorybookRule({
return null
}

const getClosestFunctionAncestor = (node: Node): Node | undefined => {
const getClosestFunctionAncestor = (node: TSESTree.Node): TSESTree.Node | undefined => {
const parent = node.parent

if (!parent || isProgram(parent)) return undefined
Expand All @@ -137,7 +130,7 @@ export = createStorybookRule({
return getClosestFunctionAncestor(parent)
}

const isUserEventFromStorybookImported = (node: ImportDeclaration) => {
const isUserEventFromStorybookImported = (node: TSESTree.ImportDeclaration) => {
return (
node.source.value === '@storybook/testing-library' &&
node.specifiers.find(
Expand All @@ -149,7 +142,7 @@ export = createStorybookRule({
)
}

const isExpectFromStorybookImported = (node: ImportDeclaration) => {
const isExpectFromStorybookImported = (node: TSESTree.ImportDeclaration) => {
return (
node.source.value === '@storybook/jest' &&
node.specifiers.find(
Expand All @@ -166,18 +159,21 @@ export = createStorybookRule({
*/

let isImportedFromStorybook = true
let invocationsThatShouldBeAwaited = [] as Array<{ node: Node; method: Identifier }>
let invocationsThatShouldBeAwaited = [] as Array<{
node: TSESTree.Node
method: TSESTree.Identifier
}>

return {
ImportDeclaration(node: ImportDeclaration) {
ImportDeclaration(node: TSESTree.ImportDeclaration) {
isImportedFromStorybook =
isUserEventFromStorybookImported(node) || isExpectFromStorybookImported(node)
},
VariableDeclarator(node: VariableDeclarator) {
VariableDeclarator(node: TSESTree.VariableDeclarator) {
isImportedFromStorybook =
isImportedFromStorybook && isIdentifier(node.id) && node.id.name !== 'userEvent'
},
CallExpression(node: CallExpression) {
CallExpression(node: TSESTree.CallExpression) {
const method = getMethodThatShouldBeAwaited(node)
if (method && !isAwaitExpression(node.parent) && !isAwaitExpression(node.parent?.parent)) {
invocationsThatShouldBeAwaited.push({ node, method })
Expand All @@ -190,7 +186,7 @@ export = createStorybookRule({
const parentFnNeedsAsync =
parentFnNode && !('async' in parentFnNode && parentFnNode.async)

const fixFn: ReportFixFunction = (fixer) => {
const fixFn: TSESLint.ReportFixFunction = (fixer) => {
const fixerResult = [fixer.insertTextBefore(node, 'await ')]

if (parentFnNeedsAsync) {
Expand Down
10 changes: 5 additions & 5 deletions lib/rules/context-in-play-function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Yann Braga
*/

import type { CallExpression, Node } from '@typescript-eslint/types/dist/ast-spec'
import { TSESTree } from "@typescript-eslint/utils";

import { createStorybookRule } from '../utils/create-storybook-rule'
import { CategoryId } from '../utils/constants'
Expand Down Expand Up @@ -45,7 +45,7 @@ export = createStorybookRule({

// any helper functions should go here or else delete this section

const isPlayFunctionFromAnotherStory = (expr: CallExpression) => {
const isPlayFunctionFromAnotherStory = (expr: TSESTree.CallExpression) => {
if (
isTSNonNullExpression(expr.callee) &&
isMemberExpression(expr.callee.expression) &&
Expand All @@ -67,7 +67,7 @@ export = createStorybookRule({
}

// Expression passing an argument called context OR spreading a variable called context
const isNotPassingContextCorrectly = (expr: CallExpression) => {
const isNotPassingContextCorrectly = (expr: TSESTree.CallExpression) => {
const firstExpressionArgument = expr.arguments[0]

if (!firstExpressionArgument) {
Expand Down Expand Up @@ -100,10 +100,10 @@ export = createStorybookRule({
// Public
//----------------------------------------------------------------------

let invocationsWithoutProperContext = [] as Node[]
let invocationsWithoutProperContext: TSESTree.Node[] = [];

return {
CallExpression(node: CallExpression) {
CallExpression(node: TSESTree.CallExpression) {
if (isPlayFunctionFromAnotherStory(node) && isNotPassingContextCorrectly(node)) {
invocationsWithoutProperContext.push(node)
}
Expand Down
4 changes: 2 additions & 2 deletions lib/rules/csf-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Yann Braga
*/

import { ExportDefaultDeclaration } from '@typescript-eslint/types/dist/ast-spec'
import { TSESTree } from "@typescript-eslint/utils";
import { getMetaObjectExpression } from '../utils'
import { CategoryId } from '../utils/constants'
import { createStorybookRule } from '../utils/create-storybook-rule'
Expand Down Expand Up @@ -43,7 +43,7 @@ export = createStorybookRule({
//----------------------------------------------------------------------

return {
ExportDefaultDeclaration(node: ExportDefaultDeclaration) {
ExportDefaultDeclaration(node: TSESTree.ExportDefaultDeclaration) {
const meta = getMetaObjectExpression(node, context)

if (!meta) {
Expand Down
11 changes: 5 additions & 6 deletions lib/rules/default-exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
*/

import path from 'path'
import { Program, Node } from '@typescript-eslint/types/dist/ast-spec'
import { TSESLint, TSESTree } from '@typescript-eslint/utils'

import { CategoryId } from '../utils/constants'
import { isImportDeclaration, isLiteral, isIdentifier } from '../utils/ast'
import { createStorybookRule } from '../utils/create-storybook-rule'
import { ReportFixFunction } from '@typescript-eslint/experimental-utils/dist/ts-eslint'

//------------------------------------------------------------------------------
// Rule Definition
Expand Down Expand Up @@ -42,9 +41,9 @@ export = createStorybookRule({
//----------------------------------------------------------------------

// any helper functions should go here or else delete this section
const getComponentName = (node: Program, filePath: string) => {
const getComponentName = (node: TSESTree.Program, filePath: string) => {
const name = path.basename(filePath).split('.')[0]
const imported = node.body.find((stmt: Node) => {
const imported = node.body.find((stmt: TSESTree.Node) => {
if (
isImportDeclaration(stmt) &&
isLiteral(stmt.source) &&
Expand Down Expand Up @@ -77,7 +76,7 @@ export = createStorybookRule({
ExportDefaultDeclaration: function () {
hasDefaultExport = true
},
'Program:exit': function (program: Program) {
'Program:exit': function (program: TSESTree.Program) {
if (!hasDefaultExport && !hasStoriesOfImport) {
const componentName = getComponentName(program, context.getFilename())
const firstNonImportStatement = program.body.find((n) => !isImportDeclaration(n))
Expand All @@ -88,7 +87,7 @@ export = createStorybookRule({
messageId: 'shouldHaveDefaultExport',
} as const

const fix: ReportFixFunction = (fixer) => {
const fix: TSESLint.ReportFixFunction = (fixer) => {
const metaDeclaration = componentName
? `export default { component: ${componentName} }\n`
: 'export default {}\n'
Expand Down
4 changes: 2 additions & 2 deletions lib/rules/hierarchy-separator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Yann Braga
*/

import { MethodDefinition, Property } from '@typescript-eslint/types/dist/ast-spec'
import { TSESTree } from "@typescript-eslint/utils";
import { getMetaObjectExpression } from '../utils'
import { isLiteral, isSpreadElement } from '../utils/ast'
import { CategoryId } from '../utils/constants'
Expand Down Expand Up @@ -42,7 +42,7 @@ export = createStorybookRule({

const titleNode = meta.properties.find(
(prop) => !isSpreadElement(prop) && 'name' in prop.key && prop.key?.name === 'title'
) as MethodDefinition | Property | undefined
) as TSESTree.MethodDefinition | TSESTree.Property | undefined

if (!titleNode || !isLiteral(titleNode.value)) {
return
Expand Down
13 changes: 5 additions & 8 deletions lib/rules/meta-inline-properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,14 @@
* @author Yann Braga
*/

import {
Identifier,
MethodDefinition,
PrivateIdentifier,
Property,
} from '@typescript-eslint/types/dist/ast-spec'
import { TSESTree } from '@typescript-eslint/utils'
import { getMetaObjectExpression } from '../utils'
import { CategoryId } from '../utils/constants'
import { createStorybookRule } from '../utils/create-storybook-rule'

type TDynamicProperty = (MethodDefinition | Property) & { key: Identifier | PrivateIdentifier }
type TDynamicProperty = (TSESTree.MethodDefinition | TSESTree.Property) & {
key: TSESTree.Identifier | TSESTree.PrivateIdentifier
}

//------------------------------------------------------------------------------
// Rule Definition
Expand Down Expand Up @@ -57,7 +54,7 @@ export = createStorybookRule({
// Helpers
//----------------------------------------------------------------------
const isInline = <T>(node: T | TDynamicProperty): node is T => {
if (!('value' in node)) {
if (!(node && typeof node === 'object' && 'value' in node)) {
return false
}

Expand Down
4 changes: 2 additions & 2 deletions lib/rules/no-title-property-in-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
* @author Yann Braga
*/

import { TSESTree } from "@typescript-eslint/utils";
import { getMetaObjectExpression } from '../utils'
import { CategoryId } from '../utils/constants'
import { createStorybookRule } from '../utils/create-storybook-rule'
import { Range } from '@typescript-eslint/types/dist/ast-spec'
import { isSpreadElement } from '../utils/ast'

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -57,7 +57,7 @@ export = createStorybookRule({
titleNode.range[1] + 1
)
const hasComma = propertyTextWithExtraCharacter.slice(-1) === ','
const propertyRange: Range = [
const propertyRange: TSESTree.Range = [
titleNode.range[0],
hasComma ? titleNode.range[1] + 1 : titleNode.range[1],
]
Expand Down
14 changes: 7 additions & 7 deletions lib/rules/no-uninstalled-addons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
isVariableDeclarator,
isVariableDeclaration,
} from '../utils/ast'
import { Property, ArrayExpression } from '@typescript-eslint/types/dist/ast-spec'
import { TSESTree } from "@typescript-eslint/utils";

//------------------------------------------------------------------------------
// Rule Definition
Expand Down Expand Up @@ -133,7 +133,7 @@ export = createStorybookRule({
}

const extractAllAddonsFromTheStorybookConfig = (
addonsExpression: ArrayExpression | undefined
addonsExpression: TSESTree.ArrayExpression | undefined
) => {
if (addonsExpression?.elements) {
// extract all nodes taht are a string inside the addons array
Expand All @@ -147,9 +147,9 @@ export = createStorybookRule({
const nodesWithAddonsInObj = addonsExpression.elements
.map((elem) => (isObjectExpression(elem) ? elem : { properties: [] }))
.map((elem) => {
const property: Property = elem.properties.find(
const property: TSESTree.Property = elem.properties.find(
(prop) => isProperty(prop) && isIdentifier(prop.key) && prop.key.name === 'name'
) as Property
) as TSESTree.Property
return isLiteral(property?.value)
? { value: property.value.value, node: property.value }
: undefined
Expand All @@ -166,7 +166,7 @@ export = createStorybookRule({
return { listOfAddons: [], listOfAddonElements: [] }
}

function reportUninstalledAddons(addonsProp: ArrayExpression) {
function reportUninstalledAddons(addonsProp: TSESTree.ArrayExpression) {
const packageJsonPath = resolve(packageJsonLocation || `./package.json`)
let packageJsonObject: Record<string, any>
try {
Expand Down Expand Up @@ -211,7 +211,7 @@ export = createStorybookRule({
AssignmentExpression: function (node) {
if (isObjectExpression(node.right)) {
const addonsProp = node.right.properties.find(
(prop): prop is Property =>
(prop): prop is TSESTree.Property =>
isProperty(prop) && isIdentifier(prop.key) && prop.key.name === 'addons'
)

Expand All @@ -223,7 +223,7 @@ export = createStorybookRule({
ExportDefaultDeclaration: function (node) {
if (isObjectExpression(node.declaration)) {
const addonsProp = node.declaration.properties.find(
(prop): prop is Property =>
(prop): prop is TSESTree.Property =>
isProperty(prop) && isIdentifier(prop.key) && prop.key.name === 'addons'
)

Expand Down
9 changes: 4 additions & 5 deletions lib/rules/prefer-pascal-case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
* @author Yann Braga
*/

import { ASTUtils } from '@typescript-eslint/experimental-utils'
import { ExportNamedDeclaration, Identifier } from '@typescript-eslint/types/dist/ast-spec'
import { ASTUtils, TSESTree } from "@typescript-eslint/utils";
import { IncludeExcludeOptions, isExportStory } from '@storybook/csf'

import { getDescriptor, getMetaObjectExpression } from '../utils'
Expand Down Expand Up @@ -55,7 +54,7 @@ export = createStorybookRule({
.replace(new RegExp(/\w/), (s) => s.toUpperCase())
}

const checkAndReportError = (id: Identifier, nonStoryExportsConfig = {}) => {
const checkAndReportError = (id: TSESTree.Identifier, nonStoryExportsConfig = {}) => {
const { name } = id
if (!isExportStory(name, nonStoryExportsConfig) || name === '__namedExportsOrder') {
return null
Expand Down Expand Up @@ -103,7 +102,7 @@ export = createStorybookRule({

let meta
let nonStoryExportsConfig: IncludeExcludeOptions
let namedExports: Identifier[] = []
let namedExports: TSESTree.Identifier[] = []
let hasStoriesOfImport = false

return {
Expand All @@ -123,7 +122,7 @@ export = createStorybookRule({
} catch (err) {}
}
},
ExportNamedDeclaration: function (node: ExportNamedDeclaration) {
ExportNamedDeclaration: function (node: TSESTree.ExportNamedDeclaration) {
// if there are specifiers, node.declaration should be null
if (!node.declaration) return

Expand Down
9 changes: 4 additions & 5 deletions lib/rules/story-exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* @author Yann Braga
*/

import type { Program } from '@typescript-eslint/types/dist/ast-spec'

import { createStorybookRule } from '../utils/create-storybook-rule'
import { CategoryId } from '../utils/constants'
Expand All @@ -15,7 +14,7 @@ import {
} from '../utils'
import { isImportDeclaration } from '../utils/ast'
import { IncludeExcludeOptions } from '@storybook/csf'
import { ObjectExpression, Identifier } from '@typescript-eslint/types/dist/ast-spec'
import { TSESTree } from "@typescript-eslint/utils";

//------------------------------------------------------------------------------
// Rule Definition
Expand Down Expand Up @@ -54,8 +53,8 @@ export = createStorybookRule({

let hasStoriesOfImport = false
let nonStoryExportsConfig: IncludeExcludeOptions = {}
let meta: ObjectExpression | null
let namedExports: Identifier[] = []
let meta: TSESTree.ObjectExpression | null
let namedExports: TSESTree.Identifier[] = []

return {
ImportSpecifier(node) {
Expand All @@ -77,7 +76,7 @@ export = createStorybookRule({
ExportNamedDeclaration: function (node) {
namedExports.push(...getAllNamedExports(node))
},
'Program:exit': function (program: Program) {
'Program:exit': function (program: TSESTree.Program) {
if (hasStoriesOfImport || !meta) {
return
}
Expand Down

0 comments on commit 3513226

Please sign in to comment.